Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
On commence par une facile.
La lumière ambiante est la plus simple qui soit, elle éclaire tout, partout, tout le temps et avec la même intensité.
Par définition la lumière
ambiante n'a pas de source précise. Elle provient de partout à la fois.
Cela explique qu'elle éclaire tout avec la même intensité.
Il est donc impossible de faire des ombres en se servant de la lumière ambiante.
Le problème avec ce type de lumière est qu'elle ne permet pas à elle seule de faire en sorte qu'on puisse distinguer les détails d'un objet. On ne voit que ses contours (s'il est de couleur unie).
Par exemple :
Ici, on voit bien (ou plutôt on ne voit rien du tout

) que la lumière étant la même partout, il est impossible de distinguer les détails d'un objet.
Bon, maintenant un peu de code :
Code : C++1 | scenegraph->setAmbientLight (video::SColorf(1.0,1.0,1.0,0.0));
|
Vous avez sous les yeux la fonction qui permet de modifier la lumière ambiante.
Et vous l'aurez deviné, le paramètre représente la nouvelle valeur de cette lumière.
Le dernier chiffre de la couleur n'est pas important dans ce cas précis. Il s'agit de la composante alpha, et elle ne changera rien à la couleur de la lumière ni à son intensité.
Par défaut, la lumière ambiante est égale à (0,0,0).
Ce qui signifie que si vous ne rajoutez aucune source de lumière, vous n'y verrez rien du tout.
En réglant la lumière ambiante à (1.0,1.0,1.0), toute la scène sera éclairée au maximum.
Quelques images pour mieux se rendre compte :


La lumière : en parler c'est bien, la voir c'est mieux !
Alors sans plus attendre faisons une petite scène de test pour que vous puissiez admirer vous-même le résultat.
Pour ne pas déroger à cette bonne vieille habitude, je vais vous donner un code dont certaines parties n'ont pas encore été expliquées dans ce tuto et ne le seront pas avant quelques chapitres. (En fait c'est une ruse pour vous obliger à aller regarder dans la doc

)
Pour cette scène vous allez avoir besoin de 2 fichiers présents dans le dossier media du SDK.
Il s'agit de "room.3ds" qui contient un modèle 3D comme
l'indique son extension, et "rockwall.bmp" qui est bien évidement une image et qui va nous servir de texture.
Et maintenant le code complet :
Code : C++ 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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 | #include <iostream>
#include <IRR/irrlicht.h>
using namespace irr;
int main(void)
{
//Cette ligne va créer un contexte d'affichage OpenGL
IrrlichtDevice *device = createDevice (video::EDT_OPENGL, core::dimension2d<s32>(800,600),32,true,true,false,0);
//On associe un driver à la fenêtre
video::IVideoDriver* driver = device->getVideoDriver ();
//Et on crée un gestionnaire de scène (scenegraph)
scene::ISceneManager *scenegraph = device->getSceneManager ();
// // // // La caméra // // // //
scene::ICameraSceneNode *camera = scenegraph->addCameraSceneNodeFPS (0,80.0f,100.0f);
camera->setPosition(core::vector3df(10.0, 50.0, -50.0));
// // // // la salle // // // //
scene::IAnimatedMesh *room = scenegraph->getMesh("room.3ds");
if (room == 0)
{
std::cout << "probleme de chargement de la salle" << std::endl;
return 1;
}
scene::IMeshSceneNode *Nroom = scenegraph->addMeshSceneNode(room->getMesh(0));
Nroom->setMaterialFlag(video::EMF_LIGHTING, true);
//On applique une texture à la salle.
scenegraph->getMeshManipulator()->makePlanarTextureMapping(
room->getMesh(0), 0.004f);
Nroom->setMaterialTexture( 0, driver->getTexture("rockwall.bmp") );
if (driver->getTexture("rockwall.bmp") == 0)
{
std::cout << "probleme de chargement de la texture "rockwall.bmp"" << std::endl;
return 1;
}
// // // // la lumière // // // //
scenegraph->setAmbientLight(video::SColorf(1.0, 1.0, 1.0,0.0));
//La boucle de rendu
while (device->run ())
{
//On indique qu'on démarre la scène
driver->beginScene (true, true, video::SColor (255,255,255,255));
//On calcule le rendu
scenegraph->drawAll ();
//On affiche le rendu à l'écran
driver->endScene ();
}
//On libère la mémoire en détruisant le device
device->drop ();
return 0;
}
|
Et voilà. Vous remarquerez qu'on a modifié un material sur le mesh de la pièce : EMF_LIGHTING.
Un petit tour dans la doc nous apprend que celui-ci permet de choisir si un mesh est sensible à la lumière ou pas.
Par défaut il est à "true", ce qui signifie qu'il est sensible à la lumière. Si vous ne rajoutez pas d'éclairage, il restera noir comme du charbon.
En le mettant à false, le mesh n'aura que faire de l'éclairage de la scène, il resplendira comme en plein jour.
Bon dans le code ci-dessus, le mettre à true n'a pas grand intérêt puisque c'est sa valeur par défaut.
Vous pouvez néanmoins le mettre à false pour tester le changement.
En jouant sur le paramètre de la fonction modifiant la lumière ambiante vous pouvez régler l'éclairage comme on vient de le voir.
Maintenant qu'on dispose d'une scène sympa pour faire des tests, on est prêt à passer à la suite.
Les lumières diffuses sont bien plus intéressantes que la lumière ambiante et par conséquent... bien plus complexes.
En fait il s'agit d'une source de lumière au sens classique du terme, comme une lampe de bureau ou un spot.
En pure théorie une lumière est dite diffuse quand elle est réfléchie par les objets qu'elle éclaire.
Pour en savoir plus, je vous renvoie sur
cette page qui vous donne une bonne définition des différents types d'éclairage.
(Et qui vous permettra de réviser vos classiques en OpenGL au passage

)
Pour reprendre l'exemple de tout à l'heure avec une lumière diffuse, regardez plutôt :
On peut nettement voir que la lumière se réfléchit sur toutes les surfaces de l'objet, là où avec une lumière ambiante on ne voyait... rien.
La fonction de base pour ajouter une lumière diffuse sous Irrlicht est :
Code : C++1 | scenegraph->addLightSceneNode (0, core::vector3df(0,0,0), video::SColorf(0.4f,0.4f,0.6f,0.0f), 100.0f);
|
Vous pouvez voir qu'il s'agit d'un noeud particulier qu'on ajoute (comme tous les noeuds) en passant par le scene graph.
Pour connaître l'utilité de chaque paramètre, c'est
par ici.
A quoi sert le paramètre radius ?
Le meilleur moyen de le savoir c'est encore de le changer pour voir ce qui se passe.
Voici deux screens qui montrent le même point de vue mais avec un radius différent :

