OpenGL ES escribe datos de profundidad para colorear

Estoy tratando de implementar una funcionalidad similar a DepthBuffer usando OpenGL ES en Android.

En otras palabras, estoy tratando de obtener el punto 3D en la superficie que se representa en el punto [x, y] en el dispositivo del usuario. Para hacer eso, necesito poder leer la distancia del fragmento en ese punto dado.

Responda en diferentes circunstancias:

Al usar OpenGL normal, puede lograr esto creandoFrameBuffer y luego adjuntar cualquieraRenderBuffer oTexture con componente de profundidad. Ambos enfoques utilizanglReadPixels, con formato interno deGL_DEPTH_COMPONENT para recuperar los datos del búfer / textura. Desafortunadamente, OpenGL ES solo admiteGL_ALPHA, GL_RGByGL_RGBA como los formatos de lectura, por lo que realmente no hay forma de alcanzar los datos de profundidad del framebuffer directamente.

El único enfoque viable que se me ocurre (y que he encontrado sugerido en Internet) es crear diferentes sombreadores solo para amortiguar la profundidad. El sombreador, que se usa solo para renderizar en profundidad, debe escribirgl_FragCoord.z valor (= el valor de distancia que queremos leer) en elgl_FragColor. Sin embargo:

La pregunta real:

Cuando yo escribogl_FragCoord.z valor en elgl_FragColor = new Vec4(vec3(gl_FragCoord.z), 1.0); y luego usarglReadPixels para volver a leer los valores rgb, esos valores leídos no coinciden con la entrada.

Lo que he intentado:

Me doy cuenta de que solo hay 24 bits (r, g, b * 8 bits cada uno) que representan los datos de profundidad, así que intenté cambiar el valor devuelto por 8, para obtener 32 bits, pero no pareció funcionar. También intenté cambiar la distancia al aplicarlo a rojo, verde y azul, pero eso no pareció funcionar como se esperaba. He estado tratando de descubrir qué está mal observando los bits, los resultados en la parte inferior.

fragmentShader.glsl (candidato # 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);

}

Método para leer los valores (=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.
}

Observaciones en bits utilizando el sombreador y el método anterior:

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

Respuestas a la pregunta(0)

Su respuesta a la pregunta