Shaders
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
De scene opzetten (optoneel)
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 { TresCanvas } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
</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
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;
}
`
// ..
De blob animeren
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 { shallowRef } from 'vue'
import { TresCanvas } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
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. 🎉
Gebruik van GLSL vite-pluging (optioneel)
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