Estoy trabajando en un renderizador de adelante hacia atrás para un motor 2D usando una proyección ortográfica. Quiero usar el búfer de profundidad para evitar el sobregiro. Tengo un búfer de profundidad de 16 bits, una cámara en Z = 100 mirando Z = 0, zNear es 1 y zFar es 1000. Cada sprite renderizado establece sus coordenadas Z en valores cada vez más distantes, lo que permite que la prueba de profundidad omita el renderizado todo lo que hay debajo.
Sin embargo, soy consciente de que la forma en que las posiciones Z terminan con valores de buffer Z no es lineal. Quiero hacer uso de la resolución completa del búfer de profundidad de 16 bits, es decir, permitir 65536 valores únicos. Entonces, por cada sprite renderizado, quiero incrementar la posición Z a la siguiente posición para correlacionar con el siguiente valor de búfer de profundidad único.
En otras palabras, quiero convertir un índice incremental (0, 1, 2, 3 ...) del sprite que se dibuja en la posición Z adecuada para que cada sprite tenga un valor de búfer de profundidad único. No estoy seguro de las matemáticas detrás de esto. ¿Cuál es el cálculo para hacer esto?
Tenga en cuenta que estoy trabajando en WebGL (básicamente OpenGL ES 2), y necesito admitir una amplia gama de hardware, por lo que si bien las extensiones como gl_FragDepth pueden facilitarlo, no puedo usarlo por razones de compatibilidad.
fuente
Respuestas:
De hecho, los valores almacenados en el búfer z no son lineales a las coordenadas z reales de sus objetos, sino a su recíproco, para dar más resolución a lo que está cerca del ojo que a lo que está más cerca del plano posterior.
Lo que se hace es que asigne una letra
zNear
a0
, y suzFar
a1
. ParazNear=1
yzFar=2
, debería verse asíLa forma de calcular esto se define por:
Dónde
... y z_buffer_value es un número entero.
La ecuación anterior se presenta por cortesía de esta increíble página , que explica los z-buffers de una manera realmente buena.
Entonces, para encontrar lo necesario
z
para un determinadoz_buffer_value
, simplemente borramosz
:fuente
z_buffer_value = k * (a + (b / z))
y simplemente reorganizo para resolverz
, obtengo:z = b / ((z_buffer_value / k) - a)
- ¿Cómo llegaste a la última fórmula diferente?(v / k) - a => (v - k * a) / k
y colapsas en(k * b) / (v - (k * a))
. Es el mismo resultado.Tal vez deberías cambiar Tu enfoque hacia algo más simple. Que haría yo; Mantenga su profundidad Z, pero mantenga una lista de lo que renderiza. Ordene esa lista según el valor de Profundidad z y renderice los objetos en el orden de la lista.
Espero que esto pueda ayudar. La gente siempre me dice que mantenga las cosas simples.
fuente
Como ya tiene una lista ordenada de elementos para renderizar (de adelante hacia atrás), ¿realmente necesita incrementar el índice Z? ¿No puede usar "menos o igual" para la "función de verificación"? De esta manera, en realidad verificaría si un píxel específico ya estaba dibujado o no.
fuente