Brouillard

Cet article fait partie d'une série d'articles sur three.js. Le premier article est les fondamentaux de three.js. Si vous ne l'avez pas encore lu et que vous débutez avec three.js, vous devriez peut-être envisager de commencer par là. Si vous n'avez pas lu sur les caméras, vous voudrez peut-être commencer par cet article.

Le brouillard dans un moteur 3D est généralement une façon de s'estomper vers une couleur spécifique en fonction de la distance par rapport à la caméra. Dans three.js, vous ajoutez du brouillard en créant un objet Fog ou FogExp2 et en le définissant sur la propriété fog de la scène.

Fog vous permet de choisir les paramètres near et far qui sont des distances par rapport à la caméra. Tout ce qui est plus proche que near n'est pas affecté par le brouillard. Tout ce qui est plus loin que far prend complètement la couleur du brouillard. Les parties entre near et far s'estompent de leur couleur de matériau à la couleur du brouillard.

Il y a aussi FogExp2 qui augmente de manière exponentielle avec la distance par rapport à la caméra.

Pour utiliser l'un ou l'autre type de brouillard, vous en créez un et l'attribuez à la scène comme dans

const scene = new THREE.Scene();
{
  const color = 0xFFFFFF;  // white
  const near = 10;
  const far = 100;
  scene.fog = new THREE.Fog(color, near, far);
}

ou pour FogExp2 ce serait

const scene = new THREE.Scene();
{
  const color = 0xFFFFFF;
  const density = 0.1;
  scene.fog = new THREE.FogExp2(color, density);
}

FogExp2 est plus proche de la réalité mais Fog est utilisé plus couramment car il vous permet de choisir un endroit où appliquer le brouillard afin que vous puissiez décider d'afficher une scène claire jusqu'à une certaine distance, puis de s'estomper vers une couleur au-delà de cette distance.

THREE.Fog
THREE.FogExp2

Il est important de noter que le brouillard est appliqué aux choses qui sont rendues. Il fait partie du calcul de chaque pixel de la couleur de l'objet. Cela signifie que si vous voulez que votre scène s'estompe vers une certaine couleur, vous devez définir le brouillard et la couleur de fond sur la même couleur. La couleur de fond est définie à l'aide de la propriété scene.background. Pour choisir une couleur de fond, vous y attachez un THREE.Color. Par exemple

scene.background = new THREE.Color('#F00');  // rouge
brouillard bleu, fond rouge
brouillard bleu, fond bleu

Voici l'un de nos exemples précédents avec l'ajout de brouillard. La seule addition est juste après la mise en place de la scène, nous ajoutons le brouillard et définissons la couleur de fond de la scène

const scene = new THREE.Scene();

+{
+  const near = 1;
+  const far = 2;
+  const color = 'lightblue';
+  scene.fog = new THREE.Fog(color, near, far);
+  scene.background = new THREE.Color(color);
+}

Dans l'exemple ci-dessous, near de la caméra est de 0.1 et far est de 5. La caméra est à z = 2. Les cubes mesurent 1 unité de large et sont à Z = 0. Cela signifie qu'avec un réglage de brouillard de near = 1 et far = 2, les cubes s'estomperont juste autour de leur centre.

Ajoutons une interface pour pouvoir ajuster le brouillard. Encore une fois, nous allons utiliser lil-gui. lil-gui prend un objet et une propriété et crée automatiquement une interface pour ce type de propriété. Nous pourrions simplement le laisser manipuler les propriétés near et far du brouillard, mais il est invalide d'avoir near supérieur à far, alors créons un assistant pour que lil-gui puisse manipuler une propriété near et far, mais nous nous assurerons que near est inférieur ou égal à far et que far est supérieur ou égal à near.

// Nous utilisons cette classe pour la passer à lil-gui
// ainsi quand elle manipule near ou far
// near n'est jamais > far et far n'est jamais < near
class FogGUIHelper {
  constructor(fog) {
    this.fog = fog;
  }
  get near() {
    return this.fog.near;
  }
  set near(v) {
    this.fog.near = v;
    this.fog.far = Math.max(this.fog.far, v);
  }
  get far() {
    return this.fog.far;
  }
  set far(v) {
    this.fog.far = v;
    this.fog.near = Math.min(this.fog.near, v);
  }
}

Nous pouvons ensuite l'ajouter comme ceci

{
  const near = 1;
  const far = 2;
  const color = 'lightblue';
  scene.fog = new THREE.Fog(color, near, far);
  scene.background = new THREE.Color(color);
+
+  const fogGUIHelper = new FogGUIHelper(scene.fog);
+  gui.add(fogGUIHelper, 'near', near, far).listen();
+  gui.add(fogGUIHelper, 'far', near, far).listen();
}

