#25 

24-05-2017 12:00:02

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

Salut Magun !

Je t'ai préparé un projet simple avec juste le shader water que j'utilise.
De mon côté j'ai pas mal gratté a chercher d'autres exemples mais c'est compliqué de comparer avec mon shader.

1) Effectivement le "gros paté" ce n'est pas le résultat voulu, je t'ai mis une capture d'écran du résultat dans l'archive que je t'ai envoyé par mail.
Oui visiblement il y a une couche de texture qui sert a faire une normal (3 couche de texture il me semble).

2) et 3) -> essai avec le nouveau projet que je t'ai envoyé.

4) Le skydome étrange sert a mettre une texture transparente avec nuages, c'est un model 3d qui tourne très lentement. J'applique la même texture sur un skydome irrlicht qui est statique et on dirait que les nuages se séparent (c'est mon bricolage çà oubli cette partie je l'ai supprimé sur le dernier).

Moi de mon côté je ne comprend pas pourquoi on crée une deuxième caméra pour la réflexion, c'est coi le principe ? Il y a une subtilité à faire çà ?

Dans le code du shader tu verra une variable "pass" qui sert à limiter la vitesse du rafraichissement sauf que dès que je l'augmente on voit vite que la réflexion n'est plus fluide.

J'ai testé mon prog sur un pc récent (ASUS ROG NVIDIA 1080) et j'ai constaté qu'on descendait à 55 fps au lieu de 60 par moment. Du coups je me suis dis qu'il y a quelque chose qui va pas.

Hors ligne


#26 

29-05-2017 14:39:21

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

???

Hors ligne


#27 

29-05-2017 22:03:41

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

tu sait, cela prend du temp (~une aprem) et je ne serait vraiment disponible qu'qpres fin juin, mais j'ai commencer a ecrire un petit code
si tu as d'avantage de temp, au lieu d'attendre la reponsse miracle, commence a realiser quelque chose : CMapReflexion
cette classe seras une implementation de ILightManager

en gros le but est de filter les nodes a rendre, c'est a dire : pour chaque "pass" du drawAll du scene manager, si un ILightManager est set il va apeller une fonction de l'objet referenecent un ILightManager

par exemple, en fouillant dans le code source d'irrlicht on trouve cela:

Code c++ :

    // render skyboxes
    {
        IRR_PROFILE(CProfileScope psSkyBox(EPID_SM_RENDER_SKYBOXES);)
        CurrentRenderPass = ESNRP_SKY_BOX;
        Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);

        if (LightManager)
        {
            LightManager->OnRenderPassPreRender(CurrentRenderPass);
            for (i=0; i<SkyBoxList.size(); ++i)
            {
                ISceneNode* node = SkyBoxList[i];
                LightManager->OnNodePreRender(node);
                node->render();
                LightManager->OnNodePostRender(node);
            }
        }
        else
        {
            for (i=0; i<SkyBoxList.size(); ++i)
                SkyBoxList[i]->render();
        }

        SkyBoxList.set_used(0);

        if (LightManager)
            LightManager->OnRenderPassPostRender(CurrentRenderPass);
    }

idem pourles objets solide, l'ombre, les objets transparent, ... etc

donc tu peut selectionner grace au type de la "pass" actuel ce que tu veut rendre ou pas, et, meme selectionner les nodes a rendre en fonction de leurs types
toi normalement tu va rendre uniquement les skybox et les objets solides. Parmit les objets solide, tu va naturelement exclure le terrain et d'autre "babiole" en fonction du gain de performance que tu souhaite

du coup tu va pouvoir utiliser cela, conjointement avec ce que tu avais deja dans CMapWater tu setLightManager avans le smgr->drawAll et tu l'unset apres (nullptr)

l'etape d'apres c'est d'ecrire cette class CMapWater correctement !! -> tu ajoute pas un ISceneNode dans un ISceneNode pour gerer ce dernier, tu fait un vrai scene node dedier a l'eau
tu donne le path des shader dans le constructeur, tu lui donne un vrai type (getType devrait retourner ESNT_WATER_SURFACE), bref on peut trouver pas mal de truc a faire avec ces deux/trois element

