Render to Texture - works intermittently.

Hi. I am trying to set up rendering to a texture using orthogonal projection. I’ve done it before with perspective projection, but I am making a 2d application and need the same functionality.
Thing is it works sometimes and sometimes it doesn’t its just random. So I’ve forgotten to initialise something. I am always doing the rendering at the same time, at the start of the frame. Here is the code:

glViewport(0,0,TEXSIZE,TEXSIZE);
render();
glBindTexture(GL_TEXTURE_2D,*texture);
// Copy Our ViewPort To The Texture
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, TEXSIZE, TEXSIZE, 0);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0,0,iRenderManager.xRes(),iRenderManager.yRes());

I call this right after clearing the screen buffer at the start of rendering. Sometimes the image is there (on its black background) and sometimes the texture is just black. Can anything think of what I’m doing wrong?

My texture creation code just to ensure I’m doing that right.
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_2D, *texture);
glTexImage2D(GL_TEXTURE_2D, 0, 4, TEXSIZE, TEXSIZE, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

maybe you didn’t enable?
i dunno, i run into that one a lot. i’m a newbie :expressionless:

I don’t see it. Perhaps best to encode you problem into a short GLUT test program that you can post in its entirety. Here’s a template to start from: link

#include <stdio.h>
#include <stdlib.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/GLee.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <vector>
#include <stack>
class RenderToTexture
{
public:
RenderToTexture();
~RenderToTexture();
void start();
unsigned int finish();
unsigned int texture;
protected:
private:
unsigned int frameBuffer;
};
RenderToTexture::RenderToTexture()
{
//ctor
glGenFramebuffersEXT(1, &frameBuffer);
glGenTextures(1, &texture);
}
RenderToTexture::~RenderToTexture()
{
//dtor
glDeleteFramebuffersEXT(1,&frameBuffer);
}
void RenderToTexture::start()
{
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 90, 90, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBuffer);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
{
    printf("error

");
}
}
unsigned int RenderToTexture::finish()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
return texture;
}

void checkGLError( const char hdr[] )
{
int err = glGetError();
if( err )
{
fprintf(stderr, "ERROR %s: %s
", hdr, gluErrorString(err));
exit(1);
}
}

void reshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
glutPostRedisplay();
}

void keyboard( unsigned char key, int x, int y )
{
// Key Bindings
switch( key )
{
case 27 : exit(0); break;
}
}
void renderQuad()
{
glBegin(GL_QUADS);
glTexCoord2f(0,0);glVertex2f(0,0);
glTexCoord2f(0,1);glVertex2f(0,30);
glTexCoord2f(1,1);glVertex2f(30,30);
glTexCoord2f(1,0);glVertex2f(30,0);
glEnd();
}
RenderToTexture* rtt;
void display()
{
glClearColor( 0,0,1,1 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1,0,0);
glDisable(GL_TEXTURE_2D);
rtt->start();
renderQuad(); // Creates a texture with a square cut out of the corner
glBindTexture(GL_TEXTURE_2D,rtt->finish());
glEnable(GL_TEXTURE_2D);
glColor3f(0,1,0);
renderQuad();// Tries to render a square in the corner with the texture on it
glutSwapBuffers();
checkGLError( “display() end” );
}

main( int argc, char *argv[] )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB );
glutCreateWindow( “window title” );
checkGLError( “Create window” );

glutReshapeFunc ( reshape );
glutDisplayFunc ( display );
glutKeyboardFunc( keyboard );
rtt = new RenderToTexture;
glutPostRedisplay();
glutMainLoop();
}

That code in the post uses a different method, the original posting uses one method involving copying the current framebuffer into a texture - the new method sets the texture as the current rendering context. Neither of them work :frowning:

Well, I don’t see a glDrawBuffer() call there.

Testing. Will update with problems as I notice them:

  1. You’re reallocating the texture’s base map every frame. That’s not good. Call glTexImage2D only once when you allocate the texture up near glGenTexture. Set the filtering there too.

  2. You are not clearing the texture you are rendering to

  3. Your code looks like you are trying to read from and write to the same texture at the same time. Generally speaking this is not allowed (see NV_texture_barrier for an exception). The only thing saving you from doing this is that you have glDisable( GL_TEXTURE_2D ) before you render to your FBO texture.

  4. After your rtt->finish() call line, do this:

glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

so you can see your texture.

  1. Also, as mentioned, use glDrawBuffer( GL_COLOR_ATTACHMENT0 ); and glDrawBuffer( GL_BACK );