2016-08-02 1 views
1

(Désolé pour mon mauvais anglais.)shadow mapping avec des résultats erronés (HLSL, Shader 3.0)

Je suis nouveau dépassement de la pile et l'écriture d'une application de jeu 3D avec MS Visual C++ 2015 compilateur, Direct3D 9 et HLSL (Shader, modèle 3.0).

J'ai mis en place une logique de rendu différé avec 4 rendre les textures cibles. J'ai stocké des valeurs de profondeur de pixels dans une texture de rendu et créé une carte d'ombre. Voici les résultats. (Toutes les mailles ont la couleur noire parce que les mailles ont de petite taille et à proximité de l'appareil. La valeur bien à distance plane est 1000.0f.)

The depth texture and the shadow map.

je rendais un quad plein écran avec les shaders de cartographie des ombres et des ombres en sortie avec une couleur rouge pour confirmer que le shader fonctionne correctement. Mais, il semble que les shaders produisent des résultats erronés. La sortie de texture de la carte ombrée se répète sur les surfaces de maillage.

https://www.youtube.com/watch?v=1URGgoCR6Zc

Voici le vertex shader de shadow mapping pour dessiner le quad.

struct VsInput { 
    float4 position : POSITION0; 
}; 

struct VsOutput { 
    float4 position : POSITION0; 
    float4 cameraViewRay : TEXCOORD0; 
}; 

float4x4 matInverseCameraViewProjection; 
float4 cameraWorldPosition; 
float farDistance; 

VsOutput vs_main(VsInput input) { 
    VsOutput output = (VsOutput)0; 

    output.position = input.position; 

    output.cameraViewRay = mul(float4(input.position.xy, 1.0f, 1.0f) * farDistance, matInverseCameraViewProjection); 
    output.cameraViewRay /= output.cameraViewRay.w; 
    output.cameraViewRay.xyz -= cameraWorldPosition.xyz; 

    return output; 
} 

Et voici le pixel shader de mappage d'ombre pour dessiner le quad.

struct PsInput { 
    float2 screenPosition : VPOS; 
    float4 viewRay : TEXCOORD0; 
}; 

struct PsOutput { 
    float4 color : COLOR0; 
}; 

texture depthMap; 
texture shadowMap; 

sampler depthMapSampler = sampler_state { 
    Texture = (depthMap); 
    AddressU = CLAMP; 
    AddressV = CLAMP; 
    MagFilter = POINT; 
    MinFilter = POINT; 
    MipFilter = POINT; 
}; 

sampler shadowMapSampler = sampler_state { 
    Texture = (shadowMap); 
    AddressU = CLAMP; 
    AddressV = CLAMP; 
    MagFilter = POINT; 
    MinFilter = POINT; 
    MipFilter = POINT; 
}; 

//float4x4 matCameraView; 
float4x4 matLightView; 
float4x4 matLightProjection; 
float4 cameraWorldPosition; 
float4 lightWorldPosition; 
float2 halfPixel; 
float epsilon; 
float farDistance; 

PsOutput ps_main(PsInput input) { 
    PsOutput output = (PsOutput)0; 
    output.color.a = 1.0f; 

    //Reconstruct the world position using the view-space linear depth value. 
    float2 textureUv = input.screenPosition * halfPixel * 2.0f - halfPixel; 
    float viewDepth = tex2D(depthMapSampler, textureUv).r; 
    float3 eye = input.viewRay.xyz * viewDepth; 
    float4 worldPosition = float4((eye + cameraWorldPosition.xyz), 1.0f); 

    //Test if the reconstructed world position has right coordinate values. 
    //output.color = mul(worldPosition, matCameraView).z/farDistance; 

    float4 positionInLightView = mul(worldPosition, matLightView); 
    float lightDepth = positionInLightView.z/farDistance; 
    float4 positionInLightProjection = mul(positionInLightView, matLightProjection); 
    positionInLightProjection /= positionInLightProjection.w; 

    //If-statement doesn't work??? 
    float condition = positionInLightProjection.x >= -1.0f; 
    condition *= positionInLightProjection.x <= 1.0f; 
    condition *= positionInLightProjection.y >= -1.0f; 
    condition *= positionInLightProjection.y <= 1.0f; 
    condition *= positionInLightProjection.z >= 0.0f; 
    condition *= positionInLightProjection.z <= 1.0f; 
    condition *= positionInLightProjection.w > 0.0f; 

    float2 shadowMapUv = float2(
     positionInLightProjection.x * 0.5f + 0.5f, 
     -positionInLightProjection.y * 0.5f + 0.5f 
    ); 

    //If-statement doesn't work??? 
    float condition2 = shadowMapUv.x >= 0.0f; 
    condition2 *= shadowMapUv.x <= 1.0f; 
    condition2 *= shadowMapUv.y >= 0.0f; 
    condition2 *= shadowMapUv.y <= 1.0f; 

    float viewDepthInShadowMap = tex2D(
     shadowMapSampler, 
     shadowMapUv 
    ).r; 
    output.color.r = lightDepth > viewDepthInShadowMap + epsilon; 
    output.color.r *= condition; 
    output.color.r *= condition2; 

    return output; 
} 

Il semble que le uv pour voir la carte d'ombre a des valeurs erronées, mais je ne peux pas comprendre ce qui est le vrai problème.

Un grand merci pour toute aide.

EDIT: J'ai mis à jour les codes de shaders. J'ai décidé d'utiliser la profondeur linéaire de l'espace de vue et j'ai confirmé que la position du monde avait la bonne valeur. Je ne comprends vraiment pas pourquoi la carte d'ombre des valeurs de coordonnées ont des valeurs erronées ...

+0

Quel mauvais anglais? –

Répondre

0

J'ai trouvé la solution.

Le premier problème est que la texture cible avait rendu un mauvais format de texture. J'aurais dû utiliser D3DFMT_R32F. (Je l'avais utilisé D3DFMT_A8R8G8B8.)

Et j'ajouté ces lignes dans mon ombre pixel shader de cartographie.

//Reconstruct the world position using the view-space linear depth value. 
float2 textureUv = input.screenPosition * halfPixel * 2.0f - halfPixel; 
float4 viewPosition = float4(input.viewRay.xyz * tex2D(depthMapSampler, textureUv).r, 1.0f); 
float4 worldPosition = mul(viewPosition, matInverseCameraView); 

... 

//If-statement doesn't work??? 
float condition = positionInLightProjection.x >= -1.0f; 
condition *= positionInLightProjection.x <= 1.0f; 
condition *= positionInLightProjection.y >= -1.0f; 
condition *= positionInLightProjection.y <= 1.0f; 
condition *= positionInLightProjection.z >= 0.0f; 
condition *= positionInLightProjection.z <= 1.0f; 
condition *= viewPosition.z < farDistance; 

La dernière ligne était la clé et a résolu mon deuxième problème. Le «farDistance» est la distance au plan lointain du tronc de la caméra. J'essaie toujours de comprendre pourquoi cela est nécessaire.

0

Il ressemble vraiment vous utilisez un mauvais parti pris. Google jusqu'à "Shadow Acne" et vous devriez trouver votre réponse à votre problème. En outre, la résolution de l'image miroir pourrait être un problème.

+0

Non, ce n'est pas mon problème. La texture de la carte ombrée se répète sur les surfaces maillées en fonction de la position et de l'angle de la caméra. Il semble que je doive vous montrer la vidéo du résultat actuel. – FooBarBazQux