Partage
  • Partager sur Facebook
  • Partager sur Twitter

[OpenGL][3D] Shadow mapping qui déconne

Sujet résolu
    21 juin 2015 à 1:44:17

    Hello !

    Voilà cela fait quelques jours que je me bats avec les ombres dans Nazara, j'ai enfin réussi à en obtenir mais elles ne sont pas correctes.

    Il y a divers bugs, notamment le fait que l'ombre ne semble pas vraiment correspondre, disparaît parfois, que le frustum de shadow mapping est plus petit que la lumière produite par le spotlight (et là j'avoue je suis toujours un peu wtf).

    Voici une vidéo pour montrer tout ça (une image valant mille mots, cette vidéo vaut 3300 000 mots ! :D ): http://youtu.be/B-GXQSSr7_A

    Alors côté implémentation, c'est du shadow mapping bête et méchant pour l'instant, avec la génération de la shadow map ici:

    	void RenderSystem::UpdateShadowMaps()
    	{
    		if (!m_shadowRT.IsValid())
    			m_shadowRT.Create();
    
    		for (const Ndk::EntityHandle& light : m_lights)
    		{
    			LightComponent& lightComponent = light->GetComponent<LightComponent>();
    			NodeComponent& lightNode = light->GetComponent<NodeComponent>();
    
    			if (!lightComponent.IsShadowCastingEnabled() || lightComponent.GetLightType() != nzLightType_Spot)
    				continue;
    
    			NzVector2ui shadowMapSize(lightComponent.GetShadowMap()->GetSize());
    
    			m_shadowRT.AttachTexture(nzAttachmentPoint_Depth, 0, lightComponent.GetShadowMap());
    
    			///TODO: Cache the matrices in the light
    			NzRenderer::SetMatrix(nzMatrixType_Projection, NzMatrix4f::Perspective(lightComponent.GetOuterAngle(), 1.f, 1.f, 1000.f));
    			NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::ViewMatrix(lightNode.GetPosition(), lightNode.GetRotation()));
    			NzRenderer::SetTarget(&m_shadowRT);
    			NzRenderer::SetViewport(NzRecti(0, 0, shadowMapSize.x, shadowMapSize.y));
    
    			NzAbstractRenderQueue* renderQueue = m_shadowTechnique.GetRenderQueue();
    			renderQueue->Clear();
    
    			for (const Ndk::EntityHandle& drawable : m_drawables)
    			{
    				GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>();
    				NodeComponent& drawableNode = drawable->GetComponent<NodeComponent>();
    
    				graphicsComponent.AddToRenderQueue(renderQueue);
    			}
    
    			NzSceneData sceneData;
    			sceneData.ambientColor = NzColor(0, 0, 0);
    			sceneData.background = nullptr;
    			sceneData.viewer = nullptr; //< Depth technique doesn't require any viewer
    
    			m_shadowTechnique.Draw(sceneData);
    		}
    	}
    

    Lors du rendu normal, les lumières sont ajoutées à la RenderQueue avec la shadow map et les matrices qui vont avec (oui il y a duplication, de toute façon mon objectif est surtout d'avoir un truc qui marche là :D ):

    			light.viewMatrix = NzMatrix4f::ViewMatrix(transformMatrix.GetTranslation(), transformMatrix.GetRotation());
    			light.projectionMatrix = NzMatrix4f::Perspective(m_outerAngle, 1.f, 1.f, 1000.f);
    

    Qui sont envoyés un peu plus loin au shader:

    							NzTextureSampler sampler;
    							sampler.SetFilterMode(nzSamplerFilter_Bilinear);
    							sampler.SetWrapMode(nzSamplerWrap_Clamp);
    							NzRenderer::SetTexture(8, light.shadowMap);
    							NzRenderer::SetTextureSampler(8, sampler);
    
    							shader->SendMatrix(shader->GetUniformLocation("LightProjMatrix"), light.projectionMatrix);
    							shader->SendMatrix(shader->GetUniformLocation("LightViewMatrix"), light.viewMatrix);
    							shader->SendInteger(shader->GetUniformLocation("ShadowMap"), 8);
    

    Le Vertex Shader s'occupe ensuite de refaire la projection:

        vLightSpacePos = LightProjMatrix * LightViewMatrix * WorldMatrix * vec4(VertexPosition, 1.0);
    

    Et le Fragment Shader s'occupe ensuite de projeter la shadow map:

    	if (vLightSpacePos.w > 0.0)
    	{
    		// Perspective
    		vec3 ProjectionCoords = vLightSpacePos.xyz / vLightSpacePos.w;
    
    		// Bias
    		vec2 UVCoords;
    		UVCoords.x = 0.5 * ProjectionCoords.x + 0.5;
    		UVCoords.y = 0.5 * ProjectionCoords.y + 0.5;
    		
    		if (UVCoords.x >= 0.0 && UVCoords.x < 1.0 &&
    			UVCoords.y >= 0.0 && UVCoords.y < 1.0 &&
    			ProjectionCoords.z >= 0.0 && ProjectionCoords.z < 1.0)
    		{
    			float Depth = texture(ShadowMap, UVCoords).x;
    			if (Depth < ProjectionCoords.z - 0.005)
    			{
    				lightDiffuse = vec3(0.0);
    				lightSpecular = vec3(0.0);
    			}
    		}
    	}
    

    Voilà, tout ceci donne le résultat en vidéo, je donne aussi le code responsable du calcul d'éclairage (j'ai renommé quelques variables pour rendre ça plus compréhensible):

    				case LIGHT_SPOT:
    				{
    					vec3 lightDir = LightPos - vWorldPos;
    					float lightDirLength = length(lightDir);
    					lightDir /= lightDirLength; // Normalisation
    					
    					float att = max(LightAttenuation - LightInvRadius*lightDirLength, 0.0);
    
    					// Ambient
    					lightAmbient += att * LightColor * LightAmbientFactor * (MaterialAmbient.rgb + SceneAmbient.rgb);
    
    					// Modification de l'atténuation pour gérer le spot
    					float curAngle = dot(LightDirection, -lightDir);
    					float innerMinusOuterAngle = LightInnerAngle - LightOuterAngle; // Ce sont des cosinus
    					att *= max((curAngle - LightOuterAngle) / innerMinusOuterAngle, 0.0);
    
    					// Diffuse
    					float lambert = max(dot(normal, lightDir), 0.0);
    
    					lightDiffuse += att * lambert * LightColor * LightDiffuseFactor;
    
    					// Specular
    					vec3 reflection = reflect(-lightDir, normal);
    					float specularFactor = max(dot(reflection, eyeVec), 0.0);
    					specularFactor = pow(specularFactor, MaterialShininess);
    
    					lightSpecular += att * specularFactor * LightColor;
    					break;
    				}
    

    Si quelqu'un pouvait me donner un coup de main pour le coup, ça m'arrangerait beaucoup, ce problème va me rendre fou.

    Je poste aussi le code, si quelqu'un veut voir quelle fonction fait quoi: Dépôt Github (Branche shadow sans une partie du code plus haut). Matrix4.inl (algorithme de génération des matrices).

    Pour le reste (RTT) c'est basiquement de l'OpenGL (m_shadowRT.AttachTexture fait appel à glFrameBufferTexture2D par exemple), voilà.

    Si besoin de plus d'information, aucun souci n'hésitez pas à demander :)

    • Partager sur Facebook
    • Partager sur Twitter

    Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

      23 juin 2015 à 11:50:58

      Bonjour,

      Le bias dans le fragment shader me semble énorme. Peut être je me trompe, mais là, le bias indique un décalage de la moitié d'une texture.

      Mais bon, ici aussi il utilise ces valeurs.

      Votre texture de profondeur semble correcte. Du coup, je ne sais pas trop. Dans les bogues que j'ai vu dans la vidéo, cela me semble être causé par le test que vous faites, qui est trop stricte (?).

      • Partager sur Facebook
      • Partager sur Twitter
        23 juin 2015 à 13:11:45

        En fait, si j'affiche le frustum et le cone de projection, on se rend très vite compte qu'il y a un problème de ce côté-là aussi:

        Il faut que je double l'angle que j'envoie pour construire le frustum si je veux que ça corresponde, mais évidemment ça ne corrige pas les ombres (ou alors je corrige mal ?).

        Quant au bias, si je l'enlève ça ne corrige malheureusement pas le problème :-/

        • Partager sur Facebook
        • Partager sur Twitter

        Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

          23 juin 2015 à 13:17:18

          Mise à jour rapide, en fait j'ai pu corriger ça (j'avais déjà essayé mais cette fois-ci ça a marché, pour une raison que j'ignore):

          Voilà donc le seul problème restant:

          Si tu as une idée, ça me serait vraiment utile :)

          Merci en tout cas d'avoir répondu.

          Edit: Aussi j'aimerai comprendre pourquoi, quand j'active le face culling (front), je me retrouve avec cette ombre:

          Je suppose que c'est lié au problème global

          Le shader ressemble maintenant à ça:

          	if (vLightSpacePos.w > 0.0)
          	{
          		vec3 ProjectionCoords = vLightSpacePos.xyz / vLightSpacePos.w;
          
          		vec2 UVCoords;
          		UVCoords.x = 0.5 * ProjectionCoords.x + 0.5;
          		UVCoords.y = 0.5 * ProjectionCoords.y + 0.5;
          		
          		float Depth = texture(ShadowMap, UVCoords).x;
          		if(Depth < ProjectionCoords.z - 0.00005)
          		{
          			lightDiffuse *= 0.5;
          			lightSpecular = vec3(0.0);
          		}
          	}
          



          -
          Edité par Lynix 23 juin 2015 à 13:39:35

          • Partager sur Facebook
          • Partager sur Twitter

          Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

            23 juin 2015 à 14:04:53

            C'est ultra étrange. Ça voudrait dire que dans ce cas, le depthbuffer utilisé par la shadow map, donne des valeurs à un.

            J'oserai croire que le souci est un souci de configuration du depthbuffer/depthtest. Pour l'instant, je n'arrive pas du tout à saisir le souci. Vous parlez du faceculling ? Mais la face est tout de même affichée ? N'est ce pas le backface culling ?

            -
            Edité par LittleWhite 23 juin 2015 à 14:17:20

            • Partager sur Facebook
            • Partager sur Twitter
              23 juin 2015 à 16:38:10

              Jusque là j'ai relu le code 3 fois mais je vois pas le problème... Je passe juste rapidement pour dire que c'est bien normal que le bias réduise et décale de 0.5, c'est pour passer des coordonnées de l'écran [-1;1] à celles d'une texture [0;1]. 

              Mais sinon t'as essayé d'enlever quelques uns de tes tests dans le fragment buffer ? Ils m'ont pas l'air incohérents mais pas nécessaires non plus, dans le doute... Tiens et puis le filtre bilinéaire sur la shadow map ça change rien non plus, je sais pas si c'est un oubli de ta part. :-°

              C'est quand même assez bizarre que l'ombre ait l'air de passer sous le sol comme ça, vu que ton FBO à l'air correct. Après faut voir aussi si t'utilises bien la même matrice pour le FBO et le rendu ou ce genre de choses. Si comme le suggère LittleWhite c'est un problème de Depth Buffer tu peux aussi faire ton propre rendu de profondeur avec une texture 32 bits.

              Sinon t'as essayé avec une lumière type unidirectionnelle (genre soleil, je sais plus si c'est le terme) ? Ça sera peut être plus facile de dire à quel niveau est le problème ?

              Voilà après tu t'y connais probablement mieux que moi donc pas totalement sûr de pouvoir aider beaucoup plus. :p

              • Partager sur Facebook
              • Partager sur Twitter
                23 juin 2015 à 19:59:36

                LittleWhite a écrit:

                C'est ultra étrange. Ça voudrait dire que dans ce cas, le depthbuffer utilisé par la shadow map, donne des valeurs à un.

                J'oserai croire que le souci est un souci de configuration du depthbuffer/depthtest. Pour l'instant, je n'arrive pas du tout à saisir le souci. Vous parlez du faceculling ? Mais la face est tout de même affichée ? N'est ce pas le backface culling ?

                Je crois avoir compris, en fait l'ombre est correcte mais elle est décalée, c'est je pense le seul problème de mon implémentation actuelle.
                (Ou alors pas du tout parce que c'est normalement du point de vue caméra, la forme est la même, wtf).

                Donc oui, en temps normal je désactive le face culling pour la génération du depth buffer pour éviter ça.

                LeParp a écrit:

                Mais sinon t'as essayé d'enlever quelques uns de tes tests dans le fragment buffer ? Ils m'ont pas l'air incohérents mais pas nécessaires non plus, dans le doute... Tiens et puis le filtre bilinéaire sur la shadow map ça change rien non plus, je sais pas si c'est un oubli de ta part. :-°

                J'ai enlevé les tests de coordonnées, depuis que j'ai corrigé le bug de projection ils ne servent en effet plus à rien.

                En revanche, à la base le code était bien plus optimisé que ça, j'ai enlevé optimisation sur optimisation en espérant que ça fonctionne, pourquoi le filtre bilinéaire ne fonctionnerait pas au juste ? À cause du format de la texture ?

                LeParp a écrit:

                Si comme le suggère LittleWhite c'est un problème de Depth Buffer tu peux aussi faire ton propre rendu de profondeur avec une texture 32 bits.

                Je suis déjà en 24 bits et à une telle distance je doute vraiment que ce soit ça le problème, mais j'essaierai.

                (Mais sinon, c'est déjà "mon propre rendu de profondeur" hein).

                LeParp a écrit:

                Sinon t'as essayé avec une lumière type unidirectionnelle (genre soleil, je sais plus si c'est le terme) ? Ça sera peut être plus facile de dire à quel niveau est le problème ?

                À tester, de ce que j'en sais c'est pas forcément plus facile à mettre en place, mais ça élimine la perspective donc ça pourrait aiguiller sur le problème, j'essaierai ça dès que possible.

                Si vous avez des idées à me faire tester n'hésitez pas ;)

                • Partager sur Facebook
                • Partager sur Twitter

                Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                  23 juin 2015 à 21:29:39

                  Lynix a écrit:

                  pourquoi le filtre bilinéaire ne fonctionnerait pas au juste ?

                  C'est pas que ça fonctionne pas, c'est juste que tu fais un test binaire au final donc c'est pas utile (sauf peut être dans des cas extrêmes). D'ailleurs c'est tout l'intérêt des VSMde pouvoir "être linéaire" et faire de l'interpolation.

                  Lynix a écrit:

                  Je suis déjà en 24 bits et à une telle distance je doute vraiment que ce soit ça le problème, mais j'essaierai.

                  (Mais sinon, c'est déjà "mon propre rendu de profondeur" hein).

                  C'était pas forcé. :p Mais oui effectivement je doute que ça change quelque chose pour le coup.

                  Bon courage pour la suite !

                  • Partager sur Facebook
                  • Partager sur Twitter
                    24 juin 2015 à 11:28:58

                    Merci LeParp, pour le rappel/l'explication sur le bias.

                    @Lynix : je crois deviner le problème. C'est que lors de l'écriture dans la shadowmap, il y a une face qui n'est pas écrite, car elle n'est pas dessiné (la face arrière). Par contre, il faut comprendre pourquoi la face avant n'est pas dessinée (je me trompe peut être d'ordre dans les faces). êtes vous sur que vous avez la même configuration de faceculling lors du rendu de la scène à l'écran, et lots du rendu de la scène dans la shadowmap ?

                    De plus, pouvez vous nous montrer le shader écrivant dans la shadowmap. Il y a peut être un test encore un peu trop stricte ? :D

                    Note : faire des tests (et donc des embranchements) dans les shaders, ce n'est pas super conseillé en terme de performances. Notamment car les pixel shader sont exécutés en parallèle et que l'optimisation est que c'est rapide car ils sont sensés faire toujours la même chose pour chaque pixel. L'embranchement viendra contredire cette hypothèse. J'espère que j'ai été clair :aie:

                    -
                    Edité par LittleWhite 24 juin 2015 à 11:30:21

                    • Partager sur Facebook
                    • Partager sur Twitter
                      24 juin 2015 à 13:48:02

                      LeParp a écrit:

                      Lynix a écrit:

                      pourquoi le filtre bilinéaire ne fonctionnerait pas au juste ?

                      C'est pas que ça fonctionne pas, c'est juste que tu fais un test binaire au final donc c'est pas utile (sauf peut être dans des cas extrêmes).

                      Ce n'est pas parce que le test est binaire que les valeurs testées elles ne sont pas interpolées, d'ailleurs le filtre bilinéaire permet ici d'adoucir les ombres (j'ai comparé) :)

                      LittleWhite a écrit:

                      @Lynix : je crois deviner le problème. C'est que lors de l'écriture dans la shadowmap, il y a une face qui n'est pas écrite, car elle n'est pas dessiné (la face arrière). Par contre, il faut comprendre pourquoi la face avant n'est pas dessinée (je me trompe peut être d'ordre dans les faces). êtes vous sur que vous avez la même configuration de faceculling lors du rendu de la scène à l'écran, et lots du rendu de la scène dans la shadowmap ?

                      Ah non, le faceculling doit être différent entre le rendu de la scène (backface culling) et le rendu de la shadow map (frontface culling).

                      Voici une comparaison entre le front culling et le back culling (avec le depth buffer l'ombre générée), les deux screenshots sont pris avec exactement le même angle de vue (pour comparer).

                      Backface culling
                      Frontface culling

                      Le shader écrivant dans le depth buffer ne fait absolument rien:

                      Vertex shader:

                      /********************Entrant********************/
                      in vec3 VertexPosition;
                      
                      /********************Sortant********************/
                      out vec4 vColor;
                      
                      /********************Uniformes********************/
                      uniform mat4 WorldViewProjMatrix;
                      
                      /********************Fonctions********************/
                      void main()
                      {
                      	gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);
                      	vColor = vec4(1.0);
                      }
                      

                      Fragment shader:

                      layout(early_fragment_tests) in;
                      
                      /********************Entrant********************/
                      in vec4 vColor;
                      
                      /********************Sortant********************/
                      out vec4 RenderTarget0;
                      
                      /********************Uniformes********************/
                      uniform vec4 MaterialDiffuse;
                      
                      /********************Fonctions********************/
                      void main()
                      {
                      	RenderTarget0 = MaterialDiffuse * vColor;
                      }

                      Pas de test, absolument rien n'est effectué de spécial.

                      LittleWhite a écrit:

                      Note : faire des tests (et donc des embranchements) dans les shaders, ce n'est pas super conseillé en terme de performances. Notamment car les pixel shader sont exécutés en parallèle et que l'optimisation est que c'est rapide car ils sont sensés faire toujours la même chose pour chaque pixel. L'embranchement viendra contredire cette hypothèse. J'espère que j'ai été clair :aie:

                      Je suis parfaitement au courant :)

                      Mais comme je l'ai dit, mon but premier est d'abord une implémentation fonctionnelle, et l'optimisation uniquement par la suite.

                      J'ai effectué plusieurs tests, notamment augmenter la profondeur du depth buffer, ou virer le bias du test de profondeur, rien n'y fait.

                      Je commence à me dire que le problème viendrait plus de ma matrice de projection:

                      template<typename T>
                      NzMatrix4<T>& NzMatrix4<T>::MakePerspective(T angle, T ratio, T zNear, T zFar)
                      {
                      	// http://msdn.microsoft.com/en-us/library/windows/desktop/bb204945(v=vs.85).aspx
                      	#if NAZARA_MATH_ANGLE_RADIAN
                      	angle /= F(2.0);
                      	#else
                      	angle = NzDegreeToRadian(angle/F(2.0));
                      	#endif
                      
                      	T yScale = F(1.0) / std::tan(angle);
                      
                      	Set(yScale / ratio, F(0.0), F(0.0), F(0.0),
                      	    F(0.0), yScale, F(0.0), F(0.0),
                      	    F(0.0), F(0.0), zFar / (zNear-zFar), F(-1.0),
                      	    F(0.0), F(0.0), (zNear*zFar) / (zNear-zFar), F(0.0));
                      
                      	return *this;
                      }

                      Ou peut-être de ma matrice de vue ?

                      template<typename T>
                      NzMatrix4<T>& NzMatrix4<T>::MakeViewMatrix(const NzVector3<T>& translation, const NzQuaternion<T>& rotation)
                      {
                      	// Une matrice de vue doit appliquer une transformation opposée à la matrice "monde"
                      	NzQuaternion<T> invRot = rotation.GetConjugate(); // Inverse de la rotation
                      
                      	return MakeTransform(-(invRot*translation), invRot);
                      }

                      Ces deux matrices sont également utilisées lors du rendu, donc ça serait étonnant, mais sait-on jamais.


                      • Partager sur Facebook
                      • Partager sur Twitter

                      Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                        24 juin 2015 à 14:45:44

                        Je ne vois pas pourquoi le "culling" doit être différent entre le calcul de la shadow et le rendu final.o_O
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                          24 juin 2015 à 16:12:52

                          Le face culling (et non pas l'object culling) doit l'être, pour éviter le self-shadowing.

                          fabien sanglar a écrit:

                          A good technique to reduce self-shadowing is to cull front facing polygons during the shadowmap rendition step, using glCullFace(GL_FRONT) and switch back to glCullFace(GL_BACK) during the second step. Here is the result:

                          Source: http://www.fabiensanglard.net/shadowmapping/index.php

                          -
                          Edité par Lynix 24 juin 2015 à 16:13:36

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                            25 juin 2015 à 11:10:57

                            Cool, vous utilisez la même source que j'avais utilisée pour faire mon shadow mapping à l'époque :) . Du coup, on va être sur la même longueur d'ondes.

                            Par contre, avec vos deux nouvelles captures, je ne vois pas du tout quoi en tirer. Les deux ont un résultat faux ?

                            Faites vous du débogage avec gDEBugger (ou autre) ? Notamment pour inspecter les différentes étapes du rendu.

                            Si la matrice de projection est fausse, cela va se voir dans le cibles de rendu, non ?

                            • Partager sur Facebook
                            • Partager sur Twitter
                              25 juin 2015 à 13:01:20

                              LittleWhite a écrit:

                              Par contre, avec vos deux nouvelles captures, je ne vois pas du tout quoi en tirer. Les deux ont un résultat faux ?

                              Oui, et en fait je me suis rendu compte que c'est extrêmement difficile à voir sur un écran non-calibré/pas très lumineux.

                              Dans les deux cas on se rend bien compte que la forme est la même, juste que la profondeur change (ce qui est logique), mais que la profondeur du cube est bien supérieure (plus foncée) que celle du sol, ça ne devrait donc pas se produire, le problème doit donc être au niveau du test, ou en tout cas des valeurs testées, je vais regarder du côté de la multiplication matricielle dans le VS.

                              LittleWhite a écrit:

                              Faites vous du débogage avec gDEBugger (ou autre) ? Notamment pour inspecter les différentes étapes du rendu.

                              Non, je ne vois pas ce que ça m'apporterait ici étant donné que je peux voir directement la depth-map et le résultat aussi.

                              LittleWhite a écrit:

                              Si la matrice de projection est fausse, cela va se voir dans le cibles de rendu, non ?

                              En effet ça aurait dû se voir depuis longtemps si c'était ça, mais bon, à ce stade je ne sais plus vraiment quoi penser.

                              • Partager sur Facebook
                              • Partager sur Twitter

                              Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                25 juin 2015 à 13:57:59

                                Bon, je confirme via du shadow volume que les ombres sont correctes.
                                Cependant:
                                Je dirais qu'il manque un morceau de l'ombre, c'est vraiment bizarre..
                                • Partager sur Facebook
                                • Partager sur Twitter

                                Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                  25 juin 2015 à 14:08:29

                                  C'est dans ce cas là, que je me demande ce que contient la shadow map. En effet, il manque un morceau d'ombre et pour moi, cela veut dire qu'elle n'est pas écrit dans la shadowmap. Pouvez-vous confirmer que la shadowmap est correct ou pas, dans un tel cas ?

                                  Peut être vous avez une mauvaise configuration du RTT et que votre depthbuffer que vous utilisez est un ancien depthbuffer (???).

                                  (En vérifiant l'état de la shadowmap, on saura si le problème vient de 1) avant la génération de la shadowmap, 2) après la génération (donc lors de l'application)).

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    25 juin 2015 à 14:10:20

                                    Petite update, si je cast l'ombre en l'air, j'obtiens ça:

                                    Ce qui est parfaitement correct.

                                    Par contre, si je mets le sol au niveau du cube:

                                    Il y aurait donc vraiment un défaut au niveau du test.

                                    LittleWhite a écrit:

                                    C'est dans ce cas là, que je me demande ce que contient la shadow map. En effet, il manque un morceau d'ombre et pour moi, cela veut dire qu'elle n'est pas écrit dans la shadowmap. Pouvez-vous confirmer que la shadowmap est correct ou pas, dans un tel cas ?

                                    Peut être vous avez une mauvaise configuration du RTT et que votre depthbuffer que vous utilisez est un ancien depthbuffer (???).

                                    (En vérifiant l'état de la shadowmap, on saura si le problème vient de 1) avant la génération de la shadowmap, 2) après la génération (donc lors de l'application)).

                                    Non la shadow map est correctement générée (je la vois tout le temps, c'est le carré blanc à côté de la source de lumière), ma pause vient de se finir donc je posterai des images détaillées de la shadow map (en boostant un peu) s'il le faut ce soir.

                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                      26 juin 2015 à 13:03:51

                                      Donc le bug:

                                      Et le depth buffer avec une tentative de le rendre plus visible (via un logiciel d'édition):

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                        26 juin 2015 à 13:27:20

                                        Mise à jour, je viens de vérifier quelque chose:

                                        Voici des screenshots de comparaison (même point de vue par groupe de deux, comparaison facile):

                                        zNear = 0.1, zFar = 1000
                                        zNear = 2, zFar = 1000

                                        zNear = 0.1, zFar = 1000
                                        zNear = 0.1, zFar = 500

                                        C'est très visible sur les deux derniers, l'ombre est plus correcte avec un zFar plus faible, ça ressemble vraiment à un problème de précision (mais comme le depth buffer apparaît de façon visible sur la seconde image, on voit bien que la précision est correcte à ce niveau, non ?).

                                        Si quelqu'un sait où se trouve le problème, moi je commence un peu à désespérer :D

                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                          28 juin 2015 à 4:50:16

                                          Autre vidéo montrant le problème peut-être d'une meilleure façon.

                                          J'ai aussi posté le problème sur Stackoverflow, il se produit sur toutes les configurations testées, il y a quelque chose qui m'échappe mais je ne sais vraiment pas quoi..

                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                            28 juin 2015 à 10:39:43

                                            Le bias ne sert-il pas aussi à éviter le self-shadowing ? Ce n'est pas simplement le culling + bias qui fait que lorsque tu rapproches trop la surface qui cast et celle qui reçoit l'ombre disparaît ?
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              28 juin 2015 à 12:16:03

                                              LeParp a écrit:

                                              Le bias ne sert-il pas aussi à éviter le self-shadowing ? Ce n'est pas simplement le culling + bias qui fait que lorsque tu rapproches trop la surface qui cast et celle qui reçoit l'ombre disparaît ?

                                              Le bias sert à éviter le "moire pattern" (je viens de me lever donc je dis peut-être des conneries), mais même si je l'enlève le résultat ne bouge pas d'un poil :-/

                                              • Partager sur Facebook
                                              • Partager sur Twitter

                                              Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                                29 juin 2015 à 9:51:58

                                                Wow, c'est quoi ces vagues sur l'ombre o_O

                                                La capture "zNear = 0.1, zFar = 500" est t-elle juste plus juste, ou complètement correcte ?

                                                -
                                                Edité par LittleWhite 29 juin 2015 à 9:52:10

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  29 juin 2015 à 10:02:21

                                                  LittleWhite a écrit:

                                                  Wow, c'est quoi ces vagues sur l'ombre o_O

                                                  Le filtrage bilinéaire sur une shadow map 256x256, c'est normal.

                                                  LittleWhite a écrit:

                                                  La capture "zNear = 0.1, zFar = 500" est t-elle juste plus juste, ou complètement correcte ?

                                                  Elle est un peu plus correcte, mais l'ombre correcte partirait de la base du cube (il est posé sur le sol).



                                                  • Partager sur Facebook
                                                  • Partager sur Twitter

                                                  Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                                    29 juin 2015 à 10:55:51

                                                    Est ce que ce n'est pas simplement que tu n'as pas la précision nécessaire avec un frumstrum de cette taille pour détecter la différence de distance entre la surface d'émission et celle de réception ? Dans ce cas soit tu prends un zFar = 100 soit abandonne le front culling ?

                                                    Si il s'agit effectivement d'un problème de précision tu peux aussi distribuer la profondeur sur les différents composantes de ta shadow maps et la reconstituer au moment du test.

                                                    EDIT : En fait ça me fait penser à un cas extrême de Peter panning, qui se résoud en n'ayant que des objets épais dans la scène et en ne faisant pas de front culling. Et puis je dois avouer que je ne sais pas vraiment pourquoi tu veux éviter le self-shadowing, le bias suffit normalement à éviter le seul problème dont il est responsable...

                                                    -
                                                    Edité par LeParp 29 juin 2015 à 13:27:32

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      29 juin 2015 à 13:20:41

                                                      zNear = 2

                                                      zFar = 50

                                                      Shadow map sur 32 bits

                                                      Front face culling désactivé.

                                                      Désolé mais ça ne change rien, il y a bel et bien un problème quelque part et je n'ai aucune idée d'où :-/

                                                      Et on voit clairement que la shadow map possède la précision suffisante, le cube est très bien démarqué.

                                                      -
                                                      Edité par Lynix 29 juin 2015 à 13:21:44

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter

                                                      Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                                        29 juin 2015 à 14:39:32

                                                        Après vérification, ça ressemble quand même beaucoup à du peter panning (source) :

                                                        Tu peux toujours enlever le bias en plus de ce que tu as déjà fais pour être sûr que ça ne soit pas ça, même si tu auras du coup du shadow acne (si ça marche il suffira de régler le bias !).

                                                        Au passage, je parlais d'un truc de ce genre pour distribuer la précision (c'est du hlsl, source) :

                                                        1. // Where to split the value. 8 bits works well for most situations.
                                                        2. float g_DistributeFactor = 256;
                                                        3. float4 DistributePrecision(float2 Moments)  
                                                        4. {  
                                                        5. float FactorInv = 1 / g_DistributeFactor;
                                                        6. // Split precision
                                                        7.     float2 IntPart;  
                                                        8.     float2 FracPart = modf(Value * g_DistributeFactor, IntPart);  
                                                        9.     // Compose outputs to make reconstruction cheap.
                                                        10.     return float4(IntPart * FactorInv, FracPart);  
                                                        11. }
                                                        12. float2 RecombinePrecision(float4 Value)  
                                                        13. {  
                                                        14.     float FactorInv = 1 / g_DistributeFactor;  
                                                        15. return (Value.zw * FactorInv + Value.xy);  

                                                        Mais je crois pas que ça joue beaucoup avec un frumstum pareil. :D

                                                        Bon et puis si c'est toujours pas ça, ça sort de mes compétences... :-°

                                                        -
                                                        Edité par LeParp 29 juin 2015 à 17:31:40

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          29 juin 2015 à 19:06:25

                                                          Que je sache, le bug dont tu me parles est un décalage de l'ombre, or moi elle n'est pas décalée, elle est coupée (ça se voit particulièrement sur la dernière vidéo).

                                                          En plus, j'ai déjà viré le bias du shader, ça n'a eu aucun effet. Ce truc va me rendre fou.

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          Mes articles | Nazara Engine | Discord NaN | Ma chaîne Twitch (programmation)

                                                            30 juin 2015 à 10:42:04

                                                            Moi, je ne trouvais pas que c'était un décalage, mais plus une partie de l'ombre (une face) qui manquait.

                                                            Avez vous essayez du débogage pas à pas avec les outils spécifique GPU (NVIDIA, ou autre gDEBugger) ?

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

                                                            [OpenGL][3D] Shadow mapping qui déconne

                                                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                            • Editeur
                                                            • Markdown