Rendering to a texture via EXT_framebuffer_object

I’m having some hassles trying to render a bunch of textures to another texture (basically, trying to dynamically create a texture atlas) via a framebuffer. I’ve got everything hooked up—for example, glClear() affects my texture properly. And once I set the modelview matrix to the identity and reset the projection matrix to gluOrtho2D(0, tex_width, tex_height, 0) (I’m using ftransform() in my vertex shader at present), I can get one—and only one—of my textures to render in my final texture. Specifically, I get one texture rendered in the upper-left corner of my destination texture—the first one. For each new texture I’m resubmitting glVertexPointer and glTexCoordPointer, as well as rebinding to the new texture to draw and translating to the new position in the texture. Nothing besides the first texture gets drawn.

My first texture has vertices (0, 0), (0, 48), (48, 48), (48, 0), while my next one has the same vertices but with a (48, 0) translation, and so on as more textures are drawn.

I wonder if I’m just confused about how framebuffer-to-texture works. None of the tutorials I poked through mentioned having to reset the modelview and projection matrices, but I didn’t even get this far (to a single rendered texture) without changing them. I’d like to completely avoid them and just figure out the final position in my vertex shader, but I don’t know how to begin. Are the final texture coordinates (0, 0) lower-left to (1, 1) upper-right, or do they use the actual storage width and height of the texture as the upper-right corner?

I’d show some code, but it’s splattered all over several places in my code base.

Try to filter out a small GLUT test program to illustrate your problem. If you’re like me while doing that you’ll figure out what your problem is. If not, you’ll have something very concrete for folks to help you on. Write a little app that tiles gluSpheres or glutSolidTeapots or something.

And no, there’s nothing magical about changing MODELVIEW and PROJECTION transforms while rendering to the same render target if you want.

Perhaps you might consider a different design approach.

I don’t think you need to set up an ortho viewport at all. Instead, draw a single quad with your modelview and projection matrices set to identity. Vertices for the quad should be (-1,-1,-1),(1,-1,-1),(1,1,-1),(-1,1,-1) with texcoords of (0,0),(1,0),(1,1),(0,1). (I think… test it out to make sure your textures aren’t all backwards and upside down ;)). When the ModelView and Projection matrices are set to identity, then your vertex coordinates are in screen space where the bottom left corner of the screen is (0,0,-1) and the top right corner of the screen is (1,1,-1). Z needs to be set to -1 or else it may get clipped.

Make sure your buffer is the size you want your destination texture to be. If you want a 10x10 atlas, you’ll need a 480x480 buffer to draw to with each texture at 48x48. Or whatever works for you. :slight_smile:

Then for each texture that you want to add to the atlas, set up a viewport at the target size and offset… say glViewport(0,0,48,48) for the first texture. Then draw your quad with the first texture active. The next viewport might be at glViewport(48,0,48,48), and draw the quad again with the second texture active. Then glViewport(96,0,48,48) etc. This can easily be done in a loop. With this approach you’ll only need to upload the quad once and draw it a bunch of times, just changing the active texture each loop.

This should achieve the desired effect. Each “screen” will be that 48x48 viewport and each will draw onto your buffer at whatever offset you specify. I’m not sure exactly how clearing will work, if it wipes the entire buffer or just the viewport. To be safe, set an original viewport to the entire size of the buffer, clear it once, then don’t clear it again.

Does that make sense? Did I understand your problem correctly?

Yeah, Bloodtoes, that worked great. Once I made absolutely sure that my modelview and projection matrices were set to the identity, that is. :eek: