OpenGL ES将深度数据写入颜色

时间:2017-08-08 19:48:24

标签: android opengl-es glsl shader depth-buffer

我试图在Android上使用OpenGL ES实现类似DepthBuffer的功能。

换句话说,我试图在用户设备上的点[x,y]上渲染的表面上获取3D点。为了使我能够在给定点读取片段的距离。

在不同情况下回答:

使用普通OpenGL时,您可以通过创建FrameBuffer来实现此目的,然后将RenderBufferTexture附加深度组件。 这两种方法都使用glReadPixels,内部格式为GL_DEPTH_COMPONENT,以从缓冲区/纹理中检索数据。不幸的是,OpenGL ES仅支持GL_ALPHAGL_RGBGL_RGBA作为回读格式,因此无法直接访问帧缓冲区的深度数据。< / p>

我能想到的唯一可行方法(以及我在互联网上发现的建议)是为深度缓冲创建不同的着色器。仅用于深度渲染的着色器应在gl_FragCoord.z上写入gl_FragColor值(=我们想要读取的距离值。)。但是:

实际问题:

当我在gl_FragCoord.z上写gl_FragColor = new Vec4(vec3(gl_FragCoord.z), 1.0);值并稍后使用glReadPixels来回读rgb值时,这些读取值不会与输入匹配。

我尝试了什么:

我意识到只有24位(r,g,b * 8位)表示深度数据,所以我尝试将返回值移位8 - 得到32位,但它没有&#39;似乎工作。我还尝试在将它应用于红色,绿色和蓝色时移动距离,但这似乎没有按预期工作。我一直试图通过观察底部的结果来弄清楚错误是什么。

fragmentShader.glsl(候选人#3):

void main() {

highp float distance = 1.0; //currently just 1.0 to test the results with different values.
lowp float red = distance / exp2(16.0);
lowp float green = distance / exp2(8.0);
lowp float blue = distance / exp2(0.0);
gl_FragColor = vec4(red, green, blue, 1.0);

}

读取值的方法(= glReadPixels

private float getDepth(int x, int y){
    FloatBuffer buffer = GeneralSettings.getFloatBuffer(1); //just creates FloatBuffer with capacity of 1 float value.
    terrainDepthBuffer.bindFrameBuffer(); //bind the framebuffer before read back.
    GLES20.glReadPixels(x, y, 1, 1, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, buffer); //read the values from previously bind framebuffer.
    GeneralSettings.checkGlError("glReadPixels"); //Make sure there is no gl related errors.
    terrainDepthBuffer.unbindCurrentFrameBuffer(); //Remember to unbind the buffer after reading/writing.
    System.out.println(buffer.get(0)); //Print the value.
}

使用着色器和放大器进行比特观察上面的方法:

Value   |           Shader input            | ReadPixels output
1.0f    |  111111100000000000000000000000   | 111111110000000100000000
0.0f    |               0                   | 0
0.5f    |   111111000000000000000000000000  | 100000000000000100000000

0 个答案:

没有答案