ce n'est que mon avis evidement, mais sa a un but : avoir un code claire, debuter une architecture, et donner de la coherence pour pouvoir l'utiliser plus tard
apres y a plus simple, mais j'aime bien experimenter, et je pensse que sa peut donner un truc pas trop mal, en offrant des possibiliter pour plus tard smile

Hors ligne


#28 

30-05-2017 18:50:28

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

Hey ! Je "n'attends" pas de réponse miracle, loin de là, je voulais juste savoir si tu avais reçu mon dernier mail avec un code plus propre !!!
Pour info, j'ai trouvé une autre solution concernant la coloration du ciel, elle vaut ce qu'elle vaut mais j'utilise setFOG :

Code c++ :


void CMapSkyColor::apply_sky_fog()
{
    SMaterial *SkyMaterial= &ColoredSkyNode->getMaterial(0);
    SkyMaterial->FogEnable      = FOGEnd;
    SkyMaterial->Lighting       = true;
    SkyMaterial->EmissiveColor  = FOGDiffuse;

    FOGSky = SColor(1, FOGRed,FOGGreen,FOGBlue);

    driver->setFog( FOGSky,
                    EFT_FOG_LINEAR,
                    FOGStart,
                    FOGEnd,
                    FOGStrength,
                    false,
                    true);
}


Je me suis bien cassé la téte à tracer la courbe de variation de couleur tout au long de la journée, pour chaque couleur RGB j'ai une courbe.
Je calcul mes couleurs en init, puis je me contente de les afficher dans l'update.
çà fonctionne super bien!

Concernant le shader de l'eau, comme je t'ai dis je part de zéro, donc j'en suis encore aux tutos de débutant. J'ai réussis à texturer un cube, et çà a été très laborieux, alors bon forcément je traine un peut derrière. Je vais essayer de créer cette classe de réflexion, par contre le contenu çà va être super tendu d'improviser mais je m'accroche. Je pense que pour toi c'est évident tout çà, pour moi j'ai l'impression de découvrir pleins de choses.

Je te remercie grandement pour tout le temps que tu investi smile

Hors ligne


#29 

02-06-2017 21:36:36

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

Salut, je suis désoler mais je n'aurait pas le temps avans le weekend prochain pour te pondre quelques chose sad
trop de taf pour cette fois ci, cordialement

ps: si le fog te statisfait pourquoi pas, mais a mon sens ce n'est pas une "vrai" solution, tu contourne juste le problème

Hors ligne


#30 

04-06-2017 00:51:28

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

Salut ! ok pas de soucis, de mon côté je comprends que ce n'est pas une "vrai" solution d'utiliser le fog, je me suis alors mis sur un shader tout simple.

Code c++ :


uniform sampler2D Texture1;
uniform float fRed;
uniform float fGreen;
uniform float fBlue;

void main ( void )
{
    vec4 color = texture2D ( Texture1 , gl_TexCoord[0] );
    color = vec4 ( fRed , fGreen , fBlue , 0.0 );
    gl_FragColor = color;
}

çà marche bien, j'arrive a assigner un material de couleur RGB.
Par contre, premier obstacle, la couleur du ciel change en fonction du temps dans mon appli,
et du coups je ne vois pas comment changer dynamiquement les valeurs RGB de mon shader.
Car une seule couleur est créée au moment de l'init, normal :

Code c++ :


virtual void OnSetConstants ( video::IMaterialRendererServices* services , s32 userData )
{
          float red = 0.2f;
          float green = 0.9f;
          float blue = 1.0f;
          services->setVertexShaderConstant("fRed", &red, 1);
          services->setVertexShaderConstant("fGreen", &green, 1);
          services->setVertexShaderConstant("fBlue", &blue, 1);
}

Dernière modification par jonath313 (04-06-2017 00:53:02)

Hors ligne


#31 

04-06-2017 10:29:34

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

quelques remarques vites fait:

Code c++ :

uniform float fRed;
uniform float fGreen;
uniform float fBlue;

peut-être transformer en

Code c++ :

uniform vec4 background;

et donc si tu veut donner une couleur a ta texture tu fait une multiplication:

Code c++ :

    vec4 color = texture2D ( Texture1 , gl_TexCoord[0] );
    gl_FragColor = color * background;

