Shaders
Diese Anleitung wird dir helfen, deine ersten Schritte mit Shadern in TresJS zu machen.
Wir werden eine einfache Szene mit einem Blob erstellen. Anschließend animieren wir ihn, um ihn sanft zu verzerren.
WARNING
Es sind Grundkenntnisse über Shader erforderlich
Einrichten der Szene (optional)
Wir importieren alle Module, die wir benötigen. Zusätzlich können wir die Orbit-Controls von Cientos verwenden. Siehe hier, wie das geht.
Nun positionieren wir unsere Kamera an der Position [11,11,11]
.
Um uns bei der Positionierung zu helfen, fügen wir zum Schluß eine einfache Ebene mit den Maßen [10, 10]
hinzu, die um die X-Achse gedreht ist.
<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
Wie du weißt, ist jede Instanz aus ThreeJs in TresJs verfügbar, also können wir auch ShaderMaterial
verwenden. Wir müssen lediglich das Präfix Tres
hinzufügen, um es zu nutzen.
Für unseren Blob können wir eine einfache SphereGeometry
verwenden. Durch das Hinzufügen von widthSegments
und heightSegments
erzielen wir einen sanften Effekt. Wir platzieren unseren Blob 4 Einheiten entlang der positiven Y-Achse.
<TresMesh :position="[0, 4, 0]">
<TresSphereGeometry :args="[2, 32, 32]" />
<TresShaderMaterial />
</TresMesh>
Das ShaderMaterial
akzeptiert spezielle Props wie uniforms
, vertexShader
und fragmentShader
. Wir können diese Objekte in unserem Skriptbereich erstellen und später der Komponente übergeben.
Für dieses Beispiel sehen unsere Uniforms so aus:
import { Vector2 } from 'three'
// ...
const uniforms = {
uTime: { value: 0 },
uAmplitude: { value: new Vector2(0.1, 0.1) },
uFrequency: { value: new Vector2(20, 5) },
}
// ..
Unser Fragment-Shader sieht so aus:
// ...
const fragmentShader = `
precision mediump float;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(1.0, vUv.y, 0.5, 1.0);
}
`
// ..
Und schließlich unser 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;
}
`
// ..
Animieren des Blobs
Ähnlich wie wir im Beispiel Grundlegende Animationen gelernt haben, beginnen wir, indem wir unseren Blob mit einer Template-Ref referenzieren.
<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>
Nun können wir den onLoop
-Callback nutzen, um uTime
zu animieren.
import { TresCanvas, useRenderLoop } from '@tresjs/core'
// ...
const { onLoop } = useRenderLoop()
onLoop(({ elapsed }) => {
if (blobRef.value) {
blobRef.value.material.uniforms.uTime.value = elapsed
}
})
// ...
Somit haben unseren ersten grundlegenden Shader zum Laufen gebracht!
Verwendung des GLSL vite-plugins (optional)
Dieser Schritt ist vollständig optional und liegt außerhalb des Scopes des TresJs-Teams
Wenn du nicht immer deine Shader inline definieren möchtest, kannst du vite-plugin-glsl nutzen, um GLSL
-Code in separate Dateien auszulagern.
Dann könnte man den Code zum Beispiel so organisieren:
├── src/
│ ├── myTresJsComponent.vue
│ ├── shaders/
│ ├── vertexShader.glsl
│ ├── fragmentShader.glsl