【问题标题】:OpenGL ES Render to TextureOpenGL ES 渲染到纹理
【发布时间】:2013-11-29 00:54:13
【问题描述】:

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

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

【问题讨论】:

    标签: iphone opengl-es render-to-texture


    【解决方案1】:

    这就是我的做法。

    我定义了一个纹理变量(我使用 Apple 的 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,就是这样,你可以像使用任何其他纹理一样使用纹理。

    【讨论】:

    • Marco,您知道为您需要渲染到的每个纹理保留帧缓冲区和渲染缓冲区需要多少开销吗?我的应用程序需要绘制几个大纹理,并且我正在使用 glFramebufferTexture2DOES 将不同的纹理附加到单个“额外”帧缓冲区。为每个人保留一个单独的帧缓冲区会更好吗?
    • 能否请您编辑您的代码,以便 initWithData:... 调用适合而不滚动?
    • 只是小细节。你想要 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 1);如果您正在使用 iphone 来“取消绑定”您的自定义帧缓冲区,则改为 0(或者甚至更好地存储以前的版本并在之后恢复它)。
    • 绑定到 Framebuffer Id 0 并不总是初始化为 GL 会话的主要帧缓冲区的 Id。我的 ES2 会话肯定存储了一个不同的会话。我建议人们参考在创建 GL 会话时给出的那个。
    • Apple 的 Texture2D 文件有链接吗?它似乎不再存在于他们的绘画应用程序中......
    【解决方案2】:

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

    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
    

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

    【讨论】:

    • 你好,你从哪里得到_renderToTextureBuffer
    • 酷,我就是这么想的。你有这个工作的例子吗?我将尝试将其添加到我的代码中(再次),但我不确定如何绘制到纹理//draw here the content you want in the texture 我可以用 VBO 和glDrawArrays() 做到这一点吗?
    猜你喜欢
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-28
    • 2016-07-23
    相关资源
    最近更新 更多