可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm using the WEBGL_depth_texture in chrome to render a scene to a framebuffer with a color and depth texture. When I display my color texture works fine, but my depthtexture is all white. Shouldn't it be like gray?
my draw texture function:
this.drawTexture = function() { //gl.viewport(0, 0, this.canvas.width, this.canvas.height); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); gl.vertexAttribPointer(this.VertexPosition, 2, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, this.vertTexCoordBuffer); gl.vertexAttribPointer(this.VertexTexture, 2, gl.FLOAT, false, 0, 0); gl.bindTexture(gl.TEXTURE_2D, this.depthTexture); gl.drawArrays(gl.TRIANGLES, 0, 6); gl.bindTexture(gl.TEXTURE_2D, null);
init:
this.colorTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.colorTexture); 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.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); this.depthTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.depthTexture); 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.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, size, size, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null); // var framebuffer = gl.createFramebuffer(); this.depthFramebuffer = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, this.depthFramebuffer); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.colorTexture, 0); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, this.depthTexture, 0);
vertex shaders:
attribute vec2 VertexPosition; attribute vec2 TextureCoord; varying vec2 vTextureCoord; void main() { gl_Position = vec4(VertexPosition, 0, 1); vTextureCoord = TextureCoord; }
Fragment Shader
precision highp float; uniform sampler2D uSampler; varying vec2 vTextureCoord; void main(void) { vec4 depth = texture2D(uSampler, vTextureCoord); gl_FragColor = depth; }
回答1:
Did you enable depth testing?
gl.enable(gl.DEPTH_TEST);
If depth testing is not on nothing is written to the depth texture.
If that isn't it here's a working example. Work backward from it to your sample.
<script src="http://greggman.github.com/webgl-fundamentals/webgl/resources/webgl-utils.js"></script> <script id="vshader" type="whatever"> attribute vec4 a_position; varying vec2 v_texcoord; void main() { gl_Position = a_position; v_texcoord = a_position.xy * 0.5 + 0.5; } </script> <script id="fshader" type="whatever"> precision mediump float; varying vec2 v_texcoord; uniform sampler2D u_sampler; void main() { vec4 color = texture2D(u_sampler, v_texcoord); gl_FragColor = vec4(color.r, 0, 0, 1); } </script> <canvas id="c" width="300" height="300"></canvas> <script> var canvas = document.getElementById("c"); var gl = getWebGLContext(canvas, {antialias:false}); if (!gl) { alert("no WebGL"); return; } // enable depth textures. var depthTextureExtension = gl.getExtension("WEBGL_depth_texture"); if (!depthTextureExtension) { alert("depth textures not supported"); } var program = createProgramFromScripts( gl, ["vshader", "fshader"], ["a_position"]); gl.useProgram(program); var verts = [ 1, 1, 1, -1, 1, 0, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 0, ]; var vertBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW); gl.enableVertexAttribArray(0); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); // create a depth texture. var depthTex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, depthTex); 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 16, 16, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null); // Create a framebuffer and attach the textures. var fb = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fb); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTex, 0); gl.bindTexture(gl.TEXTURE_2D, null); console.log(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE); // use the default texture to render with while we render to the depth texture. gl.bindTexture(gl.TEXTURE_2D, null); // Turn on depth testing so we can write to the depth texture. gl.enable(gl.DEPTH_TEST); // Render to the depth texture gl.bindFramebuffer(gl.FRAMEBUFFER, fb); gl.clear(gl.DEPTH_BUFFER_BIT); gl.drawArrays(gl.TRIANGLES, 0, 6); // Now draw with the texture to the canvas gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.bindTexture(gl.TEXTURE_2D, depthTex); gl.drawArrays(gl.TRIANGLES, 0, 6); </script>
And a fiddle for it: http://jsfiddle.net/greggman/q3ane/
回答2:
I got the same problem and the solution was to linearize the depth value.
void main(void) { float n = 1.0; float f = 2000.0; float z = texture2D(uSampler0, vTextureCoord.st).x; float grey = (2.0 * n) / (f + n - z*(f-n)); vec4 color = vec4(grey, grey, grey, 1.0); gl_FragColor = color; }
I tried at first to divided by 2 or 4 the depth value but I had always the same color for every pixels. So I thought the problem came from somewhere else. My point is, be careful.
Source: http://blog.bongiovi.tw/webgl-depth-texture/