Kapitel 9.4 Blooming (Postprocess-Effekt). Postprocess-Effekte 2D-Effekte Werden auf das gerenderte Bild im Framebuffer angewendet Beispiele: Bewegungsunschärfe.

Slides:



Advertisements
Ähnliche Präsentationen
der Universität Oldenburg
Advertisements

der Universität Oldenburg
Klassen - Verkettete Liste -
Objektorientierte Programmierung
Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure.
Kurt Rosenberg. C# für.NET oder.NET für C# is(C# == C++ && Java)? true : false ; reines C# Ausblick Überblick.
Kapitel 3: Listen Lineare Liste: endliche Folge von Elementen eines Grundtyps (n>=0), leere Liste falls n=0 Listenelemente besitzen.
Environment Mapping.
Kapitel 9.3 Dot3-Bumpmapping (Normalmapping). Bumpmaps Textur, deren Pixel unterschiedlich auf einfallendes Licht reagieren Betrachter hat den Eindruck,
Elemente der 3D-Grafikprogrammierung
Ultris Version 8: Erzeugen der Formen und Anzeigen der Vorschau
Ultris V10 Bewegen, Drehen und Kollisionserkennung.
Verteilte Software - Java - Prozedurale Programmierung 1
FH-Hof Texturen Richard Göbel. FH-Hof Anwendungen von Texturen Darstellung von 2D-Bildern Gestaltung von Oberflächen Simulation komplexer Geometrien...
Java2D Richard Göbel.
Java: Dynamische Datentypen
Listen Richard Göbel.
Indirekte Adressierung
FH-Hof Texturen Richard Göbel. FH-Hof Anwendungen von Texturen Darstellung von 2D-Bildern Gestaltung von Oberflächen Simulation komplexer Geometrien...
FH-Hof Java 2D - Kontext für Zeichenoperationen Richard Göbel.
Java: Grundlagen der Objektorientierung
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.
WHILE - Anweisung. Aufgabe : Ausgabe aller ganzen Zahlen von 0 bis 100 auf dem Bildschirm.
FOR Anweisung. Aufgabe : Ausgabe aller ganzen Zahlen von 0 bis 100 auf dem Bildschirm.
DO...WHILE Anweisung.
Shaderprogrammierung T. Goeschel + F. Theilacker
Simulation und 3D-Programmierung Praxis: Dreiecke, Texturen, Vertex-Buffer Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung.
Spieleprogrammierung mit DirectX und C++
1 Named Pipes alias FIFO Haben einen Eintrag im Dateisystem und sind somit durch Zugriffsrechte identifizierbar Ermöglichen die Kommunikation zwischen.
Praktikum Entwicklung und Einsatz von Geosoftware I - Sitzung 3 Klassen, Objekte, Arrays und Kontrollstrukturen Sommersemester 2003 Lars Bernard.
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure.
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 10 Claudio Moraga; Gisbert Dittrich FBI Unido
Programmieren mit JAVA Teil V. Grafikausgabe mit JAVA, das AWT Java wurde von Anfang an mit dem Anspruch entwickelt, ein vielseitiges, aber einfach zu.
Zusammenfassung Vorwoche
Einführung in Visual C++
1DVG3 - Paint Paint ein Zeichenprogramm. DVG3 - Paint 2 Paint – ein Zeichenprogramm.
14StrukturKlasse1 Von der Struktur zur Klasse von C zu C++ Von Jens Hoffmann
DVG Interfaces. DVG mehrfache Vererbung 4 Mehrfache Vererbung ist die Ableitung einer Klassen von mehreren anderen Klassen. –farbigerPunkt.
DVG Einführung in Java1 Einführung in JAVA.
DVG Klassen und Objekte
Special Effects Realistischeres Rendern einer Scene.
Wir müssen also überlegen: Implementierung der Knoten, Implementierung der Kanten, daraus: Implementierung des Graphen insgesamt. Annahme: die Knoteninhalte.
Struktur-Funktions-Modelle von Pflanzen - Sommersemester Winfried Kurth Universität Göttingen, Lehrstuhl Computergrafik und Ökologische Informatik.
Random Heightmap on GPU
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.
Einfach verkettete Listen (OOP)
Java ohne Kara. Java ohne Kara Ab jetzt: Java ohne Kara Ziel: Erfahrungen sammeln mit ersten Java Programmen.
Informatik 1 Übung 8. NACHBESPRECHUNG Übung 8 Rekursion Existiert Weg von A nach B?
3D- Spieleprogrammierung
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Von der Planung bis zum Hauptmenü Seminar: Softwaretechnologie II Dozent: Prof. Manfred Thaller Referent: Jan Bigalke.
X y Bild I.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure
Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fakultät.
Einführung in die Programmierung
Einführung in die Programmiersprache C 4
Informatik 1 Letzte Übung.
CuP - Java Neunte Vorlesung Entspricht Kapitel 4.2 und 5 des Skriptums
Java-Kurs - 8. Übung Besprechung der Hausaufgabe.
C++ SFINAE inkl. std::enable_if
Softwaretechnologie für Fortgeschrittene Teil Thaller Stunde IV: Bildverarbeitung IV Köln 15. Januar 2015.
Mag. Thomas Hilpold, Universität Linz, Institut für Wirtschaftsinformatik – Software Engineering 1 Algorithmen und Datenstrukturen 1 SS 2002 Mag.Thomas.
ROBERT NYSTROM GAME PROGRAMMING PATTERNS III.8 Thema: Sequencing Patterns Seminar: Softwaretechnologie II (Teil 2) Dozent: Prof. Dr. Manfred Thaller Referent:
Java Programme nur ein bisschen objektorientiert.
Tutorium Software-Engineering SS14 Florian Manghofer.
Java-Kurs Übung Grafik in Java - das Abstract Windowing Toolkit
 Präsentation transkript:

