OpenGL ES渲染到纹理

And*_*son 33 iphone opengl-es render-to-texture

我一直无法找到简单的代码来将场景渲染到OpenGL ES中的纹理(特别是对于iPhone,如果这很重要).我有兴趣知道以下内容:

  1. 如何在OpenGL ES中将场景渲染到纹理?
  2. 必须使用哪些参数来创建能够成为OpenGL ES渲染目标的纹理?
  3. 将此渲染纹理应用于其他基元是否有任何影响?

Mar*_*pic 43

这就是我的做法.

我定义了一个纹理变量(我使用Apple的Texture2D类,但如果需要,可以使用OpenGL纹理id)和帧缓冲区:

Texture2d * texture;
GLuint textureFrameBuffer;
Run Code Online (Sandbox Code Playgroud)

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

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);
Run Code Online (Sandbox Code Playgroud)

每次我想渲染纹理时,我都会:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);

...
// GL commands
...

glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
Run Code Online (Sandbox Code Playgroud)

关于你的问题3,就是这样,你可以使用纹理,就像它是任何其他纹理一样.

  • 只是小细节.你想拥有glBindFramebufferOES(GL_FRAMEBUFFER_OES,1); 如果您正在使用iphone"取消绑定"您的自定义帧缓冲区,请改为0(甚至更好地存储以前的版本并在之后恢复它). (3认同)
  • 绑定到Framebuffer Id 0并不总是初始化为GL会话的主帧缓冲区的Id.我的ES2会议肯定会存储一个不同的会话.我建议人们参考创建GL会话时给出的那个. (3认同)

Ant*_*ony 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);
}
Run Code Online (Sandbox Code Playgroud)

您可以轻松创建帧缓冲区和纹理:

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);
Run Code Online (Sandbox Code Playgroud)

您可以稍后使用_framebuffer在draw方法中将场景渲染为_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
Run Code Online (Sandbox Code Playgroud)

现在你可以用纹理做你想做的事了.如果你想做一些后期处理(模糊,绽放,阴影等......)你可以!