Compteur :
Java 3D - Chapitre 6 : Eclairage

Retour table des matières Java 3D

 

Nous avons vu dans le chapitre 4 consacré à l'apparence que l'on pouvait appliquer une couleur à un objet 3D avec la couleur des sommets, les attributs de couleur de la classe ColoringAttributes et la couleur d'émission de la classe Material.
Ces 3 façons de colorer un objet sont totalement indépendantes de l'éclairage, l'effet est le même si l'éclairage est présent ou pas.
Nous allons voir dans ce chapitre que la classe Material possède trois autres types de couleurs :
- la couleur ambiante
- la couleur diffuse
- la couleur spéculaire
Ces 3 types de couleurs n'auront d'effet que si la scène 3D est éclairée.

 

 

1. Les différentes sources lumineuses

 

Il existe 4 sortes d'éclairage dans Java 3D qui peuvent avoir une influence sur les 3 types de couleur de la classe Material que nous venons de citer :

  1. Source lumineuse ambiante (classe AmbientLight) est réfléchie par la couleur d'ambiance de la classe Material.

Soient [r1, g1, b1] les 3 composantes RGB de la lumière ambiante de la classe AmbientLight et [r2,g2,b2] les 3 composantes RGB de la couleur d'ambiance de la classe Material, alors la couleur résultante qui sera réfléchie par notre objet 3D sera : [r1r2, g1g2, b1b2].
Par exemple, si l'on prend un objet éclairé par une lumière ambiante blanche et dont la couleur ambiante de la classe Material est verte, les composantes rouges et bleues de la lumière ambiante sont absorbées et seule la composante verte va être réfléchie de manière uniforme. L'objet 3D apparaîtra donc uniformément vert.

  1. Source lumineuse unidirectionnelle (classe DirectionalLight).

Cette source peut être assimilée à une source ponctuelle placée infiniment loin de la scène à éclairer (comme le soleil par exemple). Ce sont les couleurs de diffusion (diffuseColor) et de spécularité (specularColor) de la classe Material qui réfléchissent cette lumière. Cependant, contrairement à la lumière ambiante, cette reflexion dépend de l'orientation des facettes par rapport à la direction de la lumière provenant de la source : plus une facette "regarde" la source plus elle sera éclairée.

  1. Source lumineuse ponctuelle (classe PointLight)

Cette source rayonne dans toutes les directions à partir d'un point dans l'espace, un peu comme une ampoule. Tout comme une source lumieuse unidirectionnelle, ce sont les couleurs de diffusion (diffuseColor) et de spécularité (specularColor) de la classe Material qui réfléchissent cette lumière. Et cette reflexion dépend également de l'orientation des facettes vis à vis de la source.

  1. Source lumineuse ponctuelle en forme de spot (classe SpotLight)

Cette source est identique à une source lumieuse ponctuelle excepté qu'elle ne rayonne que dans un cône bien déterminé.

 

Pour construire une source lumineuse ambiante, on peut utiliser le constructeur suivant :

public AmbientLight(Color3f color)
color est la couleur de la lumière

Cette lumière va être réfléchie par la couleur ambiante de matériau que l'on va affecter à notre objet 3D. On utilise la méthode setAmbientColor() de la classe Material pour donner une couleur ambiante à notre objet :

public void setAmbientColor(Color 3f)
color est la couleur ambiante du matériau

Dans notre exemple, nous allons construire une sphère possédant une couleur ambiante cyan éclairée par une lumière ambiante de couleur jaune.
Pour la lumière de couleur jaune, les composantes [R,G,B] valent : [1,1,0]
Pour la lumière cyan du matériau, les composants [R,G,B] valent : [0,1,1]
La matériau va donc absorber la composante rouge et va refléchir les composantes vertes et bleues. Or comme la lumière ambiante incidente n'a pas de composante bleue, seule la composante verte sera réfléchie.
En conclusion, notre objet aura donc une couleur verte !!

Sphere de couleur ambiante cyan éclairée par une lumière ambiante jaune

Le fichier LumiereAmbiante.java présente le code source complet de cet exemple.
Exécutez l'applet LumiereAmbiante.html pour voir le résultat.

 

