Skip to content

Lumières et ombres

Ce guide vous aidera à démarrer avec des lumières et des ombres simples dans TresJS.

Nous allons construire une scène simple avec trois maillages et un plan, mais seulement deux auront des ombres.

Configurer la scène (facultatif)

Nous importons tous les modules dont nous avons besoin, pour plus de commodité nous pouvons utiliser des centaines de contrôles d'orbite, voir ici pour savoir comment.

Plaçons quatre objets dans notre scène, l'un sera le plan qui recevra les ombres, deux d'entre eux projetteront des ombres et le dernier ne projettera aucune ombre.

Nous allons utiliser MeshToonMaterial. Tout simplement parce que l’on voit facilement le « soft overlay ».

vue
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
</script>

<template>
  <TresCanvas
    clear-color="#111"
    window-size
  >
    <OrbitControls />
    <TresPerspectiveCamera :position="[5, 7.5, 7.5]" />

    <TresMesh
      :position="[-2, 2, 0]"
      :rotation="[0, Math.PI, 0]"
    >
      <TresConeGeometry :args="[1, 1.5, 3]" />
      <TresMeshToonMaterial color="#82DBC5" />
    </TresMesh>
    <TresMesh
      :position="[0, 0, 0]"
    >
      <TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
      <TresMeshToonMaterial color="#4F4F4F" />
    </TresMesh>
    <TresMesh
      :position="[2, -2, 0]"
    >
      <TresSphereGeometry />
      <TresMeshToonMaterial color="#FBB03B" />
    </TresMesh>
    <TresMesh
      :position="[0, -3, 0]"
      :rotation="[-Math.PI / 2, 0, 0]"
    >
      <TresPlaneGeometry :args="[10, 10, 10, 10]" />
      <TresMeshStandardMaterial color="#f7f7f7" />
    </TresMesh>
  </TresCanvas>
</template>

Lumières (explication)

Comme vous le savez, chaque instance dans ThreeJs est disponible dans TresJs, donc tous les types de lumières sont également disponibles, il suffit d'ajouter le préfixe Tres pour les utiliser.

Mais toutes les lumières ne peuvent pas projeter des ombres, cette définition vient directement de ThreeJs et est logique. Par exemple, le but d'un ambientLight est d'éclairer tous les côtés de votre scène, cela n'a donc aucun sens de projeter des ombres. D'un autre côté, une DirectionalLight qui imite le soleil peut et doit générer des ombres.

Ombres (explication)

Il existe également de nombreux types d'ombres, par exemple une "ombre douce" est générée automatiquement lorsqu'un objet reçoit plus de lumière d'un côté, mais en bref, une "ombre par défaut ThreeJS" qui est dirigée vers une autre surface doit être projetée par un maillage et une autre maille doit le recevoir. Comme nous le voyons dans notre exemple, le Plan reçoit une ombre mais ne la projette pas. Gardez à l’esprit que tous les matériaux ne peuvent pas projeter ou recevoir des ombres.

En interne, ThreeJS génère automatiquement un nouveau maillage avec un ShadowMaterial qui met à jour chaque image, donc si vous appliquez des animations, l'ombre s'anime également, mais c'est aussi pourquoi vous devez utiliser les ombres avec précaution car elles peuvent ralentir les performances.

WARNING

Une utilisation excessive des ombres de cette manière peut affecter les performances. Il existe cependant des moyens d’améliorer les performances. Pour plus d'informations, regardez cette vidéo

Activation des ombres

Nous pouvons décomposer cela en trois étapes :

Activer les ombres dans le moteur de rendu

vue
//...

<template>
  <TresCanvas
    clear-color="#111"
    shadows
    window-size
  />
  //...
</template>

Réglez la lumière pour projeter des ombres

Nous pouvons simplement ajouter le booléen cast-shadow, Vue l'interprète comme un prop avec la valeur true.

La lumière ambiante ne génère ici aucun type d'ombre

vue
//...

<template>
  <TresAmbientLight :intensity="1" />
  <TresDirectionalLight
    cast-shadow
    :position="[0, 2, 0]"
    :intensity="1"
  />

  //...
</template>

Définir des objets pour projeter ou recevoir des ombres

Semblable à l'étape précédente, nous définissons le maillage sur lequel nous voulons projeter l'ombre (notre sphère) avec la propriété cast-shadow, et nous définissons l'objet pour qu'il reçoive l'ombre (notre plan) avec la propriété receive-shadow.

vue
//...

<template>
  <TresMesh
    cast-shadow
    :position="[2, -2, 0]"
  >
    <TresSphereGeometry />
    <TresMeshToonMaterial color="#FBB03B" />
  </TresMesh>
  <TresMesh
    receive-shadow
    :position="[0, -3, 0]"
    :rotation="[-Math.PI / 2, 0, 0]"
  >
    <TresPlaneGeometry :args="[10, 10, 10, 10]" />
    <TresMeshStandardMaterial color="#f7f7f7" />
  </TresMesh>
  //...
</template>

Nous avons maintenant toutes les étapes nécessaires pour ajouter des ombres à notre scène, et si nous appliquons ce que nous avons appris dans animations de base et ajoutons du mouvement à notre cube, vous verrez que l'ombre s'anime bien 🤩

vue
<script setup>
import { shallowRef } from 'vue'
import { TresCanvas, useRenderLoop } from '@tresjs/core'

const boxRef = shallowRef()

const { onLoop } = useRenderLoop()

onLoop(() => {
  if (boxRef.value) {
    boxRef.value.rotation.y += 0.01
  }
})
</script>

<template>
  //...
  <TresMesh
    ref="boxRef"
    cast-shadow
    :position="[0, 0, 0]"
  >
    <TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
    <TresMeshToonMaterial color="#4F4F4F" />
  </TresMesh>
  //...
</template>

Notez que je n'ai intentionnellement pas appliqué cast-shadow au Cone afin qu'il ne projette aucune ombre