Skip to main content
gamedev.net
🔒 Locked

Shadow mapping with framebuffer

Started by LizardCPP Aug 5, 2006 at 12:51 PM 8 replies 3.4k views
Original Post
LizardCPP
LizardCPP
Hey I like to do shadow mappign by using the EXT_framebuffer_object extension. Do anyone know of any god resource for this? I'm currently reading the specs. for the extension od the OpenGL Extension Registry but I would like to have a tutorial or similar, but I can't seam to find that with google. Regards Lizard
godmodder
godmodder
Take a look at www.codesampler.com in the opengl source section. They've got a good tutorial on the EXT_framebuffer_object extension and on shadow mapping.
The shadowmapping tutorial works with the old pBuffer extensions, but you should be able to mix the 2 tutorials without problems.

Hope I've been able to help,
Jeroen
LizardCPP
LizardCPP
Thank you I'm looking at thoose turoials now.

What confuses me abit is the renderbuffer thingy. What is it used for? Can't you just create a texture and attch it to the framebuffer?

Regards

Lizard
godmodder
godmodder
Hello,

the framebuffer affects what's being rendered onscreen and this is what the enduser is eventually going to see. If you want to render something offscreen, you have to render it to another buffer then the framebuffer. A buffer is just a section in memory where data resides and this is also the best way of visualizing it. Now that you have rendered to an offscreen buffer, this buffer has to be bound to a texture so that when this texture is rendered in the framebuffer, you actually get to see the contents of the offscreen buffer where the texture is.

I'm hoping you're still with me. If not, read the above lines again a few times and try to understand.

Hope I've been able to help,
Jeroen
LizardCPP
LizardCPP
Quote:
Original post by godmodder
Hello,

the framebuffer affects what's being rendered onscreen and this is what the enduser is eventually going to see. If you want to render something offscreen, you have to render it to another buffer then the framebuffer. A buffer is just a section in memory where data resides and this is also the best way of visualizing it. Now that you have rendered to an offscreen buffer, this buffer has to be bound to a texture so that when this texture is rendered in the framebuffer, you actually get to see the contents of the offscreen buffer where the texture is.

I'm hoping you're still with me. If not, read the above lines again a few times and try to understand.

Hope I've been able to help,
Jeroen


Ok yes I follow that. But is a renderbuffer really needed? It doesn't look like it in the specs: http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt

See example "(7) Render to depth texture with no color attachments".

Regards

Lizard
Lord Faron
Lord Faron
Quote:
Original post by LizardCPP
But is a renderbuffer really needed?


It depends. Renderbuffer is just a buffer that you use to store things only. Let's take rendering to texture with depth testing. If you want to do that you must set a texture as a color buffer. But what about the depth buffer? Well here's where the renderbuffer comes in. You just create the renderbuffer and use it as a depth buffer. Alternatively you could use another texture for the depth buffer but, since you only want to render the colorbuffer to the texture, doing so would have no sense.
In example #7 you only need to render the depth values so you don't need the colorbuffer. So you just bind a texture as a depth buffer and turn off color writing. In this example there is no need for a renderbuffer.

I hope I explained what renderbuffers are for.
if (time() == $) { $ = 0; }
LizardCPP
LizardCPP
Quote:
Original post by Lord Faron
Quote:
Original post by LizardCPP
But is a renderbuffer really needed?


It depends. Renderbuffer is just a buffer that you use to store things only. Let's take rendering to texture with depth testing. If you want to do that you must set a texture as a color buffer. But what about the depth buffer? Well here's where the renderbuffer comes in. You just create the renderbuffer and use it as a depth buffer. Alternatively you could use another texture for the depth buffer but, since you only want to render the colorbuffer to the texture, doing so would have no sense.
In example #7 you only need to render the depth values so you don't need the colorbuffer. So you just bind a texture as a depth buffer and turn off color writing. In this example there is no need for a renderbuffer.

I hope I explained what renderbuffers are for.


Yes thank you for explaining it.

But when doing shadowmapping it's the depth values I'm after so I could just attach a depth texture and don't use a render buffer at all?

Lizard
Lord Faron
Lord Faron
Quote:
Original post by LizardCPP
I could just attach a depth texture and don't use a render buffer at all?


Yes, but remember to disable drawing to the colorbuffer. Just like in the example.
if (time() == $) { $ = 0; }
LizardCPP
LizardCPP
Hey again

I have tried to get a example working with redering depth values to a texture
and then applayng it to a quad to se it. But I couldn't get it working so I
tried to get the codesample example working instead: link
And that worked fine, so I started to modify my implementation of that example
so that it would only render depth values instead. But no luck. See source code below (it's java with jogl).

Can anyone see what I'm doing wrong?

Lizard

Edit: The rendered quad with the depth texture attached are rendered totaly white.

EDIT: OK it WORKS =) It's just really hard to se on a laptop screen. Hope anyone has use of the code.

