2017-10-19 109 views
1

我試圖使用模板繪製對象,並且一切正常。下面是我期望的工作結果的動畫幀(從左到右)的圖片。 expected resultWebGL:使用深度模板紋理附件在framebuffer上清除顏色

當我使用framebuffer時會發生問題。據我所知,WebGL 1.0不支持將深色的模板與渲染緩衝區或紋理分開。可以通過WEBGL_depth_texture擴展名將模板和深度連接在一起完成。我正在使用該擴展名並使用framebuffer,繪製對象,但結果似乎不清楚顏色。下面是結果的動畫幀的圖片。

enter image description here

有人能解釋一下怎麼回事?

請瀏覽下面的完整代碼。

(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() { 
 
\t var glcanvas = document.getElementById("glcanvas"); 
 
\t gl = glcanvas.getContext("webgl", {stencil:true}); 
 
\t dtExt = gl.getExtension('WEBGL_depth_texture') || gl.getExtension('WEBKIT_WEBGL_depth_texture') || gl.getExtension('MOZ_WEBGL_depth_texture'); 
 
} 
 

 
function initFramebuffers() { 
 
\t gFramebuffer = gl.createFramebuffer(); 
 

 
\t gl.bindFramebuffer(gl.FRAMEBUFFER, gFramebuffer); 
 

 
\t gl.bindTexture(gl.TEXTURE_2D, gColorTexture); 
 
\t gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, gColorTexture, 0); 
 

 
\t gl.bindTexture(gl.TEXTURE_2D, gDepthStencilTexture); 
 
\t gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, gDepthStencilTexture, 0); 
 

 
\t gl.bindTexture(gl.TEXTURE_2D, null); 
 
\t gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
 
} 
 

 
function createTexture() { 
 
\t var texture = gl.createTexture(); 
 

 
\t gl.bindTexture(gl.TEXTURE_2D, texture); 
 
\t gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 
 
\t gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 
 
\t gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 
 
\t gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 
 
\t gl.bindTexture(gl.TEXTURE_2D, null); 
 

 
\t return texture; 
 
} 
 

 
function initTextures() { 
 
\t gColorTexture = createTexture(); 
 
\t gl.bindTexture(gl.TEXTURE_2D, gColorTexture); 
 
\t gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.drawingBufferWidth, gl.drawingBufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 
 

 
\t gDepthStencilTexture = createTexture(); 
 
\t gl.bindTexture(gl.TEXTURE_2D, gDepthStencilTexture); 
 
\t gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_STENCIL, gl.drawingBufferWidth, gl.drawingBufferHeight, 0, gl.DEPTH_STENCIL, dtExt.UNSIGNED_INT_24_8_WEBGL, null); 
 
\t 
 
