http://www.haradirki.de

Shader:

Nachdem du dich nun in den verschiedenen Themen mit vorgegebenen Shadern rumschlagen musstest, will ich dir hier erklären, wie man einen Shader schreibt und worauf man zu achten hat.

Shader sind Textdateien, deren Inhalt den Texturen Eigenschaften verleihen können, z.B: metallischen Glanz, Wassereigenschaften, Spielgeeigenschaften oder auch Metal-Sound von sich zu geben, wenn man über sie läuft.

Da Shader Textdateien sind, kann man sie mit jedem beliebigen Textbeartbeitungsprogramm schreiben, z.B. auch NotePad oder WordPad. Um einen Shader zu schreiben, gibt es einige Zeichen, ohne die ein Shader nicht auskommt:

  • die geschwungenen Klammern:{ } Sie markieren den Anfang und das Ende des Shaders, sowie Anfang und Ende einer Schicht (auch Stage genannt)
  • die zwei Slahes: // Sie dienen nur dazu, einen Kommentar in den Textdateien zuzulassen. Alles, was hinter diesen beiden Zeichen bis zum Ende der Zeile steht, wird von der Engine nichtmehr zum Shader gerechnet.
  • Du solltest beachten, dass du im Shader auf Grossschreibung und Umlaute verzichtest.

Wie du schon weisst, müssen Shader in die Shaderlist.txt eingetragen werden, damit sie funktionieren. Dazu öffnest du jetzt die Datei Shaderlist.txt und schreibst dort in eine neue Zeile "erstershader":

Nun öffnest du dein Textprogramm und schreibst hinein:

// mein erster Shader
textures/shader1/textur
{

{
map textures/shader1/textur.tga
}

}

Dies ist der warscheinlich einfachste Shader überhaupt - denn er verändert die Textur selbst garnicht. Doch für unsere Zwecke reicht er völlig aus. Kommen wir nun zur Erklärung des Shaders:

// mein erster Shader Ist lediglich ein Kommentar, er dient nur zur Erklärung oder dazu, bestimmte Teile des Shaders zu testzwecken abzuschalten.
textures/shader1/textur Name des Shaders - damit legst du fest, wo du später die Textur finden kannst.
{ Beginn des Shaders

{

Hier beginnt die erste Schicht

map textures/shader1/textur.tga

Mit dieser Anweisung (map <Pfad zur Textur> ) gibt man der Engine die Anweisung, die Oberfläche der Textur mit der angegebenen Textur zu belegen.

}

Hier endet die erste Schicht
} Hier endet der Shader

Nun speicherst du diese Datei im Ordner "Main/scripts" unter dem Namen "erstershader.shader" ab.

Erstellst du nun einen Ordner namens "shader1" im Textures-Ordner und kopierst dort eine beliebige Textur namens "textur" hinein, läuft der Shader.

Nun wagen wir uns an einen neuen Shader, der diesmal etwas anspruchsvoller wird. Wir wollen einen Shader haben, der aus 2 Texturen besteht. Diese beiden Texturen findest du hier. Nun gucken wir sie uns gleichmal an:

die beiden Texturen

Diese beiden Texturen sollen dargestellt werden. Du kannst natürlich auch beide Texturen durch andere ersetzen. Bei uns soll folgender Effekt entstehen: Logo1.tga UND Logo2.tga sollen gleichzeitig dargestellt werden. Dazu benutzen wir einfach den folgenden Shader:

textures/meinshader/logo2
{

{
map textures/meinshader/logo1.tga
}

{
map textures/meinshader/logo2.tga
blendfunc add
}

{
map $lightmap
blendfunc filter
}

}

Nun erkläre ich dir erstmal, was es mit den neuen Befehlen auf sich hat:

 

