Javascript 如何防止webgl在每一帧绘制时清洁画布
我试图在一个画布中显示来自不同流的多个帧,使用视口并在每个需要渲染的帧上调用draw函数。我试图复制的是一个只使用一个画布和一个webgl上下文的摄像头视频墙。问题是,每次我将一个帧渲染到特定的视口中,然后之前在不同的视口中渲染的其他帧都会消失 我甚至尝试将webgl上下文设置“preserveDrawingBuffer”属性设置为true,但没有解决这个问题 下面是我正在使用的代码:Javascript 如何防止webgl在每一帧绘制时清洁画布,javascript,webgl,Javascript,Webgl,我试图在一个画布中显示来自不同流的多个帧,使用视口并在每个需要渲染的帧上调用draw函数。我试图复制的是一个只使用一个画布和一个webgl上下文的摄像头视频墙。问题是,每次我将一个帧渲染到特定的视口中,然后之前在不同的视口中渲染的其他帧都会消失 我甚至尝试将webgl上下文设置“preserveDrawingBuffer”属性设置为true,但没有解决这个问题 下面是我正在使用的代码: this.drawNextOuptutPictureGL = function (par) {
this.drawNextOuptutPictureGL = function (par) {
var gl = this.contextGL;
var texturePosBuffer = this.texturePosBuffer;
var uTexturePosBuffer = this.uTexturePosBuffer;
var vTexturePosBuffer = this.vTexturePosBuffer;
var yTextureRef = this.yTextureRef;
var uTextureRef = this.uTextureRef;
var vTextureRef = this.vTextureRef;
var width = this.width;
var height = this.height;
var yData = par.yData;
var uData = par.uData;
var vData = par.vData;
var yDataPerRow = par.yDataPerRow || width;
var yRowCnt = par.yRowCnt || height;
var uDataPerRow = par.uDataPerRow || (width / 2);
var uRowCnt = par.uRowCnt || (height / 2);
var vDataPerRow = par.vDataPerRow || uDataPerRow;
var vRowCnt = par.vRowCnt || uRowCnt;
var viewportRow = par.viewportRow;
var viewportColumn = par.viewportColumn;
// Calculate coordinates basing on a square matrix
var square = Math.sqrt(this.viewports.length);
var x = (this.canvasElement.width / square) * (viewportColumn - 1);
var y = (this.canvasElement.height / square) * (square - viewportRow);
gl.viewport(x, y, width, height);
var tTop = 0;
var tLeft = 0;
var tBottom = height / yRowCnt;
var tRight = width / yDataPerRow;
var texturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, texturePosValues, gl.DYNAMIC_DRAW);
if (this.customYUV444) {
tBottom = height / uRowCnt;
tRight = width / uDataPerRow;
} else {
tBottom = (height / 2) / uRowCnt;
tRight = (width / 2) / uDataPerRow;
};
var uTexturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
gl.bindBuffer(gl.ARRAY_BUFFER, uTexturePosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, uTexturePosValues, gl.DYNAMIC_DRAW);
if (this.customYUV444) {
tBottom = height / vRowCnt;
tRight = width / vDataPerRow;
} else {
tBottom = (height / 2) / vRowCnt;
tRight = (width / 2) / vDataPerRow;
};
var vTexturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
gl.bindBuffer(gl.ARRAY_BUFFER, vTexturePosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vTexturePosValues, gl.DYNAMIC_DRAW);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, yDataPerRow, yRowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, yData);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, uDataPerRow, uRowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, uData);
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, vDataPerRow, vRowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, vData);
// draw image
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
有没有一种方法可以只更新特定视口而不清理整个上下文
谢谢您需要打开剪刀测试并设置剪刀矩形
gl.enable(gl.SCISSOR_TEST);
gl.scissor(x, y, width, height);
例如:
const m4=twgl.m4;
const gl=document.querySelector('canvas').getContext('webgl');
常数vs=`
属性向量4位置;
一致mat4矩阵;
void main(){
gl_位置=矩阵*位置;
}
`;
常数fs=`
精密中泵浮子;
vec4颜色均匀;
void main(){
gl_FragColor=颜色;
}
`;
//编译着色器、链接程序、查找位置
const programInfo=twgl.createProgramInfo(gl[vs,fs]);
//调用gl.createBuffer、gl.bindBuffer、gl.bufferData
const bufferInfo=twgl.primitives.createCylinderBufferInfo(gl,1,1,24,1);
常量场景=[
{
视口:[0,0,150,150],
xRot:0,
zRot:0,
背景:[1,0,0,1],
颜色:[0,1,1,1],
},
{
视口:[150,0,150,50],
xRot:Math.PI*.5,
zRot:0,
背景:[0,1,0,1],
颜色:[1,0,1,1],
},
{
视口:[150,50,150,100],
xRot:0,
zRot:Math.PI*0.25,
背景:[0,0,1,1],
颜色:[1,1,0,1],
},
];
函数渲染(时间){
时间*=0.001;
总帐启用(总帐剪刀测试);
scenes.forEach((scene,ndx)=>{
总图视口(…场景视口);
gl.scissor(…场景.视口);
gl.clearColor(…scene.bg);
总账清除(总账颜色缓冲位);
常数fov=Math.PI*0.25;
const aspect=scene.viewport[2]/scene.viewport[3];
常数近=0.1;
常数far=10;
常数矩阵=m4.透视图(视野、纵横比、近距离、远距离);
m4.转换(矩阵,[Math.sin(time+ndx),0,-4],矩阵);
m4.rotateX(矩阵,scene.xRot,矩阵);
m4.rotateZ(矩阵,scene.zRot,矩阵);
m4.旋转(矩阵、时间、矩阵);
总账使用程序(programInfo.program);
//调用gl.bindBuffer、gl.enableVertexAttributeArray、gl.VertexAttributePointer
twgl.setBuffersAndAttributes(总帐、程序信息、缓冲信息);
//调用gl.uniformXXX
twgl.设置制服(程序信息{
颜色:scene.color,
矩阵:矩阵,
});
//调用gl.DrawArray或gl.drawElements
twgl.drawBufferInfo(总账,bufferInfo);
});
请求动画帧(渲染);
}
请求动画帧(渲染)代码>
我认为您需要渲染到纹理,然后将这些纹理渲染到画布。这只是一个暗示。更多细节见此:是的,我已经看过那篇文章了。所以方法应该是使用帧缓冲区绘制纹理,然后渲染到默认缓冲区(画布),然后使用上一个纹理作为下一帧的输入,对吗?如何检索修改后的纹理以重新用作输入尚不清楚。。