Direktionale Projektion
-
Hallo!
Ich versuche gerade eine 4x4 Matrix zu erstellen, mit der ich Vektoren auf eine Ebene (im Normalfall n:0,1,0) projezieren kann. Anstelle einer Punktprojektion (D.h. der Vektor wird über einen Punkt verlängert, die Schnittgerade mit der Ebene bestimmt den projezierten Punkt) möchte ich dies jedoch mit einem zweiten Vektor projezieren (im Prinzip eine gerichtete Projektion)
Anwendung ist die korrekte Darstellung von planaren Schatten in einer komplexen Simulationsumgebung. Aber anstatt Punktlichtquellen (z.B. eine Glühlampe) sollen hierfür eben gerichtete Lichtquellen verwendet werden (siehe Sonne. Durch die große Entfernung kann man hier von annähernd parallel einfallenden Lichtstrahlen sprechen)
Ein Ansatz war, die Lichtquelle auf eine sehr große Position zu setzen. Das Ergebnis hierfür ist zwar eigentlich zufriedenstellend, jedoch funktioniert dies nur bedingt mit den Pipelines der heutigen Grafikkarten.
Ich beisse mir jetzt schon seit geraumer Zeit die Zähne an diesem Problem aus, eventuell kann mir ja jemand weiterhelfen?
Alternativ wäre natürlich die Berechnung in einem Vertex Shader möglich, jedoch möchte ich nicht unnötig GPU - Zeit verbraten, wenn dies auch in einer einfachen Matrix * Vektor Multiplikation geht.
Vielen Dank für Eure Hilfe,
Thomas
-
Ich hätte da zumindest nen Ansatz um das etwas einfacher zu machen:
Zuerst rotierst Du mal alles, sodaß der Vektor in dessen Richtung Du projizieren willst (0,0,1) ist. Dann machst Du die Projektion (jetzt einfacher, da nur noch die z-Koordinate zu verändern ist), dann machst Du die Rotation wieder rückgängig.
Das klingt jetzt zwar aufwändig. Aber diese Rotation kannst Du einfach an die Projektionsmatrix vorne/hinten mit dranmultiplizieren, sodaß Du am Ende doch nur eine einzige Projektionsmatrix hast.Jetzt bleibt noch festzustellen, wie man entlang fester Richtung auf eine beliebige Ebene projiziert.
MfG Jester
-
Hallo Jester!
Erstmal Danke für deine Schnelle Hilfe. Leider verstehe ich Deinen Ansatz nicht ganz. Ich hab mir das Ganze vorhin mal zeichnerisch verdeutlicht, allerdings wird es mir nicht ganz klar. Grundsätzlich klingt es aber schon mal ganz interessant
Kannst Du mir Deinen Ansatz etwas genauer erläutern?
TIA,
Thomas
-
Ich versuch's.
Im Moment haben wir ne sehr komplizierte Situation. Die versuchen wir jetzt zuerst zu vereinfachen. Dazu drehen wir die Szene so, daß der Projektionsvektor zu (0,0,1) wird. Das machen wir, indem wir ne Matrix T bestimmen, die das kann.
Jetzt tun wir so, als wären wir in der Situation, daß der Projektionsvektor schon (0,0,1) ist und lösen dort das Problem. Erhalten also eine Matrix A, die von dort aus die Lösung beschreibt.
Dann ist T^-1 * A * T eine Matrix, die das urpsrüngliche Problem löst. Sowas heißt in der linearen Algebra auch Basiswechsel.Das Problem ist jetzt also diese Matrix A zu bestimmen. Wobei die Projektionsrichtung die z-Achse ist. in welcher Form ist denn die Eben gegeben?
MfG Jester
-
Mmmmh... Im Prinzip ist es einfach nur die Grundfläche. (OpenGL, also Left Handed)
D.h. die XZ Ebene (Y zeigt nach Oben)
-Thomas
-
So...
Ich hab mich jetzt einfach nochmal mit Papier und Stift hingesetzt und ein bisschen nachgedacht und ne ganz einfache Lösung gefunden.
Ich poste sie einfach nochmal hier rein, vielleicht hilft das ja sonst noch jemandem, oder ich krieg einen Kommentar von Euch. Würde mich freuen.
Im Prinzip geht es ja darum einen Punkt über eine bestimmte Richtung auf die Grundfläche zu projezieren. Es sind eigentlich alle Werte vorhanden, um die noch fehlenden auszurechnen. Wir haben gegeben:
Punkt P, Projektionsvektor (Richtung) L, sowie die Grundfläche (n:0,1,0, O:0,0,0)
Zu aller erst verschiebt man die Grundfläche in den Punkt, und bestimmt den Einfallswinkel des Verschiebungsvektors in der YZ und der XZ Ebene.
Der ist gleich dem Winkel den der projezierte Punkt P` auf der Grundfläche hat.
Des weiteren ist gegeben, dass P`y = 0 ist.
P,P
, sowie die senkrechte Projektion von P auf die Ebene (P``) bilden ein Rechtwinkliges Dreieck. Bekannt ist hierbei zusätzlich der Einfallswinkel, sowie die Länge von P`` (= Py). Damit kann die Strecke P\
P`` bestimmt werden. Diese Strecke ist ja relativ zur senkrechten Projektion. Konstruiert man daraus einen Vektor und addiert hierauf P``, erhält man P`.Es ergibt sich also folgendes Gleichungssystem:
P
x = Px - Py * Lx / Ly P
y = 0
P`z = Pz - Pz * Lz / LyDies lässt sich dann ja ganz leicht in eine entsprechende Matrix umformen.
Ich hab das jetzt mal für 2D konstruiert und getestet, es scheint zu gehen.
2D - Matrix:
|1 -Lx/Ly| |0 0 |
Die Testimplementierung in OpenGL benutzt folgende Matrix (Colum Major Order):
float fvPSM[] = { 1.0f, 0.0f, 0.0f, 0.0f, -1.0f * (lightDir[0] / lightDir[1]), 0.0f, -1.0f * (lightDir[2] / lightDir[1]), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,};
Wenn mein Lighting Code nicht kaputt ist, dann sollte es passen.
Was haltet Ihr von meiner Idee?
Viele Grüße,
Thomas
-
Sieht gut aus. Hab im Moment leider nicht die Zeit alles im Detail nachzuvollziehen, aber die Beschreibung klingt sinnvoll. Und ich denke die Idee ist richtig.