textures/meinshader/logo2 Name des Shaders - damit legst du fest, wo du später die Textur finden kannst.
{ Beginn des Shaders
   

{

Beginn der ersten Stage

map textures/meinshader/logo1.tga

Der Pfad zur Textur, die in der ersten Stage dargestellt wird.

}

Ende der ersten Stage
   

{

Beginn der zweiten Stage

map textures/meinshader/logo2.tga

Der Pfad zur zweiten Textur, die in der zweiten Stage dargestellt wird.

blendfunc add

Dieser Parameter gibt an, dass die beiden Texturen additiv (also übereinander) dargestellt werden.

}

Ende der zweiten Stage
   

{

Anfang der dritten Stage

map $lightmap

Gibt an, dass die normale Textur (logo1.tga) als Lightmap verwendet wird.

blendfunc filter

Gibt an, wie die Lightmap überblendet wird.

}

Ende der dritten Stage
   
} Ende des Shaders

So, jetzt sind wir ja schon ziemlich weit - einen Shader mit 3 Stages ist schon ziemlich schwer zu verstehen. Nun toppen wir das ganze, in dem wir das Logo nun noch blinkend dargestellt haben wollen. Dazu kommt lediglich zwei Zeilen im Shader dazu - zum Schluss sieht der Shader so aus:

textures/meinshader/logo1
{
qer_editorimage textures/meinshader/logo2.tga

{
map textures/meinshader/logo1.tga
}

{
map textures/meinshader/logo2.tga
rgbGen wave square 0.5 0.5 0 1.1
blendfunc add
}

{
map $lightmap
blendfunc filter
}

}

Nun erkläre ich dir auch gleich, was die beiden neuen Zeilen bedeuten:

textures/meinshader/logo1 Name des Shaders - damit legst du fest, wo du später die Textur finden kannst.
{ Anfang des Shaders
qer_editorimage textures/meinshader/logo2.tga Gibt an, welches Bild der Shader im Radiant hat (vergibst du diesen nicht, so erscheint "Shader Image Missing")
   

{

Anfang der ersten Stage

map textures/meinshader/logo1.tga

Der Pfad zur Textur, die in der ersten Stage dargestellt wird.

}

Ende der ersten Stage
   

{

Beginn der zweiten Stage

map textures/meinshader/logo2.tga

Der Pfad zur zweiten Textur, die in der zweiten Stage dargestellt wird.

rgbGen wave square 0.5 0.5 0 1.1

generiert die Vertexfarbe. Darauf gehe ich gleich näher ein. Der Syntax "wave" generiert den "Blinkabstand" der Textur.

blendfunc add

Dieser Parameter gibt an, dass die beiden Texturen additiv (also übereinander) dargestellt werden.

}

Ende der zweiten Stage
   

{

Anfang der dritten Stage

map $lightmap

Gibt an, dass die normale Textur (logo1.tga) als Lightmap verwendet wird.

blendfunc filter

Gibt an, wie die Lightmap überblendet wird.

}

Ende der dritten Stage
   

}

Ende des Shaders

 

Nun gehe ich etwas näher auf folgenden Teil im Shader ein:

rgbGen wave square 0.5 0.5 0 1.1

rgbGen generiert ja die Vertex-Farbe. Diese wird mit der Farbe der Textur multipliziert um dann die entgültige Farbe zu erhalten. Normal ist die Vertexfarbe weiss, d.h. die Farbe ändert sich nicht ( [Texturfarbe] * 1 1 1). Mit dem Syntax "wave" wird die Engine dazu veranlasst, diese Farbe zu wechseln, d.h. man erzeugt blinkende Effekte. Die komplette Reihenfolge des Befehls lautet so:

rgbGen wave <func> <base> <amp> <phase> <freq>