\t gl.bindTexture(gl.TEXTURE_2D, null); 
 
} 
 

 
function createAndCompileShader(type, source) { 
 
\t var shader = gl.createShader(type); 
 

 
\t gl.shaderSource(shader, source); 
 
\t gl.compileShader(shader); 
 

 
\t if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 
 
\t \t throw new Error(gl.getShaderInfoLog(shader)); 
 
\t } 
 

 
\t return shader; 
 
} 
 

 
function createAndLinkProgram(glVertexShader, glFragmentShader) { 
 
\t var glProgram = gl.createProgram(); 
 

 
\t gl.attachShader(glProgram, glVertexShader); 
 
\t gl.attachShader(glProgram, glFragmentShader); 
 
\t gl.linkProgram(glProgram); 
 

 
\t if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) { 
 
\t  throw new Error("Could not initialise shaders"); 
 
\t } 
 

 
\t return glProgram; 
 
} 
 

 
function initShaderPrograms() { 
 
\t var gVertexShader = createAndCompileShader(gl.VERTEX_SHADER, [ 
 
\t \t "attribute vec3 a_vertex;", 
 
\t \t "attribute vec4 a_color;", 
 

 
\t \t "uniform mat4 u_modelViewMatrix;", 
 

 
\t \t "varying vec4 v_color;", 
 

 
\t \t "void main(void) {", 
 
\t \t \t "v_color = a_color;", 
 
\t \t \t "gl_Position = u_modelViewMatrix * vec4(a_vertex, 1.0);", 
 
\t \t "}" 
 
\t ].join("\n")); 
 

 
\t var gFragmentShader = createAndCompileShader(gl.FRAGMENT_SHADER, [ 
 
\t \t "precision mediump float;", 
 

 
\t \t "varying vec4 v_color;", 
 
\t \t "void main(void) {", 
 
\t \t \t "gl_FragColor = v_color;", 
 
\t \t "}" 
 
\t ].join("\n")); 
 

 
\t gProgram = createAndLinkProgram(gVertexShader, gFragmentShader); 
 

 
\t var gVertexShader = createAndCompileShader(gl.VERTEX_SHADER, [ 
 
\t \t "attribute vec3 a_vertex;", 
 
\t \t "attribute vec2 a_texcoord;", 
 

 
\t \t "varying vec2 v_texcoord;", 
 

 
\t \t "void main(void) {", 
 
\t \t \t "v_texcoord = a_texcoord;", 
 
\t \t \t "gl_Position = vec4(a_vertex, 1.0);", 
 
\t \t "}" 
 
\t ].join("\n")); 
 

 
\t var gFragmentShader = createAndCompileShader(gl.FRAGMENT_SHADER, [ 
 
\t \t "precision mediump float;", 
 

 
\t  "uniform sampler2D u_sampler0;", 
 

 
\t \t "varying vec2 v_texcoord;", 
 
\t \t "void main(void) {", 
 
\t \t \t "gl_FragColor = texture2D(u_sampler0, v_texcoord);", 
 
\t \t "}" 
 
\t ].join("\n")); 
 

 
\t gRectShader = createAndLinkProgram(gVertexShader, gFragmentShader); 
 
} 
 

 
function initAttribAndUniformLocations() { 
 
\t gVertexAttribLocation = gl.getAttribLocation(gProgram, "a_vertex"); 
 
\t gColorAttribLocation = gl.getAttribLocation(gProgram, "a_color"); 
 
\t gModelViewMatrixUniform = gl.getUniformLocation(gProgram, 'u_modelViewMatrix'); 
 

 
\t gRectVertexAttribLocation = gl.getAttribLocation(gRectShader, "a_vertex"); 
 
\t gRectTexcoordAttribLocation = gl.getAttribLocation(gRectShader, "a_texcoord"); 
 
} 
 

 
function initBuffers() { 
 
\t gTriangleVertexBuffer = gl.createBuffer(); 
 
\t gTriangleColorBuffer = gl.createBuffer(); 
 
\t gQuadVertexBuffer = gl.createBuffer(); 
 
\t gQuadColorBuffer = gl.createBuffer(); 
 
\t gQuadTexcoordBuffer = gl.createBuffer(); 
 

 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleVertexBuffer); 
 
\t var vertices = new Float32Array([ 
 

 
\t  0.0, -1.0, 0.0, 
 
\t  -1.0, 1.0, 0.0, 
 
\t  1.0, 1.0, 0.0, 
 

 
\t  0.0, 1.0, 0.0, 
 
\t  -1.0, -1.0, 0.0, 
 
\t  1.0, -1.0, 0.0, 
 
\t ]); 
 
\t gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); 
 

 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleColorBuffer); 
 
\t var colors = new Float32Array([ 
 
\t  0.0, 1.0, 0.0, 1.0, 
 
\t  0.0, 1.0, 0.0, 1.0, 
 
\t  0.0, 1.0, 0.0, 1.0, 
 

 
\t  0.0, 0.0, 1.0, 1.0, 
 
\t  0.0, 0.0, 1.0, 1.0, 
 
\t  0.0, 0.0, 1.0, 1.0 
 
\t ]); 
 
\t gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW); 
 

 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gQuadVertexBuffer); 
 
\t var vertices = new Float32Array([ 
 
\t  -1.0, 1.0, 0.0, 
 
\t  -1.0, -1.0, 0.0, 
 
\t  1.0, 1.0, 0.0, 
 
\t  1.0, -1.0, 0.0 
 
\t ]); 
 
\t gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); 
 

 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gQuadColorBuffer); 
 
\t var colors = new Float32Array([ 
 
\t  1.0, 0.0, 0.0, 1.0, 
 
\t  1.0, 0.0, 0.0, 1.0, 
 
\t  1.0, 0.0, 0.0, 1.0, 
 
\t  1.0, 0.0, 0.0, 1.0 
 
\t ]); 
 
\t gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW); 
 

 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gQuadTexcoordBuffer); 
 
\t var texcoords = new Float32Array([ 
 
\t  0.0, 1.0, 
 
\t  0.0, 0.0, 
 
\t  1.0, 1.0, 
 
\t  1.0, 0.0 
 
\t ]); 
 
\t gl.bufferData(gl.ARRAY_BUFFER, texcoords, gl.STATIC_DRAW); 
 

 
} 
 

 
function drawQuads() { 
 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gQuadVertexBuffer); 
 
\t gl.vertexAttribPointer(gVertexAttribLocation, 3, gl.FLOAT, false, 0, 0); 
 

 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gQuadColorBuffer); 
 
