I have been having trouble finding straightforward code to render a scene to a texture in OpenGL ES (specifically for the iPhone, if that matters). I am interested in knowing the following:
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.
This is how I'm doing it.
I define a texture variable (I use Apple's Texture2D
class, but you can use an OpenGL texture id if you want), and a frame buffer:
Texture2d * texture; GLuint textureFrameBuffer;
Then at some point, I create the texture, frame buffer and attach the renderbuffer. This you only need to do it once:
texture = [[Texture2D alloc] initWithData:0 pixelFormat:kTexture2DPixelFormat_RGB888 pixelsWide:32 pixelsHigh:32 contentSize:CGSizeMake(width, height)]; // create framebuffer glGenFramebuffersOES(1, &textureFrameBuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer); // attach renderbuffer glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture.name, 0); // unbind frame buffer glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
Every time I want to render to the texture, I do:
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer); ... // GL commands ... glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
About your question 3, that's it, you can use the texture as if it is any other texture.
To render the scene to a texture you must use a framebuffer associated with a texture. Here is a method that i created to simplify it :
void glGenTextureFromFramebuffer(GLuint *t, GLuint *f, GLsizei w, GLsizei h) { glGenFramebuffers(1, f); glGenTextures(1, t); glBindFramebuffer(GL_FRAMEBUFFER, *f); glBindTexture(GL_TEXTURE_2D, *t); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *t, 0); GLuint depthbuffer; glGenRenderbuffers(1, &depthbuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, w, h); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(status != GL_FRAMEBUFFER_COMPLETE) NSLog(@"Framebuffer status: %x", (int)status); }
You can create the frame buffer and the texture easily :
GLuint _texture, _framebuffer; GLsizei w,h; float scale = [UIScreen mainScreen].scale; w = self.view.bounds.size.width * scale; h = self.view.bounds.size.height * scale; glGenTextureFromFramebuffer(&_texture, &_framebuffer, w, h);
You can later use _framebuffer to render the scene into _texture in your draw method :
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); //draw here the content you want in the texture //_texture is now a texture with the drawn content //bind the base framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); //or if you use GLKit [view bindDrawable]; //draw normaly
Now you can do what you want with the texture. If you want to do some post processing (blur, bloom, shadow, etc...) you can !
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