Deutsch Startseite English

Wed, 28 Jun 2017

Sitemap

Lite-C,3d Game Studio

Postprocessing Shader Tutorial Teil I:

::.Grundstruktur.::

Wenn Ihr Level in der A7 Engine des 3D GameStudios so altbacken aussieht und das, obwohl Sie doch perfekte Texturen und saubere Modelle oder gar hin und wieder auf solche Shadereffekte zugreifen wie Bumpmapping, Normalmapping oder Parallaxmapping. Dann fehlen Ihnen Postprocessingeffekte. In der folgenden Tutorialserie werde ich Ihnen zeigen, wie Sie z.B. einen einfachen Blurshader programmieren und implementieren können.
Erst einmal geht es um die Grundstruktur eines solchen Shadereffektes in HLSL und um die einfache Implementierung über lite-c.

Das gesamte Tutorial zusammen mit Codebeispielen steht hier zum Download bereit.

Schwierigkeit:**

Material: lite-c, 3DGS A7 Commercial oder Professional

Zusatzmaterial: postprocessdat.rar

Vorwort | Arbeitsumgebung | Grundstruktur |
Implementierung in die A7 Engine | Effekte und Spielereien | Zusammenfassung | Additum

1. Vorwort:

Postprocessing bedeutet soviel wie Nachbearbeitung. Es sind also Effekte, die erst nachträglich hinzugefügt werden. Dabei wird der Bildschirminhalt als Textur zwischengespeichert. Der Shadereffekt wird auf jeden Pixel dieser Textur angewendet und das Ergebnis anschließend auf den Bildschirm gerendert.
Dieses Tutorial richtet sich an Anfänger, die gerade erst in die Möglichkeiten der Shaderprogrammierung einsteigen. Sie sollten aber grundlegendes Wissen über das 3DGS und Lite-C mitbringen bzw. falls Sie Postprocessing Shader in einem anderen Kontext verwenden wollen, grundlegendes Wissen über C.

Was Sie im Rahmen dieses Tutorials lernen werden:

↑Top

2. Arbeitsumgebung und Testlevel vorbereiten:

Nehmen Sie ein beliebiges buntes Level Ihrer Wahl oder das Testlevel im Downloadbereich. Es sollte mit mindestens einer Lichtquelle ausgestattet sein und bereits kompiliert worden sein. Wenn Sie möchten, können Sie auch gerne ein ganz neues Level in WED basteln, es mit Texturen belegen, Lichter einfügen und schnell kompilieren. Sollten Sie an dieser Stelle nicht weiter wissen, ziehen Sie das Benutzerhandbuch für das 3D GameStudio zu Hilfe.
Legen Sie ein neues lite-c Dokument an.
Da Sie die Acknex 7 Engine benutzen werden, müssen Sie diese per #include anbinden. Wichtig bei lite-c im Gegensatz zum C-Script in A6 ist, dass dieser Befehl nicht mit einem Semikolon abgeschlossen werden darf:

#include <acknex.h>

Zunächst erstellen Sie ein neues Material im neuen Lite-C Dokument. Ein Material enthält Parameter und Effekte, die die Darstellung von Objekten beeinflussen. Seit A7 kann man auch View-Objekten, also Ansichten wie der Standard Camera, ein eigenes Material zuweisen, das sich dann auf die Darstellung des gesamten Bildschirmes auswirkt. Genau auf diese Weise werden Sie Ihren ersten Postprocessingshader erstellen. In lite-c wird ein Material folgendermaßen definiert:

MATERIAL* mtl_MyMaterial={
 //Code
}

Im Zusammenhang mit unserem Vorhaben ist für uns ein Parameter besonders interessant:

MATERIAL* mtl_MyMaterial={
 effect="[Shader-Code]";
}

In den Effekt Parameter kommt entweder ein String mit Shadercode oder man erstellt eine externe .fx Datei z.B. myShader.fx und verweist auf sie in dem Parameter. Der Einfachheit halber werden wir unseren Shadercode direkt reinschreiben. Die zweite Methode wird im Additum angesprochen.

↑Top

3. Shadercode Grundstruktur:

Wie sieht nun die Grundstruktur eines Postprocessing Shaders aus? Schreiben Sie erst einmal den unten stehenden Code ab oder laden Sie lite-c Datei posteff.c aus dem Dowloadbereich in den Scripteditor.

MATERIAL* mtl_MyMaterial={
 effect="
//Definitionsbereich
 texture TargetMap;
//Sampler
 sampler mySampler = sampler_state{texture=<TargetMap>;};
//Shader
 float4 PP_Shader (float2 Tex: TEXCOORD0):Color0
 {
  float4 Color;
  Color=tex2D(mySampler,Tex.xy);
  return Color;
 }
}
";
}

