HLSL High-Level Shader Language

Ähnliche Dokumente
(7) Normal Mapping. Vorlesung Computergraphik II S. Müller. Dank an Stefan Rilling U N I V E R S I T Ä T KOBLENZ LANDAU

Softwareprojekt Spieleentwicklung

Seminar Game Development Game Computer Graphics. Einleitung

Wima-Praktikum 2: Bildsynthese-Phong

Lokale Beleuchtungsmodelle

Probelektion zum Thema. Shadow Rendering. Shadow Maps Shadow Filtering

Real-Time High-Dynamic Range Texture Mapping

4.3 Beleuchtung und Schattierung

"rendern" = ein abstraktes geometrisches Modell sichtbar machen

Heute. Motivation. Verfügbarkeit. Programmierbare Hardware-Shader. Technische Entwicklung von Grafikhardware. Grafikpipeline (DirectX9)

Überblick Echtzeit-Rendering. Uwe Domaratius

Workshop: Einführung in die 3D-Computergrafik. Julia Tolksdorf Thies Pfeiffer Christian Fröhlich Nikita Mattar

Thema: Hardware-Shader

RTT DeltaGen Suite. Materialeinstellungen für OpenGL, RTT RealTrace & Global illumination. Copyright 2010 by Realtime Technology AG

Jörn Loviscach Hochschule Bremen

Computergrafik 2010 Oliver Vornberger. Kapitel 18: Beleuchtung

Rendering: Lighting & Shading

Rendering Grundlagen Autodesk Maya. Grundlagen. Version Ingo Clemens brave rabbit

Modellierung von Reflexionseigenschaften verschiedener Stoffe für interaktives Echtzeit-Rendering

Computergraphik Grundlagen

Proseminar Computergraphik. Raytracing

Inhaltsverzeichnis. V Vorwort 17. V.1 An wen richtet sich dieses Buch? 18. V.2 Ansprüche an den Computer 18. V.4 Bildergalerie 19.

1. Sichtbarkeitsproblem beim Rendern einer dreidimensionalen Szene auf einer zweidimensionalen

Das Skalarprodukt zweier Vektoren

OpenGL. (Open Graphic Library)

Graphische Datenverarbeitung und Bildverarbeitung

Programmierpraktikum 3D Computer Grafik

Games Engines. Realtime Terrain Rendering

Asteroids3D Seminar: Game Programming. Anita Dieckhoff, Pedro Flemming, Jan Ole Vollmer Betreuung: Christine Lehmann

Zwischenvortrag zum Entwicklungsstand der Bachelor-Arbeit. Direct 3D-Output für ein Rendering Framework

Raytracing. Schlussbericht. Jonas Lauener 1995, Áedán Christie 1997 Melvin Ott 1997, Timon Stampfli 1997

Seminar: Programmierung von Grafikkarten (SS 2006)

Globale Beleuchtung. Thorsten Grosch. Thorsten Grosch Seit September 2009 Juniorprofessor für CV in Magdeburg

Analytische Geometrie I

OpenGL als API für Augmented und Virtual Reality

Analytische Geometrie II

Praktikum: Spieleengine im Eigenbau

RENDERING. Cobalt Xenon Argon. mit Ashlar-Vellum.

Grundlagen der Spieleprogrammierung

1 Fraktale Eigenschaften der Koch-Kurve

Linear Workflow. Linear Workflow. Version

Der Einsatz von HDRIs in LightWave 7

Analytische Geometrie Seite 1 von 6. Die Addition von Vektoren kann veranschaulicht werden durch das Aneinanderhängen von Pfeilen.

3.3 Beleuchtung und Schattierung

Parallele und funktionale Programmierung Wintersemester 2013/ Übung Abgabe bis , 16:00 Uhr

Übung Elementarmathematik im WS 2012/13. Lösung zum Klausurvorbereitung IV

3D-Transformationen. Kapitel Translation Skalierung

Rechnen mit Vektoren. 1. Vektoren im Koordinatensystem Freie Vektoren in der Ebene

Mathematik Analytische Geometrie

computer graphics & visualization

Praktikum im Bereich Praktische Informatik Echtzeitgraphik in C++ und DirectX10. computer graphics & visualization

Non-Photorealistic Rendering

