[D3D10] Shadowmapping + Deferred Rendering (Problem)
Verfasst: 07.10.2010, 22:56
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.

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

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
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
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)
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.
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
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);
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
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)