1
0

shaders.md 5.8 KB

Shaders

This guide will help you get started with shaders in TresJS.

We will build a simple scene with a blob. We will then animate the blob to softly distorted it.

Basic knowledge of how shaders work is necessary

Let's first setup our scene (optional)

We import all the modules that we need, for confort we can use the orbit-controls from cientos, check here to know how.

Also let's put our camera in the [11,11,11] position.

Lastly just for help us with the location, let's add a simple plane, rotate in the X axis, with [10, 10] units in the geometry.

<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

As you know every instance in ThreeJs is available in TresJs so is the ShaderMaterial, we just need to add the Tres prefix to use it.

For our blob, we could use a simple SphereGeometry adding some widthSegments and heightSegments to create a smooth effect. Also let's put our blob 4 units in the Y positive axis

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

The ShaderMaterial accept special properties like uniforms vertexShader and fragmentShader, so we can create it in our script section and make the bound with our instance.

For this example our uniforms end like this:

import { Vector2 } from 'three'

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

Our fragment shader, like this:

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

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

And lastly our 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;
}
`
//..

Animating the blob

Similar to what we learn in the Basic animations example.

We start by referencing our blob, using 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>

Once we got that we could use the onLoop callback to animate our uTime

import { TresCanvas, useRenderLoop } from '@tresjs/core'
 
 //...
 const { onLoop } = useRenderLoop()
 
onLoop(({ elapsed }) => {
   if (blobRef.value) {
     blobRef.value.material.uniforms.uTime.value = elapsed
   }
})
 //...

And that it is, we have our basic shader running smoothly

Using GLSL vite-pluging (optional)

This step is completly optional and is out of the scope of the TresJs team

Defining our shader inline, is not always the best idea, but if you're using VITE you can put your GLSL files in a different file just by using the (vite-plugin-glsl)[https://www.npmjs.com/package/vite-plugin-glsl].

you could have a struncture similar to this:

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