2016-11-30 2 views
0

Wie ich es verstehe, werden OpenGL-Polygone normalerweise im Clip-Raum abgeschnitten und nur diese Dreiecke (oder Teile der Dreiecke, wenn der Beschneidungsprozess sie aufteilt), die den Vergleich mit + - w überstehen. Dies erfordert dann die Implementierung eines Polygon-Clipping-Algorithmus wie Sutherland-Hodgman.Dreiecke im Bildschirmbereich pro Pixel schneiden

Ich implementiere meinen eigenen CPU-Rasterizer und möchte das jetzt vermeiden. Ich habe die NDC-Koordinaten der Scheitelpunkte verfügbar (nicht wirklich normalisiert, da ich nichts abgeschnitten habe, so dass die Positionen nicht im Bereich [-1, 1] sein können). Ich möchte diese Werte für alle Pixel interpolieren und nur Pixel zeichnen, deren NDC-Koordinaten innerhalb von [-1, 1] in den Dimensionen x, y und z liegen. Ich würde dann zusätzlich den Tiefentest durchführen.

Würde das funktionieren? Wenn ja, wie würde die Interpolation aussehen? Kann ich die Formel OpenGl spec (Seite 427 14.9) für die Attributinterpolation wie beschrieben verwenden here? Alternativ, sollte ich die Formel 14.10 verwenden, die für die Tiefeninterpolation (z) für alle 3 Koordinaten verwendet wird (ich verstehe nicht wirklich, warum dort eine andere verwendet wird)?

Update: habe ich versucht, die NDC-Werte pro Pixel durch zwei Verfahren interpoliert:

w0, w1, w2 sind die baryzentrischen Gewichte der Vertices.

1) float x_ndc = w0 * v0_NDC.x + w1 * v1_NDC.x + w2 * v2_NDC.x; float y_ndc = w0 * v0_NDC.y + w1 * v1_NDC.y + w2 * v2_NDC.y; float z_ndc = w0 * v0_NDC.z + w1 * v1_NDC.z + w2 * v2_NDC.z;

2) float x_ndc = (w0*v0_NDC.x/v0_NDC.w + w1*v1_NDC.x/v1_NDC.w + w2*v2_NDC.x/v2_NDC.w)/ (w0/v0_NDC.w + w1/v1_NDC.w + w2/v2_NDC.w); float y_ndc = (w0*v0_NDC.y/v0_NDC.w + w1*v1_NDC.y/v1_NDC.w + w2*v2_NDC.y/v2_NDC.w)/ (w0/v0_NDC.w + w1/w1_NDC.w + w2/v2_NDC.w); float z_ndc = w0 * v0_NDC.z + w1 * v1_NDC.z + w2 * v2_NDC.z;

Der Abschneide + Tiefentest immer sieht wie folgt aus:

if (-1.0f < z_ndc && z_ndc < 1.0f && z_ndc < currentDepth && 1.0f < y_ndc && y_ndc < 1.0f && -1.0f < x_ndc && x_ndc < 1.0f)

Fall 1) entspricht Gleichung 14.10 für die Interpolation. Fall 2) entspricht der Verwendung der Gleichung 14.9 für die Interpolation.

Ergebnisse documented in gifs on imgur. 1) Seltsame Dinge passieren, wenn der zweite Würfel hinter der Kamera ist oder wenn ich in einen Würfel gehe. 2) Seltsame Artefakte sind nicht sichtbar, aber wenn sich die Kamera den Scheitelpunkten nähert, verschwinden sie. Und da dies die perspective correct interpolation of attributes Scheitelpunkte (näher an der Kamera?) Sind, haben sie ein größeres Gewicht, so dass, sobald ein Scheitelpunkt abgeschnitten wird, diese Information mit starkem Gewicht auf die Dreieckspixel interpoliert wird.

Wird all dies erwartet oder habe ich etwas falsch gemacht?

+1

Ich weiß nicht, was Sie hier erreichen. Wie Nicol Bolas bereits darauf hingewiesen hat, ist das Clipping sehr wichtig, wenn ein Primitiv die Ebene "z_eye = 0" schneidet. Und die Interpolation für solche Primitiven wird völlig bedeutungslos (und für einen Knoten genau bei 'z_eye = 0' würden Sie sogar mit einer Division durch Null enden). Die Überprüfung gegen '-1 <= x, y, z <= 1' in NDC ist nicht äquivalent zu '-w <= x, y, z <= w' im Clipraum, da die Punkte, die 'w <= x erfüllen, y, z, <= -w (hinter der Kamera) würde das auch erfüllen. Ich habe keine Ahnung, was du mit "NDC.w" meinst, denn in NDC gibt es kein w (oder es wäre 1). – derhass

+1

Um dies zusammenzufassen: Meiner Meinung nach, Clipping im Bildschirm Raum macht nicht den geringsten Sinn (Uness Sie tun die [Rasterisierung selbst in homogenen Koordinaten] (http://www.cs.unc.edu/~olano/papers/2dh-tri /)), und es wird viel langsamer sein. Also ich weiß nicht, was Sie hier gewinnen. – derhass

+0

Danke für die Klärung der Sache. Ich habe Nicols Antwort dann nicht richtig verstanden (ich dachte, er meinte, dass die Mathematik auch im Falle eines Clippens gegen z_eye = 0 funktionieren könnte). In meinem Code benutzte ich NDC.w als Kameraraum z des Scheitelpunktes. Zugegeben, das macht nach der perspektivischen Teilung keinen Sinn. – pseudomarvin

Antwort

2

Das Zuschneiden gegen die nahe Ebene ist nicht unbedingt notwendig, es sei denn, das Dreieck geht im Kameraraum Z nach oder über 0 hinaus. Sobald das passiert, wird die homogene Koordinatemathematik merkwürdig.

Die meiste Hardware stört nur, Dreiecke zu schneiden, wenn sie mehr als eine Bildschirmbreite außerhalb des Ausschnittsraums erstrecken oder wenn sie die Kamera-Z von Null kreuzen. Diese Art des Clippings wird "Guard-Band-Clipping" genannt und spart viel Performance, da Clipping nicht billig ist.

Also ja, die Mathematik kann gut funktionieren. Das Wichtigste, was Sie tun müssen, wenn Sie Ihre Scanlinien einrichten, ist herauszufinden, wo sie auf dem Bildschirm beginnen/enden. Die Interpolationsmathematik ist in beiden Fällen gleich.

+0

Ich benutze eine Edge-Funktion, um zu testen, ob ein Pixel innerhalb eines Dreiecks liegt. In meinem Fall könnte das "Einrichten der Scanlinien" äquivalent dazu sein, die Min BB der Dreieckskoordinaten im Bildschirmbereich zu multiplizieren - 1], [0, Höhe - 1], richtig? – pseudomarvin

2

Ich sehe keinen Grund, warum das nicht funktionieren würde. Aber es wird viel langsamer als das traditionelle Clipping sein. Beachten Sie, dass Sie möglicherweise Probleme mit Dreiecken in der Nähe des Projektionszentrums bekommen, da diese verschwindend klein sind und Probleme bei der baryzentrischen Koordinatenberechnung verursachen können.

Der Unterschied zwischen Gleichung 14.9 und 14.10 ist, dass Tiefe im Wesentlichen z/w ist (und zu [0, 1] neu zugeordnet wird). Da die Teilung der Perspektive bereits stattgefunden hat, muss sie während der Interpolation weggelassen werden.

Verwandte Themen