Ich muss meinen eigenen Software-3D-Rasterizer schreiben und kann mein 3D-Modell aus Dreiecken bisher in den 2D-Raum projizieren:
Ich drehe, übersetze und projiziere meine Punkte, um eine 2D-Raumdarstellung jedes Dreiecks zu erhalten. Dann nehme ich die 3 Dreieckspunkte und implementiere den Scanline-Algorithmus (unter Verwendung der linearen Interpolation), um alle Punkte [x] [y] entlang der Kanten (links und rechts) der Dreiecke zu finden, damit ich das Dreieck horizontal scannen kann. Zeile für Zeile und füllen Sie es mit Pixeln.
Das funktioniert. Außer ich muss auch Z-Pufferung implementieren. Dies bedeutet, dass ich bei Kenntnis der gedrehten und übersetzten z-Koordinaten der 3 Eckpunkte des Dreiecks die z-Koordinate für alle anderen Punkte, die ich mit meinem Scanline-Algorithmus finde, interpolieren muss.
Das Konzept scheint klar genug zu sein, ich finde zuerst Za und Zb mit diesen Berechnungen:
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);
Dann mache ich für jedes Zp die gleiche Interpolation horizontal:
var Z_Slope = (right_z - left_z) / (right_x - left_x);
var Zp = left_z + ((current_point_x - left_x) * Z_Slope);
Und wenn das aktuelle z näher am Betrachter liegt als das vorherige z an diesem Index, dann schreiben Sie die Farbe in den Farbpuffer UND schreiben Sie das neue z in den z-Puffer. (Mein Koordinatensystem ist x: links -> rechts; y: oben -> unten; z: dein Gesicht -> Computerbildschirm;)
Das Problem ist, es geht drunter und drüber. Das Projekt ist hier und wenn Sie das Optionsfeld "Z-gepuffert" auswählen, werden die Ergebnisse angezeigt ... ( Beachten Sie, dass ich den Algorithmus des Malers (nur zum Zeichnen des Drahtgitters) im Modus "Z-gepuffert" verwende für Debugging-Zwecke )
PS: Ich habe hier gelesen , dass Sie die Zs in ihre Kehrwerte (Bedeutung z = 1/z
) umwandeln müssen, bevor Sie interpolieren. Ich habe das versucht, und es scheint, dass sich nichts ändert. Was vermisse ich? (Könnte jemand klarstellen, wo genau Sie z in 1 / z verwandeln müssen und wo (wenn) Sie es zurückdrehen müssen?)
[EDIT] Hier sind einige Daten darüber, welche maximalen und minimalen z-Werte ich erhalte:
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.
Kann jemand bestätigen, dass mein bisheriges Konzept korrekt ist, bevor ich mit dem sorgfältigen Debuggen beginne?
[EDIT2]
Ich habe die Z-Pufferung gelöst. Wie sich herausstellte, war die Zeichnungsreihenfolge überhaupt nicht durcheinander. Die z-Koordinaten wurden korrekt berechnet.
Das Problem war, dass ich bei dem Versuch, meine Bildrate zu erhöhen, 4px / 4px-Boxen alle 4 Pixel anstelle der tatsächlichen Pixel auf dem Bildschirm zeichnete. Also habe ich 16 Pixel pro Pixel gezeichnet, aber den Z-Puffer auf nur einen überprüft. Ich bin so ein Busen.
TL / DR: Die Frage bleibt: Wie / warum / wann müssen Sie den Kehrwert von Z (wie in 1 / z) anstelle von Z verwenden? Denn im Moment funktioniert alles so oder so. (Es gibt keinen merklichen Unterschied).