我尝试绘制启用了模板的对象,一切正常。下面是我预期的工作结果的动画帧(从左到右)的图片。
当我使用framebuffer时会出现问题。据我所知,WebGL 1.0不支持使用深度分别附加模板,也不支持渲染缓冲区和纹理。可以通过WEBGL_depth_texture
扩展名将模板和深度连接在一起来完成。我正在使用该扩展并使用framebuffer,绘制对象,但结果似乎不清楚颜色。下面是结果动画帧的图片。
有人可以解释发生了什么吗?
请浏览以下完整代码。
(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" width="480" height="360">
WebGL not supported!
</canvas>
&#13;
答案 0 :(得分: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
代码中没有任何意义。