ich habe mir einen Software Rasterizer geschrieben und dabei mehr oder weniger die OpenGL Pipeline übernommen, sprich für jedes Vertex wird zuerst ein VertexShader aufgerufen, dann wird der Frustum-Culling test gemacht, dann der Backface-Culling test.. dann wird gerastert, der DepthTest und final der PixelShader ausgeführt.
Soweit klappt das alles ganz gut, nur... beim Backface-Culling hab ich ein kleines problem.
Im prinzip macht man für den test ja einfach nur das punktprodukt zwischen der normalen und dem vektor von der kamera zum vertex.
Die normale transformiere ich mit der NormalMatrix (Transponierte, Invertierte Modelview), das Vertex mit der ModelviewProjectionMatrix.. im grunde sollte doch jetzt das Vertex (wenn man den vektor invertiert) der vektor Kamera->Vertex sein..
aber der Normal-Test klappt nicht... hab ich da nen denk fehler evtl?
Mhh.. es scheint zu funktionieren wenn ich den vertex nur mit der ModelviewMatrix transformiere, nicht mit der ModelviewProjection Matrix..
aber das wäre doch eher unpraktisch, weil dann müßte ich es ja einmal mit der modelviewProjectionMatrix und dann nochmal separat mit der modelviewMatrix transformieren... wo ist da mein fehler? :/
Ich dachte die Normalmatrix ist einfach nur die Modelviewmatrix ohne Translation, also einfach die 4te Spalte und/oder Zeile wie in der Einheitsmatrix.
@Schläfer: Nein, die Matrix muss zuerst invertiert werden und dann nochmal transponiert werden. Allerdings gibt es einen (häufigen) Spezialfall, wo sich beide Operationen genau wegheben: Wenn es sich um eine orthonormal Basis handelt, also die drei Spaltenvektoren zueinander senkrecht stehen und zudem noch normalisiert sind, dann ist die transponierte Matrix gleich der Inversen: M * M^T = Id Kann man sich auch leicht überlegen, das Skalarprodukt der Spalten/Zeilen ist dann nämlich entweder 0 oder 1. Dieser Fall tritt z.B. dann auf wenn man nur Rotationsmatrizen verwendet. Sobald man aber skaliert oder gar eine Scherung macht funktioniert das nicht mehr.
Da die Herleitung so schnell geht kann man die auch nochmal machen
Also, wir haben eine Ebene (geg. durch Normale n) die wir mit einer Matrix M transformieren wollen. Es gilt:
n^T * p = 0 für alle Punkte p auf der Ebene, wir suchen die transformierte Ebene
n'^T * p' = 0
Punkte kann man leicht transformieren, einfach die Matrix M nehmen:
<=> n'^T * Mp = 0
wir suchen nun die Matrix Q für die Normale
<=> (Qn)^T * Mp = 0
<=> n^T * Q^T * M * p = 0
Der Vektor n^T * Q^T * M muss die gleiche Richtung haben wie n, sonst würde die Gleichung nicht stimmen. Also für einen konstanten Skalarierungsfaktor c gilt:
n^T * Q^T * M = n^T * c
Also muss gelten:
Q^T * M = Id * c
wobei Id die Einheitsmatrix ist. Da uns c egal ist, setzen wir das gleich 1 und können wir nun Q berechnen:
Q = ( M^(-1) )^T
Nach der Transformation mit Q sollte man Normalen erneut normalisieren.
Mein problem ist ja nicht wie ich die normal matrix berechne etc, sondern nur generell was zum culling-test benuzt wird.
Wie macht es den OpenGL?
Ein weiteres problem an der vertex-normal ist (ja auch bei OpenGL) das die ja im shader zwar durch die normal matrix transformiert wird, allerdings in der regel nur als varying weitergegeben wird.. entweder muß OpenGL hier nun nochmal selbst die normal transformieren für den normal test, oder es benutzt sie nicht.
Wenn ich die normal vom dreieck aus den drei eckpunkten berechne habe ich immernoch das problem mit dem zweiten vektor, ich habe dann eine normal "n" berechnet, aber wie bekomme ich nun den zweiten vektor für's punktprodukt?
Und wie ist das bei OpenGL, wenn ich ein triangle im uhrzeigersinn zeichne (also im grunde falschrum) wird es ja durch das backface-culling nicht gezeichnet, wenn ich aber jetzt via glNormal die normals der vertices anpasse, dann wird es korrekt.. sprich OpenGL muß auch irgendwie die normal dafür hernehmen.
Und wie ist das bei OpenGL, wenn ich ein triangle im uhrzeigersinn zeichne (also im grunde falschrum) wird es ja durch das backface-culling nicht gezeichnet, wenn ich aber jetzt via glNormal die normals der vertices anpasse, dann wird es korrekt.. sprich OpenGL muß auch irgendwie die normal dafür hernehmen.
Du meinst du setzt im Vertexshader gl_Normal = -gl_Normal und das Culling wird umgedreht? Ich bin mir eigentlich ziemlich sicher das OpenGL die Normalen der Faces benutzt. Vertexnormalen sind nur für die Beleuchtung von Bedeutung. Insbesondere sollte gl_Normal im Vertexshader eigentlich read-only sein, zumindest steht das so hier.
Zitat:
aber wie bekomme ich nun den zweiten vektor für's punktprodukt?
Nach der perspektivischen Transformation sollte die Blickrichtung (0,0,-1) sein, ist jedenfalls ne Konvention. Entsprechend brauchst du nur testen ob die z-Koordinate deiner Face-Normale positiv oder negativ ist. Zudem brauchst auch nur die z-Koordinate der Face-Normale ausrechnen.
Ich bin mir gerade allerdings nicht sicher ob du die Face-Normale auch vor der Division durch w berechnen kannst. Da aber auch Cliping in der Pipeline vor dieser Division ist, müsste das eigentlich gehen.
OpenGL schaut laut Spezifikation nur die Vertices im Window-Space an. Formel 2.6 auf Seite 63 in der OpenGL 2.0 Spezifikation. Siehe auch ersten Absatz des Abschnitts 3.5.1 auf Seite 108.
Mitglieder in diesem Forum: 0 Mitglieder und 18 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.