Search code examples
opengl-eswebgldepth-buffer

Depth texture on screen


I am trying to obtain depth texture on my screen and I am getting a blank screen always. I am not sure what I am doing wrong. I have seen some posts about drawing the FBO to a "quad" but I am not clear on how to do so. Here is my code (I am using depth texture extension as shown here http://blog.tojicode.com/2012/07/using-webgldepthtexture.html):

function initGLTextureFrameBuffer()
{

var depthTextureExt = gl.getExtension("WEBKIT_WEBGL_depth_texture");
if (!depthTextureExt) return;   

rttFramebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);
rttFramebuffer.width = 512;
rttFramebuffer.height = 512;
colorTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, 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, rttFramebuffer.width,rttFramebuffer.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

depthTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, 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, rttFramebuffer.width, rttFramebuffer.height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);


gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTexture, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTexture,0);

gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

}

Here is my rendering function :

function drawOverlayTriangles()
{

gl.enableVertexAttribArray(shaderProgram.aVertexPosition);
gl.enableVertexAttribArray(shaderProgram.aTextureCoord);

gl.vertexAttrib1f(shaderProgram.aHasTexture, 1.0);
gl.vertexAttrib1f(shaderProgram.aisdepth, 1.0);
gl.bindBuffer(gl.ARRAY_BUFFER, imageTextureCoord);
gl.vertexAttribPointer(shaderProgram.aTextureCoord, 2, gl.FLOAT, false, 0, 0);

//Matrix upload
gl.uniformMatrix4fv(shaderProgram.uMVMatrix, false, pMVMatrix);
gl.uniformMatrix4fv(shaderProgram.uPMatrix, false, perspM);

gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer); 
gl.bindTexture(gl.TEXTURE_2D, depthTexture);
gl.uniform1i(shaderProgram.dTexture, 0);    

gl.clearColor(0,0,0,1);
gl.clear(gl.DEPTH_BUFFER_BIT |  gl.COLOR_BUFFER_BIT);   


for (var i = 0; i < overlay.numElements; i++) {
    // Upload overlay vertices                      
    gl.bindBuffer(gl.ARRAY_BUFFER, overlayVertices[i]);
    gl.vertexAttribPointer(shaderProgram.aVertexPosition, 3, gl.FLOAT, false, 0, 0);

    // Upload overlay colors
    gl.bindBuffer(gl.ARRAY_BUFFER, overlayTriangleColors[i]);       
    gl.vertexAttribPointer(shaderProgram.aVertexColor, 4, gl.FLOAT, false, 0, 0);

    // Draw overlay
    gl.drawArrays(gl.TRIANGLES, 0, overlay.elementNumVertices[i]);
}

gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

gl.disableVertexAttribArray(shaderProgram.aVertexPosition);
gl.disableVertexAttribArray(shaderProgram.aVertexColor);
gl.vertexAttrib1f(shaderProgram.aisdepth, 0.0);
}

Here is my fragment shader code:

    varying vec4 vColor;
    varying float vHasTexture;
    varying vec2 vTextureCoord;
    varying float visdepth;
    varying vec4 position_1;
    varying float DEPTH;

    uniform sampler2D uTexture;
    uniform float uTextureAlpha;

    uniform sampler2D dTexture;

    void main(void) {
        if (vHasTexture < 0.5 && visdepth < 0.5)
                gl_FragColor = vColor;

        if (vHasTexture > 0.5) 
        {   
            vec4 textureColor = texture2D(uTexture, vec2(vTextureCoord.s, vTextureCoord.t));
                gl_FragColor = vec4(textureColor.rgb, textureColor.a * uTextureAlpha);
        }

        if (visdepth > 0.5)
        {
            float z = texture2D(dTexture, vec2(vTextureCoord.s, vTextureCoord.t)).r;
            float n = 1.0;
            float f = 30.0;
            float c = (2.0 * n) / (f + n - z * (f - n));
            gl_FragColor.rgb = vec3(c);

        }   
    }

I will be grateful for any help because I have been trying to do this for a week with no luck.


Solution

  • It looks like you are trying to read from and write to the depth texture in the same pass. You have:

    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTexture,0);
    

    and

    gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer); 
    gl.bindTexture(gl.TEXTURE_2D, depthTexture);
    

    This will give you undefined results. You need a two pass algorithm. In the first pass you render to the framebuffer you created. In the second pass you render to the default framebuffer (gl.bindFramebuffer(gl.FRAMEBUFFER, 0);) with the depth texture bound for reading.

    Alternatively, if you only care about displaying the depth values as color (rather than using depth as an input to another rendering pass) you can replace the line

    float z = texture2D(dTexture, vec2(vTextureCoord.s, vTextureCoord.t)).r;
    

    with

    float z = gl_FragCoord.z;
    

    That way you are not reading from the same depth texture you are currently writing to. The built in variable gl_FragCoord is the window coordinates of the current fragment. https://www.opengl.org/sdk/docs/man/html/gl_FragCoord.xhtml

    In this case you would just render to the default framebuffer instead of rendering to the framebuffer you created.