如何在Android上的OpenGL ES中渲染深度纹理

时间:2015-01-15 17:00:43

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

我需要渲染到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

错误的文档说明:

  

并非所有帧缓冲附加点都是帧缓冲附件   完成。这意味着至少有一个附着点   renderbuffer或附加的纹理不再包含其附加对象   存在或有一个宽度或高度为零的附加图像,或   颜色附着点附有不可颜色渲染的图像,   或深度附着点具有非深度可渲染图像   附着,或模板连接点具有非模板可渲染   附图。

     

颜色可渲染格式包括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);

哪个有效。我没有看到任何更多的错误。但是,我还有问题。

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

enter image description here

但是当我尝试渲染附加到我的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 //
      }
    );

它拉伸纹理:

enter image description here

如果我删除左三角形并渲染我得到这个:

enter image description here

最后,渲染深度纹理让我全都红了:

enter image description here

1 个答案:

答案 0 :(得分:1)

一切正常,无需修复

您的深度纹理是正确的。没有什么可以解决的。

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

Higher contrast image

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

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

为什么它是红色的?

当然是红色的。它只有一个频道的图像。如果要以不同方式对其进行着色,请使用纹理混合,或在片段着色器中应用颜色。