Hallo, hier ein Fahrrad-Unfall mit WebGl, wobei ich denke, dass es auch zu einem normalen OpenGL-Problem gezählt werden kann(?):
für die Oberfläche des Objektes habe ich die Normalenvektoren berechnet, die nun Bestandteil einer scheinbar korrekten Beleuchtung mit dem Punktlicht sind. Es werden alle Triangles mit ihrer entspechenden Färbung versehen und bewirken somit einen kleinen 3D-Effekt. Doch wenn ich das 3D Objekt um 180° drehe, also die Rückfläche betrachte, ist alles nur grau. Eigentlich ist das ja einleuchtend: Die Normalenvektoren wurden auf Basis einer bestimmten Orientierung berechnet. Somit zeigen sie auf der Rückseite von der Lichtquelle weg und bekommen kein Licht ab. Doch was tun, damit auch dort ein dreidimensionaler Effekt entsteht?
Die schönsten Sommergrüße aus dem heißesten Land der Welt. Deutschland.
Also wenn es dir nicht um Realismus geht sondern nur darum irgendwas erkennen zu können ist meine Lieblingslösung im Shader das Dot-Produkt nicht bei 0.0 abzuschneiden sondern den Absolutwert zu verwenden:
//edit: hab gerade gesehen, dass du noch recht neu bist. dann sind shader wohl keine alternative
Zitat:
Eine weitere Alternative ist natürlich eine oder mehr weitere Lichtquellen, dann klappt es auch mit dem Realismus.
das ändert aber nichts daran, dass die Normale von der Rückseite in die falsche Richtung zeigt.
Code:
float diffuseFactor = abs(dot(normal, lightdir));
das is auch nicht perfekt, weil es kann ja wirklich die Normale vom Licht wegzeigen.
Der einzige Weg, der mir jetzt einfallt ist, die Normale vorher umzudrehen, wenn sie vom Betrachter wegzeigt. Das ist nämlich genau dann so, wenn man die Rückseite sieht... oder wenn bei der Berechnung von der Normale irgendwas schief gegengen is.
Code:
if (normal.z < 0.0) { normal = -normal; }
vielleicht muss da auch normal.z > 0.0 hin. je nachdem wo hinten ist. Aber so sollts gehen.
Das kann im Fragmentshader gemacht werden, ode wenns nötig ist auch im Geometrieshader. Aber auf jeden fall nach dem transformieren.
Aber wichtig ist doch die Normale nach dem Reinarbeiten der ModellView-Matrix. Sonst dreht man das Objekt per glRotatef um 180° und alles ist falsch.
Ich habe es ein mal so gelöst, dass ich BackFaceCulling aktiviert habe, also dass Rückseiten nicht gezeichnet werden, und ich diese dann explizit mit eigener Normale übergeben habe. Vorteil war bei mir, dass ich die "Hintergrundfarbe" explizit einstellen konnte. Hier mal ein Beispiel, wie das aussah:
Dateianhang:
screenshot.png
LG Ziz
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
_________________ Denn wer nur schweigt, weil er Konflikte scheut, der macht Sachen, die er hinterher bereut. Und das ist verkehrt, denn es ist nicht so schwer, jeden Tag zu tun als ob's der letzte wär’. Und du schaust mich an und fragst ob ich das kann. Und ich denk, ich werd' mich ändern irgendwann. _________________Farin Urlaub - Bewegungslos
cool, es funktioniert..ich muss nur noch verstehen, warum das funktioniert.
sharkman hat geschrieben:
Der einzige Weg, der mir jetzt einfallt ist, die Normale vorher umzudrehen, wenn sie vom Betrachter wegzeigt. Das ist nämlich genau dann so, wenn man die Rückseite sieht... oder wenn bei der Berechnung von der Normale irgendwas schief gegengen is.
Code:
if (normal.z < 0.0) { normal = -normal; }
vielleicht muss da auch normal.z > 0.0 hin. je nachdem wo hinten ist. Aber so sollts gehen.
Das kann im Fragmentshader gemacht werden, ode wenns nötig ist auch im Geometrieshader. Aber auf jeden fall nach dem transformieren.
sehr cool, damit klappt es ebenfalls. Die Lösung gefällt mir
//edit: hab gerade gesehen, dass du noch recht neu bist. dann sind shader wohl keine alternative
Er benutzt WebGL, da geht nichts ohne Shader.
Zitat:
cool, es funktioniert..ich muss nur noch verstehen, warum das funktioniert.
Das dot-Produkt zweier Vektoren A und B ist so definiert: A.x*B.x + A.y*B.y + A.z*B.z Wenn du nun A = -A setzt ist das nichts anderes als -A.x*B.x - A.y*B.y - A.z*B.z es ändert sich also nur das Vorzeichen des dot-Produktes. Die abs-Funktion ist der Betrag einer Zahl das Ergebnis ist der positive Wert der Zahl. Die Funktion ist natürlich vordefiniert, aber im Code sähe das ca. so aus:
=> Die Variante von sharkman macht also eigentlich das gleiche. Zumindest sofern man das wirklich nach dem transformieren der Normale durch gl_NormalMatrix macht, weil dann die Z-Achse der Blickrichtung der Kamera entspricht. [ Edit: Sorry, in WebGL gibt es natürlich kein vordefiniertes Uniform gl_NormalMatrix. Gemeint ist jedenfalls dein äquivalent dieser 3x3 Matrix, welches du in jedem Fall benötigst. Falls du die noch nicht eingebaut hast, die Berechnung dafür ist nicht so unglaublich kompliziert, kann ich dir gerne geben, einfach fragen ]
Ziz hat geschrieben:
Vorteil war bei mir, dass ich die "Hintergrundfarbe" explizit einstellen konnte.
Im Fragmentshader kannst du mit der Variable gl_FrontFacing (Typ bool, nur lesbar) feststellen ob der gerenderte Pixel zur Vorder- oder Rückseite gehört und entsprechend die Farbe setzen. So lässt sich das auch ohne BackFaceCulling und zweimaliges Rendern realisieren. Die Variante von Ziz hat aber natürlich den Vorteil, dass sie ohne Shader funktioniert.
Das es um webGL geht und zudem das "normal.z<0" innerhalb eines Shaders war, habe ich nicht mitbekommen, sorry. Hoffe, meine Lösung ist vielleicht trotzdem für die Nichtshaderfraktion von Interesse.
_________________ Denn wer nur schweigt, weil er Konflikte scheut, der macht Sachen, die er hinterher bereut. Und das ist verkehrt, denn es ist nicht so schwer, jeden Tag zu tun als ob's der letzte wär’. Und du schaust mich an und fragst ob ich das kann. Und ich denk, ich werd' mich ändern irgendwann. _________________Farin Urlaub - Bewegungslos
Mitglieder in diesem Forum: 0 Mitglieder und 3 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.