【问题标题】:How to render to a depth texture in OpenGL ES on Android如何在 Android 上的 OpenGL ES 中渲染到深度纹理
【发布时间】:2015-01-15 17:00:43
【问题描述】:

我需要在 Android 中渲染到深度纹理,但我无法弄清楚。我在网上搜索了几天,拼凑出以下代码:

  public void loadFrameBuffer(Context context, int resourceId) {
    final Bitmap bitmap = createBitmap(context, resourceId);

    // generate the framebuffer and texture object names
    glGenFramebuffers(1, frameBuffers, 0);
    glGenTextures(2, textures, 0);

    // bind color texture and load the texture mip level 0 texels are RGB565
    // no texels need to specified as we are going to draw into the texture
    glBindTexture(GL_TEXTURE_2D, textures[COLOR_TEXTURE]);
    texImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap, 0);
    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_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    // bind depth texture and load the texture mip level 0
    // no texels need to specified as we are going to draw into
    // the texture
    glBindTexture(GL_TEXTURE_2D, textures[DEPTH_TEXTURE]);
    texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, bitmap, 0);
    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);

    // bind the framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffers[0]);

    // specify texture as color attachment
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
      GL_TEXTURE_2D, textures[COLOR_TEXTURE],
      0);

    checkStatus();

    // specify texture as depth attachment
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
      GL_TEXTURE_2D, textures[DEPTH_TEXTURE],
      0);

    checkStatus();
  }

颜色附件的 checkStatus() 成功:GL_FRAMEBUFFER_COMPLETE 但是深度附件的 checkStatus() 是:GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

错误状态的文档:

并非所有的帧缓冲连接点都是帧缓冲连接 完全的。这意味着至少有一个连接点具有 附加的渲染缓冲区或纹理的附加对象不再位于 存在或具有宽度或高度为零的附加图像,或 颜色附加点附加了一个不可颜色渲染的图像, 或者深度附着点具有不可深度渲染的图像 附加,或模板连接点具有不可模板渲染 附上图片。

可呈现颜色的格式包括 GL_RGBA4、GL_RGB5_A1 和 GL_RGB565。 GL_DEPTH_COMPONENT16 是唯一可深度渲染的格式。 GL_STENCIL_INDEX8 是唯一可模板渲染的格式。

即使有这样的描述,我也很茫然。颜色附件效果很好。

编辑:

我在前面提到的状态错误之前的日志中看到了这个:

<core_glTexImage2D:501>: GL_INVALID_OPERATION

似乎是因为这行代码:

texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, bitmap, 0);

编辑:

我克服了错误。我从通话切换到:

texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, bitmap, 0);

这实际上是错误的,现在我正在打电话:

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, texWidth, texHeight, 0, GL_DEPTH_COMPONENT, GLES30.GL_FLOAT, null);

有效。我没有看到更多错误。但是,我仍然遇到问题。

这是直接渲染到默认缓冲区(直接到窗口)的模型:

但是当我尝试渲染附加到我的 FrameBuffer 的纹理时,映射到以下内容:

// x, y, z, S, T
      new float[]{
        // left triangle
        -1f, -1f, 0f, 0f, 0f, //
        1f, 1f, 0f, 1f, 1f, //
        -1f, 1f, 0f, 0f, 1f, //

        // right triangle
        -1f, -1f, 0f, 0f, 0f, //
        1f, -1f, 0f, 1f, 0f, //
        1f, 1f, 0f, 1f, 1f //
      }
    );

它拉伸纹理:

如果我删除左三角形并进行渲染,我会得到:

最后,渲染深度纹理让我全是红色:

【问题讨论】:

  • GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 表示其中一张图片不完整。您的设备是否可能不支持OES_depth_texture 扩展?请注意,深度纹理不是 OpenGL ES 2.0 规范的一部分,它们是一种扩展,并且已知某些设备不支持它。
  • 另外,如果你的设备支持KHR_debug,我强烈推荐使用它。使用glDebugMessageCallbackKHR()注册一个日志回调。
  • 如何查看设备是否支持OES_depth_texture?另外,我正在运行 Android 5.0.1 的 Nexus 5 上进行测试
  • 另外,我使用的是 Android SDK 附带的 Java 版本的 OpenGL ES。我没有看到 glDebugMessageCallbackKHR() 方法。
  • 嗯,Nexus 5 应该支持深度纹理,不支持调试输出。

标签: opengl-es opengl-es-2.0 opengl-3


【解决方案1】:

一切正常,没有什么需要修复的

您的深度纹理是正确的。没有什么需要修复的了。

问题似乎是您期望对比度更高的东西。我下载了您的图片并在图像编辑器中增强了对比度:

你可以看到里面有细节!但是,这里丢失了很多数据。您的屏幕最多可能有一个 8 位帧缓冲区,然后我将结果下载为 JPEG,它可以进一步量化它,但是......原始深度纹理本身可能是 16 位。所以我可以猜测,在我制作上面的图像时,我们可能已经丢失了大约 10 位。

换句话说,深度缓冲区有16位精度,但屏幕只有8位。所以,你当然看不到细节。数据很好。

为什么是红色的?

当然是红色的。这是一张只有一个通道的图像。如果您想为它着色,请使用纹理混合,或在片段着色器中应用颜色。

【讨论】:

    猜你喜欢
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多