WebGL:在带有深度模板纹理附件的帧缓冲区上未清除颜色
Posted
技术标签:
【中文标题】WebGL:在带有深度模板纹理附件的帧缓冲区上未清除颜色【英文标题】:WebGL: Color not cleared on framebuffer with depth stencil texture attachment 【发布时间】:2017-10-19 10:28:19 【问题描述】:我尝试在启用模板的情况下绘制对象,一切正常。下面是我预期的工作结果的动画帧图片(从左到右)。
当我使用帧缓冲区时会出现问题。据我了解,WebGL 1.0 不支持单独附加模板和深度,既不支持渲染缓冲区也不支持纹理。可以通过WEBGL_depth_texture
扩展将模板和深度连接在一起来完成。我正在使用该扩展并使用帧缓冲区,绘制对象,但结果似乎并不清楚颜色。下面是结果的动画帧图片。
有人能解释一下发生了什么吗?
请浏览下面的完整代码。
(function()
var gl;
var dtExt;
var gProgram;
var gRectShader;
var gVertexAttribLocation;
var gColorAttribLocation;
var gRectVertexAttribLocation;
var gRectTexcoordAttribLocation;
var gModelViewMatrixUniform;
var gTriangleVertexBuffer;
var gTriangleColorBuffer;
var gQuadVertexBuffer;
var gQuadColorBuffer;
var gQuadTexcoordBuffer;
var gFramebuffer;
var gColorTexture;
var gDepthStencilTexture;
var rotationMatrix = mat4.create();
function initGL()
var glcanvas = document.getElementById("glcanvas");
gl = glcanvas.getContext("webgl", stencil:true);
dtExt = gl.getExtension('WEBGL_depth_texture') || gl.getExtension('WEBKIT_WEBGL_depth_texture') || gl.getExtension('MOZ_WEBGL_depth_texture');
function initFramebuffers()
gFramebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, gFramebuffer);
gl.bindTexture(gl.TEXTURE_2D, gColorTexture);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, gColorTexture, 0);
gl.bindTexture(gl.TEXTURE_2D, gDepthStencilTexture);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, gDepthStencilTexture, 0);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
function createTexture()
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D, null);
return texture;
function initTextures()
gColorTexture = createTexture();
gl.bindTexture(gl.TEXTURE_2D, gColorTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.drawingBufferWidth, gl.drawingBufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gDepthStencilTexture = createTexture();
gl.bindTexture(gl.TEXTURE_2D, gDepthStencilTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_STENCIL, gl.drawingBufferWidth, gl.drawingBufferHeight, 0, gl.DEPTH_STENCIL, dtExt.UNSIGNED_INT_24_8_WEBGL, null);
gl.bindTexture(gl.TEXTURE_2D, null);
function createAndCompileShader(type, source)
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
throw new Error(gl.getShaderInfoLog(shader));
return shader;
function createAndLinkProgram(glVertexShader, glFragmentShader)
var glProgram = gl.createProgram();
gl.attachShader(glProgram, glVertexShader);
gl.attachShader(glProgram, glFragmentShader);
gl.linkProgram(glProgram);
if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS))
throw new Error("Could not initialise shaders");
return glProgram;
function initShaderPrograms()
var gVertexShader = createAndCompileShader(gl.VERTEX_SHADER, [
"attribute vec3 a_vertex;",
"attribute vec4 a_color;",
"uniform mat4 u_modelViewMatrix;",
"varying vec4 v_color;",
"void main(void) ",
"v_color = a_color;",
"gl_Position = u_modelViewMatrix * vec4(a_vertex, 1.0);",
""
].join("\n"));
var gFragmentShader = createAndCompileShader(gl.FRAGMENT_SHADER, [
"precision mediump float;",
"varying vec4 v_color;",
"void main(void) ",
"gl_FragColor = v_color;",
""
].join("\n"));
gProgram = createAndLinkProgram(gVertexShader, gFragmentShader);
var gVertexShader = createAndCompileShader(gl.VERTEX_SHADER, [
"attribute vec3 a_vertex;",
"attribute vec2 a_texcoord;",
"varying vec2 v_texcoord;",
"void main(void) ",
"v_texcoord = a_texcoord;",
"gl_Position = vec4(a_vertex, 1.0);",
""
].join("\n"));
var gFragmentShader = createAndCompileShader(gl.FRAGMENT_SHADER, [
"precision mediump float;",
"uniform sampler2D u_sampler0;",
"varying vec2 v_texcoord;",
"void main(void) ",
"gl_FragColor = texture2D(u_sampler0, v_texcoord);",
""
].join("\n"));
gRectShader = createAndLinkProgram(gVertexShader, gFragmentShader);
function initAttribAndUniformLocations()
gVertexAttribLocation = gl.getAttribLocation(gProgram, "a_vertex");
gColorAttribLocation = gl.getAttribLocation(gProgram, "a_color");
gModelViewMatrixUniform = gl.getUniformLocation(gProgram, 'u_modelViewMatrix');
gRectVertexAttribLocation = gl.getAttribLocation(gRectShader, "a_vertex");
gRectTexcoordAttribLocation = gl.getAttribLocation(gRectShader, "a_texcoord");
function initBuffers()
gTriangleVertexBuffer = gl.createBuffer();
gTriangleColorBuffer = gl.createBuffer();
gQuadVertexBuffer = gl.createBuffer();
gQuadColorBuffer = gl.createBuffer();
gQuadTexcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleVertexBuffer);
var vertices = new Float32Array([
0.0, -1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
]);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleColorBuffer);
var colors = new Float32Array([
0.0, 1.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 0.0, 1.0, 1.0
]);
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, gQuadVertexBuffer);
var vertices = new Float32Array([
-1.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
1.0, -1.0, 0.0
]);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, gQuadColorBuffer);
var colors = new Float32Array([
1.0, 0.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0
]);
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, gQuadTexcoordBuffer);
var texcoords = new Float32Array([
0.0, 1.0,
0.0, 0.0,
1.0, 1.0,
1.0, 0.0
]);
gl.bufferData(gl.ARRAY_BUFFER, texcoords, gl.STATIC_DRAW);
function drawQuads()
gl.bindBuffer(gl.ARRAY_BUFFER, gQuadVertexBuffer);
gl.vertexAttribPointer(gVertexAttribLocation, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, gQuadColorBuffer);
gl.vertexAttribPointer(gColorAttribLocation, 4, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
function drawRectQuads()
gl.bindBuffer(gl.ARRAY_BUFFER, gQuadVertexBuffer);
gl.vertexAttribPointer(gRectVertexAttribLocation, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, gQuadTexcoordBuffer);
gl.vertexAttribPointer(gRectTexcoordAttribLocation, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
function drawTriagles()
gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleVertexBuffer);
gl.vertexAttribPointer(gVertexAttribLocation, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleColorBuffer);
gl.vertexAttribPointer(gColorAttribLocation, 4, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
function renderScene()
var mvMatrix = mat4.create();
gl.clearColor(0.5, 0.5, 0.5, 1.0);
gl.bindFramebuffer(gl.FRAMEBUFFER, gFramebuffer);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.STENCIL_TEST);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.clear(gl.STENCIL_BUFFER_BIT);
gl.useProgram(gProgram);
gl.enableVertexAttribArray(gVertexAttribLocation);
gl.enableVertexAttribArray(gColorAttribLocation);
gl.disable(gl.DEPTH_TEST);
gl.colorMask(false, false, false, false);
gl.stencilFunc(gl.ALWAYS, 0, 0xff);
gl.stencilMask(0xff);
gl.stencilOpSeparate(gl.BACK, gl.KEEP, gl.KEEP, gl.INCR);
gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.DECR);
mat4.identity(mvMatrix);
mat4.scale(mvMatrix, mvMatrix, [0.5, 0.5, 0.5]);
mat4.multiply(mvMatrix, mvMatrix, rotationMatrix);
gl.uniformMatrix4fv(gModelViewMatrixUniform, false, mvMatrix);
gl.cullFace(gl.FRONT);
drawTriagles();
gl.cullFace(gl.BACK);
drawTriagles();
gl.stencilMask(0x00);
gl.stencilFunc(gl.NOTEQUAL, 0, 0xff);
gl.enable(gl.DEPTH_TEST);
gl.colorMask(true, true, true, true);
mat4.identity(mvMatrix);
mat4.scale(mvMatrix, mvMatrix, [0.75, 0.75, 0.75]);
gl.uniformMatrix4fv(gModelViewMatrixUniform, false, mvMatrix);
drawQuads();
gl.disableVertexAttribArray(gVertexAttribLocation);
gl.disableVertexAttribArray(gColorAttribLocation);
gl.flush();
gl.disable(gl.STENCIL_TEST);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
gl.bindTexture(gl.TEXTURE_2D, gColorTexture);
gl.useProgram(gRectShader);
gl.enableVertexAttribArray(gRectVertexAttribLocation);
gl.enableVertexAttribArray(gRectTexcoordAttribLocation);
drawRectQuads();
gl.disableVertexAttribArray(gRectVertexAttribLocation);
gl.disableVertexAttribArray(gRectTexcoordAttribLocation);
gl.flush();
function step(timestamp)
renderScene();
mat4.rotate(rotationMatrix, rotationMatrix, Math.PI / 360, [0, 0, 1])
window.requestAnimationFrame(step);
initGL();
initShaderPrograms();
initAttribAndUniformLocations();
initTextures();
initFramebuffers();
initBuffers();
window.requestAnimationFrame(step);
());
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
<canvas id="glcanvas" >
WebGL not supported!
</canvas>
【问题讨论】:
【参考方案1】:在清除模板缓冲区之前需要设置模板掩码
gl.stencilMask(0xff);
另外,您不需要WEBGL_depth_texture
只是为帧缓冲区制作深度+模板附件。您可以使用 DEPTH_STENCIL 渲染缓冲区
const rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rb);
另外multiline template literals 可能会为您节省很多时间。
另外gl.flush
在代码中也没有任何意义。
【讨论】:
以上是关于WebGL:在带有深度模板纹理附件的帧缓冲区上未清除颜色的主要内容,如果未能解决你的问题,请参考以下文章
在 OpenGL ES 中为帧缓冲区使用深度和模板渲染缓冲区附件
Opengl 和 Webgl:从附加到当前帧缓冲区的纹理中采样