Simple Render to Texture Example

I have been trying to figure out pbuffers, WGL_ARB_render_texture, etc. in order to avoid doing:
glBindTexture(GL_TEXTURE_2D, texID);
glCopyTexSubImage2D(GL_TEXTURE_2D, …);
in multi-pass rendering.

I have read the WGL_ARB_pbuffer and WGL_ARB_render_texture specifications and found them confusing. Also, some kind person on this board directed me to a RenderTexture class written by Mark Harris (http://www.cs.unc.edu/~harrism/misc/rendertexture.html). I finally got his project going after changing all occurances of “wglew.” to “WGL_” and all “glew.” to “GL_” to reflect changes in the GLEW (needed for his project) interface. However, I have not been able to understand his code as it involves cg and other complexities.

I have tried to use his class in a trivially simple program to understand how to render to a non-frame-buffer buffer, then use that buffer as a texture for a subsequent render to the frame buffer. I have not succeeded.

Can someone show me how to get it up and running? Below is the program that I am trying to use with the RenderTexture class and GLEW. The simple program is just supposed to render a quad offscrean, then bind that offscrean buffer to a texture, then render a quad with that texture on screan. If I get red (from the glColor3f(1.0, 0.0, 0.0) call), it is evidence that it works. Instead I get blah:

#include “RenderTexture.h”
#include <GL/glut.h>
#include <cg/cgGL.h>
#include <stdio.h>
#include <stdlib.h>

#define iWidth 256
#define iHeight 256

RenderTexture *rt = NULL;

void Init()
{
glClearColor( 0.0, 0.0, 0.0, 0.0 );
glShadeModel( GL_FLAT );

rt = new RenderTexture(iWidth, iHeight, true, false);
rt->Initialize();
}

void reshape( int width, int height )
{
glViewport( 0, 0, (GLsizei) width, (GLsizei) height );

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0, 2.0, 5.0, 10.0);

glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0);
}

void display()
{
glClear( GL_COLOR_BUFFER_BIT );

rt->EnableTextureTarget();

rt->BeginCapture();

float z_coord = 7;
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_QUADS);
glVertex3f(-1,-1,z_coord);
glVertex3f(-1,1,z_coord);
glVertex3f(1,1,z_coord);
glVertex3f(1,-1,z_coord);
glEnd();
glFlush();

rt->EndCapture();

glBindTexture(GL_TEXTURE_2D, rt->GetTextureID());
glClear( GL_COLOR_BUFFER_BIT );
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(-1,-1,z_coord);
glTexCoord2f(0,1); glVertex3f(-1,1,z_coord);
glTexCoord2f(1,1); glVertex3f(1,1,z_coord);
glTexCoord2f(1,0); glVertex3f(1,-1,z_coord);
glEnd();
glFlush();

}

int main( int argc, char** argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGBA );
glutInitWindowPosition(50, 50);
glutInitWindowSize(iWidth, iHeight);
glutCreateWindow(“TestRenderTexture”);

int err = glewInit();
if (GLEW_OK != err)
{
// problem: glewInit failed, something is seriously wrong
fprintf(stderr, "GLEW Error: %s
", glewGetErrorString(err));
exit(-1);
}

Init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);

glutMainLoop();

return 0;

}

[This message has been edited by sek (edited 09-18-2003).]

[This message has been edited by sek (edited 09-18-2003).]

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, iWidth, iHeight, 0,
GL_RGBA8, GL_FLOAT, texData_1);

The second format argument should be GL_RGBA, not GL_RGBA8.

No idea if the rest of the code (GLEW library) is correct or not.

Y.

Ysaneya, thanks for the reply. The code is not from the GLEW library. GLEW is only used for initializing the required extensions. All the calls are just gl calls, except for the methods from Mark’s RenderTexture class.

Originally posted by sek:
[b]

[quote]

void Init()
{

rt = new RenderTexture(iWidth, iHeight, true, false);

}

void display()
{

delete rt;

}

[/b][/QUOTE]

HUH???

I dont know that class, but you are only creating an object of that class once and then delete that with every call to display()?

That wont work, in fact it should give you tons of null pointer exceptions…

1234!, you are right, but in this simple program, display() only gets called once. I am just trying to see if I can get the render to texture functionality working.

Originally posted by sek:
[b]

[quote]

void reshape( int width, int height )
{

glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0);
}

[/b][/QUOTE]