<func>
gibt an, in welcher Weisse sich die Vertexfarbe ändern soll - es gibt 5 Parameter für diese Änderung:

  • sin (gleichmässige Ab- und Aufwärtsbewegung, entspricht genau der Sinuswelle)
  • triangle (Dreiecksbewegung, d.h.Gradliniger Auf- und Abbau der Werte)
  • square (Wechsel zwischen zwei Werten, also z.B. an und aus.
  • sawtooth (geradliniger Aufbau, radikaler Abfall der Kurve)
  • invertedsawthooth (radikaler Aufbau, geradliniger Abbau, Umgekehrte Sawtooth-Funktion)

<base>
gibt den Basiswert an, auf den sich später der <amp>-Wert bezieht bezieht.

<amp>
gibt den maximalen Ausschlag der Kurve in Bezug auf den Basis-Wert (<base>) an.

<phase>
Hier mit kann man eine zeitliche Verzerrung der Kurve erziehlen, damit z.B.nicht alle Shader in der gleichen Abfolge blinken. Meistens wird <phase> allerdings auf den Wert 0 gesetzt.

<freq>
steht sinnigerweisse für "Frequenz", also wie oft eine Kurve innerhalb einer Sekunde wiederholt wird. Der Wert 2 veranlasst den Shader dazu, die Kurve innerhalb einer Sekunde 2mal zu wiederholen. Der Wert 0.5 veranlasst den Shader dazu, die Kurve nur alle 2 Sekunden zu wiederholen.

Bei unserem Shader wechselt also die Vertexfarbe immer zwischen den Werten 1 1 1 und 0 0 0, d.h. das Logo wird angezeigt, wenn der Wert auf 1 1 1 steht. Wechselt der Wert auf 0 0 0, verschwindet das Logo.
.
Alpha-Texturen:

Wie du bei dem Logo gesehen hast, wird nur der "haradirki"-Schriftzug gargestellt, der Rest wird von der Engine abgeschnitten, d.h. er wird nicht dargestellt. Nun zeige ich dir, wie man eine solche Alphashader selbst hinbekommt. Zuerst erstellst du ganz normal deine Textur.

der Alphakanal der Datei  logo2.tga

Hier kannst du die Textur "logo2.tga" und deren Alpha-Channel sehen. Zwar kann man hier nicht genau den Unterschied zur richtigen Textur erkennen - doch sind die drei Innenräume von den Buchstaben "a" und "d" komplett weiss - was daraufhin deutet, dass dieser Innenraum auch von der Engine dargestellt werden soll.

Nun kommen wir aber zum Shader:

textures/meinshader/logo2
{

{
map textures/meinshader/logo2.tga
alphaFunc GT0
}

}

Nun folgt auch gleich die Erklärung zum Shader:

textures/meinshader/logo2 Name des Shaders - damit legst du fest, wo du später die Textur finden kannst.
{ Anfang des Shaders
   

{

Anfang der ersten Stage

map textures/meinshader/logo2.tga

Der Pfad zur Textur, die in der ersten Stage dargestellt wird.

alphaFunc GT0

Durch diesen Parameter zeichnet die Engine nur die Bereiche der Textur, die im Alphakanal einen höheren Wert als 0 0 0 haben (die nicht schwarz sind)

}

Ende der ersten Stage
   
} Ende des Shaders

Nun erkläre ich dir diese Zeile noch etwas genauer:

alphaFunc <syn>

Folgende Syntaxe sind hier möglich:

  • GT0 "GREATER THAN 0" (diesen Syntax haben wir in unserem Beispiel verwendet)
  • LT128 "LESS THAN 128"
  • GE128 "GREATER THAN OR EQUAL TO 128"

ACHTUNG: Hierbei sind nur die Farbwerte von 0 - 255 zulässig, nicht die gesamte 16- oder gar die 32-Bit-Palette

Unser Alpha-Kanal besteht nur aus Pixeln, die auf 0 0 0 stehen (die schwarz sind) und aus Pixeln, die auf 1 1 1 stehen (die weiss sind), d.h. das weisse wird dargestellt, das schwarze nicht.

Shader sind, wie du siehst, eine recht schwierige Angelegenheit. Jedoch lassen sich damit wirklich tolle Effekte erzielen, die jede Map enorm aufwerten. Du solltest dich hier mit dem Thema etwas genauer beschäftigen und erstmal vorhandene Shader modifizieren. Später kannst du dann versuchen, einen eigenen Shader zu schreiben.

Jedoch darfst du nie vergessen, deinen Shader in die Shaderlist.txt einzutragen - da sonst der Shader nicht geladen wird. Das kannst du leicht erkennen, da dann die Textur nicht weiss umrandet ist.


zurück zur Hauptseite