Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

FSA

Community-Fossil

  • »FSA« ist der Autor dieses Themas
  • Private Nachricht senden

1

01.07.2013, 20:10

Shadowmap Artefakte

Hallo. Ich bin so langsam am verzweifeln an einem Problem, welches ich mir nicht erklären kann.
Um ein Schatten werfendes Punktlicht zu realisieren, habe ich eine Cube-Texture vom Format R32F (32Bit Floating point). Mein Depthbuffer Format dazu ist D24S8 (24 Bit Depth). Bei einer Auflösung von 128x128 pro CubeMapFace erhalte ich Artefakte, wie im Bild 1 zu sehen, wenn mein Licht nah an einem Objekt ist. Auch bei 512x512 pro Seite habe ich diese Artefakte. Zwar enstehen sie erst bei einem größeren Radius, aber sie sind einfach stören. Mit einem PCF bekomme ich es etwas besser. Aber die Artefakte sind immer noch sichtbar. Der HLSL Code zur Berechnung der Shadowmap:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void VertDepthCube( float4 Pos : POSITION,
                 float3 Normal : NORMAL,
                 out float4 oPos : POSITION,
                 out float3 olV : TEXCOORD0 )
{
    oPos = mul( Pos, g_WorldViewProjectionMatrixLight );

    float4 positionW = mul( Pos, g_WorldMatrix );

    olV = g_Light.pos.xyz - positionW.xyz;
}

//-----------------------------------------------------------------------------
// Pixel Shader: PixShadow
// Desc: Process pixel for the shadow map
//-----------------------------------------------------------------------------
float4 PixDepthCube(float4 iPos : POSITION,
                 float3 ilV : TEXCOORD0 )   : COLOR0
{
    return length(ilV) + 0.5f;
}


Um aus der Shadowmap zu samplen, habe ich mir folgende Funktion geschrieben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
float CalculatePixelBrightnessFromShadowMapCube(float3 inObjPos, float3 vPosLight)
{
    float output = 0.0f;

    float3 PLightDirection = 0.0f;
    PLightDirection.xyz = (vPosLight.xyz - inObjPos);
    float distance = length(PLightDirection.xyz);
    PLightDirection.xyz = PLightDirection.xyz / distance;

    if(g_bPCF)
    {
        float sourcevals[9];

        float dxy = 1.0/SMAP_SIZE;

        sourcevals[0] = (texCUBE( depthMapCube, -(PLightDirection.xyz) ).x < distance)? 0.0f: 1.0f;  
        sourcevals[1] = (texCUBE( depthMapCube, -(PLightDirection.xyz + float3(dxy, 0, 0)) ).x < distance)? 0.0f: 1.0f;
        sourcevals[2] = (texCUBE( depthMapCube, -(PLightDirection.xyz + float3(0, dxy, 0)) ).x < distance)? 0.0f: 1.0f;
        sourcevals[3] = (texCUBE( depthMapCube, -(PLightDirection.xyz + float3(dxy, dxy, 0)) ).x < distance)? 0.0f: 1.0f;
        sourcevals[4] = (texCUBE( depthMapCube, -(PLightDirection.xyz + float3(-dxy, 0, 0)) ).x < distance)? 0.0f: 1.0f;
        sourcevals[5] = (texCUBE( depthMapCube, -(PLightDirection.xyz + float3(0, -dxy, 0)) ).x < distance)? 0.0f: 1.0f;
        sourcevals[6] = (texCUBE( depthMapCube, -(PLightDirection.xyz + float3(-dxy, dxy, 0)) ).x < distance)? 0.0f: 1.0f;
        sourcevals[7] = (texCUBE( depthMapCube, -(PLightDirection.xyz + float3(-dxy, -dxy, 0)) ).x < distance)? 0.0f: 1.0f;
        sourcevals[8] = (texCUBE( depthMapCube, -(PLightDirection.xyz + float3(dxy, -dxy, 0)) ).x < distance)? 0.0f: 1.0f;

        float LightAmount = 0;
        for(int i = 0; i < 9; i++)
        {
            LightAmount += sourcevals[i];
        }
        LightAmount /= 9.0f;

        return LightAmount;
    }
    else
    {
        float shadowMapDepth = texCUBE( depthMapCube, -(PLightDirection.xyz) ).x;
        
        if(distance > shadowMapDepth+0.0f)
        {
            return output;
        }       
        else
        {
            return 1.0f;
        }
    }


Danke im Voraus.
»FSA« hat folgendes Bild angehängt:
  • Map.png

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

01.07.2013, 23:14

Du musst wohl den Bias erhöhen (das, was bei dir im Code mit "+ 0.0f" auf Null gesetzt wird).
Ganz ohne Artefakte kriegt man das aber nie hin, das ist bei Light Mapping generell unmöglich.

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

3

06.07.2013, 12:46

Ich würde dazu noch den "Slope Dependent Bias" in den Raum werfen. Die Fläche da wirft wahrscheinlich auf sich selbst Schatten, weil die ShadowMap-Kamera sie aus einem sehr flachen Winkel sieht und demzufolge die Tiefenwert-Unterschiede pro Pixel sehr groß sind.

Für planare Oberflächen kann man das schon primitiv verhindern, indem man beim Lesen aus der ShadowMap einen bilinearen Filter nutzt. Für gekrümmte Oberflächen oder allgemein jede komplexere Oberfläche wird es kniffliger.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

Werbeanzeige