Deferred Shading - eine oberste "Ebene" für leuchtende Objekte

    • Deferred Shading - eine oberste "Ebene" für leuchtende Objekte

      Hallöle,

      Wer kennt und hat Erfahrung mit "Deferred Shading" in GMS?
      Bei diesem Verfahren zur Beleuchtung von 3d Spielen werden depth, normals und Farbe eines Pixels in einer Textur gespeichert und dann drübergelegt. Ermöglicht wird dass durch mehrere Render Targets die dann zusammen das Energebnis bilden. Oder irgednwie so, ich versteh's nicht ganz. :) Wikipedia hilft.

      Hab mir das halt (siehe link oben) runtergeladen und in mein Projekt eingebaut. Im GMS werden dann halt alle Objeke und die Kamera auf mehere Surfacers gezeichnet und mit Shader manipuliert und am Schluss zeichnet man dann nur noch das letzte Surface der Renderpipeline im Draw GUI oder als ortho. Grafik und volá hat man viele bunte (viel mehr als nur acht Lichter in seinem Spiel. Sehr geil das Verfahren.

      Nun gibt es aber ein Problem. Wenn man z.B. ein Lagerfeuer in sein Spiel einbauen will wird die Textur für die Flammen auch der Dunkelheit ausgesetzt. Sie sollen aber ja allein leuchten. Das Pointlight das man mit deferred shading einbauen kann reicht nicht aus um die Flammen glaubwürdig hell genug erscheinen zulassen. Wenn man d3d lighting verwendet kann man ja einfach für das Feuer d3d_set_ligthing(0) machen. Das geht aber bei deferred shading nicht so. Wie kann man dass machen?

      Mein Versuch war es das Feuer auf ein zusätzliches Surafce zuzeicnen, davon dann jeden step ein sprite zuerstellen, weil ein surface ja keine transparenten Bereiche haben kann und das sprite dann ganz oben drauf zu zeichnen.
      Das löst aber gar nichts denn 1. Ist das total rechen intensiv bei na Auflösung von 1920 * 1080 und 2. ist das Feuer dann immer ganz vorne im Bild auch wenn eigentlich ein Baum davor wäre - also ziemlich dumm so!

      Irgendjemand weiß bestimmt wie man das macht. Brauch ich einen zusätzlichen Shader dafür? FUnktionieren Texturen mit transparenten Anteilen dann überhaupt noch?

      Hoffe mir kann jemand helfen.

      edit: Der link oben führt nicht zur aktuellen Version. Der hier aber. Dort frägt auch jemand wie man "glow" einbauen kann. Dann schreibt einer das man alle shader um den Code

      GML-Quellcode

      1. float4 base = tex2D( gm_BaseTexture, IN.Texcoords );
      2. clip( base.a <= 0.5 ? -1.0:1.0 )


      erweitern muss. Doch wo muss man das im Shader einfügen? Wenn ich das irgenwo einfügen kommt bei mir ein Fehler. Und dann hab ich irgendwo im Topic dort ein link von jemanden gefunden (ich find ihn aber grad nicht mehr) der das gemacht hat mit dem "Glow". Doch leider funktionieren da keine Texturen mit transparenten Anteilen.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Morpheus ()

    • Deffered rendering unterstützt leider (aufgrund des Ansatzes) keine transparenzen "von haus aus". Viele Spiele/Engines müssen bei alphatransparenzen deshalb "hacks" in den Renderer einbauen um diese darstellen zu können. (die S.T.A.L.K.E.R. Reihe ist da ein gutes Beispiel.)

      In Bezug auf die Belichtung: Es kommt darauf an wie genau du die Lichter in deinem Renderer eingebaut hast. Beispielsweise können das ein einfaches uniform array sein, Lighvolumes, etc... (und je nachdem wie du die lichter implementiert hast wird es andere/verschiedene Lösungen für das Problem geben.)



      Mein Versuch war es das Feuer auf ein zusätzliches Surafce zuzeicnen, davon dann jeden step ein sprite zuerstellen, weil ein surface ja keine transparenten Bereiche haben kann und das sprite dann ganz oben drauf zu zeichnen.
      Das löst aber gar nichts denn 1. Ist das total rechen intensiv bei na Auflösung von 1920 * 1080

      Wieso erstellst du jedes step ein Sprite? Die Surfaces unterstützen Alpha transparenzen, das problem ist nur dass der Pixel nicht anhand des Alphawertes "geblendet" wird sondern dieser gleich den Pixel des Rendertargets überschreibt. Das könnte man aber mit einem custom shader umgehen, bei dem du diese berechnung pro pixel manuell durchführst.

      und 2. ist das Feuer dann immer ganz vorne im Bild auch wenn eigentlich ein Baum davor wäre - also ziemlich dumm so!

      Was du machen könntest ist volgendes:
      Render erstmal die gesamte Levelgeometrie ohne dem Feuer. Später nimmst du dir einen eigenen Shader zur hand welcher (das Lagerfeuer auf die finale composition zeichnet) an den dann den Depth-Buffer als parameter mitschickst. Pro pixel kannst du dir die Tiefe des Lagerfeuers in der Szene errechnen (wirst dann irgendwie die Viewspace Koordinaten berechnen müssen) und diese Information mit den zuständigen pixel auf der Depthmap vergleichen. Dann machst du eine einfache abfrage:

      GML-Quellcode

      1. if(depthBuffer.z<flamme.z){//wenn die geometrie sich hinter der Flamme befindet...
      2. //überschreibe den Pixel mit der flamme
      3. }//ansonsten lass den pixel in ruhe


      Bei Deffered Rendering gibt es (bis auf den Ansatz dass man die informationen wie Depth,normals, diffuse und texture in unterschiedliche Rendertargets aufteilt) keine "allgemeinlösung" auf die man zurückgreift. Je nachdem was du von deinem Spiel/Engine abverlangst wirst du individuelle Lösungen finden müssen. Und das verlangt schon von einem ein wenig know-how in dem Bereich ab.

    • Ok hab mich ein wenig mit Shader befasst und rumgespielt. Für alle Leute die Deferred Rendering mit "Glow" machen wollen, hier der link den ich wiéder gefunden hab:

      dropbox.com/s/c5evc2q4z7jvigd/…ferred glow maps.gmz?dl=0

      Und wenn ihr Texturen mit Transparents verwenden wollt müsst ihr Folegendes tun:

      GML-Quellcode

      1. float4 base = tex2D( gm_BaseTexture, IN.Texcoord );
      2. if( base.a <= 0.5 ) {
      3. clip(-1);
      4. }


      Diesen Code müsst ihr in alle Shader die mit HLSL9 arbeiten einfügen. Und zwar in den Fragmentshader in VoidMain an erster Stelle! Nur nicht in den Shader der "shd_depth" heißt.
      Mit meinem bisherigen Verständnis von Shadern erklär ich euch was die Zeilen machen:
      float4 base = tex2D( gm_BaseTexture, IN.Texcoord ); deklariert einen 4 dimensionalen Vektor der "base" heißt und weist ihn gm basetextur mit der dazugehörigen UV-Koordinate zu. Wir haben dann in "base" RGB und Alpha gespeichert. Oder xyz uns Alpha? Was meint ihr? :)
      Mit if( base.a <= 0.5) fragen wir auf jeden Fall ab, ob der Alphawert des Pixels kleinergleich 0,5 ist. Wenn ja dann wird dieser Pixel erst gar nicht interpoliert und gezeichnet, dass macht dann wohl die Funktion clip(-1).

      Hab ich das soweit richtig verstanden? LEWA?^^

      Wenn wir schon dabei sind, weiß jemand wo man im Internet eine Liste findet mit Shader Funktionen und den GM Shader Vartiablen wie z.B. "Texcoord"? Wie soll man sonst das Shaderprogrammieren lernen?
    • Morpheus schrieb:

      Ok hab mich ein wenig mit Shader befasst und rumgespielt. Für alle Leute die Deferred Rendering mit "Glow" machen wollen, hier der link den ich wiéder gefunden hab:

      dropbox.com/s/c5evc2q4z7jvigd/…ferred glow maps.gmz?dl=0

      Und wenn ihr Texturen mit Transparents verwenden wollt müsst ihr Folegendes tun:

      GML-Quellcode

      1. float4 base = tex2D( gm_BaseTexture, IN.Texcoord );
      2. if( base.a <= 0.5 ) {
      3. clip(-1);
      4. }


      Diesen Code müsst ihr in alle Shader die mit HLSL9 arbeiten einfügen. Und zwar in den Fragmentshader in VoidMain an erster Stelle! Nur nicht in den Shader der "shd_depth" heißt.
      Mit meinem bisherigen Verständnis von Shadern erklär ich euch was die Zeilen machen:
      float4 base = tex2D( gm_BaseTexture, IN.Texcoord ); deklariert einen 4 dimensionalen Vektor der "base" heißt und weist ihn gm basetextur mit der dazugehörigen UV-Koordinate zu. Wir haben dann in "base" RGB und Alpha gespeichert. Oder xyz uns Alpha? Was meint ihr? :)
      Mit if( base.a <= 0.5) fragen wir auf jeden Fall ab, ob der Alphawert des Pixels kleinergleich 0,5 ist. Wenn ja dann wird dieser Pixel erst gar nicht interpoliert und gezeichnet, dass macht dann wohl die Funktion clip(-1).

      Hab ich das soweit richtig verstanden? LEWA?^^

      Du hast es richtig verstanden.^^
      In "base" speicherst du den jeweiligen pixel der Textur "gm_BaseTexture" der auf den UV koordinaten "Texcoord" liegt.
      clip ist eine HLSL funktion die ähnlich zu "discard" in GLSL arbeitet. (wobei clip scheinbar weitere logik beinhaltet.)
      Damit wird einfach der shader sozusagen abgebrochen und der Pixel auf der als Rendertarget gesetzten textur nicht beschrieben.

      Wenn wir schon dabei sind, weiß jemand wo man im Internet eine Liste findet mit Shader Funktionen und den GM Shader Vartiablen wie z.B. "Texcoord"? Wie soll man sonst das Shaderprogrammieren lernen?

      Es gibt in der game maker documentation eine liste mit konstanten welche vom GM automatisch an alle shader gesendet werden und dadurch "von Haus aus" verfügbar sind:
      docs.yoyogames.com/source/dadi…ader constants/index.html

      Allerdings kann es sein dass in HLSL einige dieser variablen wiederum anders heißen können (kommt darauf an wie der GM das handelt.) Hab mit HLSL leider noch recht wenig bis gar keine Erfahrung in dem Bereich machen können.

      Wenn es um verfügbare funktionen geht, kannst du einfach online nach "HLSL functions" oder "GLSL functions" suchen. z.B: msdn.microsoft.com/en-us/libra…op/ff471376(v=vs.85).aspx
      Beachte aber dass es durchaus sein kann das einige dieser Funktionen fehlen bzw im GM nicht verfügbar sind. (Aufgrund einer älteren API z.B: DirectX 9.0c im Falle von HLSL oder eben aufgrund der fehlenden implementierung im shaderconverter was im Falle von GLSL ES passieren kann.)

      Werde mir übrigens demnächst auch mal Deffered Rendering zu gemüte führen und -versuchen- was lauffähiges zu programmieren. Allerdings höchstwahrscheinlich nicht im GM, da für sowas einfach zu viele Restriktionen vom GM (für meinen Geschmack) aufgestellt werden. u.a. die fehlende möglichkeit zur Laufzeit shader zu kompilieren oder dass Multiple Rendertargets im GM nur in kombination mit HLSL funktionieren (und selbst da crasht das immernoch auf einigen PCs...)