On va utiliser le constructeur suivant pour utiliser une lumière unidirectionnelle :

public DirectionalLight(Color3f color, Vector3f direction)
color est la couleur de la lumière
direction est la direction de la lumière

Nous rappelons que une source lumineuse unidirectionnelle ne réfléchit que les couleurs diffuses et spéculaires d'un objet. Dans l'exemple que nous allons étudier, nous allons construire un objet qui possède une couleur diffuse cyan et une source lumineuse directionnelle de couleur jaune. Pour donner une couleur diffuse à notre objet, il faut utiliser la méthode setDiffuseColor() de la classe Material :

public void setDiffuseColor(Color 3f)
color est la couleur diffuse du matériau

Tout comme notre exemple précédent sur la lumière ambiante, la composante verte sera principalement réfléchie mais à l'endroit où les normales des facettes sont orientées parallèlement à la direction de la lumière incidente, la couleur réfléchie apparaîtra jaune, couleur de la source. En fait, sur les facettes les plus éclairées, la couleur de la lumière incidente est directement réfléchie (sans absorption par le matériau) tandis que les facettes moins éclairées ne réfléchiront que les couleurs non absorbées par le matériau (tout comme la lumière ambiante).
C'est le principe d'un matériau contenant une couleur diffuse.

Sphère de couleur diffuse cyan éclairée par une lumière diffuse jaune

Le fichier LumiereDirectionnelle.java présente le code source complet de cet exemple.
Exécutez l'applet LumiereAmbiante.html pour voir le résultat.

 

On peut utiliser le constructeur suivant pour une source lumineuse ponctuelle :

public PointLight(Color3f color, Point3f position, Point3f attenuation)
color représente la lumière de cette source ponctuelle
position représente la position de la source
attenuation représente l'attenuation de la source (x = attenuation constante, y = attenuation linéaire, z = attenuation quadratique).
L'attenuation se calcule par la formule : attenuation = 1 / (x + yd + zd²) avec d distance entre la position de la source lumineuse et un point de l'objet éclairé.

Dans l'exemple que nous allons étudier pour illustrer cette source, nous allons utiliser dans le matériau qui constitue notre objet 3D (toujours une sphère ici) une couleur diffuse rouge et une couleur spéculaire verte.
Nous allons également jouer sur la brillance (shininess) du matériau.
Pour introduire une couleur spéculaire à notre matériau, il suffit d'utiliser la méthode setSpecularColor() de la classe Material :

public void setSpecularColor(Color3f color)
color est la couleur spéculaire du matériau.

La brillance d'un matériau peut être modifiée grâce à la méthode setShininess() de la classe Material :

public void setShininess(int shininess)
shininess est la brillance su matériau. La brillance peut varier entre 1 (peu brillant) et 128 (très brillant)
La valeur par défaut est de 64.
Concrètement, on va voir que notre exemple que plus on diminue la brillance et moins le halo représentant l'impact de la source lumineuse ponctuelle sera net.

