how to render water reflection

Started by
10 comments, last by fazekaim 18 years, 9 months ago
Hello, I tried to create water reflection. I made my render-to-texture code with framebuffer object:

public void reshape(GLDrawable glDrawable, int xstart,int ystart, int width, int height) {
        gl.glViewport(0,0,width,height);
        gl.glMatrixMode( GL.GL_PROJECTION);
        gl.glLoadIdentity();

        createNewFrameBuffer( width, height, MeadowLand.FBO, MeadowLand.FBORenderBuffer, MeadowLand.FBOTexture );

        gluPerspective(45,(double)width/height,1,10000);

        gl.glMatrixMode( GL.GL_MODELVIEW);
        gl.glLoadIdentity();
    }
public static void createNewFrameBuffer(int width, int height, int[] FBO, int[] FBORenderBuffer, int[] FBOTexture ){

        if( FBO[0] > 0) gl.glDeleteFramebuffersEXT( 1, FBO  );
        if( FBOTexture[0] > 0) gl.glDeleteTextures( 1, FBOTexture  );

        gl.glGenFramebuffersEXT( 1, FBO  );
        gl.glGenTextures( 1, FBOTexture );
        gl.glBindFramebufferEXT( GL.GL_FRAMEBUFFER_EXT, FBO[0] );

        gl.glGenRenderbuffersEXT( 1, FBORenderBuffer );
        gl.glBindRenderbufferEXT( GL.GL_RENDERBUFFER_EXT, FBORenderBuffer[0] );
        gl.glRenderbufferStorageEXT( GL.GL_RENDERBUFFER_EXT, GL.GL_DEPTH_COMPONENT24, width, height );
        gl.glFramebufferRenderbufferEXT( GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_RENDERBUFFER_EXT, FBORenderBuffer[0] );

        gl.glBindTexture( GL.GL_TEXTURE_2D, FBOTexture[0] );
        gl.glTexImage2D( GL.GL_TEXTURE_2D, 0, GL.GL_RGB, width, height, 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, BufferUtils.bufferOffset(0) );
        gl.glTexParameteri( GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST );
        gl.glTexParameteri( GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST );
        gl.glFramebufferTexture2DEXT( GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_2D, FBOTexture[0], 0 );

        if( !checkFrameBufferStatus( width, height ) ){
            JOptionPane.showMessageDialog(null, "FBO ohhh", "Some Error", JOptionPane.ERROR_MESSAGE);
            System.exit( -1 );
        }
        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);

    }


My render code:

            gl.glBindFramebufferEXT( GL.GL_FRAMEBUFFER_EXT, FBO[0] );
            gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
            gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
            gl.glPushMatrix();
                gl.glScalef( 1.0f, -1.0f, 1.0f );
                renderScene();
            gl.glPopMatrix();

            gl.glBindFramebufferEXT( GL.GL_FRAMEBUFFER_EXT, 0 );
            gl.glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
            gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
            gl.glPushMatrix();
                renderscene();
                renderWater();
            gl.glPopMatrix(); 

....
public void renderWater() {

        gl.glEnable( GL.GL_DEPTH_TEST);
        gl.glEnable(GL.GL_MULTISAMPLE_ARB);

        gl.glActiveTextureARB( GL.GL_TEXTURE0_ARB + 0);
        gl.glBindTexture( GL.GL_TEXTURE_2D, FBOTexture[0]);
        gl.glClientActiveTextureARB( GL.GL_TEXTURE0_ARB + 0);
        gl.glEnable( GL.GL_TEXTURE_2D);

            gl.glBegin( GL.GL_QUADS);
                gl.glMultiTexCoord2f( 0, 1, 1 );
                gl.glVertex3f( vertexes[0][0], waterLevel, vertexes[0][1] );

                gl.glMultiTexCoord2f( 0, 1 , 0 );
                gl.glVertex3f( vertexes[1][0], waterLevel, vertexes[1][1] );

                gl.glMultiTexCoord2f( 0, 0, 0 );
                gl.glVertex3f( vertexes[2][0], waterLevel, vertexes[2][1] );

                gl.glMultiTexCoord2f( 0, 0, 1 );
                gl.glVertex3f( vertexes[3][0], waterLevel, vertexes[3][1] );
            gl.glEnd();

        gl.glActiveTextureARB( GL.GL_TEXTURE0_ARB + 0);
        gl.glDisable( GL.GL_TEXTURE_2D);
        gl.glClientActiveTextureARB( GL.GL_TEXTURE0_ARB + 0);

        gl.glDisable( GL.GL_BLEND );

    }


