I've seen a lot of material on this subject, but there are some differences between the examples I've found and I'm having a hard time getting a solid understanding of the correct process. Hopefully someone can tell me if I'm on the right track. I should also mention I'm doing this on OS X Snow Leopard and the latest version of Xcode 3.
For the sake of example, let's say that I want to write to two targets, one for normal and one for color. To do this I create one framebuffer and bind two textures to it, as well as a depth texture:
glGenFramebuffersEXT(1, &mFBO); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); glGenTextures(1, &mTexColor); glBindTexture(GL_TEXTURE_2D, mTexColor); //<texture params> glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, mTexColor, 0); glGenTextures(1, &mTexNormal); glBindTexture(GL_TEXTURE_2D, mTexNormal); //<Texture params> glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, mTexNormal, 0); glGenTextures(1, &mTexDepth); glBindTexture(GL_TEXTURE_2D, mTexDepth); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, w, h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, mTexDepth, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)
Before rendering, I would bind the framebuffer again and then do:
GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }; glDrawBuffers(2, buffers);
This would mean further draw calls would draw to my framebuffer. (I think?)
I'd then set my shaders and draw the scene. In my vertex shader I would process normals/positions/colors as usual, and pass the data to the fragment shader. The fragment would then do something like:
gl_FragData[0] = OutputColor; gl_FragData[1] = OutputNormal;
At this point, I should have two textures; one with colors from all the rendered objects and one with normals. Is all of this correct? I should now be able to use those textures like any other, say rendering them to a fullscreen quad, right?
In the field of 3D computer graphics, Multiple Render Targets, or MRT, is a feature of modern graphics processing units (GPUs) that allows the programmable rendering pipeline to render images to multiple render target textures at once.
A Framebuffer is a collection of buffers that can be used as the destination for rendering. OpenGL has two kinds of framebuffers: the Default Framebuffer, which is provided by the OpenGL Context; and user-created framebuffers called Framebuffer Objects (FBOs).
Basically the steps are: Create FBO with depth renderbuffer and color texture attachment. To render to FBO unbind the target texture, bind FBO, render to FBO. Unbind FBO, bind texture, render. Show activity on this post.
In multipass techniques, you render the same "object" multiple times, with each rendering of the object doing a separate computation that gets accumulated into the final value. Each rendering of the object with a particular set of state is called a "pass" or "render pass".
Sounds and looks reasonable. This is indeed the common way to do it. If you don't need the depth data as texture for further processing, you can also use a renderbuffer for an attachment, but a texture should also work fine.
You can also use glCheckFramebufferStatusEXT
after all the setup is done, to see if the framebuffer is valid in its current configuration, but your code looks fine. If you don't have a problem and this was just for assurance, then rest assured that you're on the right track, otherwise tell us what's wrong.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With