Pixel- und Vertex-Shader

Programmierbare Shader geben der Spielegrafik eine neue Dimension. Sie ermöglichen es, Transformation, Beleuchtung und das Rendern während der Laufzeit auf Vertex- und Pixel-Ebene zu beeinflussen. Ein Shader ist ein kleines Programm, das für jeden Vertex und jeden, auf dem Bildschirm gerenderden Pixel ausgeführt wird. Es kann Position, Farbe und Normale eines Vertex oder die Texturkoordinaten ebenso steuern wie Pxelfarbe und Helligkeit. Dies geschieht in Abhängigkeit vom Einfluss des Lichtes, der Texturen oder willkürlicher C-Skript-Variblen. Dadurch erhält der Entwickler ein neues Mass an Flexibilität über die Weise in welcher Pixel gerendert werden. Mit Vertex- und Pixel-Schader lassen sich realistische Kräuselungen auf Wasser erstellen, dem Spiel ein Cartoon-Look geben, Modelle mit Fell überziehen oder der Lavafluss eines Vulkans steuern (Screenshots von GameStudio-Usern auf dem Gamestudio Shader-Forum):

 
Normalmapping-Shader
Fell-Shader

Shader gibt es in zwei Varianten: Vertex-Shader beeinflussen Mesh-Positionenvertices, Pixel-Shader beeinflussen Texturpixel. Der Shadercode wird in den Speicher der Grafikkarte geladen und direkt in die Grafikverbindung eingespeist. Shadercode ist in Assembly, heutzutage wird allerdings eine höhere Sprache vom Typ `C´, nämlich HLSL (auch bekannt unter Cg) verwendet und dann auf Assembly herunterkompiliert, was das Programmieren von Shadern erheblich vereinfacht.

Eine Shader-Beschreibung enthält Variablen-Deklarationen und Shader-Anweisungen. Pixel- und Vertex-Shader können als Teil eines Material-Effekt-Skripts definiert werden, indem die Schlüsselwörter VertexShader oder PixelShader verwendet werden.

Beispiel eines Vertex-Shaders:

float4x4 matWorldViewProj : WORLDVIEWPROJ;
float4 vecTime;


void vs_flicker_red(
   in float4 iPos : POSITION,
   in float2 iTex0 : TEXCOORD0,
   in float2 iTex1 : TEXCOORD1,
   out float4 oPos : POSITION,
   out float4 oDiffuse: COLOR0,
   out float2 oTex0 : TEXCOORD0,
   out float2 oTex1 : TEXCOORD1)
   {
     oPos = mul(iPos,matWorldViewProj);
     oTex0 = iTex0;
     oTex1 = iTex1;
     oDiffuse.r = fmod(vecTime.w * 0.1,1.0);
     oDiffuse.g = 0.0;
     oDiffuse.b = 0.0;
     oDiffuse.a = 1.0;
   }


technique flicker
{
   pass p0
   {
     VertexShader = compile vs_1_1 vs_flicker_red();
     PixelShader = NULL;
   }
}

Shader-Programmierung ist nicht gerade einfach und erfordert einige Kenntnisse in Vektor- und Matrix-Algebra. Sobald ein Shader aber sauber programmiert ist, kann ihn jeder benutzen, ohne seine interne Funktionsweise zu kennen. Eine gute Einführung ins Schreiben von Shadern für Gamestudio ist die Einführung zum Shader-Programmieren (Introduction to Shader Programming, s. u.). Die DirectX9-Dokumentation enthält Beschreibung der Shadersprache. Es gibt auch einige Bücher übers Shader-Programmieren. Ein Beispiel für's Schreiben von wiederverwendbaren Shadern finden Sie in der mtlFX-Shaderbibliothek im Ordner template6\code.

Empfohlene Tutorials und Bücher:

Hier einige Grundinformationen fürs Programmieren von Shadern:

Vertex Format

Alle Geometrie- und Modell-Vertices verwenden drei UV-Koordinatensätze für Textur, lightmap/detailmap und Shadertangenten im folgenden Format:
typedef struct VERTEX_TLSHADED {
   D3DXVECTOR3 v;
   D3DXVECTOR3 n;
   float tu1,tv1; // coordinate set 1, for texture or shadow map
   float tu2,tv2; // coordinate set 2, for texture or detail map
   float tx3,ty3,tz3,tw3; // coordinate set 3, for tangent or other purposes (A7.05 and above only!)
} VERTEX_TLSHADED;

#define D3DFVF_TLSHADED (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX3|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE4(2))

Bitte beachten Sie, daß die Koordinate tw3, welche die Ausrichtung der binormalen enthält, nur in A7.05 und höher zur Verfügung steht. A6 bis A7.4 hatten beim dritten UV-Koordinaten-Set nur 3 Werte.

Die default.fx-Shader-Funktionskollektion

Die gebräuchlichsten Shader-Funktionen finden sich in der Datei template_6\code\default.fx und lassen sich einfach in jedweden verwendeten Shader einfügen. Dadurch wird der Shader-Code nicht nur um einiges kürzer, es werden auch Fehler vermieden und Anpassungen ermöglicht, die sich automatisch auf alle Shader auswirken. Die Shader, die in Gamestudio enthalten sind verwenden sämtlich Funktionen aus der default.fx-Datei und Sie sollten es sich zur Gewohnheit machen, solche Funktionen auch für Ihre Shader zu benutzen. default.fx beinhaltet die folgenden Funktionen:

float4 DoTransform(float4 Pos);  // vertex transformation to projection space - required for every shader
float4 DoPos(float4 Pos);		  // vertex transformation to world space
float4 DoView(float4 Pos);      // vertex transformation to view space
float4 DoNormal(float4 N);      // normal transformation to world space
float DoFog(float4 Pos);        // calculates the fog at position Pos
float4 DoSunLight(float3 N);    // calculates the sun light reflected by a surface with normal N
float4 DoPointLight(float3 P, float3 N, float4 vLightPos, float4 vLightColor); 
// calculates the dynamic light from the given light source position and color
// reflected by a surface with normal N at position P. Used to sum up dynamic lights at a certain position.
void CreateTangents(float3 inNormal,float3 inTangent);
// calculates matTangent, the tangent - binormal - normal matrix. Used for all further tangent space transformations.
float3 DoTangent(float3 Vector);	// transforms the vector to tangent space

Der Gebrauch von default.fx ist in der mtlFX-Shader library nachzusehen.

DX8 Shader Migration

DX8 Vertex Shaders benötigen eine kleine Modifikation, um unter DirectX 9 zu laufen. Die folgende Anweisung:
decl
{
   stream 0;
   float v0[3]; //position
   float v3[3]; //normal
   float v7[3]; //uv 1
   float v8[3]; //uv 2
}

muss der DX9 Deklaration weichen:

dcl_position v0
dcl_normal v3
dcl_texcoord0 v7
dcl_texcoord1 v8

Edition

 C   P 

Siehe auch:

Material, Material-Shader, Shader-predefined variables

.

 

► Aktuelle Version Online