1 / 21

Kapitel 9.3

Kapitel 9.3. Dot3-Bumpmapping (Normalmapping). Bumpmaps. Textur, deren Pixel unterschiedlich auf einfallendes Licht reagieren Betrachter hat den Eindruck, dass ein Objekt detailreicher sei Aber: die Geometrie des Objekts ändert sich nicht (z. B. an der Silhouette des Objekts zu erkennen)

hall
Télécharger la présentation

Kapitel 9.3

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Kapitel 9.3 Dot3-Bumpmapping (Normalmapping)

  2. Bumpmaps • Textur, deren Pixel unterschiedlich auf einfallendes Licht reagieren • Betrachter hat den Eindruck, dass ein Objekt detailreicher sei • Aber: die Geometrie des Objekts ändert sich nicht (z. B. an der Silhouette des Objekts zu erkennen) • Es gibt zwei Arten von Bumpmaps: Heightmaps und Normalmaps

  3. Heightmaps • Graustufen-Texturen, in denen Tiefenwerte codiert sind, welche dann zur Berechnung der Schattierung herangezogen werden

  4. Normalmaps • In der Textur werden die Normalen gespeichert • 3 Farbkanäle: RGB • Jeder Kanal steht für eine Dimension der Normale • Bsp: liegt eine Textur in der XY-Ebene, so repräsentiert der Rot-Anteil die X-Richtung der Grün-Anteil die Y-Richtung der Blau-Anteil die Z-Richtung der Normale

  5. Tangentenraum • Aber: Farb-Achsen-Zuordnung ist relativ • Bei Bewegung des Objekts müssen sich die Normalen der Textur auch mit bewegen • Für jedes Polygon des Objekts muss also ein eigenes Koordinatensystem erstellt werden • Die Normale der Fläche des Polygons entspricht dann der logischen Z-Richtung der Normalmap (Blau-Anteil) • So ein Koordinatensystem nennt man Tangentenraum und die Achsen bezeichnet man als: Tangente (rot), Binormale (grün), und Normale (blau) U Die Tangente ist parallel zur U-Achse der Textur und die Binormale ist parallel zur V-Achse Textur V

  6. Die Effektdatei Benötigte Parameter // Matrizen float4x4 MatWVP : WorldViewProjection; float4x4 MatViewInv : ViewInverse; float4x4 MatWorld : World; //Direktionale Lichtquelle float3 LightDir : Direction; float4 LightColor : Diffuse; float4 LightAmbient : Ambient; //Materialien float4 MtrlDiffColor : Diffuse; float4 MtrlSpecColor : Specular; float MtrlSpecPower : SpecularPower; Texture TexDiffuse : Diffuse; //Diffusemap Texture TexNormal : Diffuse; //Normalmap

  7. Textursampler sampler SamplerDiffuse = sampler_state { texture = <TexDiffuse>; AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; MIPFILTER = LINEAR; MINFILTER = LINEAR; MAGFILTER = LINEAR; }; sampler SamplerNormal = sampler_state { texture = <TexNormal>; AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; MIPFILTER = LINEAR; MINFILTER = LINEAR; MAGFILTER = LINEAR; }; Sampler für die Diffusemap Sampler für die Normalmap

  8. Vertexshader Ein- und Ausgabestrukturen struct VertexInput { float3 Position : POSITION; float3 Normal : NORMAL; float2 Tex0 : TEXCOORD0; float3 Tangent : TANGENT; float3 Binormal : BINORMAL; }; struct VertexOutput { float4 HPosition : POSITION; float2 TexCoord : TEXCOORD0; float3 HalfVector : TEXCOORD2; float3 Normal : TEXCOORD3; float3 Tangent : TEXCOORD4; float3 Binormal : TEXCOORD5; }; Eingangsstruktur für den Vertexshader Ausgabestruktur

  9. Vertexshader VertexOutput VS_Main( VertexInput IN ) { VertexOutput OUT; float3 PosWorld; float3 CamPosWorld; float3 CamDirToPos; float3 HalfVector; CamPosWorld = MatViewInv[3].xyz; PosWorld = mul( float4(IN.Position.xyz , 1.0) , MatWorld ); CamDirToPos = normalize( PosWorld - CamPosWorld ); HalfVector = -(LightDir+CamDirToPos); OUT.Normal = normalize( mul( IN.Normal, (float3x3) MatWorld ) ); OUT.Tangent = normalize( mul( IN.Tangent, (float3x3) MatWorld ) ); OUT.Binormal = normalize( mul( IN.Binormal, (float3x3) MatWorld ) ); OUT.HPosition = mul( float4(IN.Position.xyz , 1.0) , MatWVP); OUT.TexCoord = IN.Tex0; OUT.HalfVector = HalfVector; return OUT; } Transformieren der Tangente, Normale und Binormale in das Weltkoordinatensystem (alle Achsen des Tangentenraums werden mit der Weltmatrix multipliziert)

  10. Pixelshader float4 PS_Main( VertexOutput IN ) : COLOR { float3 Normal; float4 Diffuse; float4 Specular; float3 HalfVec; float3 Light; float Intensity; float3x3 MatTex; HalfVec = normalize(IN.HalfVector); //Normalisierung des Halbvektors MatTex = float3x3( IN.Tangent, -IN.Binormal, IN.Normal ); //Tangente, (negierte)Binormale und Normale in Matrix einsetzten Normal = 2.0f * tex2D(SamplerNormal, IN.TexCoord).rgb - 1.0f; //Normale der Normalmap anhand der Farbwerte bestimmen Normal = normalize( mul( MatTex, Normal ) ); //Normale wird mit Matrix multipliziert //Berechnung des Farbwerts: Intensity = saturate( dot(Normal, -LightDir) ); Diffuse = Intensity * MtrlDiffColor * LightColor * tex2D(SamplerDiffuse, IN.TexCoord); Specular = pow( max(0,dot( HalfVec, Normal)), MtrlSpecPower ) * MtrlSpecColor * LightColor; return (Diffuse + Specular + LightAmbient); } Ein Farbwert muss zwischen 0 und 1 liegen. Die Werte Normalen der Normalmap müssen auf den Bereich zwischen -1 und 1 skaliert werden. Bsp: voller Rot-Anteil -> 1 -> Normale erhält Wert 1 in Richtung der Tangente Kein rot -> 0 -> Normale erhält Wert -1 in Richtung der Tangente

  11. Die Dot3-Bumpmapping-Klasse class CBumpEffect { protected: ID3DXEffect* m_Effect; SBumpParameter m_Parameter; public: static BOOL SetupMesh( ID3DXMesh** mesh, LPDIRECT3DDEVICE9 device ); BOOL Create( LPDIRECT3DDEVICE9 Device ); void Destroy(); void Setup( SBumpParameter& Para ); DWORDBegin( LPDIRECT3DDEVICE9 Device ); void BeginPass(DWORD pass); void EndPass(); void End(); };

  12. SBumpParameter-Struktur struct SBumpParameter { //Welche Werte wurden geändert? DWORD Changed; //Licht D3DXVECTOR4 LightColor; D3DXVECTOR4 LightAmbient; D3DXVECTOR3 LightDir; //Material D3DXVECTOR4 MtrlDiffColor; D3DXVECTOR4 MtrlSpecColor; FLOAT MtrlSpecPower; LPDIRECT3DTEXTURE9 TexDiffuse; LPDIRECT3DTEXTURE9 TexNormal; }; Alle Parameter, die wir an den Effekt übergeben wollen in einer Struktur festgehalten. Changed signalisiert welche Werte geändert wurden, damit nur diese Werte neu übergeben werden müssen.

  13. Vertexdeklaration • Dient, genau wie das Flexible Vertex-Format (FVF), zur „Beschreibung“ der Vertices • Array der Struktur D3DVERTEXELEMENT9 • Jeder Array-Eintrag beschreibt ein Attribut des Vertex (z.B. Position, Normale, Tangente…) • D3DVERTEXELEMENT9-Struktur: Typedef struct _D3DVERTEXELEMENT9 { WORD Stream; WORD Offset; BYTE Type; BYTE Method; BYTE Usage; //semantische Bedeutung des Eintrags (z.B. Tangente) BYTE UsageIndex; }

  14. Die Funktion SetupMesh BOOL CBumpEffect::SetupMesh( ID3DXMesh** mesh, LPDIRECT3DDEVICE9 device ) { D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];//Vertexdeklaration D3DVERTEXELEMENT9 endDecl= D3DDECL_END();//setzt „Endeintrag“ im Array DWORD FVF = (*mesh)->GetFVF(); ID3DXMesh* clone = NULL; BumpVertex* vertex = NULL; DWORD numVertices = (*mesh)->GetNumVertices(); if( FVF!=(D3DFVF_TEX1|D3DFVF_NORMAL|D3DFVF_XYZ|D3DFVF_TEXCOORDSIZE2(1)) ) return false; /*Prüfen, ob der Mesh die Position des V., die Normale des V. und ein Texturkoordinatenpaar gespeichert hat. Diese Werte brauchen wir zur Berechnung des Tangentenraums*/ (*mesh)->GetDeclaration( decl );//Aktuelle //Vertexdeklaration wird übergeben decl[3].Stream = 0; decl[3].Offset = 32; decl[3].Type = D3DDECLTYPE_FLOAT3; decl[3].Method = D3DDECLMETHOD_DEFAULT; decl[3].Usage = D3DDECLUSAGE_TANGENT; decl[3].UsageIndex = 0; Pro Vertex sind schon 3 Einträge im Array gespeichert: Eintrag 0: Position Eintrag 1: Normale Eintrag 2: Texturkoordinaten-Paar Hier wird die Tangente hinzugefügt (Eintrag 3)

  15. decl[4].Stream = 0; decl[4].Offset = 44; decl[4].Type = D3DDECLTYPE_FLOAT3; decl[4].Method = D3DDECLMETHOD_DEFAULT; decl[4].Usage = D3DDECLUSAGE_BINORMAL; decl[4].UsageIndex = 0; decl[5] = endDecl;//Endeintrag der Vertexdeklaration (Eintrag 5) (*mesh)->CloneMesh((*mesh)->GetOptions(), decl, device, &clone )) //Mesh wird geklont und enthält nun die neuen Deklarationen SAFE_RELEASE( (*mesh) );//alten Mesh löschen *mesh = clone;//Klon einsetzten D3DXComputeTangent( clone, 0, 0, 0, false, NULL)) //Berechnet Tangentenraum return true; } Binormale wird hinzugefügt (Eintrag 4)

  16. Weitere Funktionen… • Create: BOOL CBumpEffect::Create( LPDIRECT3DDEVICE9 Device ) { ID3DXBuffer* ErrorBuffer; if( FAILED( D3DXCreateEffectFromFile( Device, "Effects/BumpMapping_FXComposer.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; }

  17. Destroy: void CBumpEffect::Destroy() { SAFE_RELEASE( m_Effect ); } • Setup: void CBumpEffect::Setup( SBumpParameter& 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 & TEXDIFFUSE ) m_Parameter.TexDiffuse = Para.TexDiffuse; if( Para.Changed & TEXNORMAL ) m_Parameter.TexNormal = Para.TexNormal; m_Parameter.Changed |= Para.Changed; }

  18. Begin: DWORD CBumpEffect::Begin( LPDIRECT3DDEVICE9 Device ) { UINT passes = 0; // Matrizen setzen D3DXMATRIX MatWorld, MatView, MatProj; D3DXMATRIX MatWVP, MatViewInv, MatWorldInv; Device->GetTransform( D3DTS_WORLD, &MatWorld ); Device->GetTransform( D3DTS_VIEW, &MatView ); Device->GetTransform( D3DTS_PROJECTION, &MatProj ); 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( "BumpMapping" ); m_Effect->Begin( &passes, 0 ); return passes; }

  19. BeginPass: void CBumpEffect::BeginPass(DWORD pass) { // 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 & TEXDIFFUSE ) m_Effect->SetTexture( "TexDiffuse", m_Parameter.TexDiffuse ); if( m_Parameter.Changed & TEXNORMAL ) m_Effect->SetTexture( "TexNormal", m_Parameter.TexNormal ); m_Effect->BeginPass( pass ); }

  20. EndPass: void CBumpEffect::EndPass() { m_Effect->EndPass(); m_Parameter.Changed = 0; } • End: void CBumpEffect::End() { m_Effect->End(); }

More Related