[D3D10] Shadowmapping + Deferred Rendering (Problem)

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
beuschl
Beiträge: 34
Registriert: 26.07.2009, 08:47

[D3D10] Shadowmapping + Deferred Rendering (Problem)

Beitrag von beuschl »

Hi

Ich bin gerade dabei shadowmapping unter directx 10 zusammen mit meinem bestehenden deferred renderer zum laufen zu bringen. Prinzipiell scheint es auch zu funktionieren, nur bekomme ich das zusammenspiel mit meinem deferred renderer nicht richtig hin.

Für den Anfang habe ich zuerst einmal nur für DirectionalLights das shadowmapping implementiert. Beim folgenden Screenshot sieht man auch, dass das eine Objekt in der Szene einen korrekt aussehenden Schatten wirft.

Bild

Wie man auf den Bild sieht ist allerdings die gesamte Szene abgedunkelt und nur ein kleiner viereckiger bereich richtig beleuchtet. Ich glaube dieser viereckige Bereich hängt mit der Projection Matrix des Lichts zusammen, für das die Shadowmap erstellt und dann im licht shader ausgelesen wird. Ich habe aber derzeit echt keine idee, wie ich das shadowmapping für die komplette szene richtig zum laufen bringen kann und nicht nur für einen kleinen bereich.

Folgender Screenshot zeigt die Shadowmap, die ich aus der sicht des DirectionalLights erstellt habe

Bild

Anbei noch ein paar Codestücke:

Hier berechne ich die View und Projection Matrix der Lichtquelle (jedes frame, falls sich die position geändetr hat) Vor allem bei den Werten für die Projection Matrix hab ich keine Ahnung, welche ich da am besten wählen sollte, tipps wären hilfreich

Code: Alles auswählen

