Bläddra i källkod

Merge pull request #36 from Tresjs/feature/19-docs-for-core-composables

feat(core): docs for exposed composables
Alvaro Saburido 2 år sedan
förälder
incheckning
c19c95b8c1

+ 5 - 1
docs/.vitepress/config.ts

@@ -26,13 +26,17 @@ export default defineConfig({
             text: 'Instances, arguments and props',
             link: '/api/instances-arguments-and-props',
           },
+          {
+            text: 'Composables',
+            link: '/api/composables',
+          },
         ],
       },
       {
         text: 'Examples',
         items: [
           { text: 'Orbit Controls', link: '/examples/orbit-controls' },
-          { text: 'Basic Animation', link: '/examples/basic-animations' },
+          { text: 'Basic Animations', link: '/examples/basic-animations' },
           { text: 'Load Textures', link: '/examples/load-textures' },
           { text: 'Load Models', link: '/examples/load-models' },
         ],

+ 4 - 0
docs/.vitepress/theme/config.css

@@ -39,6 +39,10 @@
   --vp-button-sponsor-active-bg: transparent;
 }
 
+.VPSidebar .link.active span {
+  font-weight: bold;
+}
+
 .vp-doc a {
   text-decoration: dashed;
   font-weight: bold;

+ 201 - 0
docs/api/composables.md

@@ -0,0 +1,201 @@
+# Composables
+
+Vue 3 [Composition API](https://vuejs.org/guide/extras/composition-api-faq.html#what-is-composition-api) allows you to create reusable logic that can be shared across components. It also allows you to create custom hooks that can be used in your components.
+
+TresJS takes huge advantage of this API to create a set of composable functions that can be used to create animations, interact with the scene, and more. It also allows you to create more complex scenes that might not be possible using just the Vue Components (Textures, Loaders, etc.).
+
+The core of TresJS uses these composables internally, so you would be using the same API that the core uses. For instance, components that need to updated on the internal render loop use the `useRenderLoop` composable to register a callback that will be called every time the renderer updates the scene.
+
+## useRenderLoop
+
+The `useRenderLoop` composable is the core of TresJS animations. It allows you to register a callback that will be called on native refresh rate. This is the most important composable in TresJS.
+
+```ts
+const { onLoop, resume } = useRenderLoop()
+
+onLoop(({ delta, elapsed }) => {
+  // I will run at every frame ~ 60FPS (depending of your monitor)
+})
+```
+
+::: warning
+Be mindfull of the performance implications of using this composable. It will run at every frame, so if you have a lot of logic in your callback, it might impact the performance of your app. Specially if you are updating reactive states or references.
+:::
+
+The `onLoop` callback receives an object with the following properties based on the [THREE clock](https://threejs.org/docs/?q=clock#api/en/core/Clock):
+
+- `delta`: The delta time between the current and the last frame. This is the time in seconds since the last frame.
+- `elapsed`: The elapsed time since the start of the render loop.
+
+This composable is based on `useRafFn` from [vueuse](https://vueuse.org/core/useRafFn/). Thanks to [@wheatjs](https://github.com/orgs/Tresjs/people/wheatjs) for the amazing contribution.
+
+### Before and after render
+
+You can also register a callback that will be called before and after the renderer updates the scene. This is useful if you add a profiler to measure the FPS for example.
+
+```ts
+const { onBeforeLoop, onAfterLoop } = useRenderLoop()
+
+onBeforeLoop(({ delta, elapsed }) => {
+  // I will run before the renderer updates the scene
+  fps.begin()
+})
+
+onAfterLoop(({ delta, elapsed }) => {
+  // I will run after the renderer updates the scene
+  fps.end()
+})
+```
+
+### Pause and resume
+
+You can pause and resume the render loop using the exposed `pause` and `resume` methods.
+
+```ts
+const { pause, resume } = useRenderLoop()
+
+// Pause the render loop
+pause()
+
+// Resume the render loop
+resume()
+```
+
+Also you can get the active state of the render loop using the `isActive` property.
+
+```ts
+const { resume, isActive } = useRenderLoop()
+
+console.log(isActive) // false
+
+resume()
+
+console.log(isActive) // true
+```
+
+## useLoader
+
+The `useLoader` composable allows you to load assets using the [THREE.js loaders](https://threejs.org/docs/#manual/en/introduction/Loading-3D-models). It returns a promise with loaded asset.
+
+```ts
+import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
+
+const { scene } = await useLoader(THREE.GLTFLoader, 'path/to/asset.gltf')
+```
+
+Since the `useLoader` composable returns a promise, you can use it with `async/await` or `then/catch`. If you are using it on a component make sure you wrap it with a `Suspense` component. See [Suspense](https://vuejs.org/guide/built-ins/suspense.html#suspense) for more information.
+
+```vue
+<template>
+  <Suspense>
+    <TheComponentUsingLoader />
+  </Suspense>
+</template>
+```
+
+## useTexture
+
+The `useTexture` composable allows you to load textures using the [THREE.js texture loader](https://threejs.org/docs/#api/en/loaders/TextureLoader). It returns a promise with the loaded texture(s).
+
+```ts
+const texture = await useTexture(['path/to/texture.png'])
+```
+
+**useTexture** also accepts an object with the following properties:
+
+- `map`: a basic texture that is applied to the surface of an object
+- `displacementMap`: a texture that is used to add bumps or indentations to the object's surface
+- `normalMap`: a texture that is used to add surface detail to and variations in shading to the object
+- `roughnessMap`: a texture that is used to add roughness or a matte finish to the object's surface
+- `metalnessMap`: a texture that is used to add a metallic effect to the object's surface
+- `aoMap`: a texture that is used to add ambient occlusion (shading in areas where light is blocked by other objects) to the object.
+
+In that case it will return an object with the loaded textures.
+
+```ts
+const { map, displacementMap, normalMap, roughnessMap, metalnessMap, aoMap } = await useTexture({
+  map: 'path/to/albedo.png',
+  displacementMap: 'path/to/height.png',
+  normalMap: 'path/to/normal.png',
+  roughnessMap: 'path/to/roughness.png',
+  metalnessMap: 'path/to/metalness.png',
+  aoMap: 'path/to/ambien-occlusion.png',
+})
+```
+
+Then you can bind the textures to the material.
+
+```vue
+<template>
+  <TresMesh>
+    <TresMeshSphereGeometry />
+    <TresMeshStandardMaterial
+      :map="map"
+      :displacementMap="displacementMap"
+      :normalMap="normalMap"
+      :roughnessMap="roughnessMap"
+      :metalnessMap="metalnessMap"
+      :aoMap="aoMap"
+    />
+  </TresMesh>
+</template>
+```
+
+Similar to above composable, the `useTexture` composable returns a promise, you can use it with `async/await` or `then/catch`. If you are using it on a component make sure you wrap it with a `Suspense` component.
+
+# useCatalogue
+
+The `useCatalogue` composable allows you to extend the internal catalogue of components. It returns a function that you can use to register new components.
+
+This is specially useful if you want to use objects that are not part of ThreeJS core like[OrbitControls](https://threejs.org/docs/#examples/en/controls/OrbitControls) or third party functionality, like physics.
+
+```ts
+import { useCatalogue } from '@tresjs/core'
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
+
+const { extend } = useCatalogue()
+
+extend({ OrbitControls })
+```
+
+Then you can use the new component in your template. Notice that the new component is prefixed with `Tres` to avoid name collisions with native HTML elements, similar to the rest of the core components.
+
+```vue
+<template>
+  <TresCanvas shadows alpha>
+    <TresScene>
+      <TresOrbitControls v-if="state.renderer" :args="[state.camera, state.renderer?.domElement]" />
+    </TresScene>
+  </TresCanvas>
+</template>
+```
+
+# useTres <Badge type="warning" text="experimental" />
+
+This composable aims to provide access to the state model which contains the default renderer, camera, scene, and other useful properties. It is still experimental and it is not recommended to use it in production because is highly like subject to change.
+
+```ts
+const { state } = useTres()
+
+console.log(state.camera) // THREE.PerspectiveCamera
+console.log(state.renderer) // THREE.WebGLRenderer
+```
+
+Until this composable is stable, it is recommended to use the `provide/inject` API to acces the elements you need. These are the available keys:
+
+- `camera`: it returns the current active camera
+- `renderer`: it returns the current active renderer
+- `local-scene`: it returns the current active scene
+- `catalogue`: it returns the current catalogue of components
+- `extend` : it returns the `extend` function from the `useCatalogue` composable. Specially needed if you are a plugin author.
+- `aspect-ratio`: it returns the current aspect ratio of the canvas
+
+```ts
+import { provide, inject } from 'vue'
+
+const camera = inject<Ref<Camera>>('camera')
+const renderer = inject<Ref<WebGLRenderer>>('renderer')
+
+console.log(camera.value) // THREE.PerspectiveCamera
+console.log(renderer.value) // THREE.WebGLRenderer
+```

+ 1 - 1
docs/examples/basic-animations.md

@@ -10,7 +10,7 @@ We will build a simple scene with a cube. We will then animate the cube to rotat
 
 The `useRenderLoop` composable is the core of TresJS animations. It allows you to register a callback that will be called every time the renderer updates the scene with the browser's refresh rate.
 
-To see a detailed explanation of how it works, please refer to the **useRenderLoop** documentation.
+To see a detailed explanation of how it works, please refer to the [useRenderLoop](/api/composables#userenderloop) documentation.
 
 ```ts
 const { onLoop, resume } = useRenderLoop()

+ 1 - 3
docs/examples/load-models.md

@@ -14,7 +14,7 @@ There are several ways to load models on TresJS:
 
 The `useLoader` composable allows you to pass any type of Three.js loader and a URL to load the resource from. It returns a `Promise` with the loaded resource.
 
-For a detailed explanation of how to use `useLoader`, check out the **useLoader** documentation.
+For a detailed explanation of how to use `useLoader`, check out the [useLoader](/api/composables#useloader) documentation.
 
 ```ts
 import { useLoader } from '@tresjs/core'
@@ -41,8 +41,6 @@ Notice in the example above that we are using the `Suspense` component to wrap t
 
 A more convenient way of loading models is using the `useGLTF` composable available from [@tresjs/cientos](https://github.com/Tresjs/tres/tree/main/packages/cientos) package.
 
-To learn more about `useGLTF`, check out the **useGLTF** documentation.
-
 ```ts
 import { useGLTF } from '@tresjs/cientos'
 

+ 3 - 3
docs/examples/load-textures.md

@@ -2,7 +2,7 @@
 
 > All textures used in this example are from [ambientcg](https://ambientcg.com/).
 
-3D textures are textures that contain multiple layers of image data, allowing them to represent volumetric data or simulate three-dimensional structures. They are often used in 3D graphics and visual effects to add realism and complexity to scenes and objects.
+Three-dimensional (3D) textures are images that contain multiple layers of data, allowing them to represent volume or simulate three-dimensional structures. These textures are commonly used in 3D graphics and visual effects to enhance the realism and complexity of scenes and objects.
 
 <StackBlitzEmbed projectId="tresjs-load-textures" />
 
@@ -12,7 +12,7 @@ There are two ways of loading 3D textures in TresJS:
 
 The `useLoader` composable allows you to pass any type of Three.js loader and a URL to load the resource from. It returns a `Promise` with the loaded resource.
 
-For a detailed explanation of how to use `useLoader`, check out the **useLoader** documentation.
+For a detailed explanation of how to use `useLoader`, check out the [useLoader](/api/composables#use-loader) documentation.
 
 ```ts
 import { useLoader } from '@tresjs/core'
@@ -42,7 +42,7 @@ Notice in the example above that we are using the `Suspense` component to wrap t
 
 A more convenient way of loading textures is using the `useTexture` composable. It accepts both an array of URLs or a single object with the texture paths mapped.
 
-To learn more about `useTexture`, check out the **useTexture** documentation.
+To learn more about `useTexture`, check out the [useTexture](/api/composables#use-texture) documentation.
 
 ```ts
 import { useTexture } from '@tresjs/core'

+ 3 - 3
docs/examples/orbit-controls.md

@@ -8,7 +8,7 @@ However, it is not part of the core of ThreeJS. So to use it you would need to i
 
 This creates a problem because **TresJS** automatically creates a catalog of the core of Three so you can use them as components.
 
-Fortunately, **TresJS** provides a way to extend the catalog of components. You can do it by using the `extend` method using the **useCatalogue** composable.
+Fortunately, **TresJS** provides a way to extend the catalog of components. You can do it by using the `extend` method using the [useCatalogue](/api/composables#usecatalog) composable.
 
 For more information about extending your TresJS catalog, refer to the [extending](/advanced/extending.md) section.
 
@@ -20,7 +20,7 @@ To use `OrbitControls` you need to import it from the `three/examples/jsm/contro
 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
 ```
 
-Then you need to extend the catalogue of components using the `extend` method of the **useCatalogue** composable.
+Then you need to extend the catalogue of components using the `extend` method of the [useCatalogue](/api/composables#usecatalog) composable.
 
 ```js
 import { useCatalogue } from '@tresjs/core'
@@ -45,7 +45,7 @@ Now you can use the `TresOrbitControls` component in your scene.
 
 Since [OrbitControls](https://threejs.org/docs/index.html?q=orbit#examples/en/controls/OrbitControls) needs a reference to the camera and the renderer, you need to pass them as arguments.
 
-You can use the **useThree** composable to get the camera and the renderer.
+You can use the [useThree](/api/composables#usethree) composable to get the camera and the renderer.
 
 ```ts
 import { useThree } from '@tresjs/core'