The next bug… gluLookAt multiplies with the >current< matrix (which in your case is the modelview matrix and not the projection matrix).

Besides your example uses GLUT not GLEW.

No offense but maybe you want to try to iron the basic bugs out before you start with something else?

(After finding this bugs I havent even looked at the other code…).

EDIT: UBB codes…

[This message has been edited by 1234! (edited 09-17-2003).]

Originally posted by 1234!:
[b] [quote]

void reshape( int width, int height )
{

glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0);
}

[/b]<HR></BLOCKQUOTE>

The next bug… gluLookAt multiplies with the >current< matrix (which in your case is the modelview matrix and not the projection matrix).
[/b][/QUOTE]

This is a bug for what reason? The viewing transformation looks perfectly fine to me.

Because doing a gluLookAt with the model view beeing the current matrix mode, trashes the modelview matrix.

Thats surely not what he wants, he wants the gluLookAt after the glOrtho() call.

Please. gluLookAt is supposed to work on the modelview matrix, not the projection matrix. The code is perfectly fine.

Y.

Yeah, right my fault…

Anyway since I dont know the RenderTexture class I leave it to you guys.

Ysaneya, 1234!:

Thanks for your time on this. I guess I should have been more clear about GLEW etc. I just thought someone might have come across Mark Harris’ RenderTexture class since it was posted on these boards. Unless you have recently used the WGL_ARB_render_texture extension you probably are not going to be able to sort it out (unless you feel like playing around a bit). Also, I probably should have just left out the red texture data and just set glColor3f(1.0, 0.0, 0.0) for the first pass. Anyway… I have now resorted to trying to figure out the WGL_ARB_render_texture extension directly without going through his class; so, if anyone can help me implement render to texture functionality in the context of this simple program, it would be greatly appreciated.

Thanks again.

OK. I emailed Mark Harris and he helped me get it working. While I am not completely sure I am using the RenderTexture class completely properly, the program does seem to illustrate render to texture functionality which could be exploited in multipass rendering etc. Here is my working code:

#include “RenderTexture.h”
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

#define iWidth 256
#define iHeight 256

RenderTexture *rt = NULL;
float z_coord = 7;
void reshape(int, int);

void Init()
{
printf("Init() called
");

glClearColor( 0.0, 0.0, 0.0, 0.0 );
glShadeModel( GL_FLAT );

rt = new RenderTexture(iWidth, iHeight, true, false);
rt-&gt;Initialize(true, false, false, false, false, 8,8,8,8);

rt-&gt;BeginCapture();
reshape(iWidth, iHeight);
rt-&gt;EndCapture();

}

void reshape( int width, int height )
{
printf("reshape() called
");
glViewport( 0, 0, (GLsizei) width, (GLsizei) height );

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 10.0);

glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0);

}

void display()
{
printf("display() called
");

rt-&gt;BeginCapture();
glClear( GL_COLOR_BUFFER_BIT );
glColor4f(1.0, 0.0, 0.0, 1.0);
glBegin(GL_QUADS);
	glVertex3f(-1,-1,z_coord);
	glVertex3f(-1,1,z_coord);
	glVertex3f(1,1,z_coord);
	glVertex3f(1,-1,z_coord);
glEnd();
glFlush();
rt-&gt;EndCapture();


rt-&gt;EnableTextureTarget();
glClear( GL_COLOR_BUFFER_BIT );
glColor4f(0.0, 0.0, 1.0, 1.0);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
glBegin(GL_QUADS);
		glTexCoord2f(0,0); glVertex3f(-1,-1,z_coord);
		glTexCoord2f(0,1); glVertex3f(-1,1,z_coord);
		glTexCoord2f(1,1); glVertex3f(1,1,z_coord);
		glTexCoord2f(1,0); glVertex3f(1,-1,z_coord);
glEnd();
glFlush();
rt-&gt;DisableTextureTarget();

}

void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
{ delete rt;
exit(0);
break;
}
default: break;
}
}

int main( int argc, char** argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGBA );
glutInitWindowPosition(50, 50);
glutInitWindowSize(iWidth, iHeight);
glutCreateWindow(“myTestRenderTexture”);

int err = glewInit();
if (GLEW_OK != err)
{
// problem: glewInit failed, something is seriously wrong
fprintf(stderr, "GLEW Error: %s

", glewGetErrorString(err));
exit(-1);
}

Init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);

glutMainLoop();

return 0; 

}

[This message has been edited by sek (edited 09-18-2003).]