Browse Source

docs(app): light-shadows and shaders docs examples (#506)

* docs: add light-shadows and shader examples pages

* docs: update info in example, missing grammar correction

* docs: grammar corrections

* docs(app): fix indentation

* docs(app): fix title section names, add message as warning

* docs(app): feature-476 Apply reviews feedback

* docs(app): Fix markdown links

* docs(app): feature-476 Improve titles, and remove redundan shadow word

---------

Co-authored-by: Alvaro Saburido <alvaro.saburido@gmail.com>
Jaime A Torrealba C 1 year ago
parent
commit
7af155ccfa
3 changed files with 350 additions and 0 deletions
  1. 2 0
      docs/.vitepress/config.ts
  2. 174 0
      docs/examples/lights-shadows.md
  3. 174 0
      docs/examples/shaders.md

+ 2 - 0
docs/.vitepress/config.ts

@@ -73,6 +73,8 @@ export default defineConfig({
           { text: 'Load Textures', link: '/examples/load-textures' },
           { text: 'Load Models', link: '/examples/load-models' },
           { text: 'Load Text', link: '/examples/text-3d' },
+          { text: 'Lights & Shadows', link: '/examples/lights-shadows' },
+          { text: 'Shaders', link: '/examples/shaders' },
         ],
       },
       {

+ 174 - 0
docs/examples/lights-shadows.md

@@ -0,0 +1,174 @@
+# Light-shadows
+
+This guide will help you get started with simple light and shadows in TresJS.
+
+We will build a simple scene with three meshes and a plane but only two will have shadows.
+<SandboxDemo url="https://play.tresjs.org/#eNqVVt1y2jwQfRUN30WSKdimhLbjL3Qo9GfaadpM4K7uhbAXUGpLGkn8pJm8e1eSDXZCMmRCGGv37NHZ1XrFXWuqQH+QMlivoBW3LnSqmDREg1lJklO+GCQto5PW+4SzQgplyB3RS5rnYnMNc3JP5koU5ASjT/6vQSzrmPI11W2y0nANPAP1XQhZBQwNIm50mArVjPypZsyMBTdK5HrHv4Mz4EboRsSIapZOljQTm0sq22Ry/WU0FrlQE0lTaJMfYio4oEsyvtgxmqUCOEl4wlPBtSGLnAzIXcIJSXOgyhHE5OS/d68/jsb9k7b1YOK4iY6JUStwFprLJY3JnObaGzwEN5veSogfarMIsTJyhRlWAuOHgi3I7BXHzQTQfb9XPRNbewyD2pmcnu3dd0RwW3XMetA8B4/y3tPTMzJ475Nn81PPGaxpvoIzZ6xbAiUMNUzw4Ja8GpAoiLoWgpruHWXCL0LfRNgyuDBQyJwawBUhF/u+IOvOjPEM22uRJy2ywWex6Wj21yMR2+yEsDJbiitQWkJq2BrGtABFSSyFZlYWEv7qt8nbwH/9Ru54LtZoPu/bZ+oCcdm1K45Hjc9R4FZzt+hGUYSrxoaXoJfNPTqv2wQ/kdugqol1RG1ySc0yuPrqvSVNlTye5BcQBRh1i2LUQtuYbpt0reCeZas2rm09FYIjKShGc5LaVsGosjXrUsMq4JF2BXMM8QeJESnVpuN7tZkWqrefR7pHYntAttVcfb1I+vln+3ec9LrWplisvz2Gx2oncglqX+ejZX0ejaLe6NiKpoD991QVO71DzdEpW4OErnkOab/CqXuoRRC8/3+i2BNDeUZV9jiz+Vv791Rmtdw+FDM7Y7+zxdKQmHEDHPO6LV+YxkvxkWENbGY09/Dnumr3rhym9HL8aEDDRVibG612yw/7TkFlcKMFx5vKDaakdOAFFfv5ZW31u8U6ktbSGKnjMEwzjvEZ5GytAg4m5LII6/BhL+gHUZgxbUJrRnTSchO5QexvoZdw+wikf1OnL83NXcwG6B+JTXAE/w47PA9wiJXMlTEomI2pc9tb7xheixsiY/8d6n0FuqiXAW97vEyOrm8NPuxGrsA47WEbFM3qljhsIAXZC4h9wHPUCOxkULAjSCuoTf48eBPmbFanrO467Emj8ZKds8WDjkxFIVkO6qe03d/sTHdHf3O23U8IF7OE9M8B+43eeslX2Cyg1lju/VHiZADj3Z8mP2CLzztnIbJVXh7OE85r0CJfWY0eNlrxDGXXcE7tV/eC4Q+Pqf60dW9umVRDqMFfO876q5pJu17zht+ucA7vjmP8TJX2mfWC3q7g9/8AWlN6bg==" />
+
+## Setting up the scene (optional)
+
+We import all the modules that we need, for comfort we can use the orbit-controls from cientos,
+[check here to know how](/examples/orbit-controls).
+
+Let's put four objects in our scene, one will be the plane that receive shadows, two of them will cast shadows and the last one will not cast any shadow at all.
+
+I'm going to use [MeshToonMaterial](https://threejs.org/docs/index.html?q=toon#api/en/materials/MeshToonMaterial). Simply because we can see the "soft shadow" easily.
+
+```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="[5, 7.5, 7.5]" />
+
+    <TresMesh
+      :position="[-2, 2, 0]"
+      :rotation="[0, Math.PI, 0]"
+    >
+      <TresConeGeometry :args="[1, 1.5, 3]" />
+      <TresMeshToonMaterial color="#82DBC5" />
+    </TresMesh>
+    <TresMesh
+      :position="[0, 0, 0]"
+    >
+      <TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
+      <TresMeshToonMaterial color="#4F4F4F" />
+    </TresMesh>
+    <TresMesh
+      :position="[2, -2, 0]"
+    >
+      <TresSphereGeometry />
+      <TresMeshToonMaterial color="#FBB03B" />
+    </TresMesh>
+    <TresMesh
+      :position="[0, -3, 0]"
+      :rotation="[-Math.PI / 2, 0, 0]"
+    >
+      <TresPlaneGeometry :args="[10, 10, 10, 10]" />
+      <TresMeshStandardMaterial color="#f7f7f7" />
+    </TresMesh>
+  </TresCanvas>
+</template>
+```
+
+## Lights (explanation)
+
+As you know every instance in [ThreeJs](https://threejs.org/) is available in **TresJs** so are all the light types, we just need to add the `Tres` prefix to use them.
+
+But not all lights can cast shadows, this definition comes directly from ThreeJs and makes sense, for example the purpose of an [ambientLight](https://threejs.org/docs/index.html?q=ambient#api/en/lights/AmbientLight) is to iluminate everysingle side of your scene, so it makes no sense for it to cast shadows, on the contrary, a [DirectionalLight](https://threejs.org/docs/index.html?q=light#api/en/helpers/DirectionalLightHelper) immitating the sun can and should cast shadows.
+
+## Shadows (explanation)
+
+There are also many types of shadows, for example the "soft shadow" is generated automatially when an object receives more light from one side, but in summary a "ThreeJS default shadow" that is directed towards another surface needs to be cast by a mesh and another mesh needs to receive it. As we see in our example, the `Plane` is receiving a shadow but not casting it. Please note that not all materials can cast or receive shadows.
+
+Internally, ThreeJS automatically generates a new mesh with a [ShadowMaterial](https://threejs.org/docs/index.html?q=shado#api/en/materials/ShadowMaterial) which gets updated in each frame, that is why if you apply animations, the shadow also is animated, but also why you have to use shadows carefully, because they could slow your performance down.
+
+::: warning
+The overuse of shadows in this way could drop your performance. However, there are ways to increase your performance, for more information please check out [this video](https://youtu.be/WGNvVGrS0kY?si=q7XyL5eABKUh3gbS&t=1256)
+:::
+
+## Enabling shadows
+
+We could divide this into three steps:
+
+### Activate shadows on the renderer
+
+```vue
+//...
+
+<template>
+  <TresCanvas
+    clear-color="#111"
+    shadows
+    window-size
+  />
+  //...
+</template>
+```
+### Set the light to cast shadows
+
+We can simple put the boolean `cast-shadow`, Vue understand this as a `prop` with `true` value
+
+_The AmbientLight doesn't generate any type of shadow here_
+
+```vue
+//...
+
+<template>
+  <TresAmbientLight :intensity="1" />
+  <TresDirectionalLight
+    cast-shadow
+    :position="[0, 2, 0]"
+    :intensity="1"
+  />
+  
+  //...
+</template>
+```
+### Set the objects to cast or receive shadows
+
+Similarly to the previous step, we set the mesh that we want to cast shadow (our sphere) with the `cast-shadow` prop, and set the object to receive shadow (our plane) with the `receive-shadow` prop.
+
+```vue
+//...
+
+<template>
+  <TresMesh
+    cast-shadow
+    :position="[2, -2, 0]"
+  >
+    <TresSphereGeometry />
+    <TresMeshToonMaterial color="#FBB03B" />
+  </TresMesh>
+  <TresMesh
+    receive-shadow
+    :position="[0, -3, 0]"
+    :rotation="[-Math.PI / 2, 0, 0]"
+  >
+    <TresPlaneGeometry :args="[10, 10, 10, 10]" />
+    <TresMeshStandardMaterial color="#f7f7f7" />
+  </TresMesh>
+  //...
+</template>
+```
+
+Now we have all the necessary steps to add shadows to our scene, and if we apply what we learned in [basic animations](/examples/basic-animations), and we add movement to our cube, you will see the shadow is animated as well 🤩
+
+```vue
+<script setup>
+import { shallowRef } from 'vue'
+import { TresCanvas, useRenderLoop } from '@tresjs/core'
+
+const boxRef = shallowRef()
+
+const { onLoop } = useRenderLoop()
+
+onLoop(() => {
+  if (boxRef.value) {
+    boxRef.value.rotation.y += 0.01
+  }
+})
+</script>
+
+<template>
+  //...
+  <TresMesh
+    ref="boxRef"
+    cast-shadow
+    :position="[0, 0, 0]"
+  >
+    <TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
+    <TresMeshToonMaterial color="#4F4F4F" />
+  </TresMesh>
+  //...
+</template>
+```
+
+_Note that I intentionally did not apply `cast-shadow` to the `Cone` so it doesn't cast any shadow_

+ 174 - 0
docs/examples/shaders.md

@@ -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
+```