Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Shaderprogrammierung T. Goeschel + F. Theilacker 30.1.2008.

Ähnliche Präsentationen


Präsentation zum Thema: "Shaderprogrammierung T. Goeschel + F. Theilacker 30.1.2008."—  Präsentation transkript:

1 Shaderprogrammierung T. Goeschel + F. Theilacker

2 Überblick 1. Grundlagen 2. Die Sprache HLSL 3. Ein Shader-Compiler: fxc 4. Vertexshader 5. Pixelshader 6. Effect-Files

3 Programmierer Compiler CPUGPU delegiert einzelne Aufgaben an C++ HLSL (+Compiler)

4 Grafikkarten ursprünglich nur Pixelarrays, in denen für jeden Pixel Farbwerte abgespeichert wurden Hardware verwandelte die Inhalte dieser Arrays in analoge Signale für den Bildschirm schrittweise Zunahme der Farbtiefe und Auflösung (CGA, EGA,VGA, SVGA) seit 1990 Entwicklung von 3D-Beschleunigern: fähig, Vektordaten entgegenzunehmen und eigenständig zu rendern GPU übernahm rechenintensive Aufgaben von der CPU Entwicklung einer Render-Pipeline: Vektordaten + Transformationsmatrizen + Renderstates werden komplett von GPU verarbeitet

5 Verknüpfung der Entwicklung von Grafikkarten mit DirectX DirectX7:Transformationsmatrizen + Renderstates DirectX8:Pixelshader + Vertexshader DirectX9:Einführung der Hochsprache High Level Shader Language

6

7 Aufbau Vertexshader (vereinfacht) VerticesInput:Vertices 16 Parameter aus je 4 Gleitkommazahlen (Position, Normale, diffuse/spekulare Farbe, Texturkoordinaten) Konstanten:192 Werte aus je 4 Gleitkommazahlen (skalare Werte, Vektoren, Matrizen), vom Anwendungsprogramm gesetzt, Schnittstelle zwischen Programm und Shader Register:Ablegen von Zwischenergebnissen, automatisch verwaltet von HLSL Output:13 Werte aus je 4 Gleitkommazahlen, Ergebnisse wie z. B. geänderte Geometriedaten oder Texturkoordinaten

8 Ablauf Laden der Inputdaten und Konstanten in den Shader Aktivierung des Shaders Verarbeitung jedes einzelnen Vertices, der für das Modell gerendert werden soll Verarbeitung blind and stateless Konstanten während des Laufes nicht veränderbar Fertigstellung wenn alle Vertices im Vertexbuffer abgearbeitet wurden falls weitere Modelle für die Szene zu rendern, gegebenenfalls nächsten Lauf starten (Konstanten können nun geändert oder sogar ein anderes Shaderprogramm gewählt werden)

9 Aufbau Pixelshader (vereinfacht) PixelInput:einzelne Pixel (in einem vorherigen Schritt erzeugt, z. B. durch Vertexshader und anschließende Interpolation) Konstanten:andere Daten als beim Vertexshader, z. B. Farbwerte Texturen: Informationen über die geladenen Texturen Register:Ablegen von Zwischenergebnissen, automatisch verwaltet von HLSL Output:Ergebnisse des Shaders: diffuser und spekularer Farbwert eines Pixels

10 DIE SPRACHE HLSL skalare Datentypen: bool, half, int, float, double ALLE werden als float emuliert (GPU ist Gleitkomma-Rechner!) Deklaration wie in C++ Vektoren: int i; float f; float f = 47.11; vector ; vector meinvektorname; int2 meinintegervektor; float4 meinfloatvektor; float4 position; float4 farbwert; position[0] =...; position.g =...; position.z =...;

11 float4 ~ vector Ansprechen der Felder über meinvektor[0], meinvektor[1], meinvektor[2], meinvektor[3] oder meinvektor.r, meinvektor.g, meinvektor.b, meinvektor.a oder meinvektor.x, meinvektor.y, meinvektor.z, meinvektor.w Ansprechen von Feldern eines Arrays in Gruppen (swizzles); float3 richtung = { 1, 2.3, 4.56}; float4 position; position = float4( 1.1, 2.2, 3.3., 4.4); // per Konstuktor Float4 vier; Float3 drei; vier.xyz = drei; vier.xy = drei.yx; vier.xy = drei.xz; vier.xyz = drei.x;

