ich habe jetzt bei meinem Projekt Deferred Shading implementiert. Die Beleuchtung klappt hervorragend, jedoch habe ich ein kleineres (oder vielleicht großes Problem).
Ich benutze für den G-Buffer das Format A16B16G16R16F (das Problem besteht aber auch bei A32B32G32R32F).
Ich speichere in den G-Buffer die absolute Position des gerenderten Objects, also Vertex XYZ-Koordinaten.
Die Shadowmap rendere ich in ein R32F-Target und speichere auch dort die Z-Koordinate relativ zur Lichtposition (heisst View-Matrix ohne Projektion).
So sollte ich eigentlich erreichen eine lineare Depth-Map zu erhalten.
Dann berechne ich aus meinem Lichtkegel die Projected TexCoords um auf meiner Position-Map die Position zu ermitteln.
Danach habe ich die absolute Position, die ich mit der World-Matrix des Lichts multipliziere um so die Z-Koordinate relativ zur Position des Lichts zu erhalten.
Danach multipliziere ich die so erhaltende Position noch mit der Projektionsmatrix des Lichts, damit ich die Shadow-Map via Projected Texture auslesen kann, um die Z-Werte zu vergleichen.
Trotzdem ich einen Linearen Depth-Buffer habe, bekomme ich (trotz Bias) beim Schattenwurf Artefakte, die interessanterweise nicht abhängig von der Entfernung sind (oder auch doch, wer weiß).
Dazu hier mal Bilder:
Fehler relativ nah an der Lichtquelle und nur auf dem Boden.
Auch relativ nah an der Lichtquelle und nur auf dem Boden.
Hier keine Fehler obwohl das Licht auf der Wand ziemlich weit von der Lichtquelle entfernt ist.
Hier der Shader-Code für das Rendern der Depth-Map:
Code: Alles auswählen
float4x4 wvp; // Light World-View-Projection Matrix
float4x4 worldview; // Light World-View-Matrix
struct vs_out
{
float4 Pos : POSITION;
float TC : TEXCOORD0;
};
struct vs_in
{
float4 Pos : POSITION;
};
///
vs_out VS(vs_in ix)
{
vs_out ox;
ox.Pos = mul(ix.Pos, wvp);
ox.TC = mul(ix.Pos, worldview).z;
return ox;
}
float4 PS(float TC : TEXCOORD0) : COLOR
{
return float4(TC + 0.1f,0,0,0); // + 0.1f als Bias für die Shadowmap
}
Code: Alles auswählen
float4x4 wvp; // Camera WorldViewProjection
float4x4 shadowSpace; // Light World
float4x4 shadowProj; // Light Projection
float3 lPos; // Light Position
float4x4 projectiveMatrix =
{
0.5f, 0.0f, 0.0f, 0.0f,
0.0f,-0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.500625f, 0.500833f, 0.0f, 1.0f
}; // Werte für Texture 800 x 600
sampler2D tex0 : register(s0); // Albedo.RGB
sampler2D tex1 : register(s1); // Normals.XYZ
sampler2D tex2 : register(s2); // Relative Position.XYZ
sampler2D shadowSamp : register(s4); // Shadowmap.R
struct vs_out
{
float4 Pos : POSITION;
float4 TC0 : TEXCOORD0;
};
struct vs_in
{
float4 Pos : POSITION;
float2 TC0 : TEXCOORD0;
};
struct ps_in
{
float4 TC0 : TEXCOORD0;
float4 Col : COLOR0;
};
struct ps_out
{
float4 c0 : COLOR0;
};
///
float shadow2Dproj(sampler2D sTex, float4 texCoord, float objectZ, float bias)
{
float4x4 shadowProj2 =
{
0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
projectiveMatrix[3][0], projectiveMatrix[3][1], 0, 1.0f
}; // Shadowmap derzeit auch 800 x 600
float objectDepth = objectZ - bias;
texCoord = mul(texCoord, shadowProj2);
float mapDepth = tex2Dproj(sTex, texCoord);
return mapDepth < objectDepth ? 0.0f : 1.0f;
}
///
vs_out VS(vs_in ix)
{
vs_out ox;
ox.Pos = mul(ix.Pos, wvp);
ox.TC0 = ox.Pos;
return ox;
}
ps_out PS(ps_in ix)
{
ps_out ox;
ix.TC0 = mul(ix.TC0, projectiveMatrix);
float3 nrm = tex2Dproj(tex1, ix.TC0);
float3 pos = tex2Dproj(tex2, ix.TC0);
float4 shadowSpacePos = mul(float4(pos,1), shadowSpace);
float4 shadowUV = mul(shadowSpacePos, shadowProj);
float noShadow = shadow2Dproj(shadowSamp, shadowUV, shadowSpacePos.z, 0);
if (noShadow == 0) discard;
float3 nrmDir = (lPos-pos);
float lgt = length(nrmDir);
float att = 1.f / (0 + 0.25f*lgt + 0*lgt*lgt);
if (att == 0) discard;
float litx = dot(nrm, normalize(nrmDir));
ox.c0 = saturate(float4(1,1,1,1) * litx * att);
return ox;
}
///