Devo scrivere il mio software 3d rasterizer e finora sono in grado di proiettare il mio modello 3d fatto di triangoli nello spazio 2d:
Ruoto, traduco e proietto i miei punti per ottenere una rappresentazione dello spazio 2D di ciascun triangolo. Quindi prendo i 3 punti del triangolo e implemento l'algoritmo scanline (usando l'interpolazione lineare) per trovare tutti i punti [x] [y] lungo i bordi (sinistro e destro) dei triangoli, in modo da poter scansionare il triangolo in orizzontale, riga per riga e riempilo di pixel.
Questo funziona Tranne che devo implementare anche il buffering z. Ciò significa che conoscendo le coordinate z ruotate e tradotte dei 3 vertici del triangolo, devo interpolare la coordinata z per tutti gli altri punti che trovo con il mio algoritmo scanline.
Il concetto sembra abbastanza chiaro, per prima cosa trovo Za e Zb con questi calcoli:
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);
Quindi per ogni Zp faccio la stessa interpolazione in senso orizzontale:
var Z_Slope = (right_z - left_z) / (right_x - left_x);
var Zp = left_z + ((current_point_x - left_x) * Z_Slope);
E se l'attuale z è più vicino al visualizzatore rispetto alla z precedente in quell'indice, allora scrivi il colore nel buffer colore E scrivi il nuovo z nel buffer z. (il mio sistema di coordinate è x: sinistra -> destra; y: superiore -> inferiore; z: il tuo viso -> schermo del computer;)
Il problema è che va in tilt. Il progetto è qui e se selezioni il pulsante di opzione "Z-Buffered", vedrai i risultati ... ( nota che uso l'algoritmo del pittore (-solo- per disegnare il wireframe) in modalità "Z-Buffered" per scopi di debug )
PS: Ho letto qui che devi trasformare le z nei loro reciproci (significato z = 1/z
) prima di interpolare. L'ho provato e sembra che non ci siano cambiamenti. Cosa mi sto perdendo? (qualcuno potrebbe chiarire, esattamente dove devi trasformare z in 1 / z e dove (se) per tornare indietro?)
[EDIT] Ecco alcuni dati su quali valori z massimo e minimo ottengo:
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.
Prima di approfondire scrupolosamente il debug, qualcuno può confermare che il mio concetto finora è corretto?
[EDIT2]
Ho risolto il buffering z. A quanto pare, l'ordine del disegno non è stato affatto incasinato. Le coordinate z venivano calcolate correttamente.
Il problema era che, nel tentativo di aumentare la mia frequenza dei fotogrammi, stavo disegnando caselle 4px / 4px, ogni 4 pixel, anziché pixel effettivi sullo schermo. Quindi stavo disegnando 16 pixel per pixel, ma controllando il buffer z solo per uno di essi. Sono un tale boob.
TL / DR: la domanda è ancora valida: come / perché / quando è necessario utilizzare il reciproco di Z (come in 1 / z) anziché Z? Perché in questo momento, tutto funziona in entrambi i modi. (non c'è alcuna differenza evidente).