ensuite OnSetConstants n'est pas une initialisation, mais un "callback" et est apeller a chaque frame, tu peut donc envoyer la couleur que tu veux, a tout moment

Code c++ :

//          irr::video::SColorf background; // declarer dans la class
virtual void OnSetConstants ( video::IMaterialRendererServices* services , s32 userData )
{
          services->setVertexShaderConstant("fRed", reinterpret_cast<float*>background, 4);
}

Hors ligne


#32 

05-06-2017 01:16:24

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

Merci Magun ! çà fonctionne super bien !
Par contre voici mon code :

Code c++ :

void CColorShader::OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
        // Set inverted world matrix
        // if we are using highlevel shaders (the user can select this when
        // starting the program), we must set the constants by name.
        core::matrix4 invWorld = Driver->getTransform(video::ETS_WORLD);
        invWorld.makeInverse();
        services->setVertexShaderConstant("fRed", invWorld.pointer(), 16);

        // Set clip matrix
        core::matrix4 worldViewProj;
        worldViewProj = Driver->getTransform(video::ETS_PROJECTION);
        worldViewProj *= Driver->getTransform(video::ETS_VIEW);
        worldViewProj *= Driver->getTransform(video::ETS_WORLD);
        services->setVertexShaderConstant("fGreen", worldViewProj.pointer(), 16);

        // Set camera position
        core::vector3df pos = Dev->getSceneManager()->getActiveCamera()->getAbsolutePosition();
        services->setVertexShaderConstant ( "fBlue" , reinterpret_cast<f32*>( &pos ) , 3 );

        // Set light color
        video::SColorf col(1.0f,1.0f,1.0f,0.0f);
        services->setVertexShaderConstant("background", reinterpret_cast<f32*>(&col), 4);

        // Set transposed world matrix
        core::matrix4 world = Driver->getTransform(video::ETS_WORLD);
        world = world.getTransposed();
        services->setVertexShaderConstant("mInvWorld", world.pointer(), 16);

// ICI
services->setVertexShaderConstant("mWorldViewProj", reinterpret_cast<float*>(&background), 4);
}


pixel_color_shader.frag :

Code c++ :

uniform sampler2D Texture1;
uniform vec4 background;

void main ( void )
{
    vec4 color = texture2D ( Texture1 , gl_TexCoord[0] );
    gl_FragColor = color * background;
}


vertex_color_shader.vert :

Code c++ :

uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform vec3 mLightPos;
uniform vec4 mLightColor;

void main ( void )
{
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = mWorldViewProj * gl_Vertex;
}


Pour le fichier pixel je comprends ce que je fais, par contre pour le fichier vertex je ne saisis pas trop pourquoi j'utilise:
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform vec3 mLightPos;
uniform vec4 mLightColor;
(Je me suis inspiré d'un tuto pas très complet et j'ai laissé comme çà).
En fait ce que je ne comprends pas c'est le rapport avec un vertex, qui est un point d'un mesh 3d non ?

Hors ligne


#33 

07-06-2017 08:43:08

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

uniform c'est juste pour dire que c'est une donnée "externe" qui seras mis à jours dans ton programme, ici tu n'en utilise que trois mWorldViewProj, Texture1, background (tous accessible depuis vertex/fragment s'il sont declarer)
enssuite, en opengl tu a trois type de matrice

    projection http://rvirtual.free.fr/programmation/O … /c1106.htm
    view: en gros la camera, (position et rotation)
    world: la matrice de l'objet (position, rotation, scale) et des parents

sauf que toi tu as un objet dans sont repaire xyz et toi quand tu dessine tu est dans le repaire "scene/world" puis view puis projection
et le but c'est juste de passer d'un repaire a un autre, pour chaque objets de la scene
il faut simplement appliquer les différentes matrice "haut dessus" (object -> world -> view -> projection) et c'est mWorldViewProj * objet
mais ton object c'est pas une matrice, mais une liste de vertexes, tu applique donc ta matrice 4x4 a chaque vertex de ton object (gl_Vertex) qui est un vec3(x,y,z) harmoniser en vec4 (x,y,z,1)

mLightPos est  mal nommé, ce serait plutot mCameraPos, mLightColor inutile
et puis gl_TexCoord[0] = gl_MultiTexCoord0; c'est juste une copie,

