Skip to main content
gamedev.net
🔒 Locked

Render to texture coordinate problems

Started by CirdanValen 0 replies 1.1k views
Original Post
CirdanValen
CirdanValen
I'm trying to get render to texture working, but am having problems with the coordinate system. When I render this quad to the screen, it gets drawn in the top right corner. However, if I try binding the render target, the quad gets drawn in the bottom right corner, and ends up not getting rendered to the texture.

The quad:


graphics->beginScene();

graphics->bindRenderTarget(target);


glBegin(GL_QUADS);

glColor4f(1.f, 0.f, 0.f, 1.f);
glVertex3f(0.f, 0.f, 0.f);

glColor4f(0.f, 1.f, 0.f, 1.f);
glVertex3f(16.f, 0.f, 0.f);

glColor4f(0.f, 0.f, 1.f, 1.f);
glVertex3f(0.f, 16.f, 0.f);

glColor4f(1.f, 1.f, 0.f, 1.f);
glVertex3f(16.f, 16.f, 0.f);

glEnd();


graphics->unbindRenderTarget();


graphics->drawRenderTarget(target);


graphics->endScene();



void GraphicsDevice::bindRenderTarget(RenderTarget *target) {
// Bind the frame buffer
glBindFramebuffer(GL_FRAMEBUFFER_EXT, target->getFramebuffer());
// store the glViewport and glEnable states
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
glViewport(0, 0, target->getWidth(), target->getHeight());
glClearColor(1.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.f, 0.f, 0.f, 0.f);
glLoadIdentity();
}

void GraphicsDevice::unbindRenderTarget() {
// Restore glViewport and glEnable states
glPopAttrib();
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
}

void GraphicsDevice::drawRenderTarget(RenderTarget *target) {
glBindTexture(GL_TEXTURE_2D, target->getTexture());

glBegin(GL_QUADS);
glTexCoord2f(0.f, 0.f);
glVertex3f(0.f, 0.f, 0.f);

glTexCoord2f(1.f, 0.f);
glVertex3f(target->getWidth(), 0.f, 0.f);

glTexCoord2f(1.f, 1.f);
glVertex3f(target->getWidth(), target->getHeight(), 0.f);
glTexCoord2f(0.f, 1.f);
glVertex3f(0.f, target->getHeight(), 0.f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}


RenderTarget::RenderTarget(GraphicsDevice *graphics, GLuint width, GLuint height) {

mWidth = width;
mHeight = height;

// First create the depth buffer
glGenRenderbuffers(1, &mDepth);
glBindRenderbuffer(GL_RENDERBUFFER_EXT, mDepth);

// Tell OpenGL that this renderbuffer is going to be a depth buffer
glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, mWidth, mHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth);

glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);

// Create the frame buffer texture
glGenTextures(1, &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glBindTexture(GL_TEXTURE_2D, 0);

// Create the frame buffer
glGenFramebuffers(1, &mFbo);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo);

// Attach the texture
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, mTexture, 0);

//Attach the depth buffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mFbo);

glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);


}
shacktar
shacktar


glColor4f(0.f, 0.f, 1.f, 1.f);
glVertex3f(0.f, 16.f, 0.f);

glColor4f(1.f, 1.f, 0.f, 1.f);
glVertex3f(16.f, 16.f, 0.f);



These last two vertices are reversed. The first one should be (16, 16, 0) and the second one should be (0, 16, 0).



// Tell OpenGL that this renderbuffer is going to be a depth buffer
glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, mWidth, mHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth);



You can't call glFramebufferRenderbuffer here because a frame buffer has not been bound yet. This call to glFramebufferRenderbuffer should actually be put in place of the other call to glFramebufferRenderbuffer. The other call attaches mFbo to itself as a depth attachment which doesn't make sense. The FBO creation would actually be incomplete as a result. Rendering to the incomplete FBO is probably the source of your issue.
CirdanValen
CirdanValen
Thanks for the tip. I checked glCheckFramebufferStatus(GL_FRAMEBUFFER); and it came back complete.

I was able to solve my initial problem by setting the view matrix, which I kind of thought was the problem in the first place but wasn't sure how to fix it. My next question is, can I push the matrix settings to the stack so I don't have to keep setting it back and forth? I don't want this to become a performance problem in the future.

EDIT: looks like if I glPushAttrib/glPopAttrib with [color=#444444][font=Consolas, Menlo, Monaco,]GL_TRANSFORM_BIT it will save the matrix mode[/font]

void GraphicsDevice::setRenderTarget(RenderTarget *target) {
// store the glViewport and glEnable states
glPushAttrib(GL_VIEWPORT_BIT);

// Bind the frame buffer
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target->getFramebuffer());

// Setup the view matrix
glViewport(0, 0, target->getWidth(), target->getHeight());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, target->getWidth(), 0, target->getHeight(), -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//glClearColor(1.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glClearColor(0.f, 0.f, 0.f, 1.f);
}

void GraphicsDevice::clearRenderTarget() {

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
// Restore glViewport and glEnable state
glPopAttrib();
setViewMatrix();
}
shacktar
shacktar

Come to think of it, the FBO creation code you posted could still work but it would be hiding a bug. In the case where mDepth = mFbo, it would be alright and this is the case you've witnessed (probably mDepth and mFBO were both one since there are only one RBO and one FBO). If those two values are different (perhaps if there is a different number of RBOs than FBOs generated), then either the FBO would be incomplete or the wrong RBO would be attached.



Pushing/popping the GL_TRANSFORM_BIT saves not just the matrix mode, but the clipping planes' coefficients as well as some other flags. For efficiency reasons, you might want to steer clear of using that. As for the matrices themselves, you should use glPushMatrix and glPopMatrix.

Topic Locked

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

Sign in to reply to this topic.