Pages: 1 2
- Accueil forums
- » Aide Irrlicht C++
- » Changer la coloration de la texture d'une skybox
24-05-2017 10:00:02
- jonath313
- Membres
- Date d'inscription:
- Messages: 240
- IP: 217.128.73.71
- Courriel
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
29-05-2017 12:39:21
29-05-2017 20:03:41
- Magun
- Administrateurs

- Date d'inscription:
- Messages: 910
- IP: 109.190.12.31
- Courriel 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);
}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
Hors ligne
30-05-2017 16:50:28
- jonath313
- Membres
- Date d'inscription:
- Messages: 240
- IP: 90.52.9.217
- Courriel
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
Hors ligne
02-06-2017 19:36:36
- Magun
- Administrateurs

- Date d'inscription:
- Messages: 910
- IP: 82.234.76.73
- Courriel Site web
Salut, je suis désoler mais je n'aurait pas le temps avans le weekend prochain pour te pondre quelques chose ![]()
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
03-06-2017 22:51:28
- jonath313
- Membres
- Date d'inscription:
- Messages: 240
- IP: 86.216.185.160
- Courriel
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;
}
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);
}
Hors ligne
04-06-2017 08:29:34
- Magun
- Administrateurs

- Date d'inscription:
- Messages: 910
- IP: 82.234.76.73
- Courriel Site web
quelques remarques vites fait:
Code c++ :
uniform float fRed;
uniform float fGreen;
uniform float fBlue;Code c++ :
uniform vec4 background;Code c++ :
vec4 color = texture2D ( Texture1 , gl_TexCoord[0] );
gl_FragColor = color * background; Code c++ :
// irr::video::SColorf background; // declarer dans la class
virtual void OnSetConstants ( video::IMaterialRendererServices* services , s32 userData )
{
services->setVertexShaderConstant("background", reinterpret_cast<float*>background, 4);
}Hors ligne
04-06-2017 23:16:24
- jonath313
- Membres
- Date d'inscription:
- Messages: 240
- IP: 86.216.185.160
- Courriel
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("mInvWorld", 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("mWorldViewProj", worldViewProj.pointer(), 16);
// Set camera position
core::vector3df pos = Dev->getSceneManager()->getActiveCamera()->getAbsolutePosition();
services->setVertexShaderConstant ( "mLightPos" , reinterpret_cast<f32*>( &pos ) , 3 );
// Set light color
video::SColorf col(1.0f,1.0f,1.0f,0.0f);
services->setVertexShaderConstant("mLightColor", reinterpret_cast<f32*>(&col), 4);
// Set transposed world matrix
core::matrix4 world = Driver->getTransform(video::ETS_WORLD);
world = world.getTransposed();
services->setVertexShaderConstant("mTransWorld", world.pointer(), 16);
// ICI
services->setVertexShaderConstant("background", 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
07-06-2017 06:43:08
- Magun
- Administrateurs

- Date d'inscription:
- Messages: 910
- IP: 82.234.76.73
- Courriel 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/OpenGl/Sdin/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
19-06-2017 18:48:07
- jonath313
- Membres
- Date d'inscription:
- Messages: 240
- IP: 90.4.23.75
- Courriel
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) ?
Hors ligne
22-06-2017 12:36:55
- Magun
- Administrateurs

- Date d'inscription:
- Messages: 910
- IP: 109.190.12.31
- Courriel Site web
Salut ! ![]()
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 ![]()
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



