Maintenant que nous avons les éléments de base de notre jeu, nous pouvons aller plus loin dans la création de l'univers qu'il va faire explorer à nos joueurs. La première chose à prendre en compte est l'éclairage.
Un espace est perceptible grâce à sa géométrie, mais également par les ombres et lumières qui en dessinent les volumes et y apportent une ambiance. Nous allons voir dans ce chapitre comment illuminer notre espace et y dessiner des ombres.
Nous ne rentrons pas ici en détail dans l'apprentissage de l'éclairage puisqu'il s'agit d'une spécialité en soi qui n'est pas l'objet principal de ce livre.L'éclairage par défaut du mode jeu est basé sur les vertices : chaque vertex prend une teinte en fonction de sa distance par rapport aux lampes environnantes. La couleur des faces est déduite par interpolation. Cette technique montre ses limites assez rapidement, car l'interpolation est faussée ou rend visibles certaines arrêtes.
Il s'agit du mode d'éclairage le plus simple et historiquement le plus ancien. Il est aussi appelé éclairage Gouraud, du nom de son inventeur.
Cette technique ne permettra pas non plus de produire des ombres portées.
Pour ces raisons, il est souvent préférable de changer de technique de shading. L'option se trouve dans le panneau Render, sous l'onglet Shading. On peut choisir entre Multitexture (par défaut) et GLSL. Ce dernier dévoile plus de boutons, pour activer et désactiver certaines options (les lampes, les ombres, etc.).
En mode GLSL, l'éclairage n'est plus calculé à partir des vertices mais sur la face toute entière, pixel par pixel. Cela permet de révéler des dégradés plus fins et des reflets spéculaires fidèles à la forme d'origine. Les changements sont aussi bien visibles dans la 3D View que dans le jeu.
Dans l'exemple ci-contre, nous avons placé une lampe au niveau d'un des angles du cube, (légèrement décalée) et nous avons pris deux points de vue différents de manière à bien voir le reflet. Le résultat est parlant : en multitexture, le rendu est extrêmement triangulé et les spéculaires sont faibles, ce qui n'est pas le cas en GLSL.
Multitexture
GLSL
Pour profiter du mode GLSL, il faut penser à configurer la vue 3D en mode Textured.(raccourci : Alt+z)
Pour ajouter une lampe, il suffit de passer par le menu Add (Maj + A), sous l'option Lamp. Le seul mode non supporté actuellement est la lampe de type Area. Une fois une lampe ajoutée, on peut modifier son type ainsi que diverses options dans le panneau Lamp. Les options disponibles ne présentent pas de différence majeure avec le mode Blender Render, mais nous allons les passer en revue brièvement.
Les options communes à tout type de lampe sont tout d'abord la couleur et l'intensité (Energy). Negativepermet d'avoir une lampe dont l'éclairage va en diminuant (idéal pour fausser une ombre, mais non physiquement réaliste).
En cochant l'option This Layer Only, une lampe se trouvant dans un calque n'éclaire que les objets présents dans ce même calque. Cette option peut être utile si d'autres layers sont activés simultanément : on peut avoir une lampe qui éclaire un objet mais pas les autres.
Enfin, Specular et Diffuse spécifient si la lampe produit des reflets spéculaires et de la lumière ambiante.
Ce type de lampe est utile pour imiter les sources lumineuses qui diffusent de la lumière dans toutes les directions depuis un point fixe et central, comme une torche ou une bougie, avec une rapide diminution d'intensité. Il n'y pas d'ombre portée avec ce type de lampe.
La manière dont diminue l'intensité peut être changée avec l'option Falloff. L'option par défaut, Inverse Square, correspond à la diminution réaliste d'une lampe ponctuelle. L'option Distance indique la distance à laquelle il faut se situer pour être exposé à la moitié de l'intensité maximale, elle-même définie dans Energy.
Le type Sun est une lampe directionnelle, permettant de simuler un point éclairant la scène depuis une très grande distance et avec des rayons parallèles, comme le ferait le soleil. Seule la rotation de l'objet lampe permet de changer la provenance de la lumière, sa position n'est pas prise en compte. L'onglet Shadow permet de régler la projection d'ombre. Ce point sera traité spécifiquement dans la suite de ce chapitre. Le calcul de l'ombre est limité à un certain angle, défini par Frustum.
Le spot limite l'éclairage à un cône et permet de projeter les ombres portées. La forme du cône est paramétrable sous l'onglet Spot Shape. Comme pour le Sun, l'option Shadow est disponible.
Le type Hemi est un autre type de lampe directionnelle, sans possibilité de produire des ombres. Elle est différente de la lampe de type Sun, car la lumière provient de tous les côtés d'une demi-sphère englobant la scène. Elle peut par exemple simuler l'éclairage diffus produit par un ciel nuageux.
Comme pour les matériaux, il est possible d'affecter des textures à chaque paramètre en lien avec la lumière. Nous pouvons modifier le World qui sert de couleur de fond et agit aussi sur la couleur ambiante des matériaux, mais également sur les lampes qui peuvent ainsi varier d'intensité pour simuler l'ambiance d'un environnement.
L'application des textures sera détaillée aux chapitres suivants.
Commune aux lampes Spot et Sun, les options d'ombres sont importantes à comprendre pour une bonne qualité d'éclairage et de bonnes performances graphiques. En effet, le calcul des ombres portées dynamiques peut vite devenir gourmand en ressources, et doit être utilisé avec parcimonie. Cela reste malgré tout une option de choix pour ajouter réalisme et ambiance à une scène.
On peut modifier la couleur de cette ombre pour simuler une ambiance. Ce qui est à l'ombre de la lampe est éclairé par une lumière d'ambiance colorée.
L'option This Layer Only permet de limiter la production d'ombre aux seuls objets présents sur le même calque que la lampe.
L'option Shadow Only permet de produire une ombre sans ajouter de lumière à la scène. En fait, la lampe ne produit que les ombres. Dans l'exemple ci-dessous, nous avons dû ajouter une autre lumière pour l'éclairage général en complément du spot qui produit des ombres bleues, selon son rayon d'éclairage.
L'option Buffer Type est importante : elle détermine le mode de production de l'ombre. Une ombre est en fait une texture ajoutée par-dessus les autres. Elle a donc une définition. Le type Buffer Simple produit simplement une texture à partir de la scène, le type Variance produit lui une texture adoucie, plus floue, qui permet d'obtenir des ombres douces, au prix d'un calcul supplémentaire.
L'option Quality : Size est importante également : c'est elle qui détermine la taille de la texture utilisée pour l'ombre (toujours carrée). Ceci est particulièrement visible dans le cas d'une ombre de type Simple. Une ombre de petite taille (ex. 128) produira une ombre pixelisée alors qu'une ombre plus détaillée (512 ou 1024) sera plus précise et aura des bords plus nets.
Pour la taille des images, il est préférable d'utiliser des puissances de 2 pour optimiser le calcul. 128, 256, 512, 1024 ou 2048 sont les échelles habituellement utilisées.
Cette option est à considérer avec attention, parce qu'elle joue un rôle aussi bien sur la performance que sur l'esthétique. Des ombres de grandes tailles, en grand nombre, risquent de réduire fortement le taux de rafraîchissement de l'image, augmentant donc la qualité du rendu mais diminuant la qualité de l'animation.
Variance semble être une bonne option, permettant d'utiliser plus de lampes avec un rendu adouci tout en conservant une fréquence élevée de l'affichage.
En ajoutant, une texture à une lampe, il est possible de lui demander d'agir sur une ombre. Suivant l'effet souhaité, cela peut être nécessaire de jouer avec le positionnement des objets et des lampes sur plusieurs calques de la scène. Ici, il s'agit d'une distorsion : un objet fixe (Suzanne) ayant une ombre tout à fait différente de l'ombre attendue.
Multiplier les lampes pour améliorer l'éclairage ou ajouter des effets peut être tentant. Il faut cependant résister à cette envie lorsque des ombres dynamiques sont utilisées et bien réfléchir à l'importance d'avoir une ombre dynamique pour chaque lampe. Il est possible de produire un éclairage de bonne qualité et de figer (baker) des ombres dans les textures des objets statiques. Ceci sera détaillé dans la section Travailler le rendu du jeu dans le chapitre Pré-calcul des textures et de la lumière.
L'espace dans lequel les ombres seront produites peut également être limité, en contrôlant la distance de leur apparition (Clipping). Clip Start et Clip End sont respectivement les distances minimales et maximales entre lesquelles l'objet doit se trouver pour produire une ombre. La distance des objets sur lesquels l'ombre sera éventuellement projetée peut sortir de cette intervalle. En limitant cette distance, les interactions entre lampes facilitent ainsi les calculs du moteur de jeu. Ces distances sont représentées dans la vue 3D par un segment de droite affiché dans l'axe de la lampe, ce qui aide à les régler finement.
Interagir avec les lumières en Python est également possible. L'objectif va être de faire varier l'intensité de la lumière en fonction de la hauteur d'un objet 3D qui va rebondir sur le sol.
Les captures d'écran ci-dessous montrent la scène dans sa situation de départ ainsi que le code Python que nous allons utiliser. Vous pouvez également voir les deux briques logiques que nous utilisons pour la mise en place de la scène. La première est la brique Always. Elle est configurée en mode pulse, ce qui permet de s'assurer que l'on aura une génération d'événement constants. Attaché à cette génération d'événement, nous exécutons le script python Lamp.
Étudions maintenant en détail le script Python que nous utilisons.
from bge import logic
cont = logic.getCurrentController()
ball = cont.sensors[0].owner
light = cont.owner
light.color = [ 0.8, 0.3 , 0.6 ]
light.energy = min(ball.position.z + 0.4, 0.5)
La première ligne correspond, comme toujours, à l'import des modules recevables.
On récupère ensuite le contrôleur qui est relié à ce script Python. Ici le contrôleur est rattaché à notre lampe, or nous avons besoin de connaître la position en z de notre boule.
ball = cont.sensors[0].owner
Avec cette ligne de code, nous allons récupérer notre boule par l'intermédiaire de notre sensors Always (premier et unique sensor attaché à notre controller) que nous avons opportunément accroché à notre objet. Chaque contrôleur possède une liste appelée sensors qui répertorie la totalité des sensors qui lui sont rattachés. Ici, il n'y a qu'un seul sensor, on peut donc sans problème utiliser la notation [0] pour récupérer le premier élément de la liste.
light = cont.owner
Nous récupèrons la lumière de la manière classique, en récupérant le owner du contrôleur courant.
light.color = [ 0.8, 0.3 , 0.6 ]
Ici, nous nous amusons à modifier la couleur de la lumière pour la rendre violette.
La ligne suivante est un peu plus compliquée. On va ici modifier la puissance de notre lumière.
light.energy = min(ball.position.z + 0.4, 0.5)
Pour cela, on change la valeur de l'attribut energy
de notre spot. La fonction min
en Python nous permet de récupérer la plus petite valeur d'un ensemble, qui se limite ici à la valeur de la coordonnée en z de notre balle rebondissante à laquelle on ajoute 0.4 ou à 0.5). On va donc obtenir un effet 'jour , nuit, jour , nuit' tant que la balle rebondit. Lorsqu'elle finira par s'arrêter notre scène sera alors plongée dans le noir.
Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.
Vous devriez rafraîchir la page.