kapitel 9.4 blooming (postprocess-effekt). postprocess-effekte 2d-effekte werden auf das gerenderte...

23
Kapitel 9.4 Blooming (Postprocess-Effekt)

Upload: dietrich-aken

Post on 05-Apr-2015

102 views

Category:

Documents


0 download

TRANSCRIPT

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

Kapitel 9.4

Blooming (Postprocess-Effekt)

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

Postprocess-Effekte

2D-Effekte Werden auf das gerenderte Bild im Framebuffer

angewendet Beispiele:

Bewegungsunschärfe Unterwassersicht Farbkorrektur/-bearbeitung/-invertierung Kantenhervorhebung Schimmer-/Schleierbildung Blooming

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

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

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

Weichzeichnen

Das Weichzeichnen erfolgt durch folgenden Algorithmus: FarbwertPunkt =

(FarbwertPunkt x GewichtungPunkt) + (FarbwertebenachbartePunkte x GewichtungbenachbartePunkte)

Bsp:

w0 = 0,4; w1 = 0,2

Pixelgewichtung Eingangsbild Ausgangsbild

0,80,60,2

0,60,40

0,200

110

100

000

0w10

w1w0w1

0w10

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

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 EckeUV(1,1)rechte, untere Ecke

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

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

VerkleinerteTextur

weichzeichnen

Schritt 3

EingangstexturMit weichge-

zeichneter Texturaddieren

Eingangstextur

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

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:

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

Der Pixelshader PS_Textured

//Texturvariable definierenTexture TexInput0;

//Textursamplersampler Sampler0 = sampler_state { texture = <TexInput0>; AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; MIPFILTER = LINEAR; MINFILTER = LINEAR; MAGFILTER = LINEAR;};

//Pixelshadervoid 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.

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

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:

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

Zusätzlich müssen wir die Gewichtungen für die benachbarten Pixel ineinem Array festhalten:

static const float BlurWeights[13] = {

0.002216, 0.008764, 0.026995, 0.064759, 0.120985, 0.176033, 0.199471, 0.176033, 0.120985, 0.064759, 0.026995, 0.008764, 0.002216,

};

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

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

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;

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

Der Pixelshader PS_Add

//Texturvariable definierenTexture TexInput1;

//Textursamplersampler Sampler1 = sampler_state { texture = <TexInput1>; AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; MIPFILTER = LINEAR; MINFILTER = LINEAR; MAGFILTER = LINEAR;};

//Pixelshadervoid PS_Add( float2 texcoord : TEXCOORD0, out float4 Color : COLOR ){

Color = tex2D( Sampler0, texcoord ) + tex2D( sampler1, texcoord );

}

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

Die Blooming-Klasseclass CBloomEffect{protected:

ID3DXEffect* m_Effect; //EffektinstanzLPDIRECT3DTEXTURE9 m_texCopyOrgRT;//Kopie des aktuellen Rendetargets

//OriginalbildLPDIRECT3DTEXTURE9 m_texReduced; //verkleinerte TexturLPDIRECT3DTEXTURE9 m_texBloomed; //verkl. Textur nach WeichzeichnenLPDIRECT3DVERTEXBUFFER9 m_VB; //Vertexbuffer urspr. Rendertarget

// für die Fläche die den Bildschirm einnehmen sollLPDIRECT3DVERTEXBUFFER9 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();

};

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

