Einführung
Home Nach oben

 

Nach oben
Dungeons
Detailmap
Einführung
Multitexture Terrain
Plantbox
Aussenlevel (Block)
Tag & Nachtwechsel
KI
Waving Grass
Framerate

Shader Einführung

In nachfolgendem Tutorial sollen die Grundzüge der Verwendung von Vertex- und Pixelshader in 3dGamestudio dargestellt werden. Das Tutorial beginnt hier komplett bei den Anfängen und 

 

Einfaches Shaderbeispiel (Setze neue Textur)

Download des 3dGS Projektes

Im ersten  Beispiel soll die Textur eines Modells mit Hilfe der Shader modifiziert werden. Es wird die vorhandene Textur durch eine neue ausgetauscht.

Dies ist sicherlich keine sinnvolle Anwendung stellt aber die notwendigen Grundlagen und Strukturen dar die innerhalb der Effektdatei und der Materialdefinition in 3dGS notwendig sind.

Das Beispielprojekt enthält ein Blockmodell mit einer grauen Textur. Die Modelle müssen texturiert sein damit die Textureigenschaften geändert werden können.

Bild1: Level mit Block

Um die Textureigenschaften eines Modelles verändern zu können muss in C-Script ein Material definiert werden. Innerhalb dieser Struktur werden die Textureigenschaften zusammengefasst und beschrieben. Die verwendeten Texturen müssen in der C-Script Struktur Bitmap vorgeladen werden.

 

1. Verwendete Texturen anmelden


Source

bmap tex1 = <stone.bmp>;      // Hier wird die Textur zur Verwendung geladen

material tut1 {
    skin1 = tex1;                          // Um die Textur später verwenden zu können muss Sie dem Material
                                                    // bekannt gemacht werden.

    ...

}

Texturen müssen im Material mit den Variablen skin1, skin2, skin3 ... definiert werden. Sind Sie angemeldet können Sie später in der Effektbeschreibung der Shader verwendet werden. Die hier angemeldeten Texturen sind Material-Texturen und können dann über die Variablen mtlSkin1 für die Textur unter skin1, mtlSkin2 für die Textur unter skin2 ... verwendet werden.

Enthält ein Modell bereits Texturen können Sie über das Schlüsselwort entSkin1, entSkin2 ... verwendet werden.

2. Texturen in der Effektbeschreibung vorbelegen

Innerhalb des Materials wird über eine Effektdatei festgelegt auf welche Art und Weise die Textur auf dem Modell erscheint. Die Effektdatei folgt hierbei der festgelegten Notation von DirectX. Eine Beschreibung der Effektsprache ist unter msdn auf der Microsoftseite zu finden.

Leider handelt es sich hierbei ausschließlich um technische Dokumentationen die relativ wenig praktische Hinweise enthalten. Es fehlt ebenso der Bezug der Parameter auf Ihre Auswirkung im Programm.

Source:

material tut1 {
    skin1 = tex1;                          

    effect
    "
        texture mtlSkin1;                      // Deklaration der Texture (mtlSkin1 = erste Textur des Materials)
       
float4x4 matWorldViewProj;   // Diese Struktur wird später für die Koordinatenumwandlung
                                                           // im Vertexshader benötigt

        sampler sTex1 = sampler_state // level texture
        {
            Texture = <mtlSkin1>;         // Die erste Materialtextur wird in diesem Sampler verwendet
            MipFilter = Linear;               // Ist in dem Modell eine Textur enthalten kann diese mit
            MinFilter = Linear;               // <entSkin1> verwendet werden
            MagFilter = Linear;              
            AddressU = Wrap; 
            AddressV = Wrap;
        };

        ...                                    // Hier steht die Beschreibung des Effektes 

    ";

}

Jetzt ist die Textur für die Verwendung innerhalb der Effektdefinition und der Shader angemeldet und verfügbar.

3. Eingabe und Ausgabestrukturen für die Shader festlegen

Bevor die Shader geschrieben werden sind noch die Eingabe- und Ausgabestrukturen zu bestimmen. Sowohl der Vertex- als auch der Pixelshader erhalten eine Eingabe- und Ausgabestruktur in der die benötigten Inputvariablen und die Ausgabe des Shaders definiert werden.

Der Vertexshader erhält die Vertexposition und die Texturkoordinaten

struct VS_IN
{
    float4 Pos      : POSITION;            // Position des Vertex
    float2 Tex1     : TEXCOORD0;     // Texturkoordinate der Textur im ersten Sampler
};

bei mehreren Samplern zum überblenden von mehreren Texturen wird TEXCOORD1, TEXCOORD2 ... verwendet.

Die Rückgabe enthält die Vertexposition (evtl. geändert) und die Texturkoordinaten (evtl. geändert)

