¿Por qué las GPU dividen el espacio de clip Z por W, para la posición?

8

Antecedentes:
descubrí que es muy fácil usar un búfer de profundidad lineal, usando solo una ligera modificación en la transformación del vértice canónico. El método más simple se encuentra en la parte inferior de https://www.mvps.org/directx/articles/linear_z/linearz.htm .

Sin embargo, la advertencia es que solo funciona para triángulos que no necesitan recortarse contra los planos cercanos o lejanos. (Y una solución alternativa, de realizar la división de perspectiva en el sombreador de vértices, generará un problema similar para los otros cuatro planos de tronco).

Debido a que el recorte requiere interpolación lineal para funcionar en las cuatro coordenadas del espacio de recorte, creo que es imposible trabajar con profundidad lineal, usando solo un sombreador de vértices. Pero la razón de esto se debe a que Z está dividido por W.

¿Por qué se hace eso? X e Y deben dividirse por la distancia desde la cámara, pero la coordenada Z no lo hace, para encajar perfectamente en el cuadro NDC.

Jessy
fuente

Respuestas:

13

Si está haciendo una imagen en perspectiva y su modelo tiene intersecciones implícitas, si usa "Z lineal", esas intersecciones aparecerán en los lugares incorrectos.

Por ejemplo, considere un plano de tierra simple con una línea de postes telefónicos, retrocediendo en la distancia, que perfora el suelo (y continúe a continuación). Las intersecciones implícitas serán determinadas por los valores de profundidad interpolados. Si no se interpolan 1/Z, entonces cuando los vértices proyectados se hayan calculado con perspectiva, la imagen se verá incorrecta.

Pido disculpas por la calidad no estética de las siguientes ilustraciones, pero las hice en el '97.

La primera imagen muestra el efecto de representación requerido. (Tenga en cuenta que los "pilones" azules van bastante lejos debajo del plano del suelo, por lo que se recortan en la parte inferior de las imágenes)

ingrese la descripción de la imagen aquí

Esta segunda imagen muestra el resultado del uso de un búfer de profundidad no recíproco: (Disculpas por el cambio de escala: se copiaron de un documento antiguo de MS Word y no tengo idea de lo que sucedió con el escalado).

ingrese la descripción de la imagen aquí

Como puede ver, los resultados son incorrectos.

En otra nota, ¿estás seguro de que realmente quieres una representación Z lineal? Si representa la perspectiva, ¿seguramente uno quiere más precisión más cerca de la cámara que a distancia?

Re su comentario posterior:

“Si esos no están interpolados con 1 / Z” que no entiendo. ¿Qué interpolación es esa?

Lo primero a tener en cuenta es que, con una proyección de perspectiva estándar, las líneas rectas en el espacio mundial siguen siendo líneas rectas en el espacio en perspectiva. Las distancias / longitudes, sin embargo, no se conservan.

Para simplificar, supongamos que se utiliza una transformación de perspectiva trivial para proyectar los vértices, es decir

XScreen=XWorldZWorld
YScreen=YWorldZWorld
También debemos calcular una profundidad de espacio de pantalla recíproca, p. Ej.
ZScreen=1ZWorld
pero la Z lineal en el búfer de profundidad requeriría, para mí, algo como:
ZScreen=scaleZWorld
(Podemos suponer aquí que escala = 1)

Supongamos que tenemos una línea con puntos finales del espacio mundial

[001]and[200010]
Con el mapeo en perspectiva, estas coordenadas de mapa a espacio de pantalla
[001]and[2000.1]

El sistema / hardware de renderizado interpolará linealmente el espacio z de la pantalla, por lo que en el punto medio de la línea, como aparece en la pantalla, es decir, en el píxel (10, 0), obtendríamos una Z proyectada (inversa) valor de 0.55, que corresponde a un valor del espacio mundial Z valor de ~ 1.818. Dados los valores iniciales y finales de Z, esto es aproximadamente el 20% a lo largo de la línea.

Si, en cambio, tratamos de interpolar usando los valores Z originales, terminaríamos con Z correspondiente a un valor de espacio mundial de 5.5. Mientras nada se cruce, puede que estés bien (no lo he pensado demasiado) pero cualquier cosa con intersecciones implícitas será incorrecta.

Lo que no he mencionado es que una vez que introduce texturas correctas en perspectiva (o incluso sombreado correcto en perspectiva), debe hacer una interpolación por píxel de 1 / w y, además, también calcular, por píxel, el recíproco de ese valor interpolado.