Die Create-FunktionBOOL CBloomEffect::Create( LPDIRECT3DDEVICE9 Device ){

ID3DXBuffer* ErrorBuffer = NULL;LPDIRECT3DSURFACE9 BackBuffer = NULL;D3DSURFACE_DESC BackBufferDesc;void* VertexData;

//Erzeugen der Effektinstanz aus der FX-Dateiif( 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-DescriptorDevice->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 Backbuffersif( FAILED( Device->CreateTexture( BackBufferDesc.Width, //Breite

BackBufferDesc.Height, //Höhe1, //Mipmaps D3DUSAGE_RENDERTARGET,

//Usage BackBufferDesc.Format, //Format D3DPOOL_DEFAULT, //Pool&m_texCopyOrgRT, //Ziel NULL ) ) ) //Reserv. return false;

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

//Erzeugen der verkleinerten Texturenif( 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

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

Um die Vertexbuffer zu erstellen wird zunächst in der Header-Datei

folgende Struktur beschrieben:struct SBloomVertex{

D3DXVECTOR4 pos;FLOAT u;FLOAT v;

};

Wir werden pro Vertexbuffer 6 Vertices definieren:

Vertices[0] Vertices[1]

Vertices[4]

Vertices[2]Vertices[3] Vertices[5]

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

{//Vertices in Struktur anlegenSBloomVertex 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( -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 erstellenif( 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();}

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

{//zweiten Vertexbuffer anlegenSBloomVertex 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( -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;}

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

Die PostProcess-Funktion

void CBloomEffect::PostProcess( LPDIRECT3DDEVICE9 Device ){

UINT passes = 0;LPDIRECT3DSURFACE9 OrgRenderTarget = NULL;LPDIRECT3DSURFACE9 Surface = NULL;

// Backup des originalen RendertargetsDevice->GetRenderTarget( 0, &OrgRenderTarget );

// Wir kopieren das Target in eine Textur, damit wir es als// Eingang für einen Shader verwenden könnenm_texCopyOrgRT->GetSurfaceLevel( 0, &Surface );Device->StretchRect( OrgRenderTarget, NULL, Surface, NULL,

D3DTEXF_NONE );Surface->Release();

//Wir deaktivieren das Schreiben und Lesen des Z-BuffersDevice->SetRenderState( D3DRS_ZENABLE, false );Device->SetRenderState( D3DRS_ZWRITEENABLE, false );Device->SetFVF( SBLOOMVERTEX_FVF );

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

//momentares Rendertarget durch das verkleinerte RT ersetzenm_texReduced->GetSurfaceLevel( 0, &Surface );Device->SetRenderTarget( 0, Surface );Surface->Release();

m_Effect->SetTechnique( "Blooming" );m_Effect->Begin( &passes, 0 );

// pass 0 => Reduziere Textur!if( SUCCEEDED( Device->BeginScene() ) ){

m_Effect->SetTexture( "TexInput0", m_texCopyOrgRT ); //m_texCopyOrgRT m_Effect->BeginPass( 0 ); // übergeben (Kopie der gerenderten Szene)

// Render QuadDevice->SetStreamSource( 0, m_VBreduced, 0, sizeof(SBloomVertex) );

Device->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 ); //

m_Effect->EndPass();Device->EndScene();

}

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

// Rendertarget neu setzen!m_texBloomed->GetSurfaceLevel( 0, &Surface );Device->SetRenderTarget( 0, Surface );Surface->Release();

// pass 1 => verwischen der reduzierten Textur!if( SUCCEEDED( Device->BeginScene() ) ){

m_Effect->SetTexture( "TexInput0", m_texReduced );m_Effect->BeginPass( 1 );

// Render QuadDevice->SetStreamSource( 0, m_VBreduced, 0, sizeof(SBloomVertex) );

Device->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );//

m_Effect->EndPass();Device->EndScene();

}

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

//ursprüngl. Rendertarget wiedr an 3D-Device übergebenDevice->SetRenderTarget( 0, OrgRenderTarget );OrgRenderTarget->Release();

// pass 1 => verwischen der reduzierten Textur!if( SUCCEEDED( Device->BeginScene() ) ){

m_Effect->SetTexture( "TexInput0", m_texBloomed );m_Effect->SetTexture( "TexInput1", m_texCopyOrgRT );m_Effect->BeginPass( 2 );

// Render QuadDevice->SetStreamSource( 0, m_VB, 0, sizeof(SBloomVertex) );

Device->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );//

m_Effect->EndPass();Device->EndScene();

}

//Effekt beenden und Z-Buffer wieder aktivierenm_Effect->End();Device->SetRenderState( D3DRS_ZENABLE, true );Device->SetRenderState( D3DRS_ZWRITEENABLE, true );

}

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

Weitere Funktionen...CbloomEffect::CBloomEffect() //Konstruktor{

m_texCopyOrgRT = NULL;m_texReduced = NULL;m_texBloomed = NULL;m_VB = NULL;m_VBreduced = NULL;m_Effect = NULL;

}

void CbloomEffect::Destroy() //Destruktor{

SAFE_RELEASE( m_Effect );SAFE_RELEASE( m_VB );SAFE_RELEASE( m_VBreduced );SAFE_RELEASE( m_texCopyOrgRT );SAFE_RELEASE( m_texReduced );SAFE_RELEASE( m_texBloomed );

}

void CBloomEffect::SetBloomFactor( float factor ) //Setter-Funktion{

if( m_Effect )m_Effect->SetFloat( "BloomFactor", factor );

}