|
@@ -0,0 +1,174 @@
|
|
|
+# 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.
|
|
|
+
|
|
|
+::: warning
|
|
|
+_Basic knowledge of how shaders work is necessary_
|
|
|
+:::
|
|
|
+
|
|
|
+<SandboxDemo url="https://play.tresjs.org/#eNqVVltv2zYU/iuE91BntSU7cYrBS4q0QTt0WNcgyfZSFxsjH9tMJVIjKdle4P++j9TFVJMU3oMDndvH71x4mIferSbzJs+jsqDetHdmEi1yywzZImcpl8vzWc+aWe/1TIosV9qyB2ZWPE3V+poWbMcWWmXsBaJf/By4ONRLLktuBqwwdE1yTvo3pfI24sLC5d7EidLd0E/6TthLJa1WqXnsLkhaZToRf1JilT5ufe1KE72YyZlMlDSW3aXqzpE9D5j3ZZGmR0BpnAopFkpnBl4PM8lYcSsymgK95GmBjxHbDbz+TZanwhbz0Chp3bDoj6LxgOHPURPwXtM/Bclk+0zA8WjATivv3Z5PSdrS5mbFUThw+nsma4awJMcBDeTQtbTnBZZFqjhydDn5nEuut0Iuq4jyj7JSKjFnGReyf1TVgDn7hGVqTumVMsIKJcHFyx+51WLDfvQu/by2Dtg4GrmyuuBOXLRlL9EAgHfVDmJPGeKwonnk9G2S0eZJzI3DTJT5BnPbxdw+g+kKFKRZCloHWTqxTbKDX1NZpn8F7rlW92gohH1lAsA6BqWGb+HqjV6jqU27F5ovM4x22PBcUyKMg89oLoosr9qI2EPbB4rvAXypUuUwfavQoIGLibZuTE/bjlV8KjYPTMn6toJteH/71Z2pzP3+A0NdLB8wSnluaM52R+z8dX28WLB+ffciP/ctr442yrglLXgaNXcw8t2qrCBQY7tQkNw5BmdxtaiwliBYQk8BAomxs/3uYUlKXA8Tlz722A/j8XjWc0tgrtaG8TRfcbYWEtLQiH+rcAB0N1DcqB3uFWmTuzaXdMkz0pxNm9HHAZ/HuPrV7wsOmi5UCe3k1H1zHwfRUZhK8MI31oT388J4NBpB6pz3kcyKaVrAXNfM+YdHopkTNBLn1XF15E2+Ik2/kMrI6i3O10vj/I8H7MT/HMPmrCbGDx/m17eDTcMdhNhQ9LQ7MwuHrsK5NB2FsfkMU4ybHH0fu1lPtbK8yXIIUqvo6gOLGcgj58cJX+G1eiLfMZz3vyeSdoe95UYkbd7tvEwmk+fYNmI1aFCcxcEU9ga96nUaZjyP7o2SeFv97M9qA8qA56ACnvXCx9AZZr2VtbmZxnEyl4jHJROljiTZWOZZHLpfnESn0SieC2Njp4b3rOcfng5w9Wz+H+wqAvCvQvha3T3Frol/zVH+A/Bb34tJhPGvkRtllAkXE2K7x/wQXOd3AcTTn8D3JZksLAP+P8EaO7i+gfvFGEsSiFgTtImybnVrP2wUjf10OHAV8D1oOA7nlIkDQBtXl/wkehWn4i6EbNYmZtIarPeFWH4zkYnKcpGS/pS769adTP//0q9eZ3VBLb9kRcnXJ/T3ZlNRvsKwkC5R7n0rcSfJVuZ3N7/TBt+tES9skdbNecZ4TUalheNYub0t5By0Az/P9oO/YHgeb827jSXpXtDHRO02J6/93GyDdtYqxRdfOO/v23H5nSrtMzuJTtqC7/4DVvHLxg==" />
|
|
|
+
|
|
|
+## Setting up the scene (optional)
|
|
|
+
|
|
|
+We import all the modules that we need, for comfort we can use the orbit-controls from cientos,
|
|
|
+[look here to see how](/examples/orbit-controls).
|
|
|
+
|
|
|
+Now, let's put our camera in the `[11,11,11]` position.
|
|
|
+
|
|
|
+Lastly just to help us with the location, let's add a simple plane, rotated in the X axis, with `[10, 10]` units.
|
|
|
+
|
|
|
+```vue
|
|
|
+<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](https://threejs.org/) 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, and put our blob 4 units in the Y positive axis
|
|
|
+
|
|
|
+```vue
|
|
|
+<TresMesh :position="[0, 4, 0]">
|
|
|
+ <TresSphereGeometry :args="[2, 32, 32]" />
|
|
|
+ <TresShaderMaterial />
|
|
|
+</TresMesh>
|
|
|
+```
|
|
|
+
|
|
|
+The `ShaderMaterial` accepts special properties, like `uniforms` `vertexShader` and `fragmentShader`, so we can create it in our script section and make the bind with our instance.
|
|
|
+
|
|
|
+For this example, our uniforms look like this:
|
|
|
+
|
|
|
+```ts
|
|
|
+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 looks like this:
|
|
|
+
|
|
|
+```ts
|
|
|
+//...
|
|
|
+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:
|
|
|
+
|
|
|
+```ts
|
|
|
+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](/examples/basic-animations) example, we start by referencing our blob, using [Template Ref](https://vuejs.org/guide/essentials/template-refs.html)
|
|
|
+
|
|
|
+```vue
|
|
|
+<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 have got that, we could use the `onLoop` callback to animate our `uTime`.
|
|
|
+
|
|
|
+ ```ts
|
|
|
+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](https://vitejs.dev/) 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) (check out the link for the official documentation).
|
|
|
+
|
|
|
+And you could have a structure similar to this:
|
|
|
+
|
|
|
+```
|
|
|
+├── src/
|
|
|
+│ ├── myTresJsComponent.vue
|
|
|
+│ ├── shaders/
|
|
|
+│ ├── vertexShader.glsl
|
|
|
+│ ├── fragmentShader.glsl
|
|
|
+```
|