Je dois écrire mon propre logiciel de rastérisation 3D, et jusqu'à présent, je suis capable de projeter mon modèle 3D composé de triangles dans un espace 2D:
Je fais pivoter, traduire et projeter mes points pour obtenir une représentation spatiale 2D de chaque triangle. Ensuite, je prends les 3 points du triangle et j'implémente l'algorithme de la ligne de balayage (en utilisant l'interpolation linéaire) pour trouver tous les points [x] [y] le long des bords (gauche et droite) des triangles, afin de pouvoir balayer le triangle horizontalement, ligne par ligne, et remplissez-la de pixels.
Cela marche. Sauf que je dois également implémenter la mise en mémoire tampon z. Cela signifie que connaissant les coordonnées z pivotées et traduites des 3 sommets du triangle, je dois interpoler la coordonnée z pour tous les autres points que je trouve avec mon algorithme de ligne de balayage.
Le concept semble assez clair, je trouve d'abord Za et Zb avec ces calculs:
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);
Puis pour chaque Zp je fais la même interpolation horizontalement:
var Z_Slope = (right_z - left_z) / (right_x - left_x);
var Zp = left_z + ((current_point_x - left_x) * Z_Slope);
Et si le z actuel est plus proche du spectateur que le z précédent à cet index ALORS écrivez la couleur dans le tampon de couleur ET écrivez le nouveau z dans le tampon z. (mon système de coordonnées est x: gauche -> droite; y: haut -> bas; z: votre visage -> écran d'ordinateur;)
Le problème, c'est que ça se détraque. Le projet est là et si vous sélectionnez le bouton radio "Z-Buffered", vous verrez les résultats ... ( notez que j'utilise l'algorithme du peintre (-seulement- pour dessiner le filaire) en mode "Z-Buffered") à des fins de débogage )
PS: J'ai lu ici que vous devez transformer les z en leurs inverses (ce qui signifie z = 1/z
) avant d'interpoler. J'ai essayé, et il semble qu'il n'y ait aucun changement. Qu'est-ce que je rate? (quelqu'un pourrait-il clarifier précisément où vous devez transformer z en 1 / z et où (si) le retourner?)
[MODIFIER] Voici quelques données sur les valeurs z maximales et minimales que j'obtiens:
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.
Avant d'entrer dans un débogage minutieux, quelqu'un peut-il confirmer que mon concept jusqu'à présent est correct?
[EDIT2]
J'ai résolu le z-buffering. Il s'est avéré que l'ordre de dessin n'était pas du tout foiré. Les coordonnées z étaient calculées correctement.
Le problème était, dans le but d'augmenter ma fréquence d'images, je dessinais des boîtes 4px / 4px, tous les 4 pixels, au lieu de pixels réels à l'écran. Je dessinais donc 16 pixels par pixel, mais en vérifiant le tampon z pour un seul d'entre eux. Je suis un tel boob.
TL / DR: La question se pose toujours: comment / pourquoi / quand devez-vous utiliser l'inverse de Z (comme dans 1 / z) au lieu de Z? Parce qu'en ce moment, tout fonctionne dans les deux sens. (il n'y a pas de différence notable).