\t gl.vertexAttribPointer(gColorAttribLocation, 4, gl.FLOAT, false, 0, 0); 
 

 
\t gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
 
} 
 

 
function drawRectQuads() { 
 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gQuadVertexBuffer); 
 
\t gl.vertexAttribPointer(gRectVertexAttribLocation, 3, gl.FLOAT, false, 0, 0); 
 

 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gQuadTexcoordBuffer); 
 
\t gl.vertexAttribPointer(gRectTexcoordAttribLocation, 2, gl.FLOAT, false, 0, 0); 
 

 
\t gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
 
} 
 

 
function drawTriagles() { 
 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleVertexBuffer); 
 
\t gl.vertexAttribPointer(gVertexAttribLocation, 3, gl.FLOAT, false, 0, 0); 
 

 
\t gl.bindBuffer(gl.ARRAY_BUFFER, gTriangleColorBuffer); 
 
\t gl.vertexAttribPointer(gColorAttribLocation, 4, gl.FLOAT, false, 0, 0); 
 

 
\t gl.drawArrays(gl.TRIANGLES, 0, 6); 
 
} 
 

 

 
function renderScene() { 
 
\t var mvMatrix = mat4.create(); 
 

 
\t gl.clearColor(0.5, 0.5, 0.5, 1.0); 
 

 
\t gl.bindFramebuffer(gl.FRAMEBUFFER, gFramebuffer); 
 
\t gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 
 
\t gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
 

 
\t gl.enable(gl.STENCIL_TEST); 
 
\t gl.enable(gl.DEPTH_TEST); 
 
\t gl.enable(gl.CULL_FACE); 
 

 
\t gl.clear(gl.STENCIL_BUFFER_BIT); 
 

 
\t gl.useProgram(gProgram); 
 

 
\t gl.enableVertexAttribArray(gVertexAttribLocation); 
 
\t gl.enableVertexAttribArray(gColorAttribLocation); 
 

 
\t gl.disable(gl.DEPTH_TEST); 
 
\t gl.colorMask(false, false, false, false); 
 

 
\t gl.stencilFunc(gl.ALWAYS, 0, 0xff); 
 
\t gl.stencilMask(0xff); 
 
\t gl.stencilOpSeparate(gl.BACK, gl.KEEP, gl.KEEP, gl.INCR); 
 
\t gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.DECR); 
 

 
\t mat4.identity(mvMatrix); 
 
\t mat4.scale(mvMatrix, mvMatrix, [0.5, 0.5, 0.5]); 
 
\t mat4.multiply(mvMatrix, mvMatrix, rotationMatrix); 
 

 
\t gl.uniformMatrix4fv(gModelViewMatrixUniform, false, mvMatrix); 
 

 
\t gl.cullFace(gl.FRONT); 
 
\t drawTriagles(); 
 

 
\t gl.cullFace(gl.BACK); 
 
\t drawTriagles(); 
 

 
\t gl.stencilMask(0x00); 
 
\t gl.stencilFunc(gl.NOTEQUAL, 0, 0xff); 
 

 
\t gl.enable(gl.DEPTH_TEST); 
 
\t gl.colorMask(true, true, true, true); 
 

 
\t mat4.identity(mvMatrix); 
 
\t mat4.scale(mvMatrix, mvMatrix, [0.75, 0.75, 0.75]); 
 

 
\t gl.uniformMatrix4fv(gModelViewMatrixUniform, false, mvMatrix); 
 

 
\t drawQuads(); 
 

 
\t gl.disableVertexAttribArray(gVertexAttribLocation); 
 
\t gl.disableVertexAttribArray(gColorAttribLocation); 
 

 
\t gl.flush(); 
 

 
\t gl.disable(gl.STENCIL_TEST); 
 

 
\t gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
 
\t gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 
 
\t gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 
 

 
\t gl.enable(gl.DEPTH_TEST); 
 

 
\t gl.bindTexture(gl.TEXTURE_2D, gColorTexture); 
 

 
\t gl.useProgram(gRectShader); 
 

 
\t gl.enableVertexAttribArray(gRectVertexAttribLocation); 
 
\t gl.enableVertexAttribArray(gRectTexcoordAttribLocation); 
 

 
\t drawRectQuads(); 
 

 
\t gl.disableVertexAttribArray(gRectVertexAttribLocation); 
 
\t gl.disableVertexAttribArray(gRectTexcoordAttribLocation); 
 

 
\t gl.flush(); 
 
} 
 

 
function step(timestamp) { 
 
\t renderScene(); 
 

 
\t 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"> 
 
\t \t 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在代碼中沒有意義。