本文介绍了在Android上读取OpenGL ES的深度缓冲的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to read the depth buffer in OpenGL ES on Android, but all the values are zero.Can someone explain why is that.

    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]);
    }

模型已经绘制在屏幕上:屏幕截图

The model has been draw on screen:ScreenShot

编辑

我的项目被转移到 ES 3.0.我创建了一个 FrameBuffer、颜色和深度纹理,然后附加.我得到错误 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

I was moved my project to ES 3.0. I create a FrameBuffer, color and depth texture and then attach.I get error 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");

}

问题 1:如何解决上述错误?

Q1: How can I resolve above error?

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

Q2: How to check the depth value in depth texture

推荐答案

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

OpenGL ES does not support glReadPixels() on the depth buffer. If you call glGetError() after your glReadPixels() call, you should see a GL_INVALID_OPERATION returned.

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

I only found a vendor specific extension for this functionality: NV_read_depth_stencil. The functionality is still not standard in the latest ES spec (3.2).

除了这个扩展之外,我想不出任何在 ES 2.0 中读回深度值的方法.

Other than this extension, I can't think of any way for reading back depth values in ES 2.0.

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

In ES 3.0 and later, there is at least an indirect way. These versions support depth textures. Using this, you can get the depth using the following steps.

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

这篇关于在Android上读取OpenGL ES的深度缓冲的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!