On aurait aussi put ouvrir tout simplement un dico d'Anglais.
En anglais, "radius" signifie "rayon" (en l'occurrence celui de diffusion de la source de lumière).
Donc, en toute logique, plus le rayon de diffusion de notre lumière sera élevé et plus celle-ci éclairera loin.
Vous pouvez déjà rajouter cette ligne de code dans la scène de test que l'on vient de faire pour vous rendre compte des changements.
Vous pouvez par exemple combiner la lumière ambiante avec celle-ci ou modifier la couleur passée en paramètre pour voir la différence.
Bon. Comme toujours : ajouter une lumière c'est bien, la paramétrer c'est mieux !
Alors voyons un peu ce qu'on peut faire pour personnaliser l'éclairage.
La première chose à faire est de récupérer le noeud qu'on ajoute.
Pour cela il faut changer quelque peu le code précédent :
Code : C++1 | scene::ILightSceneNode* lumiere = scenegraph->addLightSceneNode(Nroom, core::vector3df(100,100,200),video::SColorf(0.4f, 0.4f, 0.6f, 0.0f), 100.0f);
|
Maintenant on peut accéder directement au noeud.
Il est temps maintenant d'aller mettre les mains dans le cambouis et de retourner faire un tour dans les méandres de la doc.
Voici la page qui nous intéresse :
ILightSceneNode.
Comme vous pouvez le voir, cette classe possède 2 méthodes :
- Le constructeur (que nous avons déjà vu)
- getLightData
Vous vous en doutez, c'est cette deuxième méthode que nous allons regarder de plus près.
Observez un peu ce qu'elle retourne : une structure de type
video::SLight.
Et là, sous vos yeux ébahis... des tas, que dis-je ? Des montagnes de variables paramétrables !
Ouais c'est cool, mais comment on les modifie ?
Un peu de patience jeune padawan. La clef de l'éclairage réussi se trouve assurément dans cette structure.
La méthode "classique" pour modifier l'une de ses composantes est la suivante :
Code : C++1 | lumiere->getLightData().DiffuseColor = video::SColorf(0.6, 1.0, 1.0, 1);
|
Bon là si vous avez suivi vous ne devriez même pas avoir besoin d'explications...
On appelle la fonction qui nous renvoie l'instance de la structure SLight associée au noeud, et on peut directement modifier l'une de ses composantes.
Je vous laisse le soin d'explorer les possibilités offertes par ces paramètres, mais on va quand même s'attarder sur quelques-uns d'entre eux :
Type
Type représente le type de la lumière. (jusqu'ici je pense que tout va bien

)
Cette composante peut prendre
2 valeurs qui correspondent aux 2 types de lumières possibles dans Irrlicht:
- ELT_POINT : désigne une lumière qui éclaire dans toutes les directions.
- ELT_DIRECTIONAL : désigne une lumière qui n'éclaire que dans une direction précise. (comme un spot)
Par défaut le type est ELT_POINT. Donc la lumière éclairera dans toutes les directions.
SpecularColor
SpecularColor correspond à la couleur des spéculaires.
C'est quoi une spéculaire ?
Pour faire très simple, il s'agit des reflets de la lumière.
Pour bien voir ce que cela représente, regardez plutôt
cette page d'un tutoriel pour
Blender.
Bon, et alors ?
Et alors si vous vous contentez de modifier la couleur des spéculaires de cette manière par exemple :
Code : C++1 | lumiere->getLightData().SpecularColor = video::SColorf(0.6, 0.0, 0.0, 1);
|
Vous risquez d'avoir des surprises.
Voilà le résultat:
La solution ? Elle se trouve dans un des materials du mesh.
Et plus précisément dans
Shininess qui permet justement de régler la taille des spéculaires.
Comme vous pouvez le voir, un code est gracieusement donné sur la page de la doc pour montrer la manière de s'en servir. Alors ne nous en privons pas.
Code : C++1 | Nroom->getMaterial(0).Shininess = 20.0f;
|
Voilà. Comme vous l'aurez deviné, 20.0f représente la nouvelle taille des spéculaires.
En cherchant un peu vous allez forcément finir par trouver le réglage qui vous convient.
Voilà ce que j'arrive à faire avec ce qu'on vient de voir :
Bon, évidement, des reflets sur de la pierre... Ce n'est pas très réaliste, mais ce qui compte c'est d'avoir compris.
Tout à l'heure tu parlais de manière classique de modifier les composantes.
C'est quoi la "pas classique" ?
Ah, la pas classique c'est de créer une instance de SLight et de l'affecter au mesh.
Par exemple :
Code : C++ 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | //On crée une instance
video::SLight light;
//On fait tous les réglages
light.Position = core::vector3df(0, 100, 0);
light.Type = video::ELT_POINT;
light.Radius=200.0f;
light.AmbientColor = video::SColorf(0.0f,0.0f,0.0f,1);
light.SpecularColor= video::SColorf(0.4f,0.0f,0.0f,1);
light.DiffuseColor = video::SColorf(0.6f,1.0f,1.0f,1);
light.CastShadows = true;
//Et on la copie dans un ILightSceneNode pour le paramètrer
lumiere->setLightData(light);
|
Cette méthode peut être utile si vous voulez paramétrer plusieurs ILightSceneNode de la même manière.
De manière générale ça permet à long terme d'économiser des lignes de code.
Pour finir on va revenir à un type de lumière moins compliqué à gérer.
Une lumière émissive correspond à la lumière
émise par un objet.
Un peu comme les autocollants fluorescents qu'il y a dans les paquets de lessives.
Comment ça, ça remonte au siècle dernier ?
Bref... toujours est-il qu'ils brillaient dans le noir.
Chaque mesh peut avoir sa propre lumière émissive. Il s'agit donc d'un material :
EmissiveColor.
Pour y accéder on va utiliser la même technique que pour changer la taille des spéculaires :
Code : C++1 | Nroom->getMaterial(0).EmissiveColor = video::SColor(255,0,255,255);
|
Voici ce que donne le code au dessus :
C'est tout ce qu'il y a à savoir sur les lumières émissives. Je vous avais dit qu'elles seraient simples.