【问题标题】:Read the depth buffer of OpenGL ES on Android在 Android 上读取 OpenGL ES 的深度缓冲区
【发布时间】:2016-05-04 13:31:54
【问题描述】:

我正在尝试在 Android 上读取 OpenGL ES 中的深度缓冲区,但所有值都为零。 谁能解释一下为什么会这样。

    public void onSurfaceChanged(GL10 unused, int width, int height) {
    // Adjust the viewport based on geometry changes,
    // such as screen rotation
    GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    GLES20.glClearDepthf(1.0f);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    GLES20.glDepthMask( false );

    GLES20.glViewport(0, 0, width, height);

    float ratio = (float) width / height;

    // this projection matrix is applied to object coordinates
    // in the onDrawFrame() method
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 4, 9);
}

读取深度缓冲区:

        FloatBuffer buffer = FloatBuffer.allocate(720*945);
    GLES20.glReadPixels(0, 0, 720, 945, GLES20.GL_DEPTH_COMPONENT, GLES20.GL_FLOAT, buffer);
    float[] depth = buffer.array();
    for (int i = 0; i < 720*945; i++){
            Log.i("Depth", ""+depth[i]);
    }

模型已在屏幕上绘制: ScreenShot

编辑

我的项目已迁移到 ES 3.0。我创建了一个 FrameBuffer、颜色和深度纹理,然后附加。我收到错误 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

 GLES30.glEnable(GLES30.GL_TEXTURE_2D);

    GLES30.glGenTextures(1, colorTex, 0);
    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, colorTex[0]);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
    GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, fboWidth, fboHeight, 0, GLES30.GL_RGBA, GLES30.GL_FLOAT, null);

    GLES30.glGenTextures(1, depthTex, 0);
    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, depthTex[0]);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
    GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_DEPTH_COMPONENT24, fboWidth, fboHeight, 0, GLES30.GL_DEPTH_COMPONENT, GLES30.GL_FLOAT, null);


    GLES30.glGenFramebuffers(1, fb, 0);
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fb[0]);

    GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, colorTex[0], 0);

    checkStatus("Color Test");

    GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_TEXTURE_2D, depthTex[0], 0);

    checkStatus("Depth Test");

}

Q1:如何解决上述错误?

Q2:如何查看深度纹理中的深度值

【问题讨论】:

    标签: android opengl-es depth


    【解决方案1】:

    OpenGL ES 不支持深度缓冲区上的glReadPixels()。如果您在调用glReadPixels() 之后调用glGetError(),您应该会看到返回的GL_INVALID_OPERATION

    我只找到了此功能的供应商特定扩展:NV_read_depth_stencil。该功能在最新的 ES 规范 (3.2) 中仍然不是标准的。

    除了这个扩展,我想不出任何方法可以在 ES 2.0 中读回深度值。

    在 ES 3.0 及更高版本中,至少有一种间接方式。这些版本支持深度纹理。使用它,您可以使用以下步骤获得深度。

    1. 将场景渲染到 FBO,使用纹理作为深度附件。
    2. 使用着色器渲染屏幕大小的四边形,该着色器对上一步中生成的深度纹理进行采样,并将值写入颜色缓冲区。
    3. 在颜色缓冲区上使用glReadPixels()

    【讨论】:

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