Was haben Sie nun gemacht?
Zuerst haben Sie mit "texture TargetMap;" eine zu verwendende Textur definiert. Später wird sie von der Engine mit dem Bildschirminhalt, wie einem Schreenshot, belegt werden. (Dieser "Screenshot" ist ein Buffer, der letzte render Target, auf den die sichtbare Szene gerendert wurde.) Dieser soll eben in der Nachbearbeitung (Postprocessing) modifiziert werden. Momentan ist dies die einzige Definition im sog. Definitionsbereich, den man nach Belieben erweitern kann, soweit der eigene Shadercode verlangt. Wohlgemerkt sollte ein guter Shader möglichst wenig Speicherplatz verbrauchen!
Da Sie in diesem Shadereffekt mit Texturen arbeiten, müssen Sie einen texture Sampler definieren, über den Sie den Zugriff und das Lesen der Texturinformationen steuern können. Z.B. kann man festlegen ob eine Textur gekachelt erscheinen soll oder nicht. Dies brauchen wir hier aber nicht zu tun. Insofern beschränkt sich der Sampler nur auf die Zuweisung der zu lesenden Textur (TargetMap), die zuvor von Ihnen definiert wurde.
"sampler mySampler = sampler_state{texture=<TargetMap>;};"
Allgemein gilt: Jede benutzte Variable und Textur muss vor der Verwendung im Shader definiert werden, selbst wenn sie in lite-c vordefiniert ist.
Die Sprache, die wir jetzt für unseren Shader benutzen, heißt HLSL und wurde dafür entwickelt den Grafikprozessor (GPU) der Grafikkarte, genauer gesagt die Direct3D Pipeline, zu programmieren. Es handelt sich dabei um eine Hochsprache, die seit DirectX 8 existiert. Anstelle von komplizierten und fehleranfälligen maschinennahen Assemblercodes, treten bei HLSL gewohnte Elemente von C in den Vordergrund. Zudem fallen einige sinnvolle Vereinfachungen in der Syntax auf, zu denen wir aber später kommen werden.
Jetzt wird es interessant! Die Shaderfunktion wird nach normaler C-Syntax definiert. Sie bestimmt wie Ihr Effekt schlussendlich aussehen wird.
Die Syntax für eine Pixelshadersignatur sieht folgendermaßen aus:

float4 PP_Shader (float2 Tex: TEXCOORD0):Color0

Float4 ist der Datentyp des geforderten Rückgabewertes. Bei einem Pixelshader ist dies logischerweise immer eine Farbe, die Farbe des Pixels auf dem Bildschirm. Und Pixelfarben werden mithilfe von vier Fließkommawerten (floating point values) beschrieben, nämlich Rot, Grün, Blau und Alpha (Transparenz), RGBA. Daher ein solcher Array der Größe 4.
Wie Sie sehen, werden in HLSL Arrays, oder hier auch Vektoren genannt, sehr einfach definiert, einfach die Größenzahl direkt hinter den Typ schreiben.
PP_Shader ist der Name der Shaderfunktion und kann beliebig umgeschrieben werden.
In den Parametern wird "float2 Tex: TEXCOORD0" an die Funtion von jedem Pixel übergeben. Float2 ist wieder ein Fließkommaarray und der Datentyp der Parameter-Variable Tex. Diesmal beinhaltet er aber nur zwei Werte, nämlich die X- und Y-Koordinate des jeweiligen Pixels auf dem Bild(schirm). Damit die Acknex-Engine weiß, dass sie diese Variable mit den Koordinaten zu fühlen hat, weisen Sie als Typ TEXCOORD0 zu. Die 0 am Ende ist sehr wichtig und darf nicht ausgelassen werden. Die Zuweisung erfolgt über den ":" nach dem Namen.
Und schließlich wird am Ende der Definition des Pixelshaders mit ":Color0" angegeben, was er zurückliefert, nämlich eine Farbe, wie Sie sich erinnern im float4 Format. Damit weiß die GPU, was sie mit dem Rückgabewert anfangen soll, nämlich den Pixel auf dem Bildschirm in der neuen Farbe zu zeichnen.