Les paramètres near et far définissent les valeurs minimum et maximum pour l'ajustement du brouillard. Ils sont définis lorsque nous configurons la caméra.

Le .listen() à la fin des 2 dernières lignes indique à lil-gui d'écouter les changements. De cette façon, lorsque nous changeons near à cause d'une modification de far ou que nous changeons far en réponse à une modification de near, lil-gui mettra à jour l'interface utilisateur de l'autre propriété pour nous.

Il pourrait également être agréable de pouvoir changer la couleur du brouillard, mais comme mentionné ci-dessus, nous devons synchroniser la couleur du brouillard et la couleur de fond. Ajoutons donc une autre propriété virtuelle à notre assistant qui définira les deux couleurs lorsque lil-gui la manipulera.

lil-gui peut manipuler les couleurs de 4 manières : comme une chaîne hexadécimale CSS à 6 chiffres (par exemple : #112233). Comme un objet teinte, saturation, valeur (par exemple : {h: 60, s: 1, v: }). Comme un tableau RGB (par exemple : [255, 128, 64]). Ou, comme un tableau RGBA (par exemple : [127, 200, 75, 0.3]).

Le plus simple pour notre objectif est d'utiliser la version chaîne hexadécimale, car de cette façon, lil-gui ne manipule qu'une seule valeur. Heureusement, THREE.Color dispose d'une méthode getHexString que nous pouvons utiliser pour obtenir facilement une telle chaîne, il suffit de faire précéder d'un '#' au début.

// Nous utilisons cette classe pour la passer à lil-gui
// ainsi quand elle manipule near ou far
// near n'est jamais > far et far n'est jamais < near
// Aussi, lorsque lil-gui manipule la couleur, nous allons
// mettre à jour les couleurs du brouillard et de l'arrière-plan.
class FogGUIHelper {
*  constructor(fog, backgroundColor) {
    this.fog = fog;
+    this.backgroundColor = backgroundColor;
  }
  get near() {
    return this.fog.near;
  }
  set near(v) {
    this.fog.near = v;
    this.fog.far = Math.max(this.fog.far, v);
  }
  get far() {
    return this.fog.far;
  }
  set far(v) {
    this.fog.far = v;
    this.fog.near = Math.min(this.fog.near, v);
  }
+  get color() {
+    return `#${this.fog.color.getHexString()}`;
+  }
+  set color(hexString) {
+    this.fog.color.set(hexString);
+    this.backgroundColor.set(hexString);
+  }
}

Nous appelons ensuite gui.addColor pour ajouter une interface utilisateur de couleur pour la propriété virtuelle de notre assistant.

{
  const near = 1;
  const far = 2;
  const color = 'lightblue';
  scene.fog = new THREE.Fog(color, near, far);
  scene.background = new THREE.Color(color);

*  const fogGUIHelper = new FogGUIHelper(scene.fog, scene.background);
  gui.add(fogGUIHelper, 'near', near, far).listen();
  gui.add(fogGUIHelper, 'far', near, far).listen();
+  gui.addColor(fogGUIHelper, 'color');
}

Vous pouvez voir que régler near à environ 1.9 et far à 2.0 donne une transition très nette entre non-brouillardé et complètement brouillardé. tandis que near = 1.1 et far = 2.9 devraient être à peu près les plus lisses étant donné que nos cubes tournent à 2 unités de distance de la caméra.

Une dernière chose, il existe une propriété booléenne fog sur un matériau indiquant si les objets rendus avec ce matériau sont affectés par le brouillard. Elle est par défaut à true pour la plupart des matériaux. À titre d'exemple de pourquoi vous pourriez vouloir désactiver le brouillard, imaginez que vous créez un simulateur de véhicule 3D avec une vue depuis le siège du conducteur ou le cockpit. Vous voudrez probablement désactiver le brouillard pour tout ce qui se trouve à l'intérieur du véhicule lorsque vous regardez depuis l'intérieur du véhicule.

Un meilleur exemple pourrait être une maison et un brouillard épais à l'extérieur. Disons que le brouillard est configuré pour commencer à 2 mètres de distance (near = 2) et complètement brouillardé à 4 mètres (far = 4). Les pièces sont plus longues que 2 mètres et la maison est probablement plus longue que 4 mètres, vous devez donc régler les matériaux de l'intérieur de la maison pour ne pas appliquer de brouillard, sinon, en vous tenant à l'intérieur de la maison et en regardant dehors le mur au fond de la pièce, cela aura l'air d'être dans le brouillard.

brouillard : vrai, tout

Remarquez que les murs et le plafond au fond de la pièce sont affectés par le brouillard. En désactivant le brouillard sur les matériaux de la maison, nous pouvons corriger ce problème.

brouillard : vrai, seulement les matériaux extérieurs