我试图在一个画布上显示来自不同流的多个帧,使用视口并在我必须渲染的每个帧上调用draw函数。我要复制的是仅使用一个画布和一个webgl上下文的摄像机视频墙。问题在于,每当我将一个框架渲染到特定的视口中,然后我之前在其他视口中渲染的其他框架都消失了。
我什至试图将webgl上下文设置中的“ preserveDrawingBuffer”属性设置为true,但是并没有解决。
遵循我正在使用的代码:
<header class="header">
<div class="left">variable content</div>
<div class="middle">variable content</div>
<div class="right">variable content which happens to be very long</div>
</header>
有没有一种方法可以只更新特定的视口而不清理整个上下文?
谢谢
答案 0 :(得分:1)
您需要打开剪刀测试并设置剪刀矩形
gl.enable(gl.SCISSOR_TEST);
gl.scissor(x, y, width, height);
示例:
const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl');
const vs = `
attribute vec4 position;
uniform mat4 matrix;
void main() {
gl_Position = matrix * position;
}
`;
const fs = `
precision mediump float;
uniform vec4 color;
void main() {
gl_FragColor = color;
}
`;
// compiles shaders, links program, looks up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData
const bufferInfo = twgl.primitives.createCylinderBufferInfo(gl, 1, 1, 24, 1);
const scenes = [
{
viewport: [0, 0, 150, 150],
xRot: 0,
zRot: 0,
bg: [1, 0, 0, 1],
color: [0, 1, 1, 1],
},
{
viewport: [150, 0, 150, 50],
xRot: Math.PI * .5,
zRot: 0,
bg: [0, 1, 0, 1],
color: [1, 0, 1, 1],
},
{
viewport: [150, 50, 150, 100],
xRot: 0,
zRot: Math.PI * 0.25,
bg: [0, 0, 1, 1],
color: [1, 1, 0, 1],
},
];
function render(time) {
time *= 0.001;
gl.enable(gl.SCISSOR_TEST);
scenes.forEach((scene, ndx) => {
gl.viewport(...scene.viewport);
gl.scissor(...scene.viewport);
gl.clearColor(...scene.bg);
gl.clear(gl.COLOR_BUFFER_BIT);
const fov = Math.PI * 0.25;
const aspect = scene.viewport[2] / scene.viewport[3];
const near = 0.1;
const far = 10;
const matrix = m4.perspective(fov, aspect, near, far);
m4.translate(matrix, [Math.sin(time + ndx), 0, -4], matrix);
m4.rotateX(matrix, scene.xRot, matrix);
m4.rotateZ(matrix, scene.zRot, matrix);
m4.rotateZ(matrix, time, matrix);
gl.useProgram(programInfo.program);
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
// calls gl.uniformXXX
twgl.setUniforms(programInfo, {
color: scene.color,
matrix: matrix,
});
// calls gl.drawArrays or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo);
});
requestAnimationFrame(render);
}
requestAnimationFrame(render);
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>
如果您不是在每一帧都渲染每个视口,则在创建webgl上下文时需要传递preserveDrawingBuffer: true
。
每帧仅更新一个视口的示例
const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl', {
preserveDrawingBuffer: true,
});
const vs = `
attribute vec4 position;
uniform mat4 matrix;
void main() {
gl_Position = matrix * position;
}
`;
const fs = `
precision mediump float;
uniform vec4 color;
void main() {
gl_FragColor = color;
}
`;
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
const bufferInfo = twgl.primitives.createCylinderBufferInfo(gl, 1, 1, 24, 1);
const scenes = [
{
viewport: [0, 0, 150, 150],
xRot: 0,
zRot: 0,
bg: [1, 0, 0, 1],
color: [0, 1, 1, 1],
},
{
viewport: [150, 0, 150, 50],
xRot: Math.PI * .5,
zRot: 0,
bg: [0, 1, 0, 1],
color: [1, 0, 1, 1],
},
{
viewport: [150, 50, 150, 100],
xRot: 0,
zRot: Math.PI * 0.25,
bg: [0, 0, 1, 1],
color: [1, 1, 0, 1],
},
];
let count = 0;
function render(time) {
++count;
time *= 0.001;
gl.enable(gl.SCISSOR_TEST);
const ndx = count % scenes.length;
const scene = scenes[ndx];
gl.viewport(...scene.viewport);
gl.scissor(...scene.viewport);
gl.clearColor(...scene.bg);
gl.clear(gl.COLOR_BUFFER_BIT);
const fov = Math.PI * 0.25;
const aspect = scene.viewport[2] / scene.viewport[3];
const near = 0.1;
const far = 10;
const matrix = m4.perspective(fov, aspect, near, far);
m4.translate(matrix, [Math.sin(time + ndx), 0, -4], matrix);
m4.rotateX(matrix, scene.xRot, matrix);
m4.rotateZ(matrix, scene.zRot, matrix);
m4.rotateZ(matrix, time, matrix);
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, {
color: scene.color,
matrix: matrix,
});
twgl.drawBufferInfo(gl, bufferInfo);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>