My waterplane show the fbo texture very well, but I don't know how to compute the texture coordinates, to see the water like a mirror. Now, I just put the fbo texture to the water plane. Screenshot: http://delfin.klte.hu/~fazekaim/water.jpg I should project the texture on the waterplan, but I don't know how. Thanks.
Advertisement
i use these functions to set the matrix, before and after have rendered the water:

void EnableWaterTextureMatrix(){				glMatrixMode( GL_TEXTURE );	glScalef(0.5f, 0.5f, 1.0f);	glTranslatef(1.0f, 1.0f, 0.0f);	glMultMatrixf( g_Camera.GetProjection() );	glMultMatrixf( g_Camera.GetModelView() );	glMatrixMode(GL_MODELVIEW);}void DisableWaterTextureMatrix(){	glMatrixMode(GL_TEXTURE);	glLoadIdentity();	glMatrixMode(GL_MODELVIEW);}


here's a screenshot from a demo i wrote:




[Edited by - b3rs3rk on July 11, 2005 8:11:51 AM]

Wow, congratulation!

g_Camera.GetProjection()
g_Camera.GetModelView() how can I get these matrices?

and what are the texture coordinates?

the texcoord you use on the quad you draw for the water plane are correct, but if you don't know how to get the modelview and the projection matrix i suggest to try with something simpler than a water reflection demo...

anyway, call glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); and glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
>>the texcoord you use on the quad you draw for the water plane are correct
Thanks.

>>anyway, call glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); and >>glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
Oh, i'm boob. I use it, but I thought to something else, sorry :)

It try it now...
I tried it, with this code:

private void EnableWaterTextureMatrix(){        gl.glMatrixMode( GL.GL_TEXTURE );        gl.glScalef(0.5f, 0.5f, 1.0f);        gl.glTranslatef(1.0f, 1.0f, 0.0f);        float[] modelMatrix = new float[16];gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, modelMatrix);        float[] projectionlMatrix = new float[16];gl.glGetFloatv(GL.GL_PROJECTION_MATRIX, projectionlMatrix);        gl.glMultMatrixf( modelMatrix );        gl.glMultMatrixf( projectionlMatrix );        gl.glMatrixMode( GL.GL_MODELVIEW );    }    private void DisableWaterTextureMatrix() {        gl.glMatrixMode( GL.GL_TEXTURE );        gl.glLoadIdentity();        gl.glMatrixMode( GL.GL_MODELVIEW );    }    public void renderWater() {        EnableWaterTextureMatrix();        gl.glEnable( GL.GL_DEPTH_TEST);        gl.glEnable(GL.GL_MULTISAMPLE_ARB);        activateTexture( 0, MeadowLand.FBOTexture[0], GL.GL_TEXTURE_2D );                    gl.glBegin( GL.GL_QUADS);                gl.glMultiTexCoord2f( 0, 1, 1 );                gl.glVertex3f( vertexes[0][0], waterLevel, vertexes[0][1] );                gl.glMultiTexCoord2f( 0, 1 , 0 );                gl.glVertex3f( vertexes[1][0], waterLevel, vertexes[1][1] );                gl.glMultiTexCoord2f( 0, 0, 0 );                gl.glVertex3f( vertexes[2][0], waterLevel, vertexes[2][1] );                gl.glMultiTexCoord2f( 0, 0, 1 );                gl.glVertex3f( vertexes[3][0], waterLevel, vertexes[3][1] );            gl.glEnd();        deactivateTexture( 0, GL.GL_TEXTURE_2D );        DisableWaterTextureMatrix();    }


The result: http://delfin.klte.hu/~fazekaim/water2.jpg

