2009-06-21 8 views
32

Ich habe Probleme, direkten Code zu finden, um eine Szene in OpenGL ES zu texturieren (speziell für das iPhone, wenn das wichtig ist). Ich bin daran interessiert, Folgendes zu wissen:OpenGL ES Render to Texture

  1. Wie Rendern Sie eine Szene zu einer Textur in OpenGL ES?
  2. Welche Parameter müssen Sie verwenden, um eine Textur zu erstellen, die in OpenGL ES als Renderziel dienen kann?
  3. Gibt es irgendwelche Auswirkungen mit der Anwendung dieser gerenderten Textur auf andere Primitive?

Antwort

43

So mache ich es.

definiere ich eine Textur Variable (ich verwende Texture2D Klasse von Apple, aber Sie können eine OpenGL-Textur-ID verwenden, wenn Sie möchten), und einen Rahmenpuffer:

Texture2d * texture; 
GLuint textureFrameBuffer; 

Dann irgendwann schaffe ich die Textur , Rahmenpuffer und befestigen Sie den Renderpuffer. Diese müssen Sie nur tun es einmal:

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

Jedes Mal, wenn ich auf die Textur machen will, muss ich tun:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer); 

... 
// GL commands 
... 

glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); 

Über Ihre Frage 3, das ist es, können Sie die Textur verwenden, wie wenn es irgendeine andere Textur ist.

+0

Marco, wissen Sie, wie viel Overhead in einem Framebuffer und renderbuffer für jede Textur, die Sie zum Rendern benötigen, beteiligt ist? Ich habe mehrere große Texturen, in die meine App hineingezogen werden muss, und ich befestige derzeit verschiedene mit einem einzigen "zusätzlichen" Framebuffer mit glFramebufferTexture2DOES. Wäre es besser, einen separaten Framebuffer für jeden zu behalten? –

+0

Könnten Sie bitte Ihren Code so bearbeiten, dass der Aufruf initWithData: ... ohne Scrollen passt? – nornagon

+0

Ok, bearbeitet, sieht jetzt besser aus. –

9

Um die Szene in eine Textur zu rendern, müssen Sie einen Framebuffer verwenden, der einer Textur zugeordnet ist. Hier ist eine Methode, die ich erstellt, es zu vereinfachen:

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

Sie können die Frame-Buffer erstellen und die Textur leicht:

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

können Sie später verwenden _framebuffer die Szene in _texture in Ihrem Unentschieden zu machen Methode:

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 

Jetzt können Sie tun, was Sie mit der Textur wollen. Wenn Sie einige Nachbearbeitung (Unschärfe, Blüte, Schatten, etc ...) tun möchten, können Sie!

+0

Hallo, wo hast du '_renderToTextureBuffer' her? –

+0

_renderToTextureBuffer ist _framebuffer ich korrigiere es, sry – Anthony

+0

Cool, das war, was ich dachte. Hast du das in einem Arbeitsbeispiel? Ich werde versuchen, dies wieder zu meinem Code hinzuzufügen, aber ich bin mir nicht sicher, wie ich in die Textur zeichnen soll. // zeichne hier den gewünschten Inhalt in die Textur. Kann ich das mit VBOs und 'glDrawArrays()' machen ? –