Tengo que escribir mi propio rasterizador 3D de software, y hasta ahora puedo proyectar mi modelo 3D hecho de triángulos en el espacio 2d:
Roto, traduzco y proyecto mis puntos para obtener una representación espacial en 2d de cada triángulo. Luego, tomo los 3 puntos del triángulo e implemento el algoritmo de línea de exploración (usando interpolación lineal) para encontrar todos los puntos [x] [y] a lo largo de los bordes (izquierda y derecha) de los triángulos, para poder escanear el triángulo horizontalmente, fila por fila, y llénalo con píxeles.
Esto funciona. Excepto que también tengo que implementar z-buffering. Esto significa que, conociendo las coordenadas z rotadas y traducidas de los 3 vértices del triángulo, debo interpolar la coordenada z para todos los demás puntos que encuentre con mi algoritmo de línea de exploración.
El concepto parece bastante claro, primero encuentro a Za y Zb con estos cálculos:
var Z_Slope = (bottom_point_z - top_point_z) / (bottom_point_y - top_point_y);
var Za = top_point_z + ((current_point_y - top_point_y) * Z_Slope);
Luego, para cada Zp, hago la misma interpolación horizontalmente:
var Z_Slope = (right_z - left_z) / (right_x - left_x);
var Zp = left_z + ((current_point_x - left_x) * Z_Slope);
Y si la z actual está más cerca del espectador que la z anterior en ese índice, ENTONCES escriba el color en el búfer de color Y escriba la nueva z en el búfer z. (mi sistema de coordenadas es x: izquierda -> derecha; y: arriba -> abajo; z: su cara -> pantalla de la computadora;)
El problema es que se vuelve loco. El proyecto está aquí y si selecciona el botón de opción "Z-Buffered", verá los resultados ... ( tenga en cuenta que utilizo el algoritmo del pintor (-solo- para dibujar el wireframe) en modo "Z-Buffered" para fines de depuración )
PD: He leído aquí que debes convertir las z en sus recíprocos (significado z = 1/z
) antes de interpolar. Lo intenté y parece que no hay cambio. ¿Qué me estoy perdiendo? (¿Alguien podría aclarar, precisamente dónde debe convertir z en 1 / z y dónde (si) para volverlo?)
[EDITAR] Aquí hay algunos datos sobre los valores z máximos y mínimos que obtengo:
max z: 1; min z: -1; //<-- obvious, original z of the vertices of the triangles
max z: 7.197753398761272; min z: 3.791703256899924; //<-- z of the points that were drawn to screen (you know, after rotation, translation), by the scanline with zbuffer, gotten with interpolation but not 1/z.
max z: 0.2649908532179404; min z: 0.13849507306889008;//<-- same as above except I interpolated 1/z instead of z.
//yes, I am aware that changing z to 1/z means flipping the comparison in the zBuffer check. otherwise nothing gets drawn.
Antes de entrar en una depuración minuciosa, ¿alguien puede confirmar que mi concepto hasta ahora es correcto?
[EDIT2]
He resuelto el z-buffering. Como resultado, el orden de dibujo no fue desordenado en absoluto. Las coordenadas z se calculaban correctamente.
El problema era que, en un intento de aumentar mi velocidad de cuadros, dibujaba cuadros de 4 px / 4 px, cada 4 píxeles, en lugar de píxeles reales en la pantalla. Así que dibujaba 16 píxeles por píxel, pero comprobaba el búfer z solo para uno de ellos. Soy un bobo
TL / DR: La pregunta sigue en pie: ¿Cómo / por qué / cuándo tienes que usar el recíproco de Z (como en 1 / z) en lugar de Z? Porque en este momento, todo funciona de cualquier manera. (No hay diferencia notable).