La sphère de notre exemple est composée d'un matériau possédant un lumière diffuse rouge et une lumière spéculaire verte. La couleur réfléchie près de l'impact de la source lumineuse ponctuelle (facettes les plus éclairées) sera la combinaison de ces 2 couleurs (c'est à dire jaune) tandis que c'est la couleur diffuse (rouge) qui prédominera sur les facettes moins éclairées. Les facettes non éclairées sont bien sûr noires. La source lumineuse ponctuelle utilisée ici est de couleur blanche.

Sphère (matériau de couleur diffuse rouge et spéculaire verte) éclairée par une source ponctuelle blanche

Le fichier LumierePonctuelle.java présente le code source complet de cet exemple.
Exécutez l'applet LumierePonctuelle.html pour voir le résultat.

 

Pour constuire une source lumineuse en forme de spot, voici le constructeur que l'on peut utiliser :

public void SpotLight(Color3f color, Point3f position, Point3f attenuation, Vector3f direction, float spreadAngle, float concentration)

Les 3 premiers paramètres color, position et attenuation ont exactement la même signification que pour la classe PointLight.
direction représente la direction de la génératrice du cône de lumière.
spreadAngle représente l'angle d'ouverture du cône
concentration représente la concentration de la lumière de ce spot. Cette valeur est comprise entre 0 et 127, la valeur par défaut étant 0. Plus la concentration est élevée et moins la lumière du spot est uniforme entre le centre et la périphérie du cône d'éclairage.

Sphère (matériau de couleur diffuse rouge et spéculaire verte) éclairée par un spot de couleur blanche

Le fichier LumiereSpot.java présente le code source complet de cet exemple.
Exécutez l'applet LumiereSpot.html pour voir le résultat.

Nous venons de voir dans ce paragraphe les 4 types de sources lumineuses disponibles dans Java 3D et notamment leur influence sur la couleur d'un objet possédant un matériau.
Nous allons voir dans le paragraphe suivant l'influence de l'éclairage sur la texture d'un objet.

 

2. Effets de la lumière sur les textures

 

Nous allons reprendre l'exemple du placage de texture sur une pyramide que nous avions étudié dans la partie précédente.
Cette pyramide possède des faces colorées grâce aux attributs de couleur ColoringAttributes et cette couleur sera mélangée avec les couleurs de la texture. De plus, nous allons éclairer la scène avec une lumière ponctuelle qui est située sur la gauche, ce qui va se traduire par une face gauche de la pyramide davantage éclairée que la face avant.

La seule façon de combiner la couleur des facettes avec la couleur de la texture est d'utiliser le mode d'application MODULATE lorsqu'on construit l'objet de types TextureAttributes :

TextureAttributes textureAttributes =
                        new TextureAttributes(TextureAttributes.MODULATE,
                        new Transform3D(),
                        new Color4f(1.0f, 1.0f, 1.0f, 1.0f),
                        TextureAttributes.NICEST);
appearancePyramide.setTextureAttributes(textureAttributes);

Il ne faut jamais oublier que pour que l'éclairage soit pris en compte, il faut obligatoirement que notre objet ait un matériau. Or comme ici les couleurs qui nous interessent sont les couleurs des facettes et la couleur de la texture, le mieux est d'utiliser un matériau fourni par le constructeur par défaut :

appearancePyramide.setMaterial(new Material());

Deuxième point très important, nous avons ici un objet géométrique (pyramide construite grâce à la classe GeometryInfo) qui va être éclairé par une lumière directionnelle. Or pour qu'une lumière directionnelle agisse sur notre objet il faut définir les normales aux facettes. Pour un objet simple de type Sphere, nous avions défini les normales grâce au constructeur :

Sphere sphere = new Sphere(0.5f, Primitive.GENERATE_NORMALS, 256);

Dans le cas de notre pyramide, il va falloir utiliser la classe NormalGenerator :

GeometryInfo triangleArray = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
new NormalGenerator().generateNormals(triangleArray);

La chose est d'autant plus facile ici que nous utilisons un objet géométrique de type GeometryInfo qui est le type que la méthode generateNormals() attend en paramètre.

Eclairage ponctuel et placage de texture

Le fichier LumiereTexture.java présente le code source complet de cet exemple.
Exécutez l'applet LumiereTexture.html pour voir le résultat.

 

3. Combinaison de sources lumineuses

 

Dans ce paragraphe, nous allons étudier le cas ou plusieurs lumières éclairent la scène 3D.
Lorsque plusieurs sources lumineuses illuminent un objet, celui ci va réfléchir la somme des composantes des lumières incidentes.

 

Dans notre premier exemple, nous allons éclairer une sphère avec deux sources lumineuses ambiantes :
une de couleur rouge (composantes RGB=[1,0,0]) et une de couleur verte (composantes RGB=[0,1,0]). Cela revient donc à éclairer notre objet avec une source lumineuse dont les composantes RGB valent [1,1,0], c'est à dire une couleur jaune. Pour simplfier notre exemple, nous créons notre objet avec un matériau de couleur blanche afin qu'il n'y ait pas d'absorption de lumière incidente mais une reflexion totale au contraire.
Si la somme des composantes est supérieure à 1, la valeur prise sera bien sûr 1.

Sphère blanche éclairée par deux sources ambiantes : une rouge et une verte

Le fichier LumiereAmbianteComb.java présente le code source complet de cet exemple.
Exécutez l'applet LumiereAmbianteComb.html pour voir le résultat.

 

Nous allons maintenant étudier un exemple un peu plus complexe mettant en jeu une lumière ambiante et 3 lumières ponctuelles (et donc directionnelles). L'objet à éclairer sera un objet simple de type Cone.

La lumière ambiante rouge est créée comme suit :

Light ambientLight = new AmbientLight(new Color3f(1, 0, 0));
ambientLight.setInfluencingBounds(new BoundingSphere());

On crée ensuite la lumière ponctuelle verte à gauche du cône :

Light pointLightLeft = new PointLight(new Color3f( 0, 1, 0),
                                      new Point3f(-1, 0, 0),
                                      new Point3f( 1, 0, 0));
pointLightLeft.setInfluencingBounds(new BoundingSphere());

La lumière ponctuelle bleue à droite du cône :

Light pointLightRight = new PointLight(new Color3f( 0, 0, 1),
                                       new Point3f( 1, 0, 0),
                                       new Point3f( 1, 0, 0));
pointLightRight.setInfluencingBounds(new BoundingSphere());

La lumière ponctuelle blanche face au cône :

Light pointLightFront = new PointLight(new Color3f( 1, 1, 1),
                                       new Point3f( 0, 0, 1),
                                       new Point3f( 1, 0, 0));
pointLightFront.setInfluencingBounds(new BoundingSphere());

Le cône ayant une couleur ambiante rouge, son côté gauche sera donc de couleur jaune (mélange couleur ambiante rouge plus ponctuelle verte). L'avant sera blanc (un mélange rouge plus blanc reste blanc) et le côté droit sera magenta (mélange ambiante rouge plus ponctuelle bleue).
Bien sûr, les attributs d'apparences par défaut font que le remplissage des facettes sera fait par un rendu de Gouraud, les couleurs des facettes ne seront donc pas unies mais dégradées.

Cône éclairé par 3 sources : une ambiante rouge, et 3 ponctuelles verte, blanche et bleue respectivement à gauche, au centre et à droite

Le fichier LumiereAmbianteDirComb.java présente le code source complet de cet exemple.
Exécutez l'applet LumiereAmbianteDirComb.html pour voir le résultat.

 

4. Champ d'action de l'éclairage

 

Nous avons dans tous les paragraphes précédents que les lumières s'appliquaient à la scène entière. Nous allons voir ici que l'on peut restreindre le champ d'action d'une lumière à un objet ou groupe d'objets particuliers.
Pour cela, nous allons utiliser la méthode addScope() de la classe Light :

public void addScope(Group group)
group représente le groupe d'objets sur lequel la lumière va avoir une influence.

Dans l'exemple qui va suivre, nous allons créer deux sphères possédant le même matériau de couleurs diffuses et spéculaires blanches. La première, à gauche, sera éclairée par une source lumineuse directionnelle jaune et la seconde, à droite, sera éclairée par une source lumineuse directionnelle cyan. La difficulté ici est que l'on veut que chaque sphère soit éclairée par sa propre lumière. On ne veut pas qu'une source lumineuse éclaire les 2 sphères à la fois.

La lumière de gauche (jaune) n'agit que sur la sphère de gauche et la lumière de droite (cyan) sur la sphère de droite

Le fichier LumiereLocalisee.java présente le code source complet de cet exemple.
Exécutez l'applet LumiereLocalisee.html pour voir le résultat.

 

Nous venons de voir dans ce chapitre que l'éclairage est indispensable pour donner encore plus de réalisme à une scène 3D. C'est en effet uniquement sous éclairage que les couleurs des matériaux des objets se révèlent (exceptée la couleur d'émission qui est visible sans éclairage).
La couleur résultante d'une facette est en fait le mélange des couleurs suivantes :

- couleur d'emission (emissiveColor de la classe Material)
- couleur de toutes les sources lumineuses ambiantes réfléchies par la couleur ambiante du matériau (ambiantColor de la classe Material)
- couleur de toutes les autres sources lumineuses (non ambiantes) réfléchies par les couleurs diffuses et spéculaires du matériau (diffuseColor et specularColor de la classe Material).

 

Retour haut de page

Chapitre 05 : Apparence << >> Chapitre 07 : Interaction