Deze handleiding helpt u aan de slag te gaan met shaders in TresJS.
We zullen een eenvoudige scène bouwen met een blob. Vervolgens zullen we de blob animeren om deze zachtjes te vervormen.
::: warning Basis kennis over hoe shaders werken is noodzakelijk :::
We importeren alle modules die we nodig hebben. Om het gemakkelijker te maken zullen we de orbit-controls van cientos importeren en gebruiken, kijk hier om te zien hoe.
Laten we nu onze camera in de [11,11,11]
positie plaatsen.
Om ons ten slotte te helpen met de locatie, voegen we een eenvoudig vlak toe, geroteerd in de X-as, met [10, 10]
eenheden.
<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>
Zoals u weet is elke instantie in ThreeJs beschikbaar in TresJs, en dat geldt ook voor ShaderMaterial
. We hoeven alleen maar het voorvoegsel Tres
toe te voegen om het te gebruiken.
Voor onze blob kunnen we een eenvoudige SphereGeometry
gebruiken, waarbij enkele breedte- en hoogtesegmenten worden toegevoegd om een vloeiend effect te creëren, en onze blob 4 eenheden in de positieve Y-as plaatsen
<TresMesh :position="[0, 4, 0]">
<TresSphereGeometry :args="[2, 32, 32]" />
<TresShaderMaterial />
</TresMesh>
Het ShaderMaterial
accepteert speciale eigenschappen, zoals uniforms
vertexShader
en fragmentShader
, zodat we het in onze scriptsectie kunnen maken en de binding met onze instantie kunnen maken.
Voor dit voorbeeld zien onze uniformen er als volgt uit:
import { Vector2 } from 'three'
// ...
const uniforms = {
uTime: { value: 0 },
uAmplitude: { value: new Vector2(0.1, 0.1) },
uFrequency: { value: new Vector2(20, 5) },
}
// ..
Onze fragment shader ziet er als volgt uit:
// ...
const fragmentShader = `
precision mediump float;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(1.0, vUv.y, 0.5, 1.0);
}
`
// ..
En tot slot onze vertexShader:
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;
}
`
// ..
Vergelijkbaar met wat we leren in het voorbeeld van Basic Animations, beginnen we met het verwijzen naar onze blob, met behulp van Template Ref
<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 :vertex-shader="vertexShader" :fragment-shader="fragmentShader" :uniforms="uniforms" />
</TresMesh>
</TresCanvas>
</template>
Zodra we dat hebben, kunnen we de onLoop
callback gebruiken om onze uTime
te animeren.
import { TresCanvas, useRenderLoop } from '@tresjs/core'
// ...
const { onLoop } = useRenderLoop()
onLoop(({ elapsed }) => {
if (blobRef.value) {
blobRef.value.material.uniforms.uTime.value = elapsed
}
})
// ...
En dat is alles, onze basisshader werkt soepel. 🎉
Deze stap is volledig optioneel en uit scope van het TresJs team
Het inline definiëren van onze shader is niet altijd het beste idee, maar als u vite gebruikt, kunt u uw GLSL
-bestanden in een ander bestand plaatsen door gewoon de vite-plugin-glsl (bekijk de link voor de officiële documentatie).
En je zou een structuur kunnen hebben die er ongeveer zo uitziet:
├── src/
│ ├── myTresJsComponent.vue
│ ├── shaders/
│ ├── vertexShader.glsl
│ ├── fragmentShader.glsl