Simon F
fuente
No creo que pueda entender esta respuesta sin más matemáticas / diagramas. Y sí, más precisión, más cerca, probablemente tenga sentido, pero una escala de lineal por far / z, que es estándar, no tiene sentido. Produce un búfer de profundidad que se vuelve más lineal cuanto más cerca están los dos planos de clip. Parece una combinación de dos conceptos: espacio de pantalla Z lineal y un mapeo de búfer de profundidad no constante para un truco de rendimiento.
Jessy
Específicamente, es el "si no están interpolados con 1 / Z" lo que no entiendo. ¿Qué interpolación es esa?
Jessy
1
Agregaré un texto adicional para explicar con suerte
Simon F
¡Gracias! Creo que el problema se reduce a "El sistema / hardware de representación interpolará linealmente el espacio de pantalla z". Tenía la impresión de que la posición de NDC se calcularía como (x, y, z) / wpor fragmento, pero aparentemente, en cambio, tenemos que tratar con una versión interpolada linealmente de (x/w, y/w, z/w)? Eso no me parece razonable en 2018, ¡pero sería bueno saber si ese es el truco con el que tenemos que vivir por ahora de todos modos!
Jessy
Para realizar texturas / sombreado / perspectiva correctos en perspectiva, debe interpolar linealmente los valores (Val / w) y luego, por fragmento, hacer una división por 1 / w linealmente interpolado. Es un poco difícil de explicar solo en un comentario, pero hay una pequeña explicación en computergraphics.stackexchange.com/a/4799/209 . Alternativamente, busque el artículo de Jim Blinn "Interpolación hiperbólica"
Simon F
6

Usar Z / W para el búfer de profundidad es más profundo que simplemente recortar contra los planos cercanos y lejanos. Como Simon aludió, esto tiene que ver con la interpolación entre los vértices de un triángulo, durante la rasterización.

Z / W es la opción única que permite que los valores de profundidad NDC se calculen correctamente para los puntos en el interior del triángulo, simplemente interpolando linealmente los valores de profundidad NDC desde los vértices, en el espacio de la pantalla . En principio, podríamos usar cualquier función que nos guste para asignar el espacio Z de la cámara al valor del búfer de profundidad, pero cualquier otra opción que no sea Z / W requeriría una matemática más complicada por píxel, lo que sería más lento y más difícil de Construir en hardware.

Tenga en cuenta que si usa un búfer de profundidad lineal, entonces, por supuesto, los valores de profundidad de interpolación lineal serán correctos en el espacio mundial ... ¡pero no, en general, en el espacio de la pantalla! Y es el espacio de la pantalla lo que importa para la rasterización, ya que necesitamos poder generar valores de profundidad correctos en perspectiva (y otros valores de atributos, como los UV) para cada centro de píxeles u otro punto de muestra, dentro de los límites del espacio de pantalla de un triángulo siendo rasterizado.

Nathan Reed
fuente
No sé cómo diseñar una GPU, pero me parece que todo lo que se necesita es interpolar Z en lugar de Z / W, para una profundidad lineal, y la interpolación de Z / W aún podría ocurrir después de cualquier cosa visible. Todavía no puedo decir si se trata de un buen razonamiento o de "a nadie le importa, así que no nos molestamos en actualizar".
Jessy
Interpolar Z en lugar de Z / W no da resultados correctos en el espacio de la pantalla. Z / W lo hace.
Nathan Reed
Derecha. Pero si el búfer de profundidad se cuantifica con una precisión inferior a la posición, entonces, aparte de ser eficaz cuando funciona, no es una buena idea almacenar un trozo escalado del espacio de pantalla Z. Si la interpolación lineal es todo lo que obtenemos, entonces necesita recortar suceder en el espacio visual. Y Z necesita ser interpolado antes de la división por W, para el búfer de profundidad, y después, por lo que has revisado. Entonces, ¿la respuesta a mi pregunta es "porque las GPU siempre se han interpolado en el espacio del clip porque era la única solución práctica en las primeras GPU y ha funcionado bastante bien desde entonces"?
Jessy
No estoy siguiendo lo que quieres decir con "cuantificado con una precisión menor que la posición", o "almacenar una porción escalada del espacio de pantalla Z".
Nathan Reed
1
Además, "Z necesita ser interpolado antes de la división por W, para el buffer de profundidad" —no. Eso es lo que he estado tratando de explicar. Obtendrá las respuestas incorrectas si interpola Z (o cualquier otra cosa) en el espacio de la pantalla sin dividirlo por W primero. Parece que está estancado en esta idea de que un buffer Z lineal funcionaría si no lo dividiéramos entre W. Pero no funcionará, no se interpolará en el espacio de la pantalla correctamente.
Nathan Reed