import com.sun.opengl.util.texture.TextureIO;import com.sun.opengl.util.texture.Texture;import javax.media.opengl.GLEventListener;import javax.media.opengl.GLAutoDrawable;import javax.media.opengl.GL;import javax.media.opengl.glu.GLU;import java.io.File;import java.io.IOException;/** * Date: 2006-aug-06 * Time: 11:40:09 */public class Main implements GLEventListener{    private static int WINDOW_WIDTH = 640;    private static int WINDOW_HEIGHT = 480;    private static final int RENDERBUFFER_WIDTH = 512;    private static final int RENDERBUFFER_HEIGHT = 512;    private JOGLWindow window;    private GL gl;    private GLU glu;    private int[] frameBuffer = new int[1];    private int[] textureId = new int[1];    private Texture regularTexture;    public Main()    {        window = new JOGLWindow("JOGL EXT_framebuffer_object extension test", WINDOW_WIDTH, WINDOW_HEIGHT, false);        window.addJOGLContextThread(this);        glu = new GLU();        window.activate();        while(window.isActivated())        {            window.display();            try            {                Thread.sleep(1);            }            catch(InterruptedException e)            {                e.printStackTrace();            }        }    }    public void init(GLAutoDrawable glAutoDrawable)    {        this.gl = glAutoDrawable.getGL();        gl.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);        gl.glEnable(GL.GL_TEXTURE_2D);        gl.glEnable(GL.GL_DEPTH_TEST);        gl.glMatrixMode(GL.GL_PROJECTION);        gl.glLoadIdentity();        gl.glGenFramebuffersEXT(1, frameBuffer, 0);        // Check for errors        checkFramebufferStatus();        // Create dynamic texture        gl.glGenTextures(1, textureId, 0);        gl.glBindTexture(GL.GL_TEXTURE_2D, textureId[0]);        gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_DEPTH_COMPONENT16, RENDERBUFFER_WIDTH, RENDERBUFFER_HEIGHT, 0, GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_BYTE, null);        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR );        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR );        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_COMPARE_MODE_ARB, GL.GL_NONE);        // Load a regulat texture        File file = new File("C:\\dev\\projects\\JOGLShadowMapping\\src\\NeHe.png");        try        {            regularTexture = TextureIO.newTexture(file, true);            regularTexture.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);            regularTexture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);        }        catch (IOException e)        {            e.printStackTrace();        }    }    public void display(GLAutoDrawable glAutoDrawable)    {        this.gl = glAutoDrawable.getGL();        /* Offscreen rendering */        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBuffer[0]);        gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_TEXTURE_2D, textureId[0], 0);        gl.glDrawBuffer(GL.GL_NONE);        gl.glReadBuffer(GL.GL_NONE);        checkFramebufferStatus();        gl.glViewport(0, 0, RENDERBUFFER_WIDTH, RENDERBUFFER_HEIGHT);	    gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);	    gl.glClear(GL.GL_DEPTH_BUFFER_BIT);        gl.glMatrixMode(GL.GL_MODELVIEW);	    gl.glLoadIdentity();   //     gl.glBindTexture(GL.GL_TEXTURE_2D, regularTexture.getTextureObject());        // Render        gl.glBegin(GL.GL_TRIANGLES); //       gl.glTexCoord2f(0, 0);        gl.glVertex3f(-2, 0, -6);  //      gl.glTexCoord2f(0.5f, 1);        gl.glVertex3f(0, 2, -6);  //      gl.glTexCoord2f(1, 0);        gl.glVertex3f(2, 0, -6);        gl.glEnd();        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);        /* On-screen rendering */        gl.glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);	    gl.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);	    gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );        gl.glMatrixMode(GL.GL_MODELVIEW);        gl.glLoadIdentity();	    gl.glBindTexture(GL.GL_TEXTURE_2D, textureId[0]);        // Render qaud        gl.glBegin(GL.GL_TRIANGLES);        gl.glTexCoord2f(0, 0);        gl.glVertex3f(-2, 0, -6);        gl.glTexCoord2f(0, 1);        gl.glVertex3f(-2, 2, -6);        gl.glTexCoord2f(1, 1);        gl.glVertex3f(2, 2, -6);        gl.glTexCoord2f(1, 1);        gl.glVertex3f(2, 2, -6);        gl.glTexCoord2f(1, 0);        gl.glVertex3f(2, 0, -6);        gl.glTexCoord2f(0, 0);        gl.glVertex3f(-2, 0, -6);        gl.glEnd();    }    public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height)    {        this.gl = glAutoDrawable.getGL();        WINDOW_WIDTH = width;        WINDOW_HEIGHT = height;        // Calculate aspect ratio        if (WINDOW_HEIGHT <= 0)        {            WINDOW_HEIGHT = 1;        }        final float aspect = (float) WINDOW_WIDTH / (float) WINDOW_HEIGHT;        // Create projection matrix        gl.glMatrixMode(GL.GL_PROJECTION);        glu.gluPerspective(45.0, aspect, 0.1, 10.0);   //     gl.glMatrixMode(GL.GL_MODELVIEW);   //     gl.glLoadIdentity();    }    public void displayChanged(GLAutoDrawable glAutoDrawable, boolean b, boolean b1)    {        this.gl = glAutoDrawable.getGL();    }    private void checkFramebufferStatus()    {        int status = gl.glCheckFramebufferStatusEXT(GL.GL_FRAMEBUFFER_EXT);        switch(status)        {            case GL.GL_FRAMEBUFFER_COMPLETE_EXT:                // All good                break;            case GL.GL_FRAMEBUFFER_UNSUPPORTED_EXT:                throw new RuntimeException("Frame buffer extension not supported.");            case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENTS_EXT:                throw new RuntimeException("Incompleat attachments");            case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:                throw new RuntimeException("Incompleat dimensions");            case GL.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:                throw new RuntimeException("Incompleat drw buffer");            case GL.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:                throw new RuntimeException("Incompleat duplciate attachments");            case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:                throw new RuntimeException("incompleate foramts");            case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:                throw new RuntimeException("incompleate attachments");            case GL.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:                throw new RuntimeException("Incompleate read buffer");            default:                throw new RuntimeException("Logic error");        }    }    public static void main(String[] args)    {        new Main();    }}
Lord Faron
Lord Faron
Quote:
Original post by LizardCPP
OK it WORKS =)


Glad to hear (read) it :)
if (time() == $) { $ = 0; }

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.