12 Matrizen: Texturen und Sampler: Arrays: matrix matrix meinematrix float3x2 matrix1; int3x3 matrix2; float4x4 matrix3;// der wichtigste Datentyp wegen Transformationsmatrizen texture2D meinetextur; sampler2D meinsampler;// Sampler fasst eine Textur mit Informationen zu ihrer Verarbeitung zusammen float array[10]; array[3] = 1.234;// analog zu C++

13 Annotationen: Annotationen können für das Anwendungsprogramm Informationen bereithalten auf der Ebene von HLSL sind die Annotationen irrelevant, werden nicht auf Korrektheit überprüft Standard für den Austausch mit einer übergeordneten Applikation: Stichwort SAS in der DirectX-Dokumentation Texture2d meinetextur < string texturname = meinbild.jpg; int hoehe = 256; int breite = 128; float3 colorkey = { 1, 1, 0 }; >;

14 Datenstrukturen: Speicherklassen: Variablen sind innerhalb einer Funktion lokal, außerhalb von Funktionen global. Erlaubt sind aber auch const, extern, static, shared, uniform... Operatoren: siehe DirectX-Hilfe (sehr ähnlich den Operatoren in C, solange Skalarwerte berechnet werden, aber viele Operatoren auch mit Vektoren verwendbar) Kontrollflusssteuerung: - GPU nicht für Fallentscheidungen + Schleifen konzipiert - dennoch möglich (hoher Aufwand!): if... else-Bedingungen, for-Schleifen analog zu C++ struct meine_struktur// analog zu C++ { int zahl; float4 vektor; };

15 Vordefinierte Funktionen umfangreiches Angebot, z. B. -> DirectX-Dokumentation Eigendefinierte Funktionen : GPU auch nicht für Unterprogramme konzipiert, eigendefinierte Funktionen werden schlicht durch Inlining integriert HLSL kennt keine Zeiger, deshalb explizites Festlegen der Parameter, die nur mitgegeben werden und der Parameter, die auch zurückgeliefert werden sollen: in, out, inout x = abs( x);// Absolutbetrag der Zahl x v = cross( v1, v2);// Kreuzprodukt der Vektoren v1 und v2 l = length( v);// Länge des Vektors v void meine_funktion( in float3 pos, out float x, inout int i);

16 Ein- und Ausgabesemantik: - Shader haben Eingabe- und Ausgabeschnittstelle - Eingabeschnittstelle: Shader greift sich die benötigten Daten aus der Renderpipeline - Ausgabeschnittstelle: Shader übergibt fertige Daten zurück in die Pipeline - Herstellung einer Beziehung zwischen Ein- / Ausgabestruktur des Shaders und dem Datenformat der Pipeline per Schlüsselwörtern (semantics) Beispiel: Vertex-Shader will Vertexposition, Vertexnormale und 2-dimensionale Texturkoordinate aus Pipeline entgegennehmen struct VS_INPUT { float4 pos; float3 norm; float2 tex; }; struct VS_INPUT { float4 pos: POSITION; float3 norm: NORMAL; float2 tex: TEXCOORD0; }; Semantics