struct VS_OUT
{
    float4 Pos      : POSITION;
    float2 Tex1     : TEXCOORD0;
};

Der Pixelshader erhält die Texturkoordinaten

struct PS_IN
{
    float2 Tex1     : TEXCOORD0;
};

Der Pixelshader liefert die Farbe des Pixels zurück

struct PS_OUT
{
    float4 Color     : COLOR; 
};

4. Der Vertexshader

Nachfolgender Source zeigt den Vertexshader, der zur Darstellung unserer Textur auf dem Modell benötigt wird. Er berechnet die richtigen Darstellungskoordinaten und gibt die Texturkoordinaten unverändert zurück.

VS_OUT vs( VS_IN In )
{
    VS_OUT Out = ( VS_OUT ) 0; 
    
    Out.Pos = mul( In.Pos, matWorldViewProj );         // Umrechnung des Vertex in die richtigen
                                                                                        // Darstellungskoordinaten

    Out.Tex1 = In.Tex1;                                                   // Verwendung der ungeänderten Textur-
    return Out;                                                                  // Koordinaten ==> Tile = 1
}

 

5. Der Pixelshader

Im Pixelshader werden jetzt die Farbwerte für die Bildschirmposition ermittelt festgelegt und zurückgeliefert. Hierzu kann auf die in den Samplern definierten Texturen zugegriffen werden und die vorhandenen Bildpunkte beliebig verknüpft werden.

PS_OUT ps( PS_IN In )
{
    PS_OUT Out = ( PS_OUT ) 0; 

    float4 color; 

    color = tex2D( sTex1, In.Tex1.xy );   // Hole die Bildinformation aus der ersten Textur an der im Vertex-
                                                                 // shader festgelegten Texturposition
    Out.Color = color; 

    return Out; 
}

6. Texture Tiles

Bei grossen Modellen soll eine Textur mit mehreren Tiles verwendet werden. Dies wird durch eine Veränderung der Texturkoordinaten im Vertexshader erreicht.

VS_OUT vs( VS_IN In )
{
    VS_OUT Out = ( VS_OUT ) 0; 
    
    Out.Pos = mul( In.Pos, matWorldViewProj );         
                                                                                        
    Out.Tex1 = In.Tex1.xy * 3;          // Multiplikation mit dem Tilefaktor hier 3                                                   
    return Out;                                                                  
}

Bild2: Block mit neuer Textur über Shader 

Bild3: Block mit neuer Textur und Tilefaktor 3

7. Shader anwenden

Um die Shader anwenden zu können muss in der Effektdatei noch eine Schleife technique eingetragen werden. Eine Effektdatei kann mehrere technique definitionen enthalten. Dies kann notwendig werden um auch ältere Grafikkarten zu unterstützen.

Da sich die Definition der Shadersprache erheblich ändert sind nicht alle Befehle auf alten Grafikkarten vorhanden. Daher können mehrer Implementierungen programmiert werden. Kann die erste nicht angewendet werden wird automatisch auf die zweite zurückgegriffen.

Innerhalb einer technique Definition können jetzt noch mehrer Durchläufe definiert werden. In unserem Beispiel kann das Ergebniss mit nur einem Durchlauf erreicht werden.

 

technique mytechnique
{
    pass p0
    {
        VertexShader = compile vs_1_1 vs();  // Anmeldung der Funktion vs als VertexShader
        PixelShader = compile ps_1_1 ps();    // Anmeldung der Funktion ps als Pixelshader
    }
}

 

Anmeldung der Shader unter der Shaderversion 2.0:

        VertexShader = compile vs_2_0 vs();  // Anmeldung der Funktion vs als VertexShader
        PixelShader = compile ps_2_0 ps();    // Anmeldung der Funktion ps als Pixelshader

Bei der Anmeldung einer Funktion als Vertex oder Pixelshader muss noch die aktuelle Version mitgegeben werden (z.B. vs_1_1 und ps_1_1). Hierdurch wird definiert welche Version die Grafikkarte unterstützt. Es stehen auch unterschiedliche Befehlssätze und Möglichkeiten zur Verfügung.

So kann z.B. eine alte Grafikkarte mit Shaderversion 1 nur maximal 4 Texturen in einem Durchgang überblenden, während eine moderne Grafikkarte mit Version 3.0 bis zu 16 Texturen in einem Durchgang verarbeiten kann.

 

8. Material dem Modell zuweisen

Als letzte Aktion muss jetzt das neu definierte Material mit dem Modell verbunden werden. Dazu wird in der Aktionsdefinition die dem Modell zugewiesen wird die Variable material mit dem Namen des neu definierten Materials gesetzt.

ACTION sh_tut_001 {
    my.material=tut1 ;            // Setzte die Materialdefinition als aktiv für das Modell
}