IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

DirectX Discussion :

Shadow Map - Problème d'Ombres Projetées


Sujet :

DirectX

  1. #1
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut Shadow Map - Problème d'Ombres Projetées
    Bonjour,
    Je poste ici un nouveau topic car je n'ai pas trouvé de solution à mon problème dans les autres messages déjà postés sur le sujet.
    Je programme en C++/HLSL et j'ai commencé mon shader de type "Shadow Map" à partir du tutoriel de M. Eric Cannet.
    http://eric.cannet.pagesperso-orange...w-mapping.html
    L'ombre portée est bonne mais mes objets géométriques restent ombrés.
    Je n'arrive pas à trouver si c'est mon shader qui est faux ou ma matrice LightWorldViewProjetion.
    Pour ne pas encombrer mon message, j'ai uploadé mes shaders sur Mediafire :
    ShadowDepthMap3.fx
    ShadowSceneMap.3.2.fx
    Voici comment je calcule ma matrice
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //Calcule du Point de visée de la lumière
    ADVVECTOR3 front(1., 0., 0.);
    AdvVec3TransformNormal(&front, &front, &it->m_mat_world);
     
    D3DXVECTOR3 vEyePt (x, y, z);
    D3DXVECTOR3 vLookatPt (front.x, front.y, front.z);
    D3DXVECTOR3 vUpVec (0.0f, 0.0f, 1.0f );
     
    // Get D3DX to fill in the matrix values
    D3DXMATRIX mLightView;
    D3DXMatrixLookAtRH( &mLightView, &vEyePt, &vLookatPt, &vUpVec );
     
    D3DXMATRIX mViewToLightProj = m_matWorld * mLightView * m_matProj;
    Pour le shader, j'ai divisé mon problème en deux. Je possède deux shaders, l'un pour la depth map, l'autre pour le rendu de la scène. Pour créer ma shadow map, je place ma caméra à la place de ma lumière (-4,0.0,0.0,1.0), j'applique mon shader "ShadowDepthMap3.fx" sur la scène avec un FarClip de 10. J'enregistre la depth map grâce à un screenshot et je l'enregistre dans un PNG.

    Ensuite, je charge la shadow Map dans mon shader "ShadowSceneMap3.2.fx" que j'applique sur ma scène.
    Voici le résultat :

    On peut voir que la traînée laissé par la sphère et le cube sur le plan est bon. Mais Les 3 géométries sont ombrées alors que la sphère devrait être partiellement éclairée et que les coins supérieures du cube devraient l'être également.
    Quand j'ai zoomé sur la tache blanche à la base de la lumière (encadré en rouge). J'ai pu me rendre compte que l'éclairage manquant y apparaissait comme on peut le voir ici:

    En effet, on voit bien la sphère et les coins supérieurs du cube.
    Malheureusement, je ne sais pas vraiment quoi faire de cette information et si c'est vraiment la solution de mon problème.
    J'espère que certains d'entre vous on déjà développé cette technique et qu'ils pourront "m'éclairer" sur le sujet.
    D'avance, je vous en remercie.
    InSomNia

    PS : Le PCF ne marche pas, ce n'est pas ma priorité, mais si quelqu'un peut m'aider également. Je ne dis pas non.

  2. #2
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut


    Le mystère est résolut, ma matrice Monde ne s'appliquait que pour le sol. voilà pourquoi il n'y avait que mon sol qui avait un résultat convenable.
    J'ai donc déporter mon calcul de ma matrice LightViewProj dans le vertexShadowMap. L'affichage de la depth map au début de ma source lumineuse n'a donc aucun rapport.

    Je remercie toutes les personnes qui ont jeté un oeil sur ce topic. Vous m'avez appris à me débrouiller tout seul et le sens de l'ironie...

  3. #3
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Bonjour,
    Je reviens vers vous à nouveau car j'ai un problème d'alliasing.
    Ne voulant pas aller trop vite, j'ai commencé par utiliser la technique PCF.
    je calcule donc la valeur de mon pixel en fonction des texels voisins.
    Voici ma fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    float CalcShadowTermPCF(float fLightDepth, float2 vShadowTexCoord)
    {
    	float fShadowTerm = 0.0f;
     
    	// transform to texel space
    	float2 vShadowMapCoord;
    	vShadowMapCoord.x = vpSize.x * vShadowTexCoord.x;
    	vShadowMapCoord.y = vpSize.y * vShadowTexCoord.y;
     
    	// Determine the lerp amounts           
    	float2 vLerps = frac(vShadowMapCoord);
     
    	// Read in the 4 samples, doing a depth check for each
    	float fSamples[4];	
    	fSamples[0] = (tex2D(g_samShadow, vShadowTexCoord).x + BIAS < fLightDepth) ? 0.0f: 1.0f;  
    	fSamples[1] = (tex2D(g_samShadow, vShadowTexCoord + float2(1.0/vpSize.x, 0)).x + BIAS < fLightDepth) ? 0.0f: 1.0f;  
    	fSamples[2] = (tex2D(g_samShadow, vShadowTexCoord + float2(0, 1.0/vpSize.y)).x + BIAS < fLightDepth) ? 0.0f: 1.0f;  
    	fSamples[3] = (tex2D(g_samShadow, vShadowTexCoord + float2(1.0/vpSize.x, 1.0/vpSize.y)).x + BIAS < fLightDepth) ? 0.0f: 1.0f;   
     
    	// lerp between the shadow values to calculate our light amount
    	fShadowTerm = lerp(lerp(fSamples[0], fSamples[1], vLerps.x), lerp( fSamples[2], fSamples[3], vLerps.x), vLerps.y);							  
     
    	return fShadowTerm;								 
    }


    J'obtiens alors des contours partiels, alliacés et floutés mais l'intérieur de mes ombres sont vide. Pour obtenir une ombre correcte, j'ai inversé la valeur "fShadowTerm" retourné et je la divise par deux pour réduire la noirceur de l'ombre.

    N'étant pas satisfait du résultat, j'ai donc essayé une autre façon de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    float CalcShadowTermSoftPCF3x3(float fLightDepth, float2 vShadowTexCoord)
    {
    	// Generate the 9 texture co-ordinates for a 3x3 PCF kernel
       float2 vTexCoords[9];
       // Texel size
       float fTexelWidth = 1.0f / vpSize.x;
       float fTexelHeight = 1.0f / vpSize.y;
     
       // Generate the texture co-ordinates for the specified depth-map size
       // 4 3 5
       // 1 0 2
       // 7 6 8
       vTexCoords[0] = vShadowTexCoord;
       vTexCoords[1] = vShadowTexCoord + float2( -fTexelWidth, 0.0 );
       vTexCoords[2] = vShadowTexCoord + float2(  fTexelWidth, 0.0f );
       vTexCoords[3] = vShadowTexCoord + float2( 0.0f, -fTexelHeight );
       vTexCoords[6] = vShadowTexCoord + float2( 0.0f,  fTexelHeight );
       vTexCoords[4] = vShadowTexCoord + float2( -fTexelWidth, -fTexelHeight );
       vTexCoords[5] = vShadowTexCoord + float2(  fTexelWidth, -fTexelHeight );
       vTexCoords[7] = vShadowTexCoord + float2( -fTexelWidth,  fTexelHeight );
       vTexCoords[8] = vShadowTexCoord + float2(  fTexelWidth,  fTexelHeight );
       // Sample each of them checking whether the pixel under test is shadowed or not
       float fShadowTerm = 0.0f;
       float A, B;
       float zzz;
     
       for( int i = 0; i < 9; i++ )
       {
    		 //B = (fLightDepth - 0.1f);
              A = tex2D( g_samShadow, vTexCoords[i] ).r;
              B = (fLightDepth - 0.1f);
     
              // Texel is shadowed
              fShadowTerm    += (A < B ? 0.0f : 1.0f);
       }
       // Get the average
       fShadowTerm /= 9.0f;
       return fShadowTerm;
    }


    Ici, il y a un net progrès, les contours des ombres sont entier et alliacés. Les ombres projetées sur le sol restent vide alors que les ombres plaqués sur les objets sont +/- présente (exemple la voiture à moitié ombrée).
    Ici, mon bidouillage d'inverser la valeur "fShadowTerm" va évidement altérer les ombres présentes sur cette première image. Mais le rendu final reste malgré tout plus convaincant.

    Comme on peut le voir ici, j'ai perdu les ombre sur le baril, la caisse, le cône et une partie de l'ombre sur la voiture.

    J'espère que vous saurez m'aider, n'hésitez pas à participer.
    J'aimerai ensuite poussé encore plus loin et là de nombreuses possibilités sont disponible :

    PCSS
    VSM
    CSM
    ESM
    PSM
    ...
    Laquelle me conseillerez vous de développer?

    Merci de votre aide.
    InSomNia

  4. #4
    Membre actif Avatar de ShadowTzu
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juin 2005
    Messages
    243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haute Saône (Franche Comté)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Juin 2005
    Messages : 243
    Points : 296
    Points
    296
    Par défaut
    et comment tu utilise fShadowTerm?

    essaye par exemple en sortie de ton pixelshader:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    float ShadowAlpha = 0.75f;
    color = float4(0, 0, 0, clamp(ShadowAlpha - fShadowTerm, 0, 1));
    return color;

  5. #5
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    J'ai finalement résolu mon problème en inversant le résultat contenu dans ma boucle for qui se trouve dans la fonction PCF3x3 :
    Avant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    fShadowTerm    += (A < B ? 1.0f : 0.0f);
    Après
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    fShadowTerm    += (A < B ? 0.5f : 1.0f);
    Pour la valeur retournée, je multiplie mon fShadowTerm par la valeur du Texel.

    Color = Tex * fShadowTerm ;



    NB : Je mets 0.5 au lieu de 0.0 pour ne pas avoir des ombres trop sombres.
    PS : j'ai augmenté la taille de ma texture à 1024x1024 pour gagner en précision. Quelle est la taille Optimale entre Qualité/Performance?

  6. #6
    Membre expérimenté

    Profil pro
    Programmeur
    Inscrit en
    Août 2002
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Programmeur

    Informations forums :
    Inscription : Août 2002
    Messages : 1 091
    Points : 1 679
    Points
    1 679
    Par défaut
    Citation Envoyé par 686insomnia686 Voir le message
    Quelle est la taille Optimale entre Qualité/Performance?
    Personne ne peut répondre à cette question. C'est pour cela qu'en général les jeux disposent de pré-réglages qui change la qualité des ombres suivant la puissance de la machine.
    Sinon il est en général très dur d'extraire une qualité convenable avec des shadow maps classiques (et caméra libre).

    Pour ton info, il y a un papier qui passe en revue certaines techniques :
    http://www.cg.tuwien.ac.at/research/...r2011d-pdf.pdf

    Il y a aussi un bouquin :
    http://www.realtimeshadows.com/

  7. #7
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Merci bien LeGreg, je vais jeter un oeil sur tout ça.

    Je suis à présent entrain de modifier mon shader pour incorporer plusieurs lumières dans ma scène. Je commence par la manière naïve, je vais d'abord le faire fonctionner pour 3 lumières puis je l'adapterais pour X lumières.

    J'ai d'abord adapté mon shader pour voir différents ombrages indépendement.
    Pour cela, j'ai juste créer un entier qui s'applique sur le tableau contenant mes spots.
    Le premier rendu est bon, l'ombre est correct, quand je change de spot en cours d’exécution, les ombrages suivants sont faux et quand je reviens à la première lumière, des taches apparaissent.



    Je me suis rendu compte que ma RenderColorTarget n'était pas réinitiallisée.
    J'ai donc appliqué un ColorFill mais le problème persiste.



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    IDirect3DDevice9 *device3D;
    LPDIRECT3DSURFACE9 colorRenderTarget=NULL;
    D3DCOLOR color = D3DCOLOR_ARGB(0, 0, 0, 0);
    device3D->ColorFill(colorRenderTarget, NULL, color);
    device3D->SetRenderTarget(0, colorRenderTarget);

  8. #8
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx

    Allows an application to fill a rectangular area of a D3DPOOL_DEFAULT surface with a specified color.
    Le renderTarget est-il initialisé avec D3DPOOL_DEFAULT ?

    La méthode Clear de de l'interface IDirect3DDevice9 avec D3DCLEAR_TARGET ne serait-elle pas plus adaptée ?

  9. #9
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Bonjour,
    ma rendercolor est bien en D3DPOOL_DEFAULT

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    hr = D3DXCreateTexture(dev, Width, Height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R32F, D3DPOOL_DEFAULT, (LPDIRECT3DTEXTURE9*)&pTex);
    Je clear le Z Buffer avec la fonction clear du IDirect3DDevice9 mais pour la render target, le clear affecte mon affichage qui devient tout noir...

    J'utilise donc le colorfill comme alternative, si le paramètre RECT est à NULL, toute la texture est remplie.

    J'ai oublié de préciser, les shadow map que j'ai affiché plus haut ont été faite en appelant une fonction "SnapShot" juste avant l'appel de "ColorFill". Si l'appel de cette fonction est réalisée après ColorFill donne une texture vide "Totalement bleu".

  10. #10
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Bonjour,
    Je n'ai toujours pas résolut mon problème.
    Mais je reviens vers vous avec une question "Captain Obvious" :
    "Ma shadow map est stockée dans une rendercolortarget, pourquoi quand je la récupère, le niveau de gris s'est transformé en niveau de cyan?"
    Merci à vous d'éclaircir ce mystère.

  11. #11
    Membre expérimenté

    Profil pro
    Programmeur
    Inscrit en
    Août 2002
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Programmeur

    Informations forums :
    Inscription : Août 2002
    Messages : 1 091
    Points : 1 679
    Points
    1 679
    Par défaut
    Citation Envoyé par 686insomnia686 Voir le message
    Mais je reviens vers vous avec une question "Captain Obvious" :
    "Ma shadow map est stockée dans une rendercolortarget, pourquoi quand je la récupère, le niveau de gris s'est transformé en niveau de cyan?"
    Merci à vous d'éclaircir ce mystère.
    Ce n'est pas vraiment un mystère

    Tu stockes ton niveau d'éclairage dans la composante R de ta rendertarget. Les deux autres couleurs G (vert) et B (bleu) sont inutilisées. Quand tu les lis depuis la texture, le hardware lit la valeur par défaut qui est l'intensité maximale ici. La combinaison de bleu et de vert = cyan.

  12. #12
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Effectivement, le problème vient +/- de là.
    Mon shader stocke la depth map dans tous les canaux (RGBA).
    Mais ma texture est au format RF32. Ce qui n'est pas gênant pour du shadow mapping.
    Ca l'est nettement plus pour le volumetric Light Scatering que j'essaye d'implémenter.

Discussions similaires

  1. Shadow mapping: ombre qui bouge
    Par zenux dans le forum Moteurs 3D
    Réponses: 2
    Dernier message: 09/12/2012, 23h56
  2. [Shadow mapping] Ombre noir
    Par Gonath dans le forum OpenGL
    Réponses: 8
    Dernier message: 20/07/2012, 21h45
  3. Réponses: 0
    Dernier message: 02/12/2010, 02h24
  4. Problème de shadow mapping
    Par bobbysinger dans le forum OpenGL
    Réponses: 4
    Dernier message: 07/04/2010, 11h28
  5. Réponses: 3
    Dernier message: 21/12/2009, 18h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo