Pré-requis : Chapitre 4: Textures
Voici un point qui ne manquera pas d'intéresser les plus curieux d'entre vous. En effet, quoi de plus beau qu'une scène illuminée avec gôut? Vous pourrez enfin utiliser des effets d'ombrage métant en valeur les formes de vos géometries.
Cet exemple a le mérite de présenter simplement les différentes lumières ainsi que leurs effets sur différents types de formes (avec ou sans texture, avec différentes propriétes pour l'objet Material ...). Vous apprendrez donc ici les bases de la gestion des sources lumineuses en Java3D. Cependant, les combinaisons possibles sont multiples et toutes les présenter serait fastidieux et inutile, la meilleure manière de travailler cet exemple sera donc de le paramétrer suivants vos choix et de constater le résultat. Nous essayerons donc de vous fournir les points clefs à connaître pour comprendre le rendu de Java3D en fonction de vos réglages.
Extrait 1, configurer l'objet :
//material -> uniquement si il y a des lumières
|
Extrait 2, le code d'implémentation des différentes lumières:
//lumières
|
void addTexture(Appearance app,String textureName)
|
Extrait 1, comment paramétrer l'objet pour le rendre réactif aux lumières :
Première chose très importante, il y a un paramètre supplémentaire à activer pour que la Box, ou tout autre objets primitifs du Java3D d'ailleurs, soit sensible aux rayons lumineux: il faut ajouter la génération sur chaque face des normals par rapport auxquelles seront effectuées les calculs. D'où le constructeur: "Box box=new Box (0.4f, 0.4f ,0.4f , Box. GENERATE_ TEXTURE_OORDSBox.GENERATE_NORMALS,boxApp);".
Il va nous falloir maintenant comprendre comment sont gérées les lumières au niveau de nos objets 3D. Pour cela, introduisons la classe Material. A chaque Shape3D, on peut associer par le biais de la méthode setMaterial(Material mat) un objet de type Material qui définit comment va réagir l'objet s'il est éclairé. Le constructeur de la classe Material est :"public Material(Color3f ambientColor, Color3f emissiveColor, Color3f diffuseColor, Color3f specularColor, float shininess)". On peut donc voir qu'à chaque objet nous allons associer non pas une mais quatres couleurs:
Le dernier paramètre du constructeur de Material définit simplement la brillance de l'objet avec un nombre entre 1, objet mat, et 128, objet très brillant. Nous l'avons placé à 64, ce qui d'ailleurs la valeur par défaut.
Pour notre exemple, nous avons choisi de créer l'objet avec un objet Material configuré pour que la "couleur" de l'objet box soit jaune (1f,1f,0f en RGB). Nous placons donc du jaune pour les lumières ambiantes et diffuses. On remarquera également que la couleur émissive est choisie noire, ce qui correspond à une non-émission de lumière. De plus, la lumière spéculaire est choisie blanche (1f,1f,1f), car dans la réalité c'est fréquement la cas. Par exemple, si vous éclairez un morceau de plastique avec une lumière blanche, les zones les plus exposées deviendront blanches.
Extrait 2, les différentes lumières :
Il existe plusieurs types de lumières:
Etant donné le nombre l'immense nombre de combinaisons possibles pouvant modifier le rendu d'une scène illuminée (différentes lumières, couleurs des lumières et de l'objet, caractéristiques de l'objet Appearance, ...), nous avons mis en place une méthode createScene, createScene(boolean ambientBool,boolean directBool,boolean pointBool,boolean texBool), qui accepte donc 4 paramètres booléens: dans l'ordre, un booléen pour l'absence/présence d'une lumière ambiante, deux autres pour les lumières directionnelles et ponctuelles et enfin un dernier pour charger ou non une texture sur l'objet. Ainsi, on peut rapidement voir l'effet de chaque type de lampe. Nous présentons ci-dessous quelques combinaisons que l'on peut ainsi obtenir:
![]() |
![]() |
1-createScene(false,false,false,false) | 2-createScene(true,false,false,false), AmbiantLight |
![]() |
![]() |
3-createScene(false,true,false,false), DirectionalLight | 4-createScene(false,false,true,false), PointLight |
Petite remarque: nous avons choisi toutes les lumières de couleurs blanche, mais on peut bien sûr les choisir autrement. Mais il y a quelques subtilités à connaître: si vous éclairer un Shape3D de lumière ambiante bleu (0f,0f,1f) avec seulement une lumière ambiante jaune (1f,1f,0f), alors rien n'apparaîtra car le bleu ne fait pas du tout partie de la couleur de la lumière incidente. Par contre si vous éclairez un objet jaune(1f,1f,0f) avec une lumière violette (1f,0f,1f) alors l'objet semblera rouge car c'est la seule couleur émise par la lumière que peut percevoir l'objet! Nous vous laissons maintenant tester, sur cet exemple, la multitude de réglages possibles en ésperant que les explications données vous permettront de comprendre le résultat de vos expériences.
Extrait 3, lumières et texture
Seules quelques nouvelles lignes nous intéressent particulièrement: les trois dernières lignes de l'extrait. Vous pouvez essayer de lancer l'application avec le paramètre true pour texBool mais sans ces trois lignes. Le résultat est alors net: pas de jeu de lumière apparent sur notre texture ! En effet, par défaut cela n'est pas prévu. Il suffit juste de paramétrer un objet TextureAttributes qui sera associé à un objet Appearance. C'est la méthode "public void setTextureMode(int textureMode)" de TextureAttributes qui permet de combiner texture et lumières une fois placée en MODULATE.
Il me semble intéressant que vous vous renseignez dans l'Api reference au sujet de la classe TextureAttributes qui regorgent de méthodes pour affiner les réglages (toutes ne peuvent pas être abordée ici).
Voici une bonne chose de faite. Complétons juste cet exemple avec des effets de lumières sur un objet élementaire telle que notre fameuse barrière du Chapitre 4 (exemple 2).
Je vous rassure tout de suite, cette partie sera plus brève et moins théorique que la précédente, les nouveautés seront également moins nombreuses.
Extrait 1, les lumières au niveau de la géométrie
//vecteurs normaux pour face 1
|
Extrait 2, les lumières au niveau de l'apparence
app.setMaterial
|
//lumières
|
Extrait 1, génération des normales
Comme nous l'avons précisé dans le premier exemple, les calculs pour l'éclairage d'une scène sont effectués par rapport aux vecteurs normaux des faces et aux vecteurs incidents des rayons lumineux. Seulement, dans l'exemple un, il suffisait de régler un paramètre pour que les vecteurs normaux de chaque face soient automatiquement générés; cette époque est révolue! En effet, il va maintenant vous falloir définir vous mêmes manuellement chacun de ces vecteurs. Cette tâche peut réellement être très fastidieuse, mais dans notre exemple un minimum calcul vectoriel sera nécessaire.
Les vecteurs normaux ne sont en réalité pas associés face
par face mais sommet par sommet. Donc, en plus des méthodes "setCoordinate()"
,"setColor()" et "set
TextureCoordinate()" vues précedement, il va falloir ajouter
la méthode "setNormal(int vertex,Vector3f vect)".
Extrait 2, réglale du Material de l'Appearance
Extrait 3, mise en place des lumières
.