What did i wrong?

By the way, when I create the fbo texture I call glScale(1,-1,1);
Should i mirror the camera too?
glu.gluLookAt( eye.x, -eye.y, eye.z, focus.x, focus.y, focus.z, up.x, up.y, up.z );
are you sure that the pbuffer texture is correctly filled? remember that when you render in the pbuffer you have to use the same modelview and projection you use in normal rendering, and then scale the scene up/down
>scale the scene up/down

How do you mean?
I'm using framebuffer object with the code posted above.
gl.glScalef( 1.0f, -1.0f, 1.0f );
I'm using gl.glScalef( 1.0f, -1.0f, 1.0f ), and if i'm not mistaken, the framebuffer object don't switch gl context, so it use the same projection and model matrix.

here is my render code:

public void display(GLDrawable glDrawable) {{gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );gl.glMatrixMode(GL.GL_MODELVIEW);gl.glLoadIdentity();glu.gluLookAt( eye.x, eye.y, eye.z, focus.x, focus.y, focus.z, up.x, up.y, up.z );gl.glBindFramebufferEXT( GL.GL_FRAMEBUFFER_EXT, FBO[0] );            gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);            gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);            gl.glPushMatrix();                gl.glScalef( 1.0f, -1.0f, 1.0f );                renderScene();            gl.glPopMatrix();            gl.glBindFramebufferEXT( GL.GL_FRAMEBUFFER_EXT, 0 );            gl.glClearColor(0.0f, 1.0f, 0.0f, 0.0f);            gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );            gl.glPushMatrix();                renderscene();                renderWater();            gl.glPopMatrix(); }private void EnableWaterTextureMatrix(){        gl.glMatrixMode( GL.GL_TEXTURE );        gl.glScalef(0.5f, 0.5f, 1.0f);        gl.glTranslatef(1.0f, 1.0f, 0.0f);        float[] modelMatrix = new float[16];gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, modelMatrix);        float[] projectionlMatrix = new float[16];gl.glGetFloatv(GL.GL_PROJECTION_MATRIX, projectionlMatrix);        gl.glMultMatrixf( modelMatrix );        gl.glMultMatrixf( projectionlMatrix );        gl.glMatrixMode( GL.GL_MODELVIEW );    }    private void DisableWaterTextureMatrix() {        gl.glMatrixMode( GL.GL_TEXTURE );        gl.glLoadIdentity();        gl.glMatrixMode( GL.GL_MODELVIEW );    }public void renderWater() {        EnableWaterTextureMatrix();        gl.glEnable( GL.GL_DEPTH_TEST);        gl.glEnable(GL.GL_MULTISAMPLE_ARB);        gl.glActiveTextureARB( GL.GL_TEXTURE0_ARB + 0);        gl.glBindTexture( GL.GL_TEXTURE_2D, FBOTexture[0]);        gl.glClientActiveTextureARB( GL.GL_TEXTURE0_ARB + 0);        gl.glEnable( GL.GL_TEXTURE_2D);            gl.glBegin( GL.GL_QUADS);                gl.glMultiTexCoord2f( 0, 1, 1 );                gl.glVertex3f( vertexes[0][0], waterLevel, vertexes[0][1] );                gl.glMultiTexCoord2f( 0, 1 , 0 );                gl.glVertex3f( vertexes[1][0], waterLevel, vertexes[1][1] );                gl.glMultiTexCoord2f( 0, 0, 0 );                gl.glVertex3f( vertexes[2][0], waterLevel, vertexes[2][1] );                gl.glMultiTexCoord2f( 0, 0, 1 );                gl.glVertex3f( vertexes[3][0], waterLevel, vertexes[3][1] );            gl.glEnd();        gl.glActiveTextureARB( GL.GL_TEXTURE0_ARB + 0);        gl.glDisable( GL.GL_TEXTURE_2D);        gl.glClientActiveTextureARB( GL.GL_TEXTURE0_ARB + 0);        gl.glDisable( GL.GL_BLEND );        DisableWaterTextureMatrix();    }

This topic is closed to new replies.

Advertisement