2009-06-21 177 views
32

我一直无法找到直观的代码来渲染场景到OpenGL ES中的纹理(特别是iPhone,如果有的话)。我有兴趣了解以下内容:OpenGL ES渲染到纹理

  1. 如何在OpenGL ES中渲染场景到纹理?
  2. 您必须使用哪些参数来创建能够成为OpenGL ES中渲染目标的纹理?
  3. 将这个渲染纹理应用到其他基元有什么意义吗?

回答

43

这就是我的做法。

我定义了一个纹理变量(我用苹果的Texture2D类,但如果你愿意,你可以使用一个OpenGL纹理ID)和帧缓冲器:

Texture2d * texture; 
GLuint textureFrameBuffer; 

然后在某个时候,我创建纹理,帧缓冲区并附加渲染缓冲区。这个你只需做一次:

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); 

每次我想渲染到纹理,我这样做:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer); 

... 
// GL commands 
... 

glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); 

关于你的问题3,就是这样,你可以使用质地如果它是任何其他纹理。

+0

Marco,你知道为每个需要渲染的纹理保留一个framebuffer和renderbuffer需要多少开销吗?我有几个大的纹理我的应用程序需要绘制到,我用curFramebufferTexture2DOES currnetly附加到一个单独的“额外”帧缓冲区。会保持一个单独的帧缓冲每个更好? – 2009-06-21 20:12:56

+0

您可否请编辑您的代码,以便initWithData:...调用适合不滚动? – nornagon 2010-06-12 00:08:19

9

要将场景渲染到纹理,您必须使用与纹理关联的帧缓冲区。下面是我创建简化它的方法:

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); 
} 

您可以创建的帧缓冲,轻松质地:

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); 

您可以在以后使用_framebuffer来渲染场景到_texture在平局方法:

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 

现在你可以做你想要的纹理。如果你想做一些后处理(模糊,绽放,阴影等),你可以!