au moment de la rasterisation il va interpoler automatiquement les  toutes les donner calculer ici 3 par 3 gl (1 pour chaque sommets du polygone) qui est envoyer au fragment shader (tu n'en a donc plus que 1 a traiter)
gl_TexCoord devien une coordonner sur le polygonne (au lien d'un sommet)
gl_vertex devient gl_FragCoord (tu passe du repaire objet au repaire écrans)
et cela pour touts les pixels visibles

Hors ligne


#34 

19-06-2017 20:48:07

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

Merci beaucoup pour tes conseil, j'ai réussi a faire mon premier shader et il fonctionne correctement. Pour la coloration du ciel j'en ais terminé, j'ai repris tous mes codes pour créer un module météo. J'ai appliqué mon shader aux nuages et je joue sur l'opacité pour les faire apparaitre c'est vraiment surper comme rendu.

En ce qui concerne le shader de l'eau j'ai fais quelques recherche de mon côté. Par rapport à ce que tu disais sur le fait que les "pass" soient "sélectives", dans la doc, j'ai trouvé ceci :

Code c++ :


enum E_SCENE_NODE_RENDER_PASS {
  ESNRP_NONE = 0,
  ESNRP_CAMERA = 1,
  ESNRP_LIGHT = 2,
  ESNRP_SKY_BOX = 4,
  ESNRP_AUTOMATIC = 24,
  ESNRP_SOLID = 8,
  ESNRP_TRANSPARENT = 16,
  ESNRP_TRANSPARENT_EFFECT = 32,
  ESNRP_SHADOW = 64
}



Si j'ai bien compris, quand je fais smgr->drawall(), le rendu comprend toute cette liste de type de nodes.

Je peux alors récupérer le type de la "pass" de cette manière ?:

Code c++ :


E_SCENE_NODE_RENDER_PASS CurrentPass;

void CMapWater::OnAnimate(u32 timeMs)
{
          CurrentPass = SceneManager->getSceneNodeRenderPass();

          if((CurrentPass == ESNRP_SOLID ) || (CurrentPass == ESNRP_SKY_BOX ))
          {
             /// Code de la reflexion
          }
}



Je suis sur la bonne voie où à côté de la plaque ?

Je n'ai pas trop saisi ce que tu entends par : "Dans CMapWater tu setLightManager avant le smgr->drawAll et tu l'unset apres (nullptr)" :

Code c++ :


E_SCENE_NODE_RENDER_PASS CurrentPass;

void CMapWater::OnAnimate(u32 timeMs)
{
          CurrentPass = SceneManager->getSceneNodeRenderPass();

          if((CurrentPass == ESNRP_SOLID ) || (CurrentPass == ESNRP_SKY_BOX ))
          {
             /// ...
            SceneManager->setLightManager(???);
            SceneManager->drawAll();
            SceneManager->setLightManager(0);
            /// ...
          }
}


C'est cela dont tu parle ?

Quand j'utilise le debug je me rends compte que ma variable CurrentPass est toujours à ESNRP_NONE est-ce normal ? Du coups la réflexion est jamais appelée.
Je dois passer quoi en paramètre de  setLightManager (ILightManager *lightManager) ?

Dernière modification par jonath313 (20-06-2017 00:01:25)

Hors ligne


#35 

22-06-2017 14:36:55

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

Salut ! smile

je voie que tu as avancer sur les shaders, c'est bien, tu voie c'est pas tres compliquer, bon peut-être un peut plus quand il faut faire des maths pour faires des effects un peut plus pousser
alors oui tu t'ai bien documenter, par contre l'utilisation ce n'est pas ça smile

par exemple ILightManager resembleras a quelques chose du genre

Code c++ :

#pragma once

class CMapReflexion : public scene::ILightManager
{
      public:
        CMapReflexion(scene::ISceneManager* sceneManager)
          :  SceneManager(sceneManager), SceneLightList(0),
             CurrentRenderPass(scene::ESNRP_NONE), CurrentSceneNode(0)
        {
        }

        virtual void OnPreRender(core::array<scene::ISceneNode*> & lightList)
        {
            Mode = RequestedMode;
            SceneLightList = &lightList;
        }

        virtual void OnPostRender()
        {
        }

        virtual void OnRenderPassPreRender(scene::E_SCENE_NODE_RENDER_PASS renderPass)
        {
            CurrentRenderPass = renderPass;
           
            if(renderPass == ESNRP_LIGHT)
            {
                const vector3df nodePosition = smgr->getActiveCamera()->getAbsolutePosition();

                array<LightDistanceElement> sortingArray;
                sortingArray.reallocate(SceneLightList->size());

                u32 i;
                for(i = 0; i < SceneLightList->size(); ++i)
                {
                  scene::ISceneNode* lightNode = (*SceneLightList)[i];
                  const f64 distance = lightNode->getAbsolutePosition().getDistanceFromSQ(nodePosition);
                  sortingArray.push_back(LightDistanceElement(lightNode, distance));
                }

                sortingArray.sort();

                for(i = 0; i < sortingArray.size(); ++i)
                    sortingArray[i].node->setVisible(i < 3);
            }
        }

        virtual void OnRenderPassPostRender(scene::E_SCENE_NODE_RENDER_PASS renderPass)
        {
        }

        virtual void OnNodePreRender(scene::ISceneNode* node)
        {
            nodeIsVisible = node->isVisible();
            node->setVisible(nodeIsVisible && (CurrentRenderPass == ESNRP_SOLID && CurrentRenderPass == ESNRP_SKY_BOX));
        }

        virtual void OnNodePostRender(scene::ISceneNode* node)
        {
            node->setVisible(nodeIsVisible);
        }

    private:
        bool nodeIsVisible;
        scene::ISceneManager * SceneManager;
        core::array<scene::ISceneNode*> * SceneLightList;
        scene::E_SCENE_NODE_RENDER_PASS CurrentRenderPass;
    private:

        // A utility class to aid in sorting scene nodes into a distance order
        struct LightDistanceElement
        {
            LightDistanceElement() {};

            LightDistanceElement(scene::ISceneNode* n, f64 d)
              : node(n), distance(d) { }

            scene::ISceneNode* node;
            f64 distance;

            // Lower distance elements are sorted to the start of the array
            bool operator < (const LightDistanceElement& other) const
            {
              return (distance < other.distance);
            }
        };
};



ensuite, soit tu genère ta reflexion map dans une class approprier et partager dans ton appli
soit tu reste comme ça et tu donne le ILightManager a ton CMapWater

Code c++ :


void CMapWater::OnAnimate(u32 timeMs)
{
    if (IsVisible)
    {
        video::IVideoDriver* Driver = SceneManager->getVideoDriver();

        Driver->setRenderTarget(ReflectionMap,true,true);

        scene::ICameraSceneNode* CurrentCamera=SceneManager->getActiveCamera();
        scene::ICameraSceneNode* newcamera=SceneManager->addCameraSceneNode();

        newcamera->setFarValue(CurrentCamera->getFarValue());
        newcamera->setFOV(CurrentCamera->getFOV());
        newcamera->setAspectRatio(1.33f);

        core::vector3df position=CurrentCamera->getPosition();
        position.Y=-position.Y+2.0f*RelativeTranslation.Y;
        newcamera->setPosition(position);

        core::vector3df target=CurrentCamera->getTarget();
        target.Y=-target.Y+2.0f*RelativeTranslation.Y;
        newcamera->setTarget(target);
       
        f32 last_time = Dev->getTimer()->getRealTime();

        SceneManager->setActiveCamera(newcamera);

            SceneManager->setLightManager(lmgr);
            SceneManager->drawAll();
            SceneManager->setLightManager(0);

        Driver->setRenderTarget(0);

        SceneManager->setActiveCamera(CurrentCamera);

        newcamera->remove();

        ISceneNode::OnAnimate(timeMs);
    }
}



voila c'est un exemple de base qui te permetra de filtrer t'est nodes pour la reflexion
evidement tu peut ajouter des critères dans CMapReflexion::OnNodePreRender, les objets d'une tailles inferieur a une certaine taille peuvent être desactiver, ... etc

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
883 membres
1429 sujets
11121 messages
Dernier membre inscrit: Saidov17
128 invités en ligne
Aucun membre connecté
RSS Feed