2012-04-22 6 views
17

Entonces, tengo un impostor (la geometría real es un cubo, posiblemente recortado, y la geometría impostora es una esponja Menger) y necesito calcular su profundidad.GLSL gl_FragCoord.z ​​Cálculo y configuración gl_FragDepth

Puedo calcular la cantidad para compensar en el espacio mundial con bastante facilidad. Desafortunadamente, he pasado horas sin perturbar la profundidad con él.

Los únicos resultados correctos yo puede conseguir son cuando voy:

gl_FragDepth = gl_FragCoord.z 

Básicamente, lo que necesita saber cómo se calcula gl_FragCoord.z ​​de modo que pueda:

  • Tome la transformación inversa desde gl_FragCoord.z ​​a espacio visual
  • Agregue la perturbación de profundidad
  • Transforme esta profundidad perturbada nuevamente en el mismo espacio que el original gl_FragCoord.z.

Disculpe si esto parece una pregunta duplicada; hay una serie de otras publicaciones aquí que abordan cosas similares. Sin embargo, después de implementar todos ellos, ninguno funciona correctamente. En lugar de tratar de elegir uno para obtener ayuda, en este punto, estoy pidiendo un código completo que lo haga. Debería ser solo unas pocas líneas.

+0

¿Has escrito un sombreador de vértices también? o solo un fragmento sombreador? –

+2

No le daré un código de principio general, pero puedo darle [este enlace a la Wiki de OpenGL] (http://www.opengl.org/wiki/Compute_eye_space_from_window_space). Además de este enlace a un tutorial mío sobre [impostores y profundidad que muestra cómo hacer esto también] (http://www.arcsynthesis.org/gltut/Illumination/Tut13%20Deceit%20in%20Depth.html). Transformar la profundidad de vuelta es trivial. –

+0

Michael: sí, pero es solo un pase a través del sombreador.Como sucede, los cálculos se realizan en el espacio mundial, por lo que puedo calcular el espacio visual en el programa de fragmentos. Nicol, ya había visto esa página. Lo implemento como: vec4 clip_pos = gl_ProjectionMatrix * vec4 (eye_pos, 1.0); float ndc_depth = clip_pos.z/clip_pos.w; gl_FragDepth = (((clip_far-clip_near) * ndc_depth) + clip_near + clip_far)/2.0; Desafortunadamente, la profundidad parece estar fuera del rango de profundidad, aunque no hay compensación. Gracias, – imallett

Respuesta

28

Para referencia futura, el código clave es:

float far=gl_DepthRange.far; float near=gl_DepthRange.near; 

vec4 eye_space_pos = gl_ModelViewMatrix * /*something*/ 
vec4 clip_space_pos = gl_ProjectionMatrix * eye_space_pos; 

float ndc_depth = clip_space_pos.z/clip_space_pos.w; 

float depth = (((far-near) * ndc_depth) + near + far)/2.0; 
gl_FragDepth = depth; 
+0

No debería "gl_DepthRange.far" y "gl_DepthRange.near"; ser reemplazado con los rangos cercano y lejano de la matriz de proyección en lugar de los valores del plano del clip? – Tara

+0

No, en absoluto. gl_DepthRange no es lo mismo que los valores del plano cercano y lejano utilizados para calcular la matriz de proyección. Sin embargo, podría estar malinterpretando tu punto. – Tara

+0

@Dudeson Los planos de clip simplemente determinan, a través de la matriz de proyección, qué valores se correlacionarán fuera del NDC (y, por lo tanto, serán recortados por el hardware). Estamos completamente terminados con ellos después de que se especifique la matriz de proyección. Mientras tanto, 'gl_DepthRange. (Ne | f) ar' es el rango del buffer de profundidad, y es necesario para convertir de NDC al buffer de profundidad. HTH – imallett

4

Por otra referencia en el futuro, esto es la misma fórmula que da por imallett, que estaba trabajando para mí en una aplicación OpenGL 4.0:

vec4 v_clip_coord = modelview_projection * vec4(v_position, 1.0); 
float f_ndc_depth = v_clip_coord.z/v_clip_coord.w; 
gl_FragDepth = (1.0 - 0.0) * 0.5 * f_ndc_depth + (1.0 + 0.0) * 0.5; 

Aquí, modelview_projection es 4x4 matriz de proyección de vista de modelo y v_position es la posición de espacio de objeto del píxel que se está representando (en mi caso, calculado por un raymarcher).

La ecuación proviene de la sección window coordinates de this manual. Tenga en cuenta que en mi código, near es 0.0 y far es 1.0, que son los valores predeterminados de gl_DepthRange. Tenga en cuenta que gl_DepthRange es no lo mismo que la distancia de cerca/lejos en la fórmula para perspective projection matrix! El único truco es usar el 0.0 y 1.0 (o gl_DepthRange en caso de que realmente necesite cambiarlo), he estado luchando durante una hora con el otro rango de profundidad, pero eso ya está "horneado" en mi matriz de proyección (perspectiva) .

Tenga en cuenta que de esta manera, la ecuación realmente contiene solo una multiplicación por una constante ((far - near)/2) y una sola adición de otra constante ((far + near)/2). Compare eso para multiplicar, agregar y dividir (posiblemente convertido a una multiplicación por un compilador de optimización) que se requiere en el código de imallett.