Kapitel 9.4 Blooming (Postprocess-Effekt)

Postprocess-Effekte 2D-Effekte Werden auf das gerenderte Bild im Framebuffer angewendet Beispiele: Bewegungsunschärfe Unterwassersicht Farbkorrektur/-bearbeitung/-invertierung Kantenhervorhebung Schimmer-/Schleierbildung Blooming

Blooming Effekt zur Schleierbildung Helle Pixel sollen benachbarte Pixel überstrahlen bzw. scharfe Konturen sollen ausfransen Schritte: Gerendertes Eingangsbild in Textur kopieren Diese Textur weichzeichnen neue Textur Farbwerte der beiden Texturen addieren

Weichzeichnen Das Weichzeichnen erfolgt durch folgenden Algorithmus: F arbwert Punkt = (Farbwert Punkt x Gewichtung Punkt ) + (Farbwerte benachbartePunkte x Gewichtung benachbartePunkte ) Bsp: w 0 = 0,4; w 1 = 0,2 PixelgewichtungEingangsbildAusgangsbild 0,80,60,2 0,60,40 0, w1w1 0 w1w1 w0w0 w1w1 0w1w1 0

Eine Gewichtung, die für gute Ergebnisse sorgt, ist die Gewichtung nach der Gauß-Glocke mit folgender Verteilung: Damit wir überhaupt Koordinaten für die jeweiligen Pixel haben kopieren wir das gerenderte Bild vor dem Weichzeichnen in eine Textur, und ziehen diese auf eine Fläche, die den Ausmaßen des Bildschirms entspicht. UV(0,0) linke, obere Ecke UV(1,1) rechte, untere Ecke

Die Effektdatei Bevor das Bild weichgezeichnet wird, verkleinern wir es, um Rechenaufwand zu sparen Wir gehen also nach folgendem Schema vor: Jeder Schritt stellt einen Pass in der Effektdatei dar: pass Downsize pass Bloom pass AddTextures Schritt 1 Eingangstextur verkleinern Schritt 2 Verkleinerte Textur weichzeichnen Schritt 3 Eingangstextur Mit weichge- zeichneter Textur addieren Eingangstextur