D3DXMatrixLookAtLH(&m_mView, &m_vPosition, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
D3DXMatrixOrthoLH(&m_mProj, 300.0f,300.0f, 1.0f, 12000.0f);
Nachdem ich die Shadowmap für die Lichtquelle erstellt habe (siehe Screenshot oben), zeichne ich wie üblich all meine Objekte in den GBuffer meines Defferd renderers.
Danach kommen die Lichtberechnungen für den Lightbuffer. Dafür schicke ich die Shadowmap + Licht ViewProjection Matrix zum Shader. Hier einige Ausschnitte aus diesem Shader (die meiner Meinung nach relevant sind, bzw dort der Fehler sein könnte)

SHADOW_EPSILON = 0.001f
SMAP_SIZE = 2048;
SMAP_DX = 1.0f/SMAP_SIZE

Code: Alles auswählen

float CalcShadowFactor(float4 projTexC)
{
	// Complete projection by doing division by w.
	projTexC.xyz /= projTexC.w;
	
	// Points outside the light volume are in shadow.
	if( projTexC.x < -1.0f || projTexC.x > 1.0f || 
	    projTexC.y < -1.0f || projTexC.y > 1.0f ||
	    projTexC.z < 0.0f )
	    return 0.0f;
	    
	// Transform from NDC space to texture space.
	projTexC.x = +0.5f*projTexC.x + 0.5f;
	projTexC.y = -0.5f*projTexC.y + 0.5f;
	
	// Depth in NDC space.
	float depth = projTexC.z;

	
		// Sample shadow map to get nearest depth to light.
		float s0 = g_ShadowMap.Sample(g_samShadow, projTexC.xy).r;
		float s1 = g_ShadowMap.Sample(g_samShadow, projTexC.xy + float2(SMAP_DX, 0)).r;
		float s2 = g_ShadowMap.Sample(g_samShadow, projTexC.xy + float2(0, SMAP_DX)).r;
		float s3 = g_ShadowMap.Sample(g_samShadow, projTexC.xy + float2(SMAP_DX, SMAP_DX)).r;
	
		// Is the pixel depth <= shadow map value?
		float result0 = depth <= s0 + SHADOW_EPSILON;
		float result1 = depth <= s1 + SHADOW_EPSILON;
		float result2 = depth <= s2 + SHADOW_EPSILON;
		float result3 = depth <= s3 + SHADOW_EPSILON;	
	
		// Transform to texel space.
		float2 texelPos = SMAP_SIZE*projTexC.xy;
	
		// Determine the interpolation amounts.
		float2 t = frac( texelPos );
	
		// Interpolate results.
		return lerp( lerp(result0, result1, t.x), lerp(result2, result3, t.x), t.y);
}

////////////////////////////////////
// PIXELSHADER AUSSCHNITT


    float4 projTexC = mul(position, LightVP);        // position = Worldspace, LightVP = LightViewProjectionMatrix
    float shadowFactor = CalcShadowFactor(projTexC);

 // hier werden jetzt die normalen Lichtberechnungen des Directional Lights durchgeführt
// am Ende kommt das hier
return float4(diffuseLight.rgb*shadowFactor, Specular_Directional*shadowFactor);

// der specular factor Specular_Directional wird erst beim zusammenfügen von Colorbuffer und Lightbuffer zum diffusen Lichtanteil dazugezählt, deswegen hier im alphakanal des Rendertargets gespeichert
So das wars fürs erste. Ich hoffe ihr könnt mir weiterhelfen
Glaube derzeit wie gesagt, dass der Fehler irgendwie mit der Projection Matrix des Lichts zusammenhängen könnte, aber ich habe echt keine Ahnung was für Parameter ich dort setzen soll, damit wirklich die gesamte Szene einbezogen wird (so wie es für ein Directional Light halt üblich ist)
Dirk Schulz
Establishment
Beiträge: 130
Registriert: 01.03.2009, 14:21
Alter Benutzername: frittentuete

Re: [D3D10] Shadowmapping + Deferred Rendering (Problem)

Beitrag von Dirk Schulz »

Hi,

lange her, dass ich orthogonales Shadow Mapping implementiert habe, aber hier mal wie ich es gemacht habe:

Erstmal im Shader (damit die nicht von der Shadowmap erfassten Teile erstmal hell werden) :

Code: Alles auswählen

// im Shadowsampler
AddressU = Border;
AddressV = Border;
Bordercolor = 0xffffffff;
meine LightViewProjMatrix sah ungefähr so aus:

Code: Alles auswählen

LookAt = -(D3DXVECTOR3)Light.Direction;

D3DXMatrixLookAtLH(&lightMatrix, &(D3DXVECTOR3(0.0f, 0.0f, 0.0f)), &LookAt, &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

D3DXMatrixOrthoLH(&lightproj, -1.0f, 1.0f, 0.0f, 1.0f);
Bei direktionalem Licht (also orthogonaler ProjektionsMatrix) sollte die Position keine Rolle spielen/keine Auswirkungen haben.


Hoffe das hilft.
Benutzeravatar
RustySpoon
Establishment
Beiträge: 298
Registriert: 17.03.2009, 13:59
Wohnort: Dresden

Re: [D3D10] Shadowmapping + Deferred Rendering (Problem)

Beitrag von RustySpoon »

Noch was zur Projektionsmatrix: Ich würde die definitiv in jedem Frame oder zumindest nach jeder Bewegung neu berechnen. Das Problem ist, wenn du die so aus der Hüfte dimensionierst, wird das Lichtfrustum in der Regel nicht passen. Das Ziel sollte es sein, das Lichtfrustum so klein wie möglich zu halten, um die begrenzte Auflösung der Shadowmap optimal ausnutzen zu können. Du kannst z.B. das Kamerafrustum in den Lichtraum transformieren, da dann eine Bounding-Box drumherum konstruieren und dann ergeben sich die Parameter deiner orthogonalen Projektionsmatrix von selbst. Bisschen nachkorrigieren musst du dann doch noch, es kann z.B. zu Schattierungsfehlern kommen, wenn Objekte dann aus diesem Lichtfrustum herausragen - einfach die Bounding-Box soweit vergrößern, das alle geschnittenen Objekte enthalten sind. Außerdem kann es passieren, dass Objekte, die außerhalb der Box liegen einen Schatten in den sichtbaren Bereich werfen. Ich weiß nicht, ob es da eine ultimative Lösung gibt, aber im Prinzip musst du natürlich die betroffenen Objekte einfach mit erfassen. Bei mir hat sich das damals relativ einfach lösen lassen, weil ich eine Top-Down-Perspektive hatte und man schnell errechnen kann um wieviel man die Box in welche Richtung vergrößern muss.
beuschl
Beiträge: 34
Registriert: 26.07.2009, 08:47

Re: [D3D10] Shadowmapping + Deferred Rendering (Problem)

Beitrag von beuschl »

mhm das hat irgendwie nicht hingehaut.

allerdings: wenn ich im shader bei

if( projTexC.x < -1.0f || projTexC.x > 1.0f ||
projTexC.y < -1.0f || projTexC.y > 1.0f ||
projTexC.z < 0.0f )
return 0.0f;

das return 0.0f auf return 1.0f ändere, ist meine szene richtig beleuchtet und der schatten ist auch da! ändere ich aber meine Projection matrix des lichts auf andere werte (zb die von dir) D3DXMatrixOrthoLH(&lightproj, -1.0f, 1.0f, 0.0f, 1.0f);
hab ich wieder eine dunkle szene bzw ein riesiges schwarzes viereck am "boden"

erst wenn ich ca solche werte habe D3DXMatrixOrthoLH(&lightproj, 300.0f, 300.0f, 1.0f, 1000.0f); sehe ich überhaupt einen schatten, bzw wird beim erstellen der shadowmap einer in die textur gezeichnet... anonsten bleibt die shadowmap immer komplett weiss (1.0f) und daher hab ich am ende in der szene auch keinen schatten

hab echt ka warum das so ist, kann mir jemand das erklären?
joggel

Re: [D3D10] Shadowmapping + Deferred Rendering (Problem)

Beitrag von joggel »

beuschl hat geschrieben: erst wenn ich ca solche werte habe D3DXMatrixOrthoLH(&lightproj, 300.0f, 300.0f, 1.0f, 1000.0f); sehe ich überhaupt einen schatten,...
http://msdn.microsoft.com/en-us/library ... 85%29.aspx
Laut Doku müssen deine Werte diese Größe haben, denn es sind ja die Dimensionen der Projektionsebene, oder?
Antworten