Jetzt geht es ans Eingemachte! Zwischen den beiden geschweiften Klammern steht der entscheidende Shadercode, der mit einer return Anweisung enden muss, weil Sie doch eine Farbe zurückliefern wollen. Sonst käme es zu einer Fehlermeldung, weil die Funktion eine return-Anweisung erwartet!
Zuallererst definieren Sie eine lokale Variable des Types float und nennen Sie z.B. Color. Sie soll im nächsten Schritt die Farbe des zu zeichnenden Pixel erhalten.
In der simplen Zeile "Color=tex2D(mySampler,Tex.xy);" wird nichts anderes gemacht, als der Variable Color die Farbe des Pixels der Bildschirmtextur an der Stelle xy zuzuweisen. Hier sehen Sie eine Besonderheit von HLSL. Denn über ".Komponente1Komponente2" können in einem Befehl beide Koordinaten verwendet werden. Der Befehl Color=tex2D(Sampler,Koordinaten) wird Ihnen noch häufiger begegnen. Tex2D() liest mithilfe des Samplers die Farbe eines Pixels der angegebenen Textur an den Koordinaten ab und gibt sie zurück. Der Shader wird auf jeden Pixel angewendet, sodass die Koordinaten jedes Mal automatisch aktualisiert werden. Später wird dieser Befehl viele interessante Effekte ermöglichen.
Schließlich folgt die abschließende return Anweisung.

Nun ist alles nötige gemacht und Sie können den Shader ausprobieren. Doch halt! Wie soll die Grafikkarte wissen, was sie mit der Funktion anfangen soll? Was jetzt noch fehlt, ist das Herzstück des gesamten Shaders, die Technique: Zuerst definieren Sie eine neue technique namens PP.
Sie kann mehrere Pässe enthalten. In jedem Pass wird der Bildschirminhalt mithilfe des benutzten Pixelshaders gerendert. Für Ihren einfachen Effekt benötigen Sie nur einen: pass p1

technique PP{
 pass p1{
  PixelShader= compile ps_1_0 PP_Shader();
  VertexShader=null;
 }
}

Im Pass wird angegeben welcher Pixelshader ausgeführt werden soll. "compile ps_1_0" vor dem Funktionsaufruf gibt an, dass der Shader für das Shadermodell 1.0 geschrieben ist. Spätere Shadermodelle wie 2.0, 3.0 oder 4.0 ermöglichen mehr Effekte, laufen aber nicht auf älteren Rechnern. Der Shader sollte deswegen stets mit der niedrigst möglichen Version kompiliert werden. Hier reicht Shadermodell 1.0 völlig aus. Weil ein Postprocessingshader nur aus einem Pixelshader besteht, schreiben Sie für VertexShader=null;
übrigens: Wenn Sie einen Shader programmieren, der ein höheres Shadermodell zwingend erfordert, ist es gut wenn möglich eine zweite technique namens fallback zu definieren. Sie sollte eine vereinfachte Version des Shaders enthalten, damit Besitzer älterer Hardware nicht ganz außer Acht gelassen werden. Sie wird ausgeführt, wenn die erste nicht kompiliert werden kann.
Nun ist Ihr erster Postprocessing Shader fertig und muss nur noch zugewiesen werden.

alles wissenswerte dieses Abschnitts:

↑Top | weiter

Sitemap | Kontakt | Impressum

Copyright von kstudios.de © 2007-2017 bei Grygoriy Kulesko

News

28.05.2012
Something,
Something is coming...
#^+o

24.12.2010
Frohe Weihnachten,
Und wieder ist fast ein ganzes Jahr vergangen. Leider gab es 2010 nur wenige Aktualisierungen auf kstudios. Und auch wenn der veröffentlichte erste Prototyp von BlackBox zu den Highlights gehörte, waren viele versprochene Dinge nicht dabei. Wird sich das im nächstes Jahr ändern? Das hoffe ich aber versprechen kann ich nichts. kstudios wird in jedem Fall weitergeführt. Denn diese Seite ist wie ein Teil von mir.
Für alle, die glauben ein Informatik-Studium sei das einfachste, was man studieren kann: Informatik gehörte nicht umsonst ursprünglich ausschließlich zur Mathematik. Aber spannender und weltbezogener ist es allemal.
Was sind meine Vorsätze fürs Neue Jahr? Die Prüfungen zufriedenstellend bestehen, mich mal in Unity 3.1 einzuarbeiten (mal ehrlich, wenn man kostenlos ein derartiges Entwicklungstool hinterher geworfen bekommt, greift man doch zu), an BlackBox weiter zu basteln und mich in den neuen Blender einzuarbeiten. Ich denke das klingt ganz passabel.
Nun denn:
Ein frohes Fest und guten Rutsch ins Neue Jahr wünscht euch kstudios.de!

Neuestes Video


Quick terrain/ Schnelles Terrain Tutorial (no sound) from Grygoriy Kulesko on Vimeo.

Zufallsbild

aus dem Screenshot- und Artworkbereich

Vote

Derzeitig finden keine Votings statt.

Partner

Werden Sie Link-Partner von kstudios.de und an dieser Stelle erscheint ein Link zu Ihrer Website!
Kontakt