Proseminar Computergraphik. 3D - Modellierung

D-Texturen. Reflectance Mapping 3D-Texturen. Farbtexturen

Christina Nell 3D-Computergrafik Seminararbeit im Hauptseminar Grafikprogrammierung. Universität Ulm Sommersemester 2008

y x x y ( 2x 3y + z x + z

Entwicklung von Environment-Shadern in Cg und CgFX unter Berücksichtigung des Workflows zur Erstellung virtueller Szenenbilder im WDR Köln

Computer-Graphik I Transformationen & Viewing

2 Geradengleichungen in Parameterform. Länge und Skalarprodukt

Färben, texturieren und rendern in Solid Edge

Seminar: Grafikprogrammierung

Prüfungsteil 2, Aufgabe 4 Analytische Geometrie

Programmieren mit DirectX

EPA-Präsentation Tim Keller

Licht und Schatten Visualieren mit dem PC. Andreas Asperl

Analytische Geometrie - Schnittwinkel. u 1, u 2 Richtungsvektoren der Geraden

Materialien zur Visualisierung 2002/03 Die Meisterschaft des 1. FC Holzbein eine Einführung in die Vektorrechnung

Markus' Formelsammlung für die Vektorgeometrie

00. Einiges zum Vektorraum R n

MF Breadcrumbs. Sergej Schefer & Fabian Marx

Vektoren - Basiswechsel

3D-Computergrafik und animation. Shading und globale Beleuchtungsverfahren, Animationstechniken

Geometrie. Bei der Addition von Vektoren erhält man einen Repräsentanten des Summenvektors +, indem man die Repräsentanten von aneinanderfügt:

Das lineare Gleichungssystem

Grundlegende Algorithmen

C# Programm: Raytracer (3D Renderer)

DirectX und OpenGL. Proseminar Multimedia-Hardwareerweiterungen Michel Weimerskirch, 15. Februar 2006

Farbtiefe. Gängige Farbtiefen

Computer-Graphik 1 Lighting & Shading

Texture Based Direct Volume Rendering

& sind die Vektorkomponenten von und sind die Vektorkoordinaten von. A x. a) Der Betrag eines Vektors

4. Kapitel 3D Engine Geometry

Transformationen im 3D-Raum

Seminar - Paralleles Rechnen auf Grafikkarten

Einführung in GLSL - OpenGL Shading Language. Athanasios Karamalis

Skalarprodukt. Anwendung auf die Berechnung von einfachen Abständen und Winkeln sowie Normalenvektor. Ganz einfache Erklärung der Grundlagen:

Formelsammlung Mathematik Grundkurs Inhalt

Terrain Rendering v 1.0

Vektorgeometrie. Inhaltsverzeichnis. Fragen und Antworten. (bitte nur für den Eigengebrauch verwenden)

Shadow Volumes für animierte 3DCharaktere auf der GPU

Java 3D. Linien, Flächen und Objekte Axel Bartsch, Okt. 2002

(x 1. Vektoren. g: x = p + r u. p r (u1. x 2. u 2. p 2

Eine Einführung in die Architektur moderner Graphikprozessoren

Transkript:

HLSL Einführung 1 HLSL High-Level Shader Language High-Level Shader Language ist eine relativ neue Programmiersprache für die Graphic Processing Unit (GPU). Mit HLSL ist das Programmieren von Shadern mit DirectX 9 um einiges einfacher geworden. Anders als in Assembler kann der Code nun in vertrauter C-Syntax geschrieben werden, der dann von D3DX, einer Hilfsbibliothek von DirectX, in die Maschinensprache übersetzt wird. Einordnung in der Direct3D Render-Pipeline Wie man in der nachfolgenden Darstellung gut erkennen kann, bilden Vertex- und Pixel-Shader eine Art alternativen Weg für die Vertices / Pixel. Dadurch hat der Programmierer totale Kontrolle über die Transformation und Beleuchtung der Vertices. Es ist sogar möglich, jeden einzelnen Pixel individuell zu gestalten. Abb. 1: Render-Pipeline

HLSL Einführung 2 Vertex-Shader Der Vertex-Shader liest Vertexdaten (lokaler Positionsvektor, Normalenvektor, ) aus den gefüllten Registern und transformiert diese. Ein Positionsvektor (meistens der projizierte Vertex) muss immer zurückgegeben werden. Es ist nicht möglich, einen Vertex zu entfernen oder hinzuzufügen. Wie man oben in der Darstellung erkennen kann, hat der Vertex-Shadern keinen Einfluss auf die nachfolgenden (Pixel-)Operationen. Die Tesselierungseinheiten werden dem Vertex-Shader mittels Vertex-Deklaration mitgeteilt respektive in ein Shader-Register geschrieben. Der Vertex- bzw. Pixel-Shader öffnet dann einfach diese Register und liest die benötigten Daten heraus. Die folgende Deklaration sorgt dafür, dass der Vertex-Shader den Positions- und Normalenvektor (in Object-Space) aller Vertices, die die Direct3D- Pipeline durchwandern, bekommt. IDirect3DVertexDeclaration9* g_lpvertexdecl; D3DVERTEXELEMENT9 VertexDeclElem[] = // Stream, Offset, Type, Method, Usage (Position des Vertex) 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, // 2D Texturkoordinaten angeben, Offset: 3 * 4 Bytes = 12 0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() // Ende der Deklaration }; IDirect3DDevice9::CreateVertexDeclaration(DeclElem, &g_lpvertexdecl); IDirect3DDevice9::SetVertexDeclaration(g_lpVertexDecl); Pixel-Shader Der Pixel-Shader, wer hätte das gedacht, kümmert sich um die einzelnen Pixel, die durch vorhergehende Operationen noch nicht aus der Pipeline entfernt wurden. Die Rückgabewerte des Vertex-Shaders sind die Eingabewerte des Pixel-Shaders. Der Vertex-Shader gibt also sozusagen seine Ergebnisse weiter an den Pixel-Shader. Übergebene Positionsvektoren (Weltkoordinaten, lokale Koordinaten oder View-Space) werden zwischen den Vertices interpoliert, um den Pixel möglichst genau zu treffen. Diese Tatsache macht es dann auch möglich, eine wesentlich schönere Beleuchtung auf Pixel-Basis durchzuführen. Der Pixel-Shader beeinflusst im Gegensatz zum Vertex- Shader die nachfolgenden Pipeline-Stufen. Der Rückgabewert eines Pixel-Shaders ist immer die Endfarbe (float4-wert) des gerade bearbeiteten Pixels.

HLSL Einführung 3 Beleuchtung Ambiente Beleuchtung Die Lichtstrahlen fallen gleichmässig aus allen Richtungen auf das Objekt, so dass zu jedem Pixel, unabhängig von seiner Lage, ein konstanter Farbwert addiert werden kann. Dieser Wert sollte weder null (total dunkel) noch eins sein. Die Texelfarbe wird einfach aus einer Textur gelesen und dient als Farbgrundlage für das Objekt. Pixel Color = Texel Color A Color A Intensity Abb. 2: Ambient Lighting Diffuse Beleuchtung Bei der diffusen Beleuchtung hat die Lichtquelle eine Position im Raum. Die Lichtstrahlen fallen also aus einer gezielten Richtung auf das Objekt. Die Intensität, mit der die Lichtquelle das Objekt beeinflusst, ist abhängig vom Winkel zwischen Normalenvektor der Objektoberfläche und Richtungsvektor des Lichts. N L = N L cos α Wenn beide Vektoren normalisiert sind, kann die Formel wie folgt vereinfacht werden: N L = cos α Das Punktprodukt wird mit der Streufarbe (engl. diffuse color) multipliziert. Nun variiert die Lichtstärke in Abhängigkeit des Einfallswinkels α. Wird das Punktprodukt negativ, so wird anstatt des negativen Werts die Null verwendet, denn wenn der Winkel grösser als 90 wird, fällt ja kein Licht mehr auf die Objektfläche. Die Reflektion des Lichts ist jedoch unabhängig von der Position der Kamera. Pixel Color = Texel Color D Color D Intensity ( N L )

HLSL Einführung 4 Abb. 3: Diffuse Lighting (N dot L) Spekulare Beleuchtung Ein weiteres Beleuchtungselement ist das Glanzlicht. Die Intensität ist auch hier abhängig vom Einfallswinkel der Lichtstrahlen, aber zusätzlich auch noch vom Beobachterstandort. Damit lassen sich glänzende, polierte Oberflächen simulieren. Eine mögliche Formel für die spekulare Beleuchtung ist das Beleuchtungsmodell von Phong: Die Phong sche Formel verwendet den Betrachtungsvektor sowie den Reflektionsvektor des Lichts. Auch diese Vektoren müssen normalisiert vorliegen. R = 2 ( N L ) N L V = Eye Position Vertex Position V R = V R cos α ( V R ) n = ( cos α ) n Je höher der Exponent n, desto genauer ist die Reflektionslinse. Für metallische Objekte sollte man hier einen hohen Wert (z.b. 64) wählen. Die ganze Formel der Phong-Beleuchtung lautet: Pixel Color = S Color S Intensity ( V R ) n

HLSL Einführung 5 Abb. 4: Diffuse & Specular Lighting Kombination der Beleuchtungsmodelle Kombiniert man alle drei Beleuchtungsmodelle, so erhält man folgende Formel: Pixel Color = Texel Color ( A Color A Intensity + D Color D Intensity ( N L ) ) + S Color S Intensity ( V R ) n Das ganze in der Praxis: Die Vertex-Shader-Funktion transformiert lediglich dien Positionsvektor und speichert die Texturkoordinaten, den Normalenvektor und die Position in Weltkoordinaten in einer Struktur ab. Der Pixel-Shader sorgt danach für Per-Pixel-Lighting, also Beleuchtung auf Pixelbasis! // V E R T E X - S H A D E R VS_OUTPUT VSEffect( float4 Pos : POSITION, float3 Normal : NORMAL, float2 Tex : TEXCOORD0 ) VS_OUTPUT Out = (VS_OUTPUT)0; // Texturkoordinaten unverändert speichern Out.Tex = Tex; // zu Weltkoordinaten transformieren Out.WPos = mul( Pos, g_mviewprojection ); Out.Normal = mul( Normal, g_mworld ); // Weltkoordinaten weiter transformieren Out.Pos = mul( Out.WPos, g_mviewprojection ); } return Out; // P I X E L - S H A D E R float4 PSEffect( VS_OUTPUT In ) : COLOR // Basisfarbe aus Textur lesen float4 BaseColor = tex2d( BaseMapSampler, In.Tex ); float3 N = normalize( In.Normal ); float3 L = -normalize( g_lightdir ); // saturate sorgt dafür, dass der Wert nicht negativ wird float Angle = saturate( dot( N, L ) ); // Winkel α float3 R = normalize( 2 * Angle * N - L ); // Reflektionsvektor

HLSL Einführung 6 float3 V = normalize( g_eyepos - In.WPos ); // View-Vektor } // Farbe = Ambient + Diffus + Specular return BaseColor * ( g_ambientcolor * g_fambient + g_diffusecolor * g_fdiffuse * Angle ) + g_specularcolor * pow( saturate(dot( R, V )), 8 ); Hinweis: Faktoren für die Intensität der einzelnen Komponenten wären eigentlich gar nicht nötig. Stattdessen kann man die Umgebungs- und Streufarbe etwas herunterskalieren; das Endergebnis ist in etwa dasselbe. Hemispherical Lighting Bei dieser Beleuchtungstechnik wird die Szene in zwei Hälften die obere und untere Hemisphäre unterteilt. Für jeden einzelnen Vertex wird geprüft, ob er mehr von der oberen oder unteren Hälfte sichtbar ist. Jeder der beiden Hemisphären wird eine Farbe zugeteilt (Sky Color und Ground Color). Nun wird die Vertexfarbe durch das Zusammenblenden dieser beiden Grundfarben in Abhängigkeit des Winkels zwischen Himmelvektor (Sky Vector) und Vertexnormalen ermittelt. Damit wirkt die Beleuchtung noch realistischer. Der folgende Code ist gegenüber der Formel in der DirectX SDK Doku vereinfacht: float LerpFactor = (dot(normal, g_skydir) + 1) / 2; // Boden und Himmelfarbe vermischen ResColor += lerp(g_ground, g_sky, LerpFactor); Abb. 5: Hemispherical Lighting Schattierungsterm Lässt man die Berechnung eines Schattierungsterms weg, dann wird die Objektfläche fälschlicherweise auch erhellt, wenn der Lichtvektor vom Objekt selbst verdeckt ist. Es gibt mehrere Möglichkeiten, diesen Schattierungsfaktor für die Streu- und Glanzfarbe zu berechnen. Hier eine Variante (Variablennamen beziehen sich auf das Codebeispiel von oben): float Shadow = saturate( 4 * Angle );

HLSL Einführung 7 Punktlichter Der bisherige Ansatz hat sich auf direktionale Lichter (Richtungslichter) beschränkt. Diese sind so weit entfernt, dass eine Berechnung des Lichtrichtungsvektors für jeden einzelnen Vertex resp. Pixel wegfällt. Im Gegensatz zu den Richtungslichtern spielt bei Punktlichtern die Distanz zur Lichtquelle eine bedeutende Rolle. Objekte in unmittelbarer Entfernung werden natürlich stärker beleuchtet als jene, die weit entfernt sind. Der Abschwächungsfaktor kann mit einer der folgenden Formeln berechnet werden: Attenuation = 1 ( x / r ) 2 + ( y / r ) 2 + ( z / r ) 2 Attenuation = Intensity / ( L L ) Attenuation = Intensity / ( const + linear * distance + quadratic * distance 2 ) Alle drei Formeln verwenden natürlich die Distanz zwischen Vertex / Pixel und Lichtquelle. Bei der Berechnung der Distanz muss die Wurzel natürlich nicht gezogen werden. Die dritte Formel entspricht der von Direct3D. Schlussendlich spielt es keine Rolle, welchen Term man verwendet. Wichtig ist aber, dass nur die Streu- und Glanzfarbe mit dem Abschwächungsfaktor multipliziert werden. Environment Mapping Environment Mapping ist eine Technik, mit der unter anderem spiegelnde Oberflächen simuliert werden können (Reflection). In einer sog. Cube-Map ( Würfeltextur ) sind sechs Texturen untergebracht, welche die Szene um das Objekt von allen sechs Seiten (rechts, links, oben, unten, vorne, hinten) beinhalten. Im Vertex- oder Pixel-Shader muss dann nur noch der Reflektionsvektor berechnet werden. α α Normalenvektor Die Berechnung des Reflektionsvektors R läuft eigentlich gleich wie bei der diffusen Beleuchtung. float3 N = normalize(normal); float3 EyeVec = normalize(camerapos VertexPos); float3 ReflVec = reflect(eyevec, N); Die Funktion reflect aus der HLSL Bibliothek tut folgendes: EyeVec - 2 * dot(eyevec, N) * N Damit haben wir den Reflektionsvektor und können nun die Texelfarbe aus der Cube-Map extrahieren: float4 ReflColor = texcube(environmentsampler, ReflVec); Es gibt auch noch die Möglichkeit, Objekte so darzustellen, dass die Objekte dahinter leicht verzerrt erscheinen, als ob man durch ein rundes Glas hindurchschauen würde. Diese Technik ebenfalls Bestandteil von Environment Mapping nennt sich Refraction. Wie bei Reflection muss auch hier ein

HLSL Einführung 8 Vektor berechnet werden, um anschliessend wieder die Farbe aus der Textur lesen zu können. Der Term zur Berechnung dieses Vektors ist hier aber wesentlich komplizierter. Doch auch dafür existiert bereits eine vordefinierte Funktion in der DirectX Bibliothek namens reflect. Diese erwartet drei Parameter: Sichtvektor (Betrachterposition zu Vertex), Normalenvektor, etaratio. Mit dem letzten Parameter kann die Verzerrungsstärke angegeben werden. Empfehlenswert sind Werte zwischen 0.7 (sehr stark verzerrt) und 1.0 (keine Verzerrung). Hier die Formel nach Snell s Law: float cosi = dot(-i, N); float cost2 = 1.0f - etaratio * etaratio * (1.0f - cosi * cosi); float3 T = etaratio * I + ((etaratio * cosi - sqrt(abs(cost2))) * N); ReflVec = T * (float3)(cost2 > 0) Abb. 6: Environment Mapping Reflection (links) und Refraction (rechts) Normal Mapping Normal Maps sind Texturen, die verwendet werden können, um Wölbungen und Grübchen auf Oberflächen vorzutäuschen. Der grosse Vorteil dabei ist, dass man mit Normal Mapping (auch unter dem Begriff Bump Mapping bekannt) einen hohen Detailgrad erreichen kann, was sonst nur mit tausenden von zusätzlichen Triangles möglich wäre. In einer Normal Map sind, wie der Name schon sagt, die Normalenvektoren gespeichert, die anstelle der Oberflächennormalen für die Lichtberechnung verwendet werden. Jeder Texel repräsentiert eine Normale, wobei die einzelnen Farbkanäle der x-, y- und z-achse des Vektors entsprechen. Um den Lichtvektor, der üblicherweise in Weltkoordinaten vorliegt, mit der Normalen aus der Textur vergleichen zu können, muss die Lichtrichtung auch in Texturkoordinaten (engl. texture space) transformiert werden. Der Lichtvektor wird einmal pro Objekt mit der inversen Weltmatrize in Object-Space gebracht und dann mit der so genannten Tangent-Matrix transformiert. Jeder Vertex hat quasi einen Normalenvektor, eine Tangente und eine Binormale. Diese drei Vektoren liegen in lokalen Koordinaten (Object-Space) vor. Mit diesen drei Achsenvektoren kann eine Matrix gebildet werden, mit der man Vektoren vom Object- in den Tangent-Space bringen kann.

HLSL Einführung 9 Abb. 7: Tangent-Space Beispielcode (Vertex- und Pixel-Shader): VS_OUTPUT VSNormalMapping(float4 Pos : POSITION, float2 Tex : TEXCOORD0, float3 Normal : NORMAL, float3 Tangent : TANGENT0) VS_OUTPUT Out = (VS_OUTPUT)0; float4 WorldPos = mul(pos, g_mworld); Out.Pos = mul(worldpos, g_mviewproj); Out.Tex = Tex * g_ftexnoise; float3 ViewVec = g_objspacecamerapos - Pos; float3 LightVec = g_objspacelightpos - Pos; // Licht- und View-Vektor in Tangent-Space transformieren float3 TempViewVec; Out.LightVec.x = dot(lightvec, cross(tangent, Normal)); Out.LightVec.y = dot(lightvec, Tangent); Out.LightVec.z = dot(lightvec, Normal); TempViewVec.x = dot(viewvec, cross(tangent, Normal)); TempViewVec.y = dot(viewvec, Tangent); TempViewVec.z = dot(viewvec, Normal); Out.HalfAngle = Out.LightVec + TempViewVec; } return Out; float4 PSNormalMapping(VS_OUTPUT In) : COLOR // Texture lookups (Normalenvektoren und Farben herauslesen) float4 TexColor = tex2d(basesampler, In.Tex); float3 Normal = tex2d(bumpsampler, In.Tex); // Normalenvektoren erstellen float3 Smooth = 0.5, 0.5, 1.0}; Normal = lerp(smooth, Normal, g_fbumpscale); Normal = normalize((normal * 2.0f) - 1.0f); float Att = saturate(g_flightradius / dot(in.lightvec, In.LightVec)); In.LightVec = normalize(in.lightvec); float3 HalfAngle = normalize(in.halfangle); float Angle = saturate(dot(normal, In.LightVec)); float4 NdotH = dot(normal, HalfAngle); float4 Specular = pow(saturate(ndoth), g_fspecpower); float Shadow = saturate(4 * Angle); } return (TexColor * g_ambient * g_fambient) + (Att * Shadow * ( (TexColor * g_diffuse * g_fdiffuse * Angle) + (g_specular * Specular * g_fspecular) ));

HLSL Einführung 10 Abb. 7: Normal Mapping in Action Displacement Mapping Diese Technik basiert auf der Veränderung der Geometriedaten in Echtzeit. Im Vertex-Shader werden aus einer so genannten Displacement Map, die im 8-bit Format vorliegt, die Graustufen extrahiert. Je heller der Texel, desto weiter wird der Vertex entlang seiner Normalen verschoben. So ist es möglich, die Oberfläche einer gewöhnlichen Kugel ohne grossen Aufwand geometrisch zu verformen. Sogar ein Terrain liesse sich mit dieser Technik realisieren! Displacement Mapping setzt das Shader-Model 3 voraus, denn erst seit dieser Version wird das lesen von Texturdaten (texture lookups) im Vertex- Shader unterstützt. Momentan ist dieser Shader nur auf wenigen Grafikkarten (ab der Geforce 6- Reihe) lauffähig. Trotzdem lohnt es sich, diese Technik einmal näher zu betrachten, denn Zukunftsorientierung ist sehr wichtig =). // V E R T E X - S H A D E R VS_OUTPUT VSEffect(float4 Pos : POSITION; float3 Normal : NORMAL; float2 Tex : TEXCOORD0) VS_OUTPUT Out = (VS_OUTPUT)0; Out.Tex = In.Tex; Out.WPos = mul(in.pos, g_mworld); Out.Normal = mul(in.normal, g_mworld); // Welttransformation float fdisplace = tex2dlod(displacesampler, float4(in.tex.x, In.Tex.y, 0, 0)); float3 DisplacePos = Out.WPos + float4(out.normal, 1.0) * fdisplace; Out.Wpos = DisplacePos; // abgeänderte Vertex-Position projizieren Out.Pos = mul(float4(displacepos, 1), g_mviewproj);

HLSL Einführung 11 } return Out; // P I X E L S H A D E R float4 PSEffect(VS_OUTPUT In) : COLOR // Basisfarbe aus Textur lesen und zurückliefern return tex2d(basemapsampler, In.Tex * g_ftexnoise); } Die korrekte Beleuchtung eines Objekts mit Displacement Mapping ist leider nicht ganz so simpel, denn wenn die Vertices verschoben werden, ändern sich die Normalenvektoren. Das heisst, man müsste die Normalen jedes Mal wieder neu berechnen. Für all jene, die nicht Inhaber von Geforce 6-Karten sind, gibt es eine alternative Möglichkeit, nämlich das so genannte Virtual Displacement Mapping. Virtual deshalb, weil die Geometrie nicht wirklich verformt wird. Mit dieser Technik erzielt man bessere Ergebnisse als mit Parallax Mapping, doch dafür ist die Umsetzung etwas komplizierter. Wer sich dafür interessiert, der sollte sich einmal das Skript View-Dependent Displacement Mapping von Nvidia ansehen. Parallax Mapping Ähnlich wie bei Bump Mapping wird auch hier Geometrie vorgetäuscht. Aus einer so genannten Height-Map werden, wie der Name schon sagt, die Höhendaten gelesen. Entlang des zweidimensionalen View-Vectors (Vertex-zu-Kamera-Vektor) werden dann die Texturkoordinaten, je nach Height-Map-Wert, leicht verschoben, sodass beim schrägen Betrachten Oberflächen dreidimensional ausschauen können. Abb. 8: Diese Wand besteht tatsächlich nur aus zwei Dreiecken

HLSL Einführung 12 Abb. 9: Parallax Bump Mapping (links), Bump Mapping (Mitte), N.L Beleuchtung (rechts) Ausblick Zum Thema Shader könnte man ein ganzes Buch schreiben. Dem Programmierer stehen jegliche Tore offen und er kann seiner Phantasie freien Lauf lassen. Einzig und allein die Hardware selbst definiert eine obere Schranke. Mit Shadern lässt sich, wie bereits angetönt, praktisch jeder Effekt erzielen, sei es jetzt Charakteranimation oder irgendeine Material- oder Wolkensimulation. Zum Schluss noch ein paar Appetithäppchen: Abb. 10: Pixel-Shader 2.0 Wood and Marble

HLSL Einführung 13 Quellenverzeichnis Literaturverzeichnis http://www.zfxcon.info/zfxcon03/proceedings/zfxcon03_wengel.pdf [05.04.05] http://www.neatware.com/lbstudio/web/hlsl.html [18.10.05] http://www.fh-landshut.de/%7egschied/opengl/13-cganwendungckabek/3.3%20refractive%20environment%20mapping.html [10.04.05] Brünger, Thomas (2004). Spiele-Programmierung Grafik-Engine. PC Games Hardware, 08.2004, 150ff Abbildungsverzeichnis Abb.1-10: eigene Screenshots und Grafiken Copyright 2005 by Reto Da Forno Irrtümer vorbehalten. 19.10.05 www.keepcoding-development.ch.vu