iphone - OpenGL ES renderizado para textura
opengl-es render-to-texture (2)
He estado teniendo problemas para encontrar un código sencillo para representar una escena en una textura en OpenGL ES (específicamente para el iPhone, si eso importa). Estoy interesado en saber lo siguiente:
- ¿Cómo se renderiza una escena con una textura en OpenGL ES?
- ¿Qué parámetros debe usar para crear una textura que sea capaz de ser un objetivo de renderizado en OpenGL ES?
- ¿Hay alguna implicación con la aplicación de esta textura procesada a otras primitivas?
Así es como lo estoy haciendo.
Texture2D
una variable de textura (utilizo la clase Texture2D
de Apple, pero puede usar una ID de textura OpenGL si lo desea), y un buffer de cuadros:
Texture2d * texture;
GLuint textureFrameBuffer;
Luego, en algún momento, creo la textura, frame buffer y adjunto el renderbuffer. Esto solo debes hacerlo una vez:
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);
Cada vez que quiero renderizar la textura, hago:
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
...
// GL commands
...
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
Sobre su pregunta 3, eso es todo, puede usar la textura como si fuera cualquier otra textura.
Para representar la escena en una textura, debe usar un framebuffer asociado con una textura. Aquí hay un método que creé para simplificarlo:
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);
}
Puede crear el búfer de cuadros y la textura fácilmente:
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);
Luego puede usar _framebuffer para representar la escena en _texture en su método de dibujo:
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
Ahora puedes hacer lo que quieras con la textura. Si quieres hacer un procesamiento posterior (desenfoque, floración, sombra, etc.) ¡puedes!