Skip to content

Shaders

Ce guide vous aidera à démarrer avec les shaders dans TresJS.

Nous allons construire une scène simple avec un blob. Ensuite, nous l'animerons pour le déformer doucement.

WARNING

Il est nécessaire d’avoir des connaissances de base sur le fonctionnement des shaders

Configurer la scène (facultatif)

Nous importons tous les modules dont nous avons besoin. Pour plus de commodité, nous pouvons utiliser les orbit-controls de cientos. Voir ici comment.

Mettons notre caméra en position [11,11,11].

Enfin, pour nous aider avec le placement, ajoutons un plan simple, tourné sur l'axe X, avec une mesure de [10, 10] unités.

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

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

    <TresMesh :rotation="[-Math.PI / 2, 0, 0]">
      <TresPlaneGeometry :args="[10, 10]" />
      <TresMeshBasicMaterial color="#444" />
    </TresMesh>
  </TresCanvas>
</template>

ShaderMaterial

Comme vous le savez, chaque instance dans ThreeJs est disponible dans TresJs, nous pouvons donc également utiliser le ShaderMaterial, il suffit d'ajouter le préfixe Tres pour l'utiliser.

Pour notre blob, nous pourrions utiliser un simple SphereGeometry en ajoutant des widthSegments et heightSegments pour créer un effet fluide et positionner notre blob 4 unités sur l'axe Y positif.

vue
<TresMesh :position="[0, 4, 0]">
  <TresSphereGeometry :args="[2, 32, 32]" />
  <TresShaderMaterial />
</TresMesh>

Le ShaderMaterial accepte des propriétés spéciales, telles que uniforms, vertexShader et fragmentShader, afin que nous puissions le créer dans notre section de script et établir la connexion à notre instance.

Pour cet exemple, nos uniformes ressemblent à ceci :

ts
import { Vector2 } from 'three'

// ...
const uniforms = {
  uTime: { value: 0 },
  uAmplitude: { value: new Vector2(0.1, 0.1) },
  uFrequency: { value: new Vector2(20, 5) },
}
// ..

Notre fragment shader ressemble à ceci :

ts
// ...
const fragmentShader = `
precision mediump float;
varying vec2 vUv;

void main() {
    gl_FragColor = vec4(1.0, vUv.y, 0.5, 1.0);
}
`
// ..

Et enfin notre vertexShader:

ts
const vertexShader = `
uniform vec2 uAmplitude;
uniform vec2 uFrequency;
uniform float uTime;

varying vec2 vUv;

void main() {
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
    modelPosition.y += sin(modelPosition.x * uFrequency.x - uTime) * uAmplitude.x;
    modelPosition.x += cos(modelPosition.y * uFrequency.y - uTime) * uAmplitude.y;

    vec4 viewPosition = viewMatrix * modelPosition;
    gl_Position = projectionMatrix * viewPosition;
    vUv = uv;
}
`
// ..

Animer le blob

Semblable à ce que nous avons appris dans l'exemple des Animations de bases, Nous commençons par référencer notre blob en utilisant Template Ref

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

const blobRef = shallowRef(null)
// ...
</script>

<template>
  <TresCanvas
    clear-color="#111"
    window-size
  >
    <OrbitControls />
    <TresPerspectiveCamera :position="[11, 11, 11]" />
    <TresMesh
      ref="blobRef"
      :position="[0, 4, 0]"
    >
      <TresSphereGeometry :args="[2, 32, 32]" />
      <TresShaderMaterial />
    </TresMesh>
  </TresCanvas>
</template>

Une fois que nous avons fait cela, nous pouvons utiliser le rappel onLoop pour animer notre uTime.

ts
import { TresCanvas, useRenderLoop } from '@tresjs/core'

// ...
const { onLoop } = useRenderLoop()

onLoop(({ elapsed }) => {
  if (blobRef.value) {
    blobRef.value.material.uniforms.uTime.value = elapsed
  }
})
// ...

Et voilà, notre shader de base fonctionne correctement.

Avec GLSL vite-plugin (optionel)

Cette étape est totalement facultative et hors du cadre de l'équipe TresJs.

Définir notre shader en ligne n'est pas toujours la meilleure idée, mais si vous utilisez vite, vous pouvez mettre vos fichiers GLSL dans un fichier différent en utilisant le vite-plugin-glsl. (voir lien pour la documentation officielle)

Et vous devriez avoir une structure similaire à celle-ci :

├── src/
│   ├── myTresJsComponent.vue
│   ├── shaders/
│       ├── vertexShader.glsl
│       ├── fragmentShader.glsl