17 Shader-Hauptprogramm: es gibt immer einen Entrypoint (vergleichbar mit main bei C++, nur dass Name nicht festgelegt -> beim Kompilieren muss Name des Hauptprogramms extra angegeben werden) struct VS_OUTPUT { float4 pos: POSITION; float2 tex: TEXCOORD0; }; VS_OUTPUT vs_main( VS_INPUT inp) { VS_OUTPUT outp; // Output aus dem Input berechnen... return outp; } float4 vs_main( float4 inp : POSITION) : POSITION {...// auch ohne eigene Struktur für Einstiegspunkt möglich! }

18 EIN SHADER-COMPILER: FXC seperates Kompilieren sinnvoll zum Überprüfen auf Syntaxfehler Compiler fxc zur Verfügung im DirectX-SDK Verzeichnis wichtig das Target Profil (/T) und der Entrypoint Name (/E) (Dateiname shader.vsh, Vertexshader-Version 2.0, Entrypoint vs_main) fxc /Tvs_2_0 /Evs_main shader.vsh

19 VERTEXSHADER rasante technische Entwicklung Shaderversion 2.0 -> maximal 256 Instruktionen Shaderversion 3.0 -> maximal Instruktionen Beispiel: Entwicklung eines Vertexshaders, der dynamisch eine Beule an einer Kugel erzeugt und diese um die Kugel herumlaufen lässt Position + Größe der Beule müssen dem Shader dafür vor jedem Renderlauf mitgeteilt werden ohne Vertexshader eine extrem komplexe Aufgabe, für jeden Renderlauf müsste das komplette Modell geändert werden (im Vertexbuffer)

20 Festlegen der Schnittstellen Festlegen der Konstanten: struct VS_INPUT { float4 pos: POSITION; float2 tex: TEXCOORD0;// wird hier einfach nur weitergereicht }; struct VS_OUTPUT { float4 transpos: POSITION; float2 tex: TEXCOORD0; // für nachfolgende Texturierung }; float4x4 vs_transformation;// World-, View- und Projektionstransformation float4 vs_mittelpunkt;// Mittelpunkt der Beule float vs_radius;// Radius der Beule

21 Rahmen für das Shaderprogramm: VS_OUTPUT vs_main (VS_INPUT inp) { VS OUTPUT outp; // hier kommt gleich der Shadercode hin return outp; }

22 Shaderprogramm: Beulentransformation der Vertices VS_OUTPUT vs_main (VS_INPUT inp) { VS OUTPUT outp; float4 dir; float len; outp.transpos = inp.pos; dir = inp.pos - vs_mittelpunkt; len = length(dir); if ((len > 0) && (len < vs_radius)) { dir = normalize( dir); outp.transpos = vs_mittelpunkt + vs_radius * dir; } outp.transpos = mul( outp.transpos, vs_transformation); outp.tex = inp.tex; return outp; }

23 Der passende Anwendungscode: (so könnte ein Test aussehen, ob im Vertexformat des Meshs alle Informationen vorhanden sind, die unser Shaderprogramm erwartet) DWORD fvf; fvf = (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1|D3DFVF_TEXCOORDSIZE2(0)); if(mesh->GetFVF() & fvf != fvf) {... Fehler, der Mesh hat nicht das erwartete FVF }

24 Class shader { private:... LPDIRECT3DVERTEXSHADER9 vertexshader; LPD3DXCONSTANTTABLE vs_konstanten; D3DXHANDLEvs_transformation; D3DXHANDLE vs_mittelpunkt; D3DXHANDLE vs_radius; void create_shader(); public: shader(); ~shader(); void create( LPDIRECT3DDEVICE9 dev); void render( D3DXMATRIX *trans, D3DXVECTOR4 *m, float r); }; create_shader: verbindet unter anderem die drei Handles mit den globalen Variablen im Vertexshader render: erhält bei jedem Aufruf Position und Radius der Beule, damit Beule um die Kugel wandern kann

25 create_shader() void shader::create:shader() { LPD3DXBUFFER code = 0; D3DXCompileShaderFromFile(vs.vsh, 0, 0, vs_main, vs_1_1, 0, &code, 0, &vs_konstanten); device->CreateVertexShader((DWORD*)code->GetBufferPointer(),&vertexshader); code->Release(); vs_transformation = vs_konstanten->GetConstantByName(0, vs_transformation); vs_mittelpunkt = vs_konstanten->GetConstantByName(0, vs_mittelpunkt); vs_radius = vs_konstanten->GetConstantByName(0, vs_radius); }

26 create_shader() void shader::create:shader() { LPD3DXBUFFER code = 0; D3DXCompileShaderFromFile(vs.vsh, 0, 0, vs_main, vs_1_1, 0, &code, 0, &vs_konstanten); device->CreateVertexShader((DWORD*)code->GetBufferPointer(),&vertexshader); code->Release(); vs_transformation = vs_konstanten->GetConstantByName(0, vs_transformation); vs_mittelpunkt = vs_konstanten->GetConstantByName(0, vs_mittelpunkt); vs_radius = vs_konstanten->GetConstantByName(0, vs_radius); }

27 mit diesen Mitteln nun die Renderfunktion: void shader::render(D3DXMATRIX *trans, D3DXVECTOR4 *m, float r) { DWORD i; vs_konstanten->SetMatrix( device, vs_transformation, trans); vs_konstanten->SetVector( device, vs_mittelpunkt, m); vs_konstanten->SetFloat( device, vs_radius, r); device->SetVertexShader( vertexshader); for( i = 0; i < anz_mat; i++) { device->SetMaterial( materialien+i);// Rendern des Meshs device->SetTexture( 0, texturen[i]); mesh->DrawSubset( i); } device->SetVertexShader( 0);// Zurückschalten auf die klassische Renderpipeline }

28


Herunterladen ppt "Shaderprogrammierung T. Goeschel + F. Theilacker 30.1.2008."

Ähnliche Präsentationen


Google-Anzeigen