technique Blooming { pass Downsize { VertexShader= compile vs_2_0 VS_Passthru(); PixelShader= compile ps_2_0 PS_Textured(); } pass Bloom { VertexShader= compile vs_2_0 VS_Passthru(); PixelShader= compile ps_2_0 PS_Bloom(); } pass AddTextures { VertexShader= compile vs_2_0 VS_Passthru(); PixelShader= compile ps_2_0 PS_Add(); } void VS_Passthru( float4 Pos : POSITION, float2 tex : TEXCOORD0, out float4 oPos : POSITION, out float2 texcoord : TEXCOORD0 ) { oPos= Pos; texcoord= tex; } Der Vertexshader leitet die Vertices einfach weiter:

Der Pixelshader PS_Textured //Texturvariable definieren TextureTexInput0; //Textursampler sampler Sampler0 = sampler_state { texture = ; AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; MIPFILTER = LINEAR; MINFILTER = LINEAR; MAGFILTER = LINEAR; }; //Pixelshader void PS_Textured( float2 texcoord : TEXCOORD0, out float4 Color : COLOR ) { Color = tex2D( Sampler0, texcoord ); } Der Pixelshader selbst sorgt nicht dafür, dass die Textur verkleinert wird. Dazu müssen wir in der C++-Klasse ein verkleinertes surface als Rendertarget für diesen Pass verwenden.

Vorbereitungen für den Pixelshader PS_Bloom float2 HorizontalPixel[13] = { { -6, 0 }, { -5, 0 }, { -4, 0 }, { -3, 0 }, { -2, 0 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 0 }, { 5, 0 }, { 6, 0 }, }; float2 VerticalPixel[13] = { { 0, -6 }, { 0, -5 }, { 0, -4 }, { 0, -3 }, { 0, -2 }, { 0, -1 }, { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, { 0, 6 }, }; Zunächst müssen wir 2 Arrays anlegen, damit wir jeweils 12 benachbarte Pixel in der horizontalen und vertikalen Ebene verrechnen können:

Zusätzlich müssen wir die Gewichtungen für die benachbarten Pixel in einem Array festhalten: static const float BlurWeights[13] = { , , , , , , , , , , , , , }; Da unsere verkleinerte Textur 256 x 256 Pixel groß sein soll, müssen wir noch folgendes definieren: #define REDUCED_WIDTH 256 #define REDUCED_HEIGHT 256

Der Pixelshader PS_Bloom void PS_Bloom( float2 texcoord : TEXCOORD0, out float4 Color : COLOR ) { float2 uvoffset; Color = float4( 0.0f, 0.0f, 0.0f, 1.0f ); for( int i=0; i < 13; i++ ) { uvoffset = VerticalPixel[i].xy/float2( 1.0f, REDUCED_HEIGHT ) //Bestimmen des offsets (Abstands)zum Nachbarpixel Color+= tex2D( Sampler0, texcoord + uvoffset ) * BlurWeights[i]; //Gewichtung eines Nachbarpixels mit diesem multiplizieren und //zu Color addieren uvoffset = HorizontalPixel[i].xy/float2( REDUCED_WIDTH, 1.0f); Color+= tex2D( Sampler0, texcoord + uvoffset ) * BlurWeights[i]; //die beiden Schritte für die horizontale Ebene wiederholen } Color=Color*BloomFactor; //neuen Farbwert mit konstantem Faktor addieren } Parameter wird vorher definiert: float BloomFactor = 1.2f;

Der Pixelshader PS_Add //Texturvariable definieren TextureTexInput1; //Textursampler sampler Sampler1 = sampler_state { texture = ; AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; MIPFILTER = LINEAR; MINFILTER = LINEAR; MAGFILTER = LINEAR; }; //Pixelshader void PS_Add( float2 texcoord : TEXCOORD0, out float4 Color : COLOR ) { Color = tex2D( Sampler0, texcoord ) + tex2D( sampler1, texcoord ); }

Die Blooming-Klasse class CBloomEffect { protected: ID3DXEffect* m_Effect;//Effektinstanz LPDIRECT3DTEXTURE9 m_texCopyOrgRT;//Kopie des aktuellen Rendetargets // Originalbild LPDIRECT3DTEXTURE9 m_texReduced;//verkleinerte Textur LPDIRECT3DTEXTURE9 m_texBloomed;//verkl. Textur nach Weichzeichnen LPDIRECT3DVERTEXBUFFER9 m_VB;//Vertexbuffer urspr. Rendertarget // für die Fläche die den Bildschirm einnehmen soll LPDIRECT3DVERTEXBUFFER9 m_VBreduced;//Vertexbuffer verkl. Rendertarget // Fläche für verringerte Eingangstexturen public: CBloomEffect(); BOOL Create( LPDIRECT3DDEVICE9 Device ); void PostProcess( LPDIRECT3DDEVICE9 Device ); void SetBloomFactor( float factor ); void Destroy(); };

Die Create -Funktion BOOL CBloomEffect::Create( LPDIRECT3DDEVICE9 Device ) { ID3DXBuffer*ErrorBuffer = NULL; LPDIRECT3DSURFACE9BackBuffer = NULL; D3DSURFACE_DESCBackBufferDesc; void*VertexData; //Erzeugen der Effektinstanz aus der FX-Datei if( FAILED( D3DXCreateEffectFromFile( Device, "Effects/bloom.fx", NULL, NULL, 0, NULL, &m_Effect, &ErrorBuffer ) ) ) { char *Errors = (char*) ErrorBuffer->GetBufferPointer(); fprintf( stderr, "%s", Errors ); return false; } //Wir holen uns Informationen über das aktuelle Rendertarget über den surface-Descriptor Device->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &BackBuffer ); BackBuffer->GetDesc( &BackBufferDesc );//Surface-Descriptor enthält Info über Auflösung etc. SAFE_RELEASE(BackBuffer); //Textur erzeugen mit Hilfe der Auflösung und des Formats des Backbuffers if( FAILED( Device->CreateTexture(BackBufferDesc.Width, //Breite BackBufferDesc.Height,//Höhe 1, //MipmapsD3DUSAGE_RENDERTARGET, //UsageBackBufferDesc.Format,//Format D3DPOOL_DEFAULT, //Pool&m_texCopyOrgRT, //ZielNULL ) ) )//Reserv. return false;

//Erzeugen der verkleinerten Texturen if( FAILED( Device->CreateTexture(REDUCED_WIDTH, REDUCED_HEIGHT, 1, D3DUSAGE_RENDERTARGET, BackBufferDesc.Format, D3DPOOL_DEFAULT, &m_texReduced, NULL ) ) ) return false; if( FAILED( Device->CreateTexture(REDUCED_WIDTH, REDUCED_HEIGHT, 1, D3DUSAGE_RENDERTARGET, BackBufferDesc.Format, D3DPOOL_DEFAULT, &m_texBloomed, NULL ) ) ) return false; Breite und Höhe der verkleinerten Texturen müssen wir vorher definieren: #define REDUCED_WIDTH 256 #define REDUCED_HEIGHT 256

Um die Vertexbuffer zu erstellen wird zunächst in der Header-Datei folgende Struktur beschrieben: struct SBloomVertex { D3DXVECTOR4 pos; FLOATu; FLOATv; }; Wir werden pro Vertexbuffer 6 Vertices definieren: Vertices[0]Vertices[1] Vertices[4] Vertices[2] Vertices[3]Vertices[5]

{ //Vertices in Struktur anlegen SBloomVertex Vertices[6] = { { D3DXVECTOR4( -0.5f, -0.5f, 0.0f, 1.0f), 0.0f, 0.0f }, { D3DXVECTOR4( BackBufferDesc.Width-0.5f, -0.5f, 0.0f, 1.0f), 1.0f, 0.0f }, { D3DXVECTOR4( -0.5f, BackBufferDesc.Height-0.5f, 0.0f, 1.0f), 0.0f, 1.0f }, { D3DXVECTOR4( BackBufferDesc.Width-0.5f, -0.5f, 0.0f, 1.0f), 1.0f, 0.0f }, { D3DXVECTOR4( BackBufferDesc.Width-0.5f, BackBufferDesc.Height- 0.5f, 0.0f, 1.0f), 1.0f, 1.0f }, }; //mit Hilfe der Struktur Vertexbuffer m_VB erstellen if( FAILED( Device->CreateVertexBuffer( sizeof(SBloomVertex)*6, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,D3DPOOL_DEFAULT, &m_VB, NULL ) ) ) return false; if( FAILED( m_VB->Lock( 0, 0, &VertexData, D3DLOCK_DISCARD ) ) ) return false; memcpy( VertexData, Vertices, sizeof(SBloomVertex)*6 ); m_VB->Unlock(); }

{ //zweiten Vertexbuffer anlegen SBloomVertex Vertices[6] = { { D3DXVECTOR4( -0.5f, -0.5f, 0.0f, 1.0f), 0.0f, 0.0f }, { D3DXVECTOR4( REDUCED_WIDTH-0.5f, -0.5f, 0.0f, 1.0f), 1.0f, 0.0f }, { D3DXVECTOR4( -0.5f, REDUCED_HEIGHT-0.5f, 0.0f, 1.0f), 0.0f, 1.0f }, { D3DXVECTOR4( REDUCED_WIDTH-0.5f, -0.5f, 0.0f, 1.0f), 1.0f, 0.0f }, { D3DXVECTOR4( REDUCED_WIDTH-0.5f, REDUCED_HEIGHT-0.5f, 0.0f, 1.0f), 1.0f, 1.0f }, }; if( FAILED( Device->CreateVertexBuffer( sizeof(SBloomVertex)*6, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &m_VBreduced, NULL ) ) ) return false; if( FAILED( m_VBreduced->Lock( 0, 0, &VertexData, D3DLOCK_DISCARD ) ) ) return false; memcpy( VertexData, Vertices, sizeof(SBloomVertex)*6 ); m_VBreduced->Unlock(); } return true; }

Die PostProcess -Funktion void CBloomEffect::PostProcess( LPDIRECT3DDEVICE9 Device ) { UINTpasses= 0; LPDIRECT3DSURFACE9OrgRenderTarget= NULL; LPDIRECT3DSURFACE9Surface= NULL; // Backup des originalen Rendertargets Device->GetRenderTarget( 0, &OrgRenderTarget ); // Wir kopieren das Target in eine Textur, damit wir es als // Eingang für einen Shader verwenden können m_texCopyOrgRT->GetSurfaceLevel( 0, &Surface ); Device->StretchRect( OrgRenderTarget, NULL, Surface, NULL, D3DTEXF_NONE ); Surface->Release(); //Wir deaktivieren das Schreiben und Lesen des Z-Buffers Device->SetRenderState( D3DRS_ZENABLE, false ); Device->SetRenderState( D3DRS_ZWRITEENABLE, false ); Device->SetFVF( SBLOOMVERTEX_FVF );

Weitere Funktionen...