Environment Mapping.

Slides:



Advertisements
Ähnliche Präsentationen
Computer Graphics Shader
Advertisements

Hauptseminar - Computer Graphics
Kapselung , toString , equals , Java API
Progwerkstatt JAVA Klasse, Objekte, Konstruktoren, Methoden
Trigonometrische Funktionen
Kollisionen erkennen Kollisions- und Schnittpunkttests auf Dreieckbasis Kollisions- und Schnittpunkttests auf Viereckbasis Einsatz von achsenausgerichteten.
Kapitel 9.4 Blooming (Postprocess-Effekt). Postprocess-Effekte 2D-Effekte Werden auf das gerenderte Bild im Framebuffer angewendet Beispiele: Bewegungsunschärfe.
Kapitel 9.3 Dot3-Bumpmapping (Normalmapping). Bumpmaps Textur, deren Pixel unterschiedlich auf einfallendes Licht reagieren Betrachter hat den Eindruck,
Elemente der 3D-Grafikprogrammierung
Geometrie in DirectX: Vektoroperationen Kapitel – Spieleprogrammierung mit DirectX und C++ Kaiser/Lensing.
Ultris V10 Bewegen, Drehen und Kollisionserkennung.
C.M. Presents D.A.R. und Ein Bisschen dies und das!
_____________________________ Einführung in die Bildbearbeitung Jucquois-Delpierre 1 Grundlagen Photoshop Ein zentraler Begriff bei Pixelgrafiken.
5. Beleuchtung und Schattierung
Ein Beispiel in Java.
Klassenvariable. Da man für jede Kuh bzw. jede Henne auf dem Markt den gleichen Preis für ein Liter Milch, bzw. den gleichen Preis für ein Ei bekommt,
Konstruktoren.
Shaderprogrammierung T. Goeschel + F. Theilacker
Simulation und 3D-Programmierung Praxis: Dreiecke, Texturen, Vertex-Buffer Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung.
Softwaretechnologie II (Teil 1): Simulation und 3D Programmierung
Positionierung und Ausrichtung der Kamera. void balance::kamera_bewegen( float seit, float hoch, float vor) { D3DXVECTOR3 v, s, h, t; v = da_gucke_ich_hin.
V03 Laden und Speichern von Spielfeldern und der Spielfeldeditor.
Exotische Texturformen
Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure.
Java3d „Licht und Material“
Zusammenfassung Vorwoche
Die Skriptsprache Perl (8) Wolfgang Friebel DESY Zeuthen.
So animieren Sie Kreisdiagramme mit der Eingangs-Animation „Rad“
Arrays,Strings&Pointer in C/C++
DVG Klassen und Objekte
Special Effects Realistischeres Rendern einer Scene.
Heute: Scherenzange zeichnen
Balance V01 Der Windows-Rahmen S Vortrag von Lisa Rau.
3D Programmierung Version 12 - Highscores. Die vom Spieler erzielte Punktzahl wird mit 5 vorgegebenen Punktzahlen verglichen und, falls nötig, in die.
FH-Hof Licht Richard Göbel. FH-Hof Licht in Java3D - Basisideen Bereitstellung unterschiedlicher Lichtquellen Definition der Wirkung einer Beleuchtung.
F5. Kurzübersicht folgende Parameter werden näher Vorgestellt: FarbeGlanzpunkteTransparenz TexturenHalomaterialienLensflares.
Java programmieren mit JavaKara
Grundgrößen der Lichttechnik
XNA 3D Tutorial Anzeigen eines Objektes. Inhalt Lernen Sie, wie Sie Modelle implementieren. Initializing Lernen Sie, wie Sie Modelle aus der Content Directory.
Universität zu Köln Institut für Historisch-Kulturwissenschaftliche Informationsverarbeitung Prof. Dr. Manfred Thaller AM 3 Übung: Softwaretechnologie.
3D- Spieleprogrammierung
Bildbearbeitung im Unterricht
Von der Planung bis zum Hauptmenü Seminar: Softwaretechnologie II Dozent: Prof. Manfred Thaller Referent: Jan Bigalke.
Quantum Computing Hartmut Klauck Universität Frankfurt WS 05/
Beweissysteme Hartmut Klauck Universität Frankfurt WS 06/
Einführung in die Programmiersprache C 4
Informatik 1 Letzte Übung.
Vom Umgang mit Daten. public void myProgram() { int[] saeulenWerte = new int[world.getSizeX()]; for (int i = 0; i < saeulenWerte.length; i++) { saeulenWerte[i]
Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Softwaretechnologie II (Teil 1): Simulation und 3D Programmierung.
Programmbereich, zu dem eine Deklaration gehört Arten von Gültigkeitsbereichen -Namespace : Deklarationen von Klassen, Interfaces, Structs, Enums, Delegates.
Helwig Hauser Teil 4: Texturing Farbe, Struktur, Umgebung.
Beleuchtungsmodelle, Schattierungsmodelle
CuP - Java Vierte Vorlesung Entspricht ungefähr Kapitel 2.1 des Skriptums Montag, 14. Oktober 2002.
PHP: Operatoren und Kontrollstrukturen
Michael Schmidt computer graphics & visualization Texture Mapping Lapped Textures.
Parallelisierung für Multiprozessor-Maschinen
Vom graphischen Differenzieren
Erfahrungen mit Microsoft DirectX 8 W. Krug, April 2002.
Einführung Blue J. Inhaltsverzeichnis  Definition  Vokabeln.
Die Welt der Shader Universität zu Köln WS 14/15 Softwaretechnologie II (Teil 1) Prof. Dr. Manfred Thaller Referent: Lukas Kley Fortgeschrittene Techniken.
Stefan Röttger Universität Stuttgart (VIS). Überblick 1. Motivation 2. Shadow Volumes [Crow77] 3. Verfahren ohne Stencil Buffer 4. Demonstrationsfilm.
1. Charakteranimation 2. PlugIns schreiben und laden Universität zu Köln Institut für Historisch-Kulturwissenschaftliche Informationsverarbeitung WS 2010/2011.
Die Renderpipeline.
Multimedia und Virtual Reality Vorlesung am Martin Kurze Multimedia in 3D.
Objektorientierte Programmierung (OOP)
Funktionen, Felder und Parameter- übergabe. Funktionsaufruf mit Feld als Parameter: Parameter = Name des Feldes.
Tutorium Software-Engineering SS14 Florian Manghofer.
Tutorium Software-Engineering SS14 Florian Manghofer.
Lineare Optimierung Nakkiye Günay, Jennifer Kalywas & Corina Unger Jetzt erkläre ich euch die einzelnen Schritte und gebe Tipps!
Implementieren von Klassen
 Präsentation transkript:

Environment Mapping

Environment mapping ist ein Materialeffekt, bei dem das Material eines Objekts die Umgebung reflektiert Folgende Eigenschaften braucht man zur Berechnung: - Reflexionseigenschaften des Materials auf diffuses Licht - Reflexionseigenschaften des Materials auf spekulares Licht - den Grad der spekularen Reflexion - die Umgebungstextur - die Intensität der Spiegelung Zur Implementation dieser Eigenschaften brauchen wir das Phong-Reflexionsmodell, auf dem die D3DMATERIAL9-Materialstruktur basiert

In DirectX setzt sich ein Material aus 4 Komponenten zusammen: - ambiente Komponente - diffuse Komponente - spekulare Komponente - emissive Komponente (Selbstleucht-Eigenschaft) Aus den ersten 3 setzt sich das reflektierte Licht zusammen -> ARGB-Farbwert Die Umgebungsfarbe berechnet sich dabei folgendermaßen: AmbientColor = AmbientColorMaterial * AmbientColorLichtquelle (kanalweise Multiplikation)

Die diffuse Komponente hängt davon ab, wie das Objekt zur Lichtquelle positioniert ist, daher müssen wir Richtung des Lichts und die Normale der Objektoberfläche einbeziehen: DiffuseColor = DiffuseColorMaterial * DiffuseLichtquelle * max(0, L N ) Ist der Winkel zwischen dem negativen, normierten Richtungsvektor des Lichts und der Flächennormale = 0 => Skalarprodukt ergibt 1 90° => Skalarprodukt ergibt 0 >90° => Skalarprodukt negativ => Flächen, die dem Licht zugewandt sind, werden erhellt, abgewandte Flächen verdunkelt → →

Die spekulare Reflexion simuliert den Glanzpunkt Dies ist eine direkte Spiegelung der Lichtquelle

→ → SpecularColor = SpecularColorMaterial * SpecularColorLichtquelle * max (0, H N ) n n ist die Größe und Intensität des Glanzpunktes Dieses Beleuchtungsmodell ist das Standard-Modell von DirectX für die Fixed-Function-Pipeline Nun setzen wir dies in eine FX-Datei um: → →

// Matrizen float4x4 MatWVP; // = World View Projection float4x4 MatViewInv; // = Inverse der View-Matrix -> zur Berechnung der Position des Betrachters float4x4 MatWorld; // zur Transformation der Normalen eines Modells in Weltkoordinatensystem // Directionale Lichtquelle float3 LightDir; // muss normiert sein! float4 LightColor; // verwendet für diffuse & spekulare Komponente float4 LightAmbient; // wirkt sich auf alle Objekte der Szene aus // Materialien float4 MtrlDiffColor; float4 MtrlSpecColor; float MtrlSpecPower;

Ein- und Ausgabestruktur der Vertices // Eingang Vertexshader struct VertexInput { float3 Position : POSITION; float3 Normal : NORMAL; }; // Ausgang Vertexshader struct VertexOutput { float4 HPosition : POSITION; float4 Diffuse : COLOR0; float4 Specular : COLOR1;

VertexOutput VS_Main( VertexInput IN ) { VertexOutput OUT; float3 NormalWorld; float3 PosWorld; float3 CamPosWorld; float3 CamDirToPos; float3 HalfVector; NormalWorld = normalize( mul( IN.Normal, (float3x3) MatWorld ) ); CamPosWorld = MatViewInv[3].xyz; PosWorld = mul( float4(IN.Position.xyz , 1.0) , MatWorld ); CamDirToPos = normalize( PosWorld - CamPosWorld ); HalfVector = -normalize( LightDir+CamDirToPos ); OUT.HPosition = mul( float4(IN.Position.xyz , 1.0) , MatWVP); OUT.Diffuse = max( 0, dot( NormalWorld, -LightDir ) ) * MtrlDiffColor * LightColor; OUT.Specular = pow( max( 0, dot( HalfVector, NormalWorld) ), MtrlSpecPower ) * MtrlSpecColor * LightColor; return OUT;

Der Pixelshader ist sehr simpel gehalten, da die Berechnungen der Farben im Vertexshader vorgenommen wurden. Dies dient der Leistungssteigerung. float4 PS_Main( VertexOutput IN ) : COLOR { return IN.Diffuse + IN.Specular + LightAmbient; } technique EnvMapping pass p0 VertexShader = compile vs_2_0 VS_Main(); PixelShader = compile ps_2_0 PS_Main(); ColorArg1[0] = Diffuse; AlphaArg1[0] = Diffuse; ColorOp[0] = SelectArg1; AlphaOp[1] = SelectArg1;

Hiermit haben wir eine Beleuchtungsroutine geschaffen, die das Licht in der Szene reflektiert. Um jedoch die gesamte Umgebung zu reflektieren, sind noch einige weitere Schritte notwendig. Grundsätzlich könnte ein Modell der Abbildung so aussehen:

Um aber die gesamte Umgebung auf eine Textur zu mappen, bedarf es eines Tricks, dem sogenannten Cubemapping Hierbei wird die Umgebung auf die Innenseiten eines Würfels abgebildet, in dessen Mitte sich unser Objekt befindet. Wichtig ist hierbei natürlich, dass der eigentliche Würfel für den User unsichtbar ist und nur die Reflexionen des Würfels auf das Objekt zu sehen sind

Hierzu bietet DirectX ein Interface namens IDirect3DCubeTexture9 Mithilfe des DirectX Texture Tool (liegt dem SDK bei) können wir aus 6 einzelnen Bildern eine Cubemap-Textur erzeugen Mit D3DXCreateTextureFromFile wird das Cubemap-Objekt geladen Unsere FX-Datei müssen wir mit folgenden Parametern erweitern: Texture TexDiffuse; // für den diffusen Kanal Texture TexEnvironment; // die Cubemap-Textur float MtrlReflectionFactor; // Faktor, der die Stärke der Reflexion des Objekts angibt Die Textursampler für die beiden Texturen sehen so aus:

sampler SamplerDiffuse = sampler_state { texture = <TexDiffuse>; AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; MIPFILTER = LINEAR; MINFILTER = LINEAR; MAGFILTER = LINEAR; }; sampler SamplerEnvironment = sampler_state texture = <TexEnvironment>;

Der VertexInput des Vertexshaders muss um ein Texturkoordinatenpaar ergänzt werden float2 Tex0 : TEXCOORD0; Die Texturkoordinaten der Cubemap werden im Pixelshader berechnet. Dazu müssen die Reflexionsvektoren der einzelnen Vertices übergeben werden (als dreidimensionale Texturkoordinaten, da HLSL keine Semantik für Reflexionskoordinaten hat) Der VertexOutput wird ergänzt: float2 TexCoordDiff : TEXCOORD0; float3 TexCoordCube : TEXCOORD1;

VertexOutput VS_Main( VertexInput IN ) { … OUT.TexCoordDiff = IN.Tex0; OUT.TexCoordCube = reflect( CamDirToPos, NormalWorld ); return out; } Die Texturkoordinaten für die diffuse Textur werden einfach weitergereicht, der Reflexionsvektor wird mithilfe der Funktion reflect aus dem Vektor vom Betrachter auf den Vertex und der Vertexnormale errechnet

float4 PS_Main( VertexOutput IN ) : COLOR { Der Pixelshader wird ergänzt: float4 PS_Main( VertexOutput IN ) : COLOR { float4 Environment = texCUBE( SamplerEnvironment, IN.TexCoordCube ); // sampelt Farbe aus der Cubemap mithilfe des Reflektionsvektors float4 Diffuse = IN.Diffuse * tex2D( SamplerDiffuse, IN.TexCoordDiff ); float4 Specular = IN.Specular; Diffuse = lerp( Diffuse, Environment, MtrlReflectionFactor ); // hier wird geregelt, wie stark das Objekt spiegelt. Beim Maximum entspricht die Pixelfarbe der Environmentfarbe, ansonsten der diffusen Farbe. lerp ist eine lineare Interpolation, die beide Farben mithilfe des Materialfaktors mischt return (Diffuse + Specular + LightAmbient); }

Nun die umgebende C++-Klasse #pragma once #include <d3dx9.h> class CEnvEffect { protected: ID3DXEffect* m_Effect; SEnvParameter m_Parameter; public: BOOL Create( LPDIRECT3DDEVICE9 Device ); void Destroy(); void Setup( SEnvParameter& Para ); DWORD Begin( LPDIRECT3DDEVICE9 Device ); void BeginPass(DWORD pass); void EndPass(); void End(); };

struct SEnvParameter { //Welche Werte wurden geändert? DWORD Changed; //Licht, x-Wert entspricht Rot, y-Wert Grün, z-Wert blau, w dem Alpha-Kanal D3DXVECTOR4 LightColor; D3DXVECTOR4 LightAmbient; D3DXVECTOR3 LightDir; //Material D3DXVECTOR4 MtrlDiffColor; D3DXVECTOR4 MtrlSpecColor; FLOAT MtrlSpecPower; FLOAT MtrlReflectionFactor; LPDIRECT3DTEXTURE9 TexDiffuse; LPDIRECT3DCUBETEXTURE9 TexEnvironment; }; Lediglich die Matrizen fehlen hier, diese werden direkt aus dem 3D-Device geholt

Changed teilt uns mit, welche Variablen geändert wurden, damit wir die Parameterübergabe möglichst effizient halten: enum EEnvParameter { LIGHTCOLOR = 1, LIGHTAMBIENT = 2, LIGHTDIR = 4, MTRLDIFFCOLOR = 8, MTRLSPECCOLOR = 16, MTRLSPECPOWER = 32, MTRLREFLECTIONFACTOR = 64, TEXDIFFUSE = 128, TEXENVIRONMENT = 256 }; Per bitweises Oder können die einzelnen Parameter verknüpft werden (Bsp.: Changed TEXDIFFUSE | TEXENVIRONMENT ; )

Nun zu den einzelnen Funktionen BOOL CEnvEffect::Create( LPDIRECT3DDEVICE9 Device ) { ID3DXBuffer* ErrorBuffer; if( FAILED( D3DXCreateEffectFromFile( Device, "Effects/cube_environmentmapping.fx", NULL, NULL, 0/* D3DXSHADER_DEBUG|D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT|D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT*/, NULL, &m_Effect, &ErrorBuffer ) ) ) char *Errors = (char*) ErrorBuffer->GetBufferPointer(); fprintf( stderr, "%s", Errors ); return false; } return true; void CEnvEffect::Destroy() SAFE_RELEASE( m_Effect );

void CEnvEffect::Setup( SEnvParameter& Para ) { if( Para.Changed & LIGHTCOLOR ) m_Parameter.LightColor = Para.LightColor; if( Para.Changed & LIGHTAMBIENT ) m_Parameter.LightAmbient = Para.LightAmbient; if( Para.Changed & LIGHTDIR ) m_Parameter.LightDir = Para.LightDir; if( Para.Changed & MTRLDIFFCOLOR ) m_Parameter.MtrlDiffColor = Para.MtrlDiffColor; if( Para.Changed & MTRLSPECCOLOR ) m_Parameter.MtrlSpecColor = Para.MtrlSpecColor; if( Para.Changed & MTRLSPECPOWER ) m_Parameter.MtrlSpecPower = Para.MtrlSpecPower; if( Para.Changed & MTRLREFLECTIONFACTOR ) m_Parameter.MtrlReflectionFactor = Para.MtrlReflectionFactor; if( Para.Changed & TEXDIFFUSE ) m_Parameter.TexDiffuse = Para.TexDiffuse; if( Para.Changed & TEXENVIRONMENT ) m_Parameter.TexEnvironment = Para.TexEnvironment; m_Parameter.Changed |= Para.Changed; }

DWORD CEnvEffect::Begin( LPDIRECT3DDEVICE9 Device ) { UINT passes = 0; // Matrizen setzen D3DXMATRIX MatWorld, MatView, MatProj; D3DXMATRIX MatWVP, MatViewInv; // Matrizen aus dem 3D-Device holen Device->GetTransform( D3DTS_WORLD, &MatWorld ); Device->GetTransform( D3DTS_VIEW, &MatView ); Device->GetTransform( D3DTS_PROJECTION, &MatProj ); // Weitergeben der Matrizen an die Effektinstanz m_Effect->SetMatrix( "MatWorld", &MatWorld ); MatWVP = (MatWorld*MatView)*MatProj; m_Effect->SetMatrix( "MatWVP", &MatWVP ); D3DXMatrixInverse( &MatViewInv, NULL, &MatView ); m_Effect->SetMatrix( "MatViewInv", &MatViewInv ); m_Effect->SetTechnique( "EnvMapping" ); m_Effect->Begin( &passes, 0 ); return passes; }

void CEnvEffect::BeginPass(DWORD pass) // Übergibt restliche Parameter an Effektinstanz { // Parameter setzen if( m_Parameter.Changed & LIGHTCOLOR ) m_Effect->SetValue( "LightColor", m_Parameter.LightColor, sizeof( D3DXVECTOR4 ) ) ; if( m_Parameter.Changed & LIGHTAMBIENT ) m_Effect->SetValue( "LightAmbient", m_Parameter.LightAmbient, sizeof( D3DXVECTOR4 ) ); if( m_Parameter.Changed & LIGHTDIR ) m_Effect->SetValue( "LightDir", m_Parameter.LightDir, sizeof( D3DXVECTOR3 ) ); if( m_Parameter.Changed & MTRLDIFFCOLOR ) m_Effect->SetValue( "MtrlDiffColor", m_Parameter.MtrlDiffColor, sizeof( D3DXVECTOR4 ) ); if( m_Parameter.Changed & MTRLSPECCOLOR ) m_Effect->SetValue( "MtrlSpecColor", m_Parameter.MtrlSpecColor, sizeof( D3DXVECTOR4 ) ); if( m_Parameter.Changed & MTRLSPECPOWER ) m_Effect->SetFloat( "MtrlSpecPower", m_Parameter.MtrlSpecPower ); if( m_Parameter.Changed & MTRLREFLECTIONFACTOR ) m_Effect->SetFloat( "MtrlReflectionFactor", m_Parameter.MtrlReflectionFactor ); if( m_Parameter.Changed & TEXDIFFUSE ) m_Effect->SetTexture( "TexDiffuse", m_Parameter.TexDiffuse ); if( m_Parameter.Changed & TEXENVIRONMENT ) m_Effect->SetTexture( "TexEnvironment", m_Parameter.TexEnvironment ); m_Effect->BeginPass( pass ); }

void CEnvEffect::EndPass() { m_Effect->EndPass(); m_Parameter.Changed = 0; } void CEnvEffect::End() m_Effect->End(); Damit wären wir fertig. Allerdings werden bei dieser Methode andere Objekte, die sich in der Szene befinden, nicht reflektiert, da wir nur die statische Cubemap benutzen. Wir müssen also einen Weg finden, auch bewegliche Objekte mit einzubeziehen.

Hierzu postieren wir die Kamera in die Mitte unseres Objekts und setzen den Öffnungswinkel der Kamera auf 90°. Dann rendern wir die Szene und drehen die Kamera nach oben, unten, links, rechts und hinten. Das ergibt 6 Seiten einer Cubemap. Wir nutzen die Seiten der Cubemap als Rendertarget und lassen uns jeweils das passende Surface geben, um es als Backbuffer im 3D-Device zu verwenden. Danach müssen wir den (vorher gespeicherten) regulären Backbuffer wieder an das Device übergeben. Die Funktion ID3DXRenderToEnvMap nimmt uns diese beiden Schritte ab. LPDIRECT3DSURFACE9 BackBuffer; D3DSURFACE_DESC BBDesc; 3DDEVICE->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &BackBuffer); BackBuffer->GetDesc (& BBDesc ); BackBuffer->Release();

D3DXCreateRenderToEnvMap( 3DDevice, 256, 1, BBDesc D3DXCreateRenderToEnvMap( 3DDevice, 256, 1, BBDesc.Format, TRUE, D3DFMT_D16, &m_RenderToEnvMap ) ) ) Die Parameter: 1. 3D-Device 2. Größe der gewünschten Textur (hier: 256 Pixel) 3. Anzahl der Mipmaps 4. Pixelformat (hier: das vom ursprünglichen Backbuffer) 5. Flag, das angibt, ob wir Stencil- und Tiefen-Buffer verwenden möchten 6. Format des Tiefen-Stencil-Buffers (hier: 16-Bit-Z-Buffer) 7. das ID3DXRenderToEnvMap-Objekt, das erstellt werden soll D3DXCreateCubeTexture( 3DDevice, 256, 1, D3DUSAGE_RENDERTARGET, BBDesc.Format, D3DPOOL_DEFAULT, &m_CubeTex ) ) ) 2. Größe der einzelnen Seite der Cubemap 4. Verwendungszweck der Textur (-> Rendertarget) 5. Pixelformat der Textur (siehe Backbuffer) 6. Ressourcen-Pool, in dem die Textur abgelegt werden soll 7. Doppelpointer auf das zu erstellende IDirect3DCubeTexture9-Objekt

HRESULT RenderIntoCube() { HRESULT hr; D3DXMATRIX matProj; // Erstellen einer Matrix, die einen Öffnungswinkel von 90° und ein Seitenverhältnis von 1 hat D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI*0.5f, 1.0f, 0.5f, 1000.0f); hr = m_RenderToEnvMap->BeginCube( m_CubeTex ); if (FAILED(hr)) return hr; for( UINT i = 0; i < 6; i++ ) // Über Face können wir die einzelnen Seiten der Cubemap definieren: m_RenderToEnvMap->Face( (D3DCUBEMAP_FACES) i, 0 ); D3DXMATRIX matView; // Erstellt eine View-Matrix für alle Seiten der Cubemap: matView = D3DUtil_GetCubeMapViewMatrix((D3DCUBEMAP_FACES) i); // Szene wird gerendert: RenderScene( matView, matProj); } m_RenderToEnvMap->End( 0 ); return S_OK;

Damit sind wir (endlich) fertig! Vielen Dank für die Aufmerksamkeit!