【问题标题】:Android OpenGL ES Framebuffer objects - rendering depth-buffer to textureAndroid OpenGL ES Framebuffer 对象 - 将深度缓冲区渲染到纹理
【发布时间】:2011-05-01 19:09:46
【问题描述】:

我正在使用运行 Froyo 的 Android 设备,支持 OpenGL ES 1.1 和 OpenGL ES 2.0

我想将深度缓冲区渲染为纹理。在看过许多其他平台(包括 iPhone)上的 OpenGL、OpenGL ES 示例后,我尝试了许多 FBO 配置。

我似乎能够获得带有颜色纹理的 FBO 设置,但每次我附加深度纹理时都会失败。

我当前的代码基于this example,但也创建了颜色纹理,而不是将绘制和读取缓冲区设置为无。

是否有在 Android 上配置 OpenGL ES FBO 以将深度渲染到纹理的简单示例?或者是否有描述支持和不支持的文档?


感谢 cmets - 我特别需要 ES 1.1 的解决方案,如果它可以在 Android 上找到并运行。我还想看看 ES 2 - 我不确定我是否理解将深度信息打包到颜色缓冲区中的想法 - 你有没有参考资料可以让我更好地理解这个想法?

关于代码 - 我的来源与我上面发布的链接几乎没有不同。 Framebuffer状态为未完成。


感谢片段着色器的建议 - 我现在明白了。如果我无法获得另一个解决方案,我会看看。我的理想是同时获得深度和颜色 - 如果我能提供帮助,我真的不想单独渲染颜色和深度。

【问题讨论】:

  • 由于无法直接评论 Android 对深度缓冲区附件的支持(因此无法提供实际答案),如果您愿意依赖 ES 2.0,那么解决方法是打包深度信息放入颜色缓冲区,然后在相关时刻将其解包。同质深度始终在 0 到 1 的范围内,因此定点方案不会有太大问题。
  • 你应该发布代码。当它失败时,它意味着什么?它会产生 GL 错误?什么是 Framebuffer 状态?
  • 要将深度打包到颜色缓冲区中,您只需制作一个片段着色器,将片段的 Z 位置写入颜色通道。如果您使用的是 Windows 并想要一个示例,请下载 RenderMonkey 并尝试一下,我很确定其中一个示例可以做到这一点。

标签: android opengl-es depth-buffer


【解决方案1】:

好的,一个答案。让它在带有 OpenGL ES 2 的 Android 2.2 上工作:

    // Create a frame buffer
    glGenFramebuffers( 1, &(frame_buffer ) );

    // Generate a texture to hold the colour buffer
    glGenTextures(1, &(colour_texture) );
    glBindTexture(GL_TEXTURE_2D, colour_texture);
    // Width and height do not have to be a power of two
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
            pixelWidth, pixelHeight,
            0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    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_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    // Probably just paranoia
    glBindTexture(GL_TEXTURE_2D, 0);

    // Create a texture to hold the depth buffer
    glGenTextures(1, &(depth_texture) );
    glBindTexture(GL_TEXTURE_2D, depth_texture);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
            pixelWidth, pixelHeight,
            0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);

    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_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glBindTexture(GL_TEXTURE_2D, 0);        

    glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer);

    // Associate the textures with the FBO.

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                    GL_TEXTURE_2D, colour_texture, 0);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                    GL_TEXTURE_2D, depth_texture, 0);

    // Check FBO status.    
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

    if ( status == GL_FRAMEBUFFER_COMPLETE )
    {
        // Success
    }

真的很琐碎,遵循 OpenGL ES2 手册并按照正确的顺序执行所有操作。

在 OpenGL ES 1.1 上进行了尝试,将 OES 添加到所需的函数调用中,并将 _OES 添加到常量中,因为帧缓冲区对象是一个扩展。任何将深度纹理附加到帧缓冲区的尝试都会导致帧缓冲区对象不完整。

所以目前我的结论是,这不适用于 Android 上的 OpenGL ES 1.1,但它显然适用于 ES 2.2。

如果有人有 ES 1.1 的解决方案,看到它会很有趣。

【讨论】:

  • 谈到 ES 1.1,我发现了使用渲染缓冲区而不是纹理的示例。
  • 请注意,在 Lollipop+ 上,可能需要先创建一个 GL 上下文,并使其成为最新,然后再进行任何屏幕外 GL 代码 - 否则所有 GL 调用都会给出错误代码。在 Lollipop 之前,框架的内部上下文在调用应用程序代码时是活动的。 (对于屏幕 GL 来说不是问题,因为在将视图附加到显示器时,会为您创建一个上下文。)我仍在尝试找到一些简单的方法来创建该上下文...
【解决方案2】:

许多设备不支持渲染到深度纹理。您需要为深度缓冲区附加渲染缓冲区。

【讨论】:

  • 谢谢-知道这很有用。您能否提供一些代码或链接来说明如何“为您的深度缓冲区附加渲染缓冲区”? (如果没有这样的细节,最好作为对现有答案的评论,而不是单独的答案。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多