[OpenGL] Reflections / Normals



  • Hey,
    Ich hätte zwei Fragen bzgl. Spiegelungen.
    Ich habe eine Szene mit einem kleinen Teich.
    Hier möchte ich Spiegelungen in der Wasseroberfläche darstellen.

    Die gedachte Vorgehensweise:
    Erst alles gespiegelt in eine Textur rendern.
    Dann rendere ich alles normal.
    Im Anschluss schreibe ich die Wasseroberfläche in den Stencilbuffer damit ich weiß welche Pixel ich später aus der anfangs gerenderten Textur auslesen muss.

    1.) Ist dies soweit in Ordnung? Oder gibt es eine bessere/neuere Methode festzustellen wo im Bild Wasser zu sehen ist.

    2.) Die Spiegelungen sollten dabei nicht 1:1 die invertierte Szene darstellen, sondern abhängig von der sich bewegenden Wasseroberfläche die verzerrte Szene zeigen.
    Wie komme ich hier an die zu jedem Pixel/Fragment zugehörigen WasseroberflächenNormale?

    Alle Trianglenormals der Wellengeometrie zu speichern bringt mir nicht viel, da es ja auf den jeweiligen Blickwinkel im Bild ankommt welcher Pixel welchen Teil eines Triangles zeigt.

    Per unProject einen Strahl für jeden Pixel(Ist hier Pixel=Fragment?) erzeugen und testen welches Triangle(und damit die zugehörige Normale) aus der Wellengeometrie geschnitten wird ist reichlich aufwendig und braucht vmtl auch recht viel Leistung.
    Gibt es da eine bessere/schnellere Methode?

    Und als Ergänzung:
    Wie kann ich die erhaltenen Normals dazu verwenden die Szene zu verzerren?
    Also praktisch Pixel.xy=UseNormalsToDistortScene(Texture.xy)

    Auch möchte ich das ganze mit OpenGl 3.x erreichen. Also keine deprecated-Funktionen nutzen.

    MfG und Danke im Voraus!



  • Gruebler schrieb:

    Die gedachte Vorgehensweise:
    Erst alles gespiegelt in eine Textur rendern.
    Dann rendere ich alles normal.
    Im Anschluss schreibe ich die Wasseroberfläche in den Stencilbuffer damit ich weiß welche Pixel ich später aus der anfangs gerenderten Textur auslesen muss.

    Klingt gut, den Stencil Buffer kannst du dir aber mehr oder weniger sparen, das macht dir der Z-Buffer schon automatisch.

    Gruebler schrieb:

    Wie komme ich hier an die zu jedem Pixel/Fragment zugehörigen WasseroberflächenNormale?

    Normalerweise verwendet man da eine Normal- oder DuDv-Map.

    Gruebler schrieb:

    Wie kann ich die erhaltenen Normals dazu verwenden die Szene zu verzerren?

    Das geht über Shader, Tutorials dazu findest du in rauen Mengen bei google...



  • Danke für deine schnelle Antwort!

    dot schrieb:

    Gruebler schrieb:

    Wie komme ich hier an die zu jedem Pixel/Fragment zugehörigen WasseroberflächenNormale?

    Normalerweise verwendet man da eine Normal- oder DuDv-Map.

    Ich nehme an das sind Arrays mit den Daten für den Shader.
    Ist das dann ein Array mit den Normalen der Triangles der Wasser-Ebene im 3D Raum ? (Also bei 500x500 Triangles - 500x500 Normals)
    Oder (und das möchte ich ja als Ergebnis erzeugen) ein Array von Normals zu jedem Pixel auf dem Bildschirm (Bei einer Bildschirmauflösung von 1024x768 also 1024x768 Normals.)
    Mich interessiert hier ja wie ich die Normals von jedem Pixel bekomme um damit dann weiter rechnen zu können.

    Oder ist mit NormalMap /DuDvMap eine Vorgehensweise und nicht der Datentyp(NormalArray) an sich gemeint.

    dot schrieb:

    Gruebler schrieb:

    Wie kann ich die erhaltenen Normals dazu verwenden die Szene zu verzerren?

    Das geht über Shader, Tutorials dazu findest du in rauen Mengen bei google...

    Dass ich das im Fragment Shader mache hatte ich mir schon gedacht.
    Mich interessiert (wie bei Punkt 1) eher die praktische als die theoretische Vorgehensweise.
    Also wie ich praktisch die Normal (vorausgesetzt ich kenne die Normale jedes Pixels(bzw. dessen zugehöriges Dreieck im Raum) ) verwende um damit einen anderen Pixel an die Stelle zu zeichnen...
    Also die Normale ist ja die des Triangles vom aktuellen Pixel auf dem Bildschirm. Als würde ich durch diesen aktuellen Pixel einen Strahl auf die Wellen schicken. Dort schneidet dieser dann ein Dreieck und so ordne ich die Normale dieses Triangles dem aktuellen Pixel zu. (Ist dies dann eine NormalMap?)

    Und dann habe ich zwar den aktuellen Pixel und die Normale, aber wie berechne ich dann auf welchen Pixel(vom Bildschirm) die Normale vom aktuellen Pixel zeigt?

    Hoffe ihr versteht was ich meine, Ich würde mich auch über links zu dem Thema freuen.



  • Gruebler schrieb:

    Also die Normale ist ja die des Triangles vom aktuellen Pixel auf dem Bildschirm. Als würde ich durch diesen aktuellen Pixel einen Strahl auf die Wellen schicken. Dort schneidet dieser dann ein Dreieck und so ordne ich die Normale dieses Triangles dem aktuellen Pixel zu. (Ist dies dann eine NormalMap?)

    Und wie genau gedenkst du das mit einem Shader anzustellen?

    Eine Normalmap ist eine Textur in der quasi für jeden Pixel deiner Wasseroberfläche eine Normale drin ist. Du renderst einfach deine Wasseroberfläche mit dieser Textur drauf. Weiters mappest du deine zweite Textur in der die gespiegelte Szene drin ist auf deine Wasseroberfläche. Für jedes Fragment holst du dir dann die jeweilige Normale aus der Normalmap und berechnest dir irgendwie ein Offset das du auf die Texturkoordinaten für die Spieglung addierst. Mit diesen Koordianten samplest du dann die Spiegelung und voilà. Eine DuDv Map enthält einfach gar keine Normalen mehr sondern direkt die Offsets.



  • dot schrieb:

    Gruebler schrieb:

    Also die Normale ist ja die des Triangles vom aktuellen Pixel auf dem Bildschirm. Als würde ich durch diesen aktuellen Pixel einen Strahl auf die Wellen schicken. Dort schneidet dieser dann ein Dreieck und so ordne ich die Normale dieses Triangles dem aktuellen Pixel zu. (Ist dies dann eine NormalMap?)

    Und wie genau gedenkst du das mit einem Shader anzustellen?

    Das hätte ich vorher gemacht und später die Daten an den Shader übergeben.

    dot schrieb:

    Eine Normalmap ist eine Textur in der quasi für jeden Pixel deiner Wasseroberfläche eine Normale drin ist.

    Ok, also Pixel des Outputs(Bildschirm oder FBO). Und wie befülle ich die NormalMap mit Werten? Die Daten müssen ja von der Wasseroberfläche kommen.
    Sorry, ich stehe da gerade wirklich auf der Leitung.
    Das Einzige was ich mir im Moment darunter vorstellen kann ist, dass ich beim Rendern der einzelnen Triangles der Wellen, bei jedem Vertex im VertexShader die Normale des Triangles an den FragmentShader übergebe.
    Und der FragmentShader fügt dann für den aktuellen Pixel die Normale aus dem Triangle in eine Art Array(Größe des Outputs) ein.
    Somit würde also dieser FragmentShader nach und nach diese "NormalMap" befüllen.
    War das so gemeint? (Vermutlich nicht 😃 )

    dot schrieb:

    Du renderst einfach deine Wasseroberfläche mit dieser Textur drauf. Weiters mappest du deine zweite Textur in der die gespiegelte Szene drin ist auf deine Wasseroberfläche. Für jedes Fragment holst du dir dann die jeweilige Normale aus der Normalmap und berechnest dir irgendwie ein Offset das du auf die Texturkoordinaten für die Spieglung addierst. Mit diesen Koordianten samplest du dann die Spiegelung und voilà. Eine DuDv Map enthält einfach gar keine Normalen mehr sondern direkt die Offsets.

    Alles klar. Das geschieht alles im FragmentShader, nehme ich an.



  • Gruebler schrieb:

    dot schrieb:

    Gruebler schrieb:

    Also die Normale ist ja die des Triangles vom aktuellen Pixel auf dem Bildschirm. Als würde ich durch diesen aktuellen Pixel einen Strahl auf die Wellen schicken. Dort schneidet dieser dann ein Dreieck und so ordne ich die Normale dieses Triangles dem aktuellen Pixel zu. (Ist dies dann eine NormalMap?)

    Und wie genau gedenkst du das mit einem Shader anzustellen?

    Das hätte ich vorher gemacht und später die Daten an den Shader übergeben.

    Ok, das wäre natürlich unglaublich langsam 😉

    Gruebler schrieb:

    Und wie befülle ich die NormalMap mit Werten? Die Daten müssen ja von der Wasseroberfläche kommen.

    Anders rum, die Normalmap bestimmt wie deine Wasseroberfläche aussieht 😉

    Gruebler schrieb:

    Alles klar. Das geschieht alles im FragmentShader, nehme ich an.

    Exakt.



  • dot schrieb:

    Anders rum, die Normalmap bestimmt wie deine Wasseroberfläche aussieht 😉

    Verstehe. Die meisten Tutorials die ich gefunden habe, erstellen eine NormalMap aus einer Textur, die vorher mit einem ZeichenProgramm erstellt wurde.
    Da sich die Wasseroberfläche aber verändern sollte, stellt sich mir die Frage wie ich die NMap erstelle.

    Und rein zum Verständnis: Gibt es dabei dann eine Veränderung der Vertices oder bleibt die Wasserebene durchgehend eine flache Ebene?
    Ich dachte erst die WasserVertices würden verändert und deren Normals dann für die Normalmap verwendet.

    Außerdem ergab sich beim Lesen einiger Tutorials die Frage:
    Wie kann man dann mit dem Wasser an einer bestimmten Stelle interagieren? Dafür brauche ich ja die Position im Raum. Wenn ich die Normalmap aber über die Oberfläche spanne, gibt es ja keinen Zusammenhang zwischen den Einträgen in der Normalmap und den Punkten im Raum, oder?



  • Gruebler schrieb:

    Da sich die Wasseroberfläche aber verändern sollte, stellt sich mir die Frage wie ich die NMap erstelle.

    Na dann brauchst du eine animierte Normalmap...

    Gruebler schrieb:

    Und rein zum Verständnis: Gibt es dabei dann eine Veränderung der Vertices oder bleibt die Wasserebene durchgehend eine flache Ebene?

    Du kannst die Vertices natürlich auch bewegen.

    Gruebler schrieb:

    Wie kann man dann mit dem Wasser an einer bestimmten Stelle interagieren? Dafür brauche ich ja die Position im Raum. Wenn ich die Normalmap aber über die Oberfläche spanne, gibt es ja keinen Zusammenhang zwischen den Einträgen in der Normalmap und den Punkten im Raum, oder?

    Doch klar, jedem Punkt auf der Wasseroberfläche entspricht ein Wert aus der Normalmap!?

    Ich würde dir empfehlen einfach mal die ganz einfache perfekte Spiegelung an einer flachen Ebene zu implementieren, ohne Animation, Interaktion, Normalmaps oder sonstigen Firlefanz. Daran hast du fürs Erste sicherlich genug zu knabbern...



  • dot schrieb:

    Doch klar, jedem Punkt auf der Wasseroberfläche entspricht ein Wert aus der Normalmap!?

    Ok also eine Normalmap hat soviele Einträge wie die Wasseroberfläche Vertices, ja?

    dot schrieb:

    Ich würde dir empfehlen einfach mal die ganz einfache perfekte Spiegelung an einer flachen Ebene zu implementieren, ohne Animation, Interaktion, Normalmaps oder sonstigen Firlefanz. Daran hast du fürs Erste sicherlich genug zu knabbern...

    Eine perfekte Spiegelung habe ich schon implementiert, daher ja meine Frage wie es nun weitergeht.



  • Gruebler schrieb:

    Ok also eine Normalmap hat soviele Einträge wie die Wasseroberfläche Vertices, ja?

    Nein, lies dir bitte mal durch was Normalmapping ist.


Anmelden zum Antworten