triangulos - dibujar el valor de profundidad en opengl usando shaders
triangulo 3d opengl (2)
Quiero dibujar el búfer de profundidad en el sombreador de fragmentos, hago esto:
Sombreador de vértices:
varying vec4 position_;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
position_ = gl_ModelViewProjectionMatrix * gl_Vertex;
Sombreador de fragmentos:
float depth = ((position_.z / position_.w) + 1.0) * 0.5;
gl_FragColor = vec4(depth, depth, depth, 1.0);
Pero todo lo que imprimo es blanco, ¿qué estoy haciendo mal?
¿En qué espacio quieres dibujar la profundidad? Si desea dibujar la profundidad del espacio de la ventana, puede hacer esto:
gl_FragColor = vec4(gl_FragCoord.z);
Sin embargo, esto no será particularmente útil, ya que la mayoría de los números estarán muy cerca de 1.0. Solo los objetos extremadamente cercanos serán visibles. Esta es la naturaleza de la distribución de los valores de profundidad para un búfer de profundidad utilizando una proyección de perspectiva estándar.
O, para decirlo de otra manera, es por eso que te estás poniendo blanco.
Si desea estos valores en un espacio lineal, deberá hacer algo como lo siguiente:
float ndcDepth = ndcPos.z =
(2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
(gl_DepthRange.far - gl_DepthRange.near);
float clipDepth = ndcDepth / gl_FragCoord.w;
gl_FragColor = vec4((clipDepth * 0.5) + 0.5);
De hecho, el valor de "profundidad" de un fragmento se puede leer desde su valor z en el espacio del clip (es decir, después de todas las transformaciones de la matriz). Eso es correcto.
Sin embargo, su problema está en la división por w
. División por w
se llama división por perspectiva . Sí, es necesario que la proyección en perspectiva funcione correctamente.
Sin embargo La división por w
en este caso "agrupa" todos sus valores (como ha visto), hasta estar muy cerca de 1.0. Hay una buena razón para esto: en una proyección en perspectiva , w= (some multiplier) *z
. Es decir, usted está dividiendo el valor de z (cualquiera que sea el valor calculado) por el (algún factor de) z original. No es de extrañar que siempre obtengas valores cercanos a 1.0. Casi estás dividiendo z por sí mismo.
Como una solución muy simple para esto, intente dividir z
solo por el plano lejano, y envíelo al sombreador de fragmentos como profundidad .
Sombreador de vértices
varying float DEPTH ;
uniform float FARPLANE ; // send this in as a uniform to the shader
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
DEPTH = gl_Position.z / FARPLANE ; // do not divide by w
Sombreador de fragmentos:
varying float DEPTH ;
// far things appear white, near things black
gl_Color.rgb=vec3(DEPTH,DEPTH,DEPTH) ;
El resultado es un fundido no muy malo, de aspecto muy lineal.