jay
jay

Reputation: 153

JOGL 2.0, render depth buffer to texture

I am trying to implement simple shadow mapping technique in JOGL 2.0 and I struggle with rendering depth values into texture. Maybe I am doing it completely wrong but it is weird that rendering scene in color works properly. I have also found a similar question here at stackoverflow, which is asked here: Render the depth buffer into a texture using a frame buffer

and problem is solved by calling

gl.glDrawBuffer(GL2.GL_NONE);
gl.glReadBuffer(GL2.GL_NONE);

However, this does not help in my case. When I render scene in texture in color as normally, function works properly. Here is the result:

Render scene into texture (RGBA)

However, after trying to render depth values, it just renders white color (and something which doesn't correspond with the scene at all)

Depth values rendering problem

---- UPDATED code, which is working properly now:

private void initializeFBO3(GL2 gl) {

//Create frame buffer
gl.glGenFramebuffers(1, frameBufferID, 0);
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBufferID[0]);

// ------------- Depth buffer texture --------------
gl.glGenTextures(1,depthBufferID,0);
gl.glBindTexture(GL2.GL_TEXTURE_2D, depthBufferID[0]);

gl.glTexImage2D(GL2.GL_TEXTURE_2D,          // target texture type
        0,                                  // mipmap LOD level
        GL2.GL_DEPTH_COMPONENT,         // internal pixel format
                                            //GL2.GL_DEPTH_COMPONENT
        shadowMapWidth,                     // width of generated image
        shadowMapHeight,                    // height of generated image
        0,                          // border of image
        GL2.GL_DEPTH_COMPONENT,     // external pixel format 
        GL2.GL_UNSIGNED_INT,        // datatype for each value
        null);  // buffer to store the texture in memory

//Some parameters
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);     


//Attach 2D texture to this FBO
gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER,
        GL2.GL_DEPTH_ATTACHMENT,
        GL2.GL_TEXTURE_2D,
        depthBufferID[0],0);

gl.glBindTexture(GL2.GL_TEXTURE_2D, 0);

//Disable color buffer
//https://stackoverflow.com/questions/12546368/render-the-depth-buffer-into-a-texture-using-a-frame-buffer
gl.glDrawBuffer(GL2.GL_NONE);
gl.glReadBuffer(GL2.GL_NONE);

//Set pixels ((width*2)* (height*2))
//It has to have twice the size of shadowmap size
pixels = GLBuffers.newDirectByteBuffer(shadowMapWidth*shadowMapHeight*4);

//Set default frame buffer before doing the check
//http://www.opengl.org/wiki/FBO#Completeness_Rules
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);

int status = gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER);

// Always check that our framebuffer is ok
if(gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER) != GL2.GL_FRAMEBUFFER_COMPLETE)
{
    System.err.println("Can not use FBO! Status error:" + status);
} 
}

public void display(GLAutoDrawable drawable) {
    GL2 gl = drawable.getGL().getGL2(); // get the OpenGL graphics context
    gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); 

    gl.glLoadIdentity();  // reset the model-view matrix

    //Render scene into Frame buffer first
    gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBufferID[0]);
        renderSmallScene(gl);

    //Read pixels from buffer
    gl.glBindFramebuffer(GL2.GL_READ_FRAMEBUFFER, frameBufferID[0]);
    //Read pixels 
    gl.glReadPixels(0, 0, shadowMapWidth, shadowMapHeight, GL2.GL_DEPTH_COMPONENT , GL2.GL_UNSIGNED_BYTE, pixels);

    //Switch back to default FBO
    gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
        drawSceneObjects(gl);


    //Draw pixels, format has to have only one 
    gl.glDrawPixels(shadowMapWidth, shadowMapHeight, GL2.GL_LUMINANCE , GL2.GL_UNSIGNED_BYTE, pixels);

   }

Working result:

Rendering depth component

Upvotes: 0

Views: 2196

Answers (1)

Michael IV
Michael IV

Reputation: 11506

You must read about using FBO and OpenGL in general.

In your code you create FBO and its attachments in each frame. That's wrong.It's huge overhead.Construct your FBOs on init only once.Second, you must bind FBO in order to draw into it (or read from it), otherwise OpenGL will draw into default FBO.Take a look here and here

So ,once your FBO is ready you render into it like this:

glBindFrameBuffer((GL_DRAW_FRAMEBUFFER, yourFbo);

   drawSceneObjects(gl);

glBindFrameBuffer((GL_READ_FRAMEBUFFER, yourFbo);

   readPixelsHere()


 glBindFrameBuffer((GL_FRAMEBUFFER, 0);///switch to default FBO

In fact , in your case ,as you leave the FBO bound,just call

    glBindFrameBuffer((GL_READ_FRAMEBUFFER, yourFbo);

after drawing your geometry.

Also , if you are not using shaders there is no reason to use textures as FBO attachments.Create render buffer instead.

Upvotes: 1

Related Questions