2009-06-21 209 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 

現在你可以做你想要的紋理。如果你想做一些後處理(模糊,綻放,陰影等),你可以!