Shaders
Esta guía te ayudará a comenzar con los shaders en TresJS.
Construiremos una escena simple con un blob. Luego alo animaremos para distorsionarlo suavemente.
WARNING
Es necesario tener conocimientos básicos sobre cómo funcionan los shaders
Configurando la escena (opcional)
Importamos todos los módulos que necesitamos. Para mayor comodidad, podemos usar los orbit-controls de cientos. Consulta aquí para ver cómo.
Ahora, coloquemos nuestra cámara en la posición [11,11,11]
.
Por último, para ayudarnos con la ubicación, agreguemos un plano simple, rotado en el eje X, con una medida de [10, 10]
unidades.
<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
Como sabes, cada instancia en ThreeJs está disponible en TresJs, por lo que también podemos usar el ShaderMaterial
, solo necesitamos agregar el prefijo Tres
para utilizarlo.
Para nuestro blob, podríamos usar una simple SphereGeometry
agregando algunos widthSegments
y heightSegments
para crear un efecto suave, y colocar nuestro blob 4 unidades en el eje Y positivo.
<TresMesh :position="[0, 4, 0]">
<TresSphereGeometry :args="[2, 32, 32]" />
<TresShaderMaterial />
</TresMesh>
El ShaderMaterial
acepta propiedades especiales, como uniforms
, vertexShader
y fragmentShader
, por lo que podemos crearlo en nuestra sección de script y hacer la conexión con nuestra instancia.
Para este ejemplo, nuestros uniforms se ven así:
import { Vector2 } from 'three'
// ...
const uniforms = {
uTime: { value: 0 },
uAmplitude: { value: new Vector2(0.1, 0.1) },
uFrequency: { value: new Vector2(20, 5) },
}
// ..
Nuestro fragment shader se ve así:
// ...
const fragmentShader = `
precision mediump float;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(1.0, vUv.y, 0.5, 1.0);
}
`
// ..
Y finalmente nuestro 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;
}
`
// ..
Animando el blob
Similar a lo que aprendimos en el ejemplo de Animaciones básicas, comenzamos haciendo referencia a nuestro blob utilizando 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 />
</TresMesh>
</TresCanvas>
</template>
Una vez que hayamos hecho eso, podemos usar el callback onLoop
para animar nuestro uTime
.
import { TresCanvas, useRenderLoop } from '@tresjs/core'
// ...
const { onLoop } = useRenderLoop()
onLoop(({ elapsed }) => {
if (blobRef.value) {
blobRef.value.material.uniforms.uTime.value = elapsed
}
})
// ...
Y eso es todo, tenemos nuestro shader básico funcionando sin problemas.
Usando GLSL vite-plugin (opcional)
Este paso es completamente opcional y está fuera del alcance del equipo de TresJs
Definir nuestro shader en línea no siempre es la mejor idea, pero si estás utilizando vite, puedes colocar tus archivos GLSL
en un archivo diferente utilizando el vite-plugin-glsl (consulta el enlace para obtener la documentación oficial).
Y podrías tener una estructura similar a esta:
├── src/
│ ├── myTresJsComponent.vue
│ ├── shaders/
│ ├── vertexShader.glsl
│ ├── fragmentShader.glsl