# Getting Started
Cientos (Spanish word for "hundreds", pronounced `/ฮธjentos/`) is a collection of useful ready-to-go helpers and components that are not part of the **core** package. The name uses the word in Spanish to multiply by 100, to refer to the potential reach of the package to hold amazing abstractions.
::prose-note
The cientos package uses three-stdlib module under the hood instead of the `three/examples/jsm` module. This means that you don't need to extend the catalogue of components using the extend method, cientos does that for you.
::
It just works. ๐ฏ
## Next Steps
Continue your journey:
- [Installation guide](https://cientos.tresjs.org/getting-started/installation)
- [Usage](https://cientos.tresjs.org/getting-started/usage)
- [Upgrade guide](https://cientos.tresjs.org/getting-started/upgrade-guide)
# Installation Guide
## Manual installation
If you prefer to set up Cientos manually or add it to an existing [Tres.js](https://tresjs.org/){rel=""nofollow""} project
::code-group
```bash [pnpm]
pnpm add @tresjs/cientos
```
```bash [npm]
npm install @tresjs/cientos
```
```bash [yarn]
yarn add @tresjs/cientos
```
::
## Via `create-tres` wizard
When using `create-tres` to create a new project, the cli will prompt you to install cientos.
::code-group
```bash [npm]
npx create-tres my-tres-project
```
```bash [yarn]
yarn create tres my-tres-project
```
```bash [pnpm]
pnpm create tres my-tres-project
```
::
::read-more
---
to: https://docs.tresjs.org/getting-started/installation#quick-start-recommended
---
For more information about the `create-tres` wizard please refer to this link.
::
## Nuxt :u-icon{name="i-simple-icons-nuxt"}
If you're using nuxt, installing our nuxt module will detect automatically cientos.
::read-more
---
to: https://docs.tresjs.org/getting-started/installation#nuxt-project
---
For more information about the Nuxt module please refer to this link.
::
# Usage
## Basic Usage
All instances of cientos provide one (or many) examples of how to use it, similar to this one:
```js
import { OrbitControls } from '@tresjs/cientos'
```
Now you can use the `OrbitControls` component in your scene.
```vue
```
::prose-note
Note that you donโt need to include the **Tres** prefix (for example, ``) to use the component. All cientos components have the same name as their three-stdlib counterpart.
::
### Props
All the props are listed with their respective instance and in case it is not specified all the props are **reactive**, for example:
```vue {3,15-16}
```
::prose-note
All the props and properties are **reactive** unless the docs of the instance says the contrary.
::
### Events
Some instances fire events which you can listen to as you normally would do using Vue [emits](https://vuejs.org/guide/components/events.html#emitting-and-listening-to-events){rel=""nofollow""}, for example:
```vue {3,5,11}
```
### Exposed properties
All instances expose a `instance` property by default which contains the base of its abstractions. For example:
```vue {2}
```
# Loading Models
Cientos gives you three ways to get a `.glb`/`.gltf` model on screen. They are not alternatives to
each other so much as three points on the same line: the further down this page you go, the more
control you get over the model's tree.
| Approach | Control | Typed | Best for |
| :----------------------------------------------------------------------------------- | :------------------------------- | :------- | :------------------------------------------------- |
| [``](https://cientos.tresjs.org/api/loaders/gltf-model) | Whole scene, as-is | No | Dropping a model in as-is |
| [`useGLTF`](https://cientos.tresjs.org/api/loaders/use-gltf) | Pick nodes and materials by hand | Optional | Reusing parts of a model |
| [`tres gltf` codegen](https://cientos.tresjs.org/#generate-a-component-with-the-cli) | Every node is an element | Yes | Production scenes, interaction, per-node overrides |
## Drop the model in
The fastest path. `GLTFModel` loads the file and renders its scene graph untouched:
```vue [TheModel.vue]
```
You get the whole model or nothing. There is no way to swap one mesh's material, attach a click
handler to a door, or hide a node, because none of them exist as elements in your template.
## Pick the parts you need
`useGLTF` hands you the parsed `nodes` and `materials`, so you compose the scene yourself:
```vue [TheModel.vue]
```
This is the right tool when you only want a couple of nodes out of a bigger file. For a whole
model it stops scaling: you are hand-writing an element per node, re-reading the tree in Blender
to find the names, and re-writing all of it when the artist re-exports.
::prose-note
`nodes` and `materials` are keyed by the names in the file, so their shape is only known at
runtime. Pass the shape as generics to get them typed, see [Typed nodes and materials](https://cientos.tresjs.org/#typed-nodes-and-materials) below.
::
## Generate a component with the CLI
`@tresjs/cli` writes that element-per-node component for you, typed, from the model itself:
```bash
npx @tresjs/cli gltf public/models/mug.glb
# โ src/models/Mug.gen.vue
# 1 slot: Mug
```
```vue [src/models/Mug.gen.vue]
```
Import it like any other component:
```vue [App.vue]
```
### Overriding a node
Every named node is a `` whose fallback is the generated markup, so you change one mesh
from the parent without touching the generated file:
```vue [App.vue]
```
Regenerate after the artist re-exports and the override survives, because it never lived in the
generated file. If the node is renamed, the override becomes a **type error** instead of quietly
doing nothing at runtime.
::prose-warning
Treat `*.gen.vue` files as build output: edit the parent, not the generated file. The CLI refuses
to overwrite a file it did not generate, so a hand-edited one needs `--force` to regenerate.
::
::read-more{to="https://docs.tresjs.org/cli/gltf"}
Full `tres gltf` reference: slots, animations, shadows, Draco and every flag.
::
## Typed nodes and materials
`useGLTF` takes two generics that type `nodes` and `materials`. The CLI writes them for you, but
you can also declare them by hand:
```ts
import type { Mesh, MeshStandardMaterial } from 'three'
import { useGLTF } from '@tresjs/cientos'
interface ModelNodes { Body: Mesh }
interface ModelMaterials { Skin: MeshStandardMaterial }
const { nodes, materials } = useGLTF('/models/robot.glb')
nodes.value.Body.geometry // Mesh, not any
```
::prose-note
The names come from the file at runtime, so these interfaces are a claim about the model, not a
proof. That is exactly why generating them from the model is worth it.
::
## Animated models
Clips live on the loaded `state`, and [`useAnimations`](https://cientos.tresjs.org/api/miscellaneous/use-animations) turns
them into actions:
```vue [Knight.vue]
```
A generated component wires all of that up and exposes `actions` keyed by a union of the model's
clip names, so `actions.Idle` type-checks and `actions.Idl` does not:
```vue [App.vue]
```
::prose-note
Keep the element carrying the animation `ref` mounted and gate its **children** on loading. A
`ref` on a `v-if`ed element is still `undefined` one flush after the clips land, and the mixer
would then be built with no root to bind against.
::
## Draco-compressed models
Pass `draco: true` and the loader pulls the decoder from Google's CDN, or point `decoderPath` at
a local copy:
```ts
const { state } = useGLTF('/models/mug.glb', { draco: true })
```
A Draco model renders nothing without it. The CLI detects compression while parsing and writes
`{ draco: true }` into the generated component for you.
## Where to find models
- [poly.pizza](https://poly.pizza/){rel=""nofollow""} โ free 3D models
- [Pmndrs Market](https://market.pmnd.rs/){rel=""nofollow""} โ free assets, curated
- [KayKit](https://kaylousberg.itch.io/){rel=""nofollow""} โ animated CC0 character packs
# Upgrade Guide
## From v4 to v5
Cientos doesn't have any breaking changes from v4 to v5 but please check the [Upgrade Guide](https://docs.tresjs.org/getting-started/upgrade-guide){rel=""nofollow""} of the core.
## Migration Guide from v3
The following are the breaking changes introduced in v4. We recommend reading through all of them to ensure a smooth transition.
### Updated defineExport properties
Since the beginning we exported our components' underlying `Three.js` instances using the name `value`. This created a very ambiguous situation with some components. When we access them using a `ref` in the ``, we ended up with something like:
```html
...
...
```
This behavior caused confusion and resulted in a poor developer experience. To address it properly, we needed to introduce a breaking change, and we felt this was the right moment to do so.
The new implementation remains very similar conceptually. However, instead of having two ambiguous `value` references, we have standardized all components around `instance`. To access the component, you should now use:
```text
// Correct in v4 โ
console.log(starsRef.value.instance)
```
### Remove TweakPane from deps
We removed the built-in `useTweakPane` integration because it was adding overhead and friction:
- Incompatible with [Tweakpane v4](https://tweakpane.github.io/docs/){rel=""nofollow""}
- Large bundle impact
- Repetitive boilerplate and not very intuitive
If you still want to use Tweakpane with Tres, you can follow the cookbook recipe: {rel=""nofollow""}
### Move directives to core
Community adoption of directives has been solid, so they now live in the core package. Import them from `@tresjs/core`:
```ts
// Correct โ
import { vLog } from '@tresjs/core'
```
Instead of:
```ts
// Wrong โ
import { vLog } from '@tresjs/cientos'
```
### Changes in KeyboardControls
`KeyboardControls` was redesigned to provide floating controls similar to the Unreal Engine, which better matches the componentโs intent. We also bundled `PointerLockControls` inside `KeyboardControls`, so you donโt need to wire it manually anymore.
[Learn more](https://cientos.tresjs.org/api/controls/keyboard-controls){rel=""nofollow""}
# Align
::scene-controls-wrapper
:abstractions-align
::
Calculates a bounding box around its children and aligns them as a group within their parent. The component measures its contents and realigns on every frame unless `cacheKey` is set.
## Usage
```vue {2,13,18}
```
## Props
All props are optional.
| Prop | Description | Default |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `top` | If `true`, aligns bounding box bottom to `0` on the y-axis | `false` |
| `bottom` | If `true`, aligns bounding box top to `0` on the y-axis. | `false` |
| `left` | If `true`, aligns bounding box right to `0` on the x-axis. | `false` |
| `right` | If `true`, aligns bounding box left to `0` on the x-axis. | `false` |
| `front` | If `true`, aligns bounding box back to `0` on the z-axis. | `false` |
| `back` | If `true`, aligns bounding box front to `0` on the z-axis. | `false` |
| `disable` | If `true`, disables alignment on all axes. | `false` |
| `disableX` | If `true`, disables alignment on the x-axis. | `false` |
| `disableY` | If `true`, disables alignment on the y-axis. | `false` |
| `disableZ` | If `true`, disables alignment on the z-axis. | `false` |
| `precise` | See [Box3.setFromObject](https://threejs.org/docs/index.html?q=box3#api/en/math/Box3.setFromObject){rel=""nofollow""}. | `true` |
| `onAlign` | Callback that fires when updating, after measurement. | |
| `cacheKey` | If set, component will only update when `cacheKey`'s value changes. If unset, component will update every frame. | `undefined` |
## AlignCallbackOptions
```ts
export interface AlignCallbackOptions {
/** The next parent above */
parent: Object3D
/** The outmost container group of the component */
container: Object3D
width: number
height: number
depth: number
boundingBox: Box3
boundingSphere: Sphere
center: Vector3
verticalAlignment: number
horizontalAlignment: number
depthAlignment: number
}
```
# Billboard
::scene-controls-wrapper
:abstractions-billboard
::
Adds a `THREE.Group` that always faces the camera.
## Usage
```vue {2,10,14}
```
## Props
| Prop | Description | Default |
| :----------- | :------------------------------------------------------------------------------- | ------- |
| `autoUpdate` | Whether the `` should face the camera automatically on every frame. | `true` |
| `lockX` | Whether to lock the x-axis. | `false` |
| `lockY` | Whether to lock the y-axis. | `false` |
| `lockZ` | Whether to lock the z-axis. | `false` |
# Camera Shake
::scene-controls-wrapper
:abstractions-camera-shake
::
`` is a component that adds **natural**, *noise-driven motion* to the **active camera**.
It offers **per-axis control**, **adjustable intensity**, and *optional decay* โ perfect for *handheld feel*, *footsteps*, *impacts*, or *engine rumble* โ and is based on the [Drei `CameraShake` component](https://drei.docs.pmnd.rs/staging/camera-shake#camerashake){rel=""nofollow""}.
## Usage
```vue {2,11,16}
```
::prose-note
`` is fully compatible with **``**.
To ensure it works *as expected*, make sure to add the **`make-default`** prop:
```vue
```
::
## Props
| Prop | Description | Default |
| ---------------- | --------------------------------------------------- | ------- |
| `intensity` | The intensity of the shake (0โ1). | `1` |
| `decay` | If `true`, intensity decays over time. | `false` |
| `decayRate` | How fast intensity changes when `decay` is enabled. | `0.65` |
| `maxYaw` | Maximum yaw angle in radians. | `0.01` |
| `maxPitch` | Maximum pitch angle in radians. | `0.01` |
| `maxRoll` | Maximum roll angle in radians. | `0.01` |
| `yawFrequency` | Frequency of yaw oscillation. | `0.1` |
| `pitchFrequency` | Frequency of pitch oscillation. | `0.1` |
| `rollFrequency` | Frequency of roll oscillation. | `0.1` |
# Decal
`` projects a flat texture onto the surface of a parent mesh,
conforming to its geometry. Multiple decals can stack on the same mesh
with explicit z-layering, the JSON layout round-trips losslessly, and
the entry-by-entry shape stays human-readable.
- ๐จ Drop-in **editor UI** via `` โ placement, rotate / scale / snap, tint, flip, layers, undo / redo, import / export.
- ๐ **Programmatic API** via [`useDecalEditor()`](https://cientos.tresjs.org/#programmatic-api-usedecaleditor) for custom panels and automation.
- ๐ผ๏ธ **Texture palette** โ pass an array of `Texture` to `:map`.
- ๐งฉ **Custom material** โ override the default via the slot.
- ๐พ **Lossless JSON** โ `v-model:data` round-trips to plain JSON.
- โก **BVH-accelerated** โ auto-detected via [`useBVH`](https://cientos.tresjs.org/api/debug-performance/use-bvh); 10โ100ร faster on dense meshes.
- ๐ **Per-mesh stacking** โ `zIndex` with automatic polygon-offset.
::scene-wrapper
:abstractions-decal
::
## Usage
The minimal setup is a `` placed as a child of any ``,
with a JSON list of stamped decals bound via `v-model:data` and one or
more textures via `:map`.
```vue
```
::prose-note
The `v-model:data` array is the **single source of truth** โ every
decal you can see lives in it. It serializes to plain JSON so you can
save / load it from a backend, localStorage, or a `.json` file.
::
## Multiple textures (palette)
Pass an array to `:map` to give users a palette of textures to pick
from. The array returned by [`useTextures`](https://cientos.tresjs.org/api/loaders/use-textures)
plugs in directly:
```vue
```
Each entry references its texture by `name` โ `` auto-fills
`texture.name` from the URL filename when missing, so JSON `map`
fields round-trip cleanly.
## Custom material
The default material is `MeshBasicMaterial`. Override it via the slot
to plug in any Three.js material โ `MeshStandardMaterial`,
`MeshPhysicalMaterial`, or a custom shader.
```vue
```
::prose-note
Keep `transparent: true` and `polygonOffset: true` on any custom
material, otherwise stacking and alpha handling won't work as expected.
Color / opacity tint from the editor only applies to materials
exposing `.color` and `.opacity` (`MeshBasicMaterial`,
`MeshStandardMaterial`, โฆ) โ bespoke shader materials are skipped
silently.
::
## Stacking decals (z-layering)
Each decal has a `zIndex` controlling its draw order on the parent
mesh. Higher = on top. The component handles z-fighting via
`polygonOffset` automatically โ but if you stack many decals near
parallel surfaces and still see flicker, raise `layerGap`.
::scene-wrapper
:abstractions-decal-stacking
::
```vue
```
zIndex stacks are **per-mesh** โ two decals on different meshes never
compete for the same layer slot.
## Editable mode + ``
Add the `editable` prop to mount the interactive editor, then pair it
with `` โ a full in-canvas editor that ships as a drop-in
HTML overlay sitting **outside** ``.
::prose-warning
`` needs its stylesheet โ import it **once** at your app
entry. `` itself is style-less, so this is only needed when you
mount ``.
```ts
// Vite / Vue โ in main.ts
import '@tresjs/cientos/styles.css'
```
```ts
// Nuxt โ in nuxt.config.ts
export default defineNuxtConfig({
css: ['@tresjs/cientos/styles.css'],
})
```
::
::scene-wrapper
:abstractions-decal-editable
::
Three panels: a floating **handle** anchored to the editing decal, a
bottom **dock** (texture picker + edit tools), a right-side **layer
panel**.
- **Floating handle** (rotate + scale + snap + live `scale% ยท rotationยฐ ยท L` badge)
- **Color tint & opacity**
- **Mirror** (flip X / flip Y)
- **Layer controls** (`L+` / `L-`)
- **Visibility toggle**
- **Per-row remove**
- **Layer panel** (mesh-grouped, drag-to-reorder)
- **Texture picker** (drag or click-to-arm)
- **Mode badge** (placing / editing status)
- **Undo / Redo** buttons
- **Import / Export** buttons
```vue
```
### How the wiring works
- `v-model:data="layout.cube"` โ each `` owns one slice of the
layout object. The slice's key matches the parent mesh's `name`.
- `ref="decalRef"` โ grab a reference to any `` in the canvas;
the session is canvas-shared so it doesn't matter which.
- `session = decalRef.value?.editor` โ the editor session powers
``. Pass it through.
- `:data="layout"` on `` โ the full mesh-keyed layout, so
the overlay can render the layer panel and route imports back to each
Decal by name.
::prose-note
The overlay is full-viewport (`position: fixed; inset: 0`) by default.
When embedding inside a bounded stage (docs, modal, sidebar preview),
pass `contained` so the overlay positions itself absolutely against
the nearest positioned ancestor instead.
::
```vue
...
```
## Import / Export
The Export button in the dock auto-downloads the current layout as
`decal-layout-YYYY-MM-DD.json`. The Import button opens a file picker;
the loaded JSON is sanitised (unknown mesh keys and unknown texture
names are dropped with a warning) and routed back through each
`` automatically โ no extra host code needed.
```vue
```
## Targeting a loaded model (`.glb`)
A `` can be a **direct child of ``**. Auto-resolution
walks one step up the scene graph and only accepts a `Mesh` โ so the
behaviour depends on what the `` wraps.
### When `:object` is a `Mesh`
The decal auto-resolves the wrapped mesh as its target. This is the
simplest option for a single-mesh asset:
```vue
```
::prose-note
The resolved parent is the ``'s retargeting proxy rather than
the raw object. This is transparent in practice โ geometry, `matrixWorld`
and raycasting all forward to the wrapped object โ so the decal projects
and follows transforms correctly.
::
### When `:object` is a `Group`
A named node in a `.glb` is often a `Group` containing several child
meshes (e.g. a ceramic body + a metallic interior). Auto-resolution
returns `null` in that case and the decal silently does nothing โ pass
the actual target child via `:mesh`:
```vue
```
### Targeting an extracted sub-mesh
Alternatively, **wrap a `` around an extracted sub-mesh**. Reach
for this when you need to target one named sub-mesh of a larger model (and
keep its material): use
[`useGraph`](https://docs.tresjs.org/api/composables.html#usegraph){rel=""nofollow""} to
pull the sub-mesh, then build a regular `` around its
`:geometry`:
```vue
```
The mesh's `geometry` and `material` come from the loaded model; the
`` lives inside a regular `` with a clean scene-graph
parent.
::prose-warning
A saved decal's `position` is stored in **world space**, so it is
re-projected onto the parent using the parent's transform **at load
time**. A persisted layout therefore only round-trips if the parent sits
at the same transform it had when the decal was authored. Parents under a
continuously- or randomly-animated wrapper (e.g. ``, which starts
at a random phase each reload) move out from under the saved point, so the
projection clips to nothing and the decal vanishes. Author and persist
decals on parents whose transform is deterministic at load time, or apply
the animation only after the layout has mounted.
::
## JSON schema
Each entry in the `data` array follows the `DecalJsonEntry` shape; the
layout passed to `` groups these by mesh name as
`DecalLayout = Record`.
Full schema
```ts
interface DecalJsonEntry {
id: string // stable UUID
position: [number, number, number] // target-mesh local space (raycast hit, baked into the parent's frame)
orientation: [number, number, number] // Euler XYZ
size: [number, number, number] // extents along X/Y; Z = projection depth
zIndex: number // per-mesh layer order, โฅ 0
map: string | null // matches a texture's .name
flipX?: boolean // omitted when false
flipY?: boolean // omitted when false
color?: string // hex (e.g. '#ff6b35'), omitted when no tint
opacity?: number // 0..1, omitted when 1
visible?: boolean // omitted when true; false hides the decal
}
type DecalLayout = Record
// { sphere: [...], cube: [...] }
```
## `` props
| Prop | Description | Default |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| **data** | Two-way list of stamped decals (use with `v-model:data`). | `[]` |
| **map** | A single `Texture` or array of `Texture[]`. With multiple, the editor lets the user cycle through them as a palette. | `null` |
| **mesh** | Optional explicit target mesh (`Mesh` or `ShallowRef`). When omitted, the scene-graph parent of `` is auto-resolved via a hidden anchor ``. The decal mesh is imperatively parented to the target so it follows the target's runtime `position` / `rotation` / `scale` via the scene-graph hierarchy. | `null` |
| **editable** | When `true`, mounts the interactive editor (raycast, hover, click-to-place, drag-from-thumbnail). Required for `` interactions to work on this Decal. | `false` |
| **baseSize** | Reference size used to derive each decal's size from the texture aspect ratio. | `1` |
| **baseOffset** | Distance along the surface normal (parent units) to avoid z-fighting between the decal and the host mesh. | `0.01` |
| **layerGap** | Extra offset added per `zIndex` step on top of `baseOffset`. Increase if stacked decals still flicker. | `0.001` |
| **cullThreshold** | Drops projected triangles whose face normal makes an angle steeper than `acos(threshold)` with the projector. Mitigates [#21187](https://github.com/mrdoob/three.js/issues/21187){rel=""nofollow""}. Pass `0` to disable. | `0.2` |
| **edgeColor** | Color of the edge outline drawn around a decal while it is hovered (pointer or layer panel) in editable mode. | `#0000ff` |
## `` events
| Event | Payload | Description |
| ------------- | ------------------------------------------ | ------------------------------------------------------------------------- |
| `update:data` | `DecalJsonEntry[]` | v-model partner โ fires whenever the JSON list changes. |
| `add` | `DecalEntry` | A new decal has been committed (create mode โ confirm). |
| `update` | `DecalEntry` | An existing decal has been committed (update mode โ confirm). |
| `delete` | `DecalEntry` | A decal has been removed (delete button or `Del` / `Backspace`). |
| `select` | `DecalEntry` | Edition began on `entry` (panel click, 3D click, or programmatic). |
| `cancel` | โ | Edition was aborted without commit (`Esc`, click-outside in create mode). |
| `decalClick` | `{ entry: DecalEntry, event: MouseEvent }` | Fires on click of any stamped decal, even when `editable` is `false`. |
## `` exposed (via `ref`)
The template ref resolves to `DecalImperativeApi` โ import the type for
full autocompletion:
```ts
import type { DecalImperativeApi } from '@tresjs/cientos'
const decalRef = ref(null)
```
| Property | Type | Description |
| --------------- | ------------------------- | -------------------------------------------------------------------------------------- |
| `editor` | `DecalEditorSession` | The canvas-shared editor session. Pass it to ``. |
| `beginEditById` | `(id: string) => boolean` | Programmatically start editing a specific decal. Returns `false` if the id is unknown. |
| `commit` | `() => void` | Commit the in-flight edit (same as `Enter`). |
| `cancel` | `() => void` | Abort the in-flight edit (same as `Esc`). |
| `remove` | `() => void` | Delete the currently edited decal (same as `Del`). |
## `` props
| Prop | Description | Default |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| **session** | `DecalEditorSession | null` โ obtained from any `` ref via `decalRef.value?.editor`. Mandatory for the overlay to wire up the interactive logic. | `null` |
| **data** | Mesh-name-keyed map of decal slices โ `{ sphere: [...], cube: [...] }`. Each key matches a `` whose child `` owns the slice. | `{}` |
| **textures** | The full texture palette shown in the dock's picker. | `[]` |
| **theme** | `'light'` or `'dark'` โ overlay theme tokens. | `'light'` |
| **snapAngle** | Rotation step (degrees) applied when the snap toggle is on. Snap-tick ring on the handle adapts automatically. | `15` |
| **exportFilename** | Filename for the built-in JSON download. When omitted, defaults to `decal-layout-YYYY-MM-DD.json`. Pass `null` to skip the auto-download (the `@export` event still fires). | `decal-layout-YYYY-MM-DD.json` |
| **contained** | Scope the overlay to the nearest positioned ancestor instead of pinning it to the viewport. Useful for embedding the editor inside a docs page or a bounded host stage. | `false` |
## `` events
| Event | Payload | Description |
| -------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `export` | `DecalLayout` | Fires after the user clicks Export. The download (if enabled) has already been triggered โ use this for side effects (POST, analyticsโฆ). |
| `import` | `DecalLayout` | Fires after the user picks a JSON file. The layout has been sanitised (unknown keys dropped) and already applied to the bound Decals. |
## Caveats
- โจ The overlay sits at `position: fixed; inset: 0; pointer-events: none` with
individual panels opting back in. It sits **above** the canvas by default
(`z-index: 1000000`) โ adjust via host CSS if needed.
- ๐จ `` ships its own theme in a global stylesheet under the
`.cientos-decal-ui` namespace, so host styles aren't affected. The CSS
variables (`--accent`, `--dock-bg`, etc.) can be overridden by targeting
the namespace.
- ๐ถ Decals are **per-canvas** โ if you have multiple `` in your
app, each one has its own independent session. Pair each ``
with the right `session` (from one of the Decals inside that canvas).
- ๐งฉ The parent mesh resolution defaults to the scene-graph parent. If your
setup needs a different target (e.g. a mesh referenced from outside the
Decal's parent slot), pass `:mesh="meshRef"`.
## Limitations
::prose-note
Decal vertices are baked into the **target mesh's local space** at
build time (the decal mesh is imperatively re-parented to the target,
so `position` / `rotation` / `scale` on the parent are followed via
the scene graph โ no rebuild needed).
Runtime deformations that change vertex positions outside of a
transform are **not** followed:
- **`SkinnedMesh`** skinning is not applied โ the decal stays in rest
pose. See [three.js#7926](https://github.com/mrdoob/three.js/issues/7926){rel=""nofollow""}.
- **`morphAttributes`** on the parent are ignored.
- Direct mutations of the parent's `geometry.attributes.position`
(e.g. CPU wave displacement, GPGPU) โ the projection is baked once.
- Decals near silhouettes can wrap around onto opposite faces (see
[three.js#21187](https://github.com/mrdoob/three.js/issues/21187){rel=""nofollow""}) โ
mitigated by the `cullThreshold` prop, default `0.2`.
`` warns once per parent mesh when it detects these conditions.
::
## Keyboard shortcuts
| Shortcut | Action |
| ----------------- | ------------------------------------------------ |
| `Enter` | Confirm the in-flight edit |
| `Esc` | Cancel (revert updates, drop pending placements) |
| `Del` / `โซ` | Delete the edited decal (or cancel a create) |
| `โZ` / `Ctrl+Z` | Undo |
| `โงโZ` / `Ctrl+โงZ` | Redo |
| Click outside | Auto-commit an in-flight update; cancel a create |
## Programmatic API (`useDecalEditor`)
Skip `` entirely or augment it with custom panels โ
`useDecalEditor()` returns the same canvas-scoped session every Decal
shares. Call it from any component inside `` (after at
least one `` has mounted).
```ts
import { useDecalEditor } from '@tresjs/cientos'
const session = useDecalEditor()
```
The session exposes reactive state (`editingEntry`, `editingMode`,
`canUndo`, `canRedo`, โฆ), by-id mutators (`beginEditById`,
`setZIndexById`, `setVisibilityById`, `removeById`), batched updates
(`setMeshData`), commit / delete / cancel listeners, undo / redo, and
a `registerDecalEntry` hook for external entries. Helper utilities
(`ensureTextureNames`, `getTextureName`, `getTextureAspect`,
`invalidateDecalGeometry`) are exported alongside.
Full API reference
### Reactive state
```ts
session.editingEntry // ShallowRef
session.editingMode // Ref<'create' | 'update' | null>
session.lockedMeshUuid // Ref
session.hoveredEntry // ShallowRef
session.canUndo // Ref
session.canRedo // Ref
```
### Mutating decals by id
```ts
session.beginEditById(id) // start editing a placed decal
session.setZIndexById(id, newZ) // reorder one decal
session.setVisibilityById(id, false) // hide / show
session.removeById(id) // delete
```
When the targeted id matches the **currently editing** entry, mutations
land on the in-flight buffer (committed on `Enter`, reverted on `Esc`).
Otherwise they update `data` immediately and record history.
### Batched mesh updates
```ts
session.setMeshData(meshName, nextEntries, { recordHistory: true })
```
A single emit avoids the stale-snapshot race that hits multiple
back-to-back `setZIndexById` calls in the same tick.
### Listening to commits
```ts
const off = session.onCommit((entry, mode) => {
console.log(mode, entry) // mode: 'create' | 'update'
})
session.onDelete((entry) => { /* โฆ */ })
session.onCancel(() => { /* โฆ */ })
// All return an unsubscribe function:
onBeforeUnmount(off)
```
### Undo / redo
```ts
session.canUndo.value // Ref
session.undo() // returns true if something was undone
session.redo()
```
History is per-canvas, capped at 100 operations, disabled mid-edit.
### Power user โ external entries
Plug a decal-like object that lives outside a `` (custom data
source, server snapshot, fake entry for tests) by registering a
`DecalEntryActions` bundle so the `*ById` session methods route to it:
```ts
import type { DecalEntryActions } from '@tresjs/cientos'
session.registerDecalEntry('decal-7', {
beginEdit: () => { /* โฆ */ },
setZIndex: (newZ) => { /* โฆ */ },
setVisibility: (visible) => { /* โฆ */ },
remove: () => { /* โฆ */ },
} satisfies DecalEntryActions)
onBeforeUnmount(() => session.unregisterDecalEntry('decal-7'))
```
### Helper utilities
| Helper | Use |
| ------------------------------- | ------------------------------------------------------------------------------- |
| `ensureTextureNames(textures)` | Back-fills `texture.name` from `userData.name` or the filename in `image.src`. |
| `getTextureName(texture)` | Single-texture variant โ returns a stable name or `null`. |
| `getTextureAspect(texture)` | `{ x, y }` aspect ratio for custom-sized decals. |
| `invalidateDecalGeometry(mesh)` | Force a rebuild on the next frame โ call when the parent mesh moved or swapped. |
# Edges
::scene-controls-wrapper
:abstractions-edges
::
The `cientos` package provides an abstraction of [EdgesGeometry](https://threejs.org/docs/#api/en/geometries/EdgesGeometry){rel=""nofollow""} from Three.js, `` is specifically designed for rendering visible edges of objects in a scene graph. This enhances the visual quality by highlighting contours and providing a stylized appearance which contributes to the artistic aspect of 3D visualizations.
## Usage
```vue {3,12}
```
## Props
`` is based on [LineSegments](https://threejs.org/docs/#api/en/objects/LineSegments){rel=""nofollow""} & [Line](https://threejs.org/docs/#api/en/objects/Line){rel=""nofollow""} and supports all of its props.
| Prop | Description | Default |
| :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- |
| **color** | `THREE.Color` โ Color of the edges. :br More informations : [TresColor](https://docs.tresjs.org/api/instances-arguments-and-props.html#colors){rel=""nofollow""} โ [THREE.Color](https://threejs.org/docs/#api/en/math/Color){rel=""nofollow""} | `#ff0000` |
| **threshold** | `number` โ An edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value | `1` |
# Fit
::scene-wrapper
:abstractions-fit
::
`` uniformly scales and positions its children as a group. By default, it fits its children into a 1 ร 1 ร 1 box at the world origin.
Alternatively, the children can be fit into a `Box3` or an `Object3D`.
Or the children can simply be resized. With `` the children are scaled relative to the center of their calculated bounding box.
## Usage
```vue {2,20,27}
```
## Props
| Name | Description |
| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **into** | If `into` is:* omitted or explicitly `undefined`: position/scale children to fit into a 1 ร 1 ร 1 `Box3` at world origin.
* `null`: turn off ``; reset scale/position of children.
* `number`: convert argument to `Vector3(number, number, number)`.
* `[number, number, number]`: convert argument to `Vector3`.
* `Vector3`: position/scale children to fit inside a `Box3` of size `Vector3` at target objects' cumulative center.
* `Box3`: position/scale children to fit inside `Box3`.
* `Object3D`: position/scale children to fit inside calculated `Box3`. [See `THREE.Box3.setFromObject`](https://threejs.org/docs/#api/en/math/Box3.setFromObject){rel=""nofollow""}. `` must not contain the `Object3D` and vice-versa.:br default: :br`new Box3(new Vector3(-0.5, -0.5, -0.5), new Vector3(0.5, 0.5, 0.5))` |
| **precise** | [See `precise` argument in `THREE.Box3.setFromObject`](https://threejs.org/docs/index.html?q=box3#api/en/math/Box3.setFromObject){rel=""nofollow""}:br:br default: :br`false` |
# Abstractions
:api-list{list-name="abstraction-list"}
# Instances
::scene-controls-wrapper
:abstractions-instances
::
Rendering the same mesh many times is one drawcall per copy, and drawcalls are what a scene runs
out of first. `` owns a single `THREE.InstancedMesh` and `` is a
placeholder that registers itself with it, so a `v-for` of a thousand nodes costs **one** drawcall.
An `` behaves like any other node in the graph: give it `position`, nest it under a
group, animate that group, toggle it with `v-if`, listen for `@click` on one of them.
## Usage
```vue {3,14,16-21}
```
::prose-note
The `geometry` and `material` are yours: `` never disposes them.
::
## Per-instance color
`` takes a `color` prop, written into the batch's `instanceColor` buffer. The buffer is
only allocated once at least one instance asks for a color, so an uncolored batch pays nothing.
```vue
```
## Pointer events
Each placeholder raycasts against the batch's geometry at its own transform, so pointer events land
on the single instance you clicked, not on the whole batch.
```vue
```
## Hiding instances
Two ways, and they differ in what they cost:
- `:visible="false"` keeps the instance registered but drops it from the batch for that frame.
Use it for something that toggles often.
- `v-if` unmounts the placeholder and unregisters it. Use it when the node is really gone.
Either way the remaining instances are packed densely, so hidden ones cost nothing on the GPU.
## Nesting and transforms
Instances read their world matrix, so parent transforms work exactly as you would expect:
```vue
```
## Animating instances
Anything that moves an instance's node moves it in the batch, because the batch re-reads world
matrices every frame. An `AnimationMixer` included: a mixer resolves its tracks by `Object3D`
name, and an `` takes a `name` like any other node, so a clip can drive one directly.
```vue
```
::prose-note
Inside a ``, `name` and `batch` are different things: `batch` picks which
`InstancedMesh` to join, `name` is what this node is called. `tres gltf --instance` emits both,
because a batch is keyed after its first mesh and every copy in it shares that key.
::
A track that finds no node is not silent: three logs
`THREE.PropertyBinding: No target node found for track: .position.` once for it.
## Limit and growth
`limit` is the initial buffer allocation, not a cap. If more instances register than it allows, the
batch reallocates its buffers (doubling), keeps every instance, and warns once in dev telling you
which `limit` would have avoided the reallocation.
```vue
```
Set it close to your real maximum when you know it: reallocating mid-scene is avoidable work.
## Why every instance shows up in the scene graph
Open the devtools on a batch of 500 and you will see 500 nodes. That is expected, not a leak.
Each `` is a real `Object3D` in the graph. That is precisely what buys you the ergonomics:
`position` is just a transform, nesting under a group works because the group is its parent, `v-if`
works because unmounting a node unregisters it, and `@click` works because there is a node to hit.
The batch reads each node's world matrix every frame and packs it into the instance buffer.
What those nodes do **not** do is render. They carry no geometry and never enter the render list, so
500 of them still cost one drawcall. What you are seeing in the graph is bookkeeping, not draw work.
The costs that are real:
| | Cost |
| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Per frame | One world-matrix update and one matrix multiply per instance. |
| On pointer move | A raycast per instance, but only for instances that have a pointer handler (or inherit one from an ancestor). A scatter with no handlers costs nothing. |
| Memory | One bare `Object3D` per instance. |
::prose-note
If you have tens of thousands of instances that never move, never toggle and never need picking, a
`TresInstancedMesh` whose `instanceMatrix` you fill yourself will always be cheaper. ``
trades that per-node overhead for being able to write instances as ordinary Vue nodes.
::
## Props
### Instances
| Prop | Description | Default |
| :--------- | :---------------------------------------------------------------- | ----------- |
| `geometry` | Geometry shared by every instance. Not disposed by the component. | *required* |
| `material` | Material shared by every instance. Not disposed by the component. | *required* |
| `limit` | Initial buffer allocation. Grows automatically when exceeded. | `1000` |
| `batch` | Key this batch registers under with an ancestor ``. | `undefined` |
| `name` | Name for the `InstancedMesh` itself. | `undefined` |
Exposes the underlying `THREE.InstancedMesh` through `instance`.
### Instance
| Prop | Description | Default |
| :-------- | :--------------------------------------------------------------------------------------- | ----------- |
| `batch` | Batch to join, by its key in ``. Omit for the nearest ``. | `undefined` |
| `name` | Name for this instance's node, so a mixer or `getObjectByName` can find it. | `undefined` |
| `color` | Per-instance color, written into `instanceColor`. | `undefined` |
| `visible` | `false` drops the instance from the batch without unregistering it. | `true` |
Transform props (`position`, `rotation`, `scale`, โฆ) and pointer events behave like any other node.
::read-more{to="https://cientos.tresjs.org/api/abstractions/merged"}
Instancing several meshes at once, for example every node of a glTF model, is what `` is for.
::
# Levioso (Float)
::scene-controls-wrapper
:abstractions-levioso
::

The `cientos` package provides a `` wrapper that makes its content โฆ float, just like Magic ๐ชโจ
## Usage
```vue {3,11,13}
```
## Props
| Prop | Description | Default |
| :--------------- | :--------------------------------------------------- | ------------- |
| `speed` | Floating speed, higher it rocks more ๐ค. | `1` |
| `rotationFactor` | Factor for Euler rotation. | `1` |
| `floatFactor` | Factor for Up/down movement. | `1` |
| `range` | Range of y-axis values the object will float within. | `[-0.1, 0.1]` |
# Mask
::scene-controls-wrapper
:abstractions-mask
::
`` uses the stencil buffer to cut out areas of the screen.
::prose-warning
To use `` you *must* add `:stencil="true"` to your ``.
`` relies on the [`stencil buffer`](https://threejs.org/docs/#api/en/renderers/WebGLRenderer){rel=""nofollow""}. In recent versions of THREE.js, by default, the stencil buffer is not created.
::
## Usage
```vue {2,16-19}
```
## Props
| Prop | Description | Default |
| :--------------- | :----------------------------------------------------------------------------------------------------------- | ------- |
| **`id`** | Id of the stencil buffer to use. Each mask must have a `number` id. Multiple masks can refer to the same id. | |
| **`colorWrite`** | Whether the colors of the mask's own material will leak through. | `false` |
| **`depthWrite`** | Whether the depth of the mask's own material will leak through. | `false` |
## useMask
Composable that returns the stencil configuration to apply a mask to a material. Use it with `v-bind` on materials that should be affected by the mask.
**Parameters:**
- `id` - The mask id to use (number or Ref)
- `inverse` - Whether to invert the mask (boolean or Ref), defaults to `false`
```vue
```
# Merged
::scene-controls-wrapper
:abstractions-merged
::
`` takes a `{ name: mesh }` map and builds one instanced batch per entry. Any descendant,
at any depth and in any component, joins one by key with ``.
That is what makes repeating a whole model cheap: a robot made of two meshes drawn 49 times is
**two** drawcalls, not 98.
## Usage
The model becomes its own component, and knows nothing about the batches beyond their names:
```vue [Robot.vue]
```
The provider hands over the meshes and renders as many copies as it likes:
```vue {12-18}
```
::prose-note
Nothing needs to be threaded through props or slots: the batches are provided, so an ``
finds the one it names no matter how deep it sits or how many components stand between them.
::
## Instancing a whole glTF
`useGLTF` gives you `nodes`, so instancing every repeated mesh of a model is a matter of picking the
ones worth batching:
```vue
```
The payoff is across models, not within one: twenty machines sharing two batches is two drawcalls.
## Opting a node out
An `` is all-or-nothing per node: it uses the batch's geometry and material. When one
node needs its own material, a different geometry, or its own shader, render a normal ``
instead of an ``. You trade one drawcall for full control over that node, and every
other node stays batched.
## Props
| Prop | Description | Default |
| :------- | :--------------------------------------------------------------------------------------------------------------- | ---------- |
| `meshes` | One batch per entry, keyed by what `` joins. | *required* |
| `limit` | Initial buffer allocation per batch. One batch per entry in `meshes`, so it defaults lower than ``. | `100` |
Exposes the named batch registry through `instances`.
::read-more{to="https://cientos.tresjs.org/api/abstractions/instances"}
Per-instance colors, pointer events, visibility and the `limit` growth behaviour are documented on ``.
::
# Outline
::scene-controls-wrapper
:abstractions-outline
::
`` creates an inverted-hull outline using its parent's geometry. Supported parents are `` and ``.
## Usage
```vue {3,15,20}
```
## Props
| Props | Description | Default |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| color | Outline color | `'black'` |
| screenspace | Whether line thickness is independent of zoom | `false` |
| opacity | Outline opacity | `1` |
| transparent | Outline transparency | `false` |
| thickness | Outline thickness | `0.05` |
| angle | Geometry crease angle (`0` is no crease). See [BufferGeometryUtils.toCreasedNormals](https://threejs.org/docs/#examples/en/utils/BufferGeometryUtils.toCreasedNormals){rel=""nofollow""} | `Math.PI` |
# Sampler
::scene-controls-wrapper
:abstractions-sampler
::
Declarative abstraction around MeshSurfaceSampler & InstancedMesh. It samples points from the passed mesh and transforms an InstancedMesh's matrix to distribute instances on the points.
## Usage
```vue {2,11-20}
```
## Props
| Props | Description |
| ------------ | ------------------------------------------------------------------ |
| mesh | **Mesh** Surface mesh from which to sample |
| count | **Number** Number of samples |
| instanceMesh | **InstanceMesh** InstanceMesh to scatter |
| weight | **String** A vertex attribute to be used as a weight when sampling |
| transform | **Function** A function that can be used as a custom sampling |
## useSurfaceSampler
A hook to obtain the result of the :sampler[as a buffer. Useful for driving anything other than InstancedMesh via the Sampler.]
```vue {2,10}
```
# ScreenSizer
::scene-wrapper
:abstractions-screen-sizer
::
Adds a `` wrapper that scales to "screen space". By default `1` THREE world unit will be translated to 1 screen pixel.
E.g. a BoxGeometry with a height, width, and depth of 100 each, will be scaled to 100 screen pixels in each dimension.
## Usage
```vue {3,10,15}
```
## Props
Inherits all props from `THREE.Object3D`.
# ScreenSpace
::scene-controls-wrapper
:abstractions-screen-space
::
`` wraps its children in a `` and positions them in front of the active camera at `:depth`.
Additionally, the `top`, `bottom`, `left`, `right` props can be used to position them similarly to CSS `position: absolute` property when using a `PerspectiveCamera` or an `OrtographicCamera`.
## Usage
```vue {2,11,16}
```
## Props
| Prop | Description | Default |
| :------- | :---------------------------------------------------------- | --------------------------------------- |
| `depth` | Distance from the camera | `-1` |
| `top` | Similar to CSS `top` property. Cannot be used with `bottom` | `0.5` (vertical center of the screen) |
| `bottom` | Similar to CSS `bottom` property. Cannot be used with `top` | |
| `left` | Similar to CSS `left` property. Cannot be used with `right` | `0.5` (horizontal center of the screen) |
| `right` | Similar to CSS `right` property. Cannot be used with `left` | |
# Camera Controls
::scene-controls-wrapper
:controls-camera-controls
::
[CameraControls](https://github.com/yomotsu/camera-controls){rel=""nofollow""} is a camera controller similar to [OrbitControls](https://cientos.tresjs.org/api/controls/orbit-controls) yet supports smooth transitions and more features.
However, it is thirty party library for ThreeJS. So to use it you would need to install and import using [npm](https://www.npmjs.com/package/camera-controls){rel=""nofollow""}.
## Usage
```vue {7}
```
::prose-warning
Is really important that the Perspective camera is set first in the canvas. Otherwise might break.
::
## Props
Certainly! Here's the properties of the object in raw markdown table format:
| Prop | Description | Default |
| :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| **makeDefault** | Whether to make this the default controls. | `false` |
| **camera** | The camera to control. | `undefined` |
| **domElement** | The DOM element to listen to. | `undefined` |
| **minPolarAngle** | Minimum vertical angle in radians. | `0` |
| **maxPolarAngle** | Maximum vertical angle in radians. | `Math.PI` |
| **minAzimuthAngle** | Minimum horizontal angle in radians. | `-Infinity` |
| **maxAzimuthAngle** | Maximum horizontal angle in radians. | `Infinity` |
| **distance** | Current distance. | `camera.position.z` |
| **minDistance** | Minimum distance for dolly. PerspectiveCamera only. | `Number.EPSILON` |
| **maxDistance** | Maximum distance for dolly. PerspectiveCamera only. | `Infinity` |
| **infinityDolly** | `true` to enable Infinity Dolly for wheel and pinch. | `false` |
| **minZoom** | Minimum camera zoom. | `0.01` |
| **maxZoom** | Maximum camera zoom. | `Infinity` |
| **smoothTime** | Approximate time in seconds to reach the target. A smaller value will reach the target faster. | `0.25` |
| **draggingSmoothTime** | The smoothTime while dragging. | `0.125` |
| **maxSpeed** | Max transition speed in units per second. | `Infinity` |
| **azimuthRotateSpeed** | Speed of azimuth (horizontal) rotation. | `1.0` |
| **polarRotateSpeed** | Speed of polar (vertical) rotation. | `1.0` |
| **dollySpeed** | Speed of mouse-wheel dollying. | `1.0` |
| **dollyDragInverted** | `true` to invert direction when dollying or zooming via drag. | `false` |
| **truckSpeed** | Speed of drag for truck and pedestal. | `2.0` |
| **dollyToCursor** | `true` to enable Dolly-in to the mouse cursor coords. | `false` |
| **dragToOffset** | Whether to drag to offset. | `false` |
| **verticalDragToForward** | The same as `.screenSpacePanning` in Three.js's OrbitControls. | `false` |
| **boundaryFriction** | Friction ratio of the boundary. | `0.0` |
| **restThreshold** | Controls how soon the `rest` event fires as the camera slows. | `0.01` |
| **colliderMeshes** | An array of Meshes to collide with the camera. Be aware colliderMeshes may decrease performance. The collision test uses 4 raycasters from the camera since the near plane has 4 corners. | `[]` |
| **mouseButtons** | Configuration of actions on mouse input. | See [`User input config`](https://cientos.tresjs.org/#user-input-config) for details |
| **touches** | Configuration of actions on touch. | See [`User input config`](https://cientos.tresjs.org/#user-input-config) for details |
## User input config
You can easily override the default user input config by defining `mouseButtons` and/or `touches` props that correspond to [`camera-controls` settings](https://github.com/yomotsu/camera-controls?#user-input-config){rel=""nofollow""}. For ease of use, we're re-exporting the `CameraControls` class as `BaseCameraControls` which gives you access to the `ACTION` enum.
```vue
...
...
```
### Mouse buttons
| Button to assign | Options | Default |
| ----------------------- | -------------------------------------------------------------- | --------------------------------------------------------------- |
| `mouseButtons.left` | `ROTATE` \| `TRUCK` \| `OFFSET` \| `DOLLY` \| `ZOOM` \| `NONE` | `ROTATE` |
| `mouseButtons.right` | `ROTATE` \| `TRUCK` \| `OFFSET` \| `DOLLY` \| `ZOOM` \| `NONE` | `TRUCK` |
| `mouseButtons.wheel` ยน | `ROTATE` \| `TRUCK` \| `OFFSET` \| `DOLLY` \| `ZOOM` \| `NONE` | `DOLLY` for Perspective camera, `ZOOM` for Orthographic camera. |
| `mouseButtons.middle` ยฒ | `ROTATE` \| `TRUCK` \| `OFFSET` \| `DOLLY` \| `ZOOM` \| `NONE` | `DOLLY` |
1. Mouse wheel event for scroll "up/down", on mac "up/down/left/right".
2. Mouse wheel "button" click event.
### Touches
| Fingers to assign | Options | Default |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `touches.one` | `TOUCH_ROTATE` \| `TOUCH_TRUCK` \| `TOUCH_OFFSET` \| `DOLLY` \| `ZOOM` \| `NONE` | `TOUCH_ROTATE` |
| `touches.two` | `TOUCH_DOLLY_TRUCK` \| `TOUCH_DOLLY_OFFSET` \| `TOUCH_DOLLY_ROTATE` \| `TOUCH_ZOOM_TRUCK` \| `TOUCH_ZOOM_OFFSET` \| `TOUCH_ZOOM_ROTATE` \| `TOUCH_DOLLY` \| `TOUCH_ZOOM` \| `TOUCH_ROTATE` \| `TOUCH_TRUCK` \| `TOUCH_OFFSET` \| `NONE` | `TOUCH_DOLLY_TRUCK` for Perspective camera, `TOUCH_ZOOM_TRUCK` for Othographic camera. |
| `touches.three` | `TOUCH_DOLLY_TRUCK` \| `TOUCH_DOLLY_OFFSET` \| `TOUCH_DOLLY_ROTATE` \| `TOUCH_ZOOM_TRUCK` \| `TOUCH_ZOOM_OFFSET` \| `TOUCH_ZOOM_ROTATE` \| `TOUCH_ROTATE` \| `TOUCH_TRUCK` \| `TOUCH_OFFSET` \| `NONE` | `TOUCH_TRUCK` |
## Events
```vue
```
| Event | Description |
| :--------- | :-------------------------------------------- |
| **start** | Dispatched when the control starts to change. |
| **change** | Dispatched when the control changes. |
| **end** | Dispatched when the control ends to change. |
# Controls
:api-list{list-name="control-list"}
# Keyboard Controls
::scene-controls-wrapper
:controls-keyboard-controls
::
`` is a simple keyboard controller for the camera. The camera's movements are bound to:
| Keyboard | Action |
| :-------- | :------------ |
| `W` / `โ` | Move forward |
| `S` / `โ` | Move backward |
| `A` / `โ` | Move left |
| `D` / `โ` | Move right |
| `E` | Move up |
| `Q` | Move down |
::prose-note
`KeyboardControls` uses `PointerLockControls` under the hood. You can use [PointerLockControls props and events](https://cientos.tresjs.org/pointer-lock-controls#props).
::
## Usage
```vue {3,10}
```
::prose-warning
Is really important that the Perspective camera is set first in the canvas. Otherwise might break.
::
## Props
| Prop | Description | Default |
| :-------------- | :---------------------------------------------------------------------------------- | ----------- |
| **moveSpeed** | Speed movement. | 0.2 |
| **makeDefault** | If `true`, the controls will be set as the default controls for the scene. | `true` |
| **camera** | The camera to control. | `undefined` |
| **domElement** | The DOM element to listen to. | `undefined` |
| **selector** | Accept an id element as string. If set, the new element will be used as the trigger | `undefined` |
## Events
```vue
isActive(state)" />
```
| Event | Description |
| :--------- | :----------------------------------------------------------------- |
| **isLock** | Return `true` if "lock", `false` if "unlock" events are triggered. |
| **change** | Dispatched when the control changes. |
# Map Controls
::scene-controls-wrapper
:controls-map-controls
::
[MapControls](https://threejs.org/docs/index.html?q=controls#examples/en/controls/MapControls){rel=""nofollow""} similar to OrbitControls, this control is intended for transforming a camera over a map from bird's eye perspective, but uses a specific preset for mouse/touch interaction and disables screen space panning by default.
## Usage
```vue {7}
```
::prose-warning
It is really important that the perspective camera is set first in the canvas. Otherwise the scene might break.
::
## Props
| Prop | Description | Default |
| :--------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| **makeDefault** | If `true`, the controls will be set as the default controls for the scene. | `false` |
| **camera** | The camera to control. | `undefined` |
| **domElement** | The dom element to listen to. | `undefined` |
| **screenSpacePanning** | Defines how the camera's position is translated when panning. If `true`, the camera pans in screen space. Otherwise, the camera pans in the plane orthogonal to the camera's up direction. | `false` |
::prose-note
All the props of the orbit controls component apply here too.
::
# Orbit Controls
::scene-controls-wrapper
:controls-orbit-controls
::
[OrbitControls](https://threejs.org/docs/index.html?q=orbit#examples/en/controls/OrbitControls){rel=""nofollow""} is a camera controller that allows you to orbit around a target. It's a great way to explore your scene.
## Usage
```vue {7}
```
::prose-warning
Is really important that the Perspective camera is set first in the canvas. Otherwise might break.
::
## Props
| Prop | Description | Default |
| :--------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| **makeDefault** | If `true`, the controls will be set as the default controls for the scene. | `false` |
| **camera** | The camera to control. | `undefined` |
| **domElement** | The dom element to listen to. | `undefined` |
| **target** | The target to orbit around. | `undefined` |
| **enableDamping** | If `true`, the controls will use damping (inertia), which can be used to give a sense of weight to the controls. | `true` |
| **dampingFactor** | The damping inertia used if `.enableDamping` is set to true. | `0.05` |
| **autoRotate** | Set to true to automatically rotate around the target. | `false` |
| **autoRotateSpeed** | How fast to rotate around the target if `.autoRotate` is true. | `2` |
| **enablePan** | Whether to enable panning. | `true` |
| **keyPanSpeed** | How fast to pan the camera when the keyboard is used. Default is 7.0 pixels per keypress. | `7.0` |
| **keys** | This object contains references to the keycodes for controlling camera panning. Default is the 4 arrow keys. | `{ LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' }` |
| **maxAzimuthAngle** | How far you can orbit horizontally, upper limit. If set, the interval [min, max] must be a sub-interval of [- 2 PI, 2 PI], with ( max - min < 2 PI ). Default is Infinity. | `Infinity` |
| **minAzimuthAngle** | How far you can orbit horizontally, lower limit. If set, the interval [min, max] must be a sub-interval of [- 2 PI, 2 PI], with ( max - min < 2 PI ). Default is - Infinity. | `-Infinity` |
| **maxPolarAngle** | How far you can orbit vertically, upper limit. Range is 0 to Math.PI radians, and default is Math.PI. | `Math.PI` |
| **minPolarAngle** | How far you can orbit vertically, lower limit. Range is 0 to Math.PI radians, and default is 0. | `0` |
| **minDistance** | The minimum distance of the camera to the target. Default is 0. | `0` |
| **maxDistance** | The maximum distance of the camera to the target. Default is Infinity. | `Infinity` |
| **minZoom** | The minimum field of view angle, in radians. Default is 0. | `0` |
| **maxZoom** | The maximum field of view angle, in radians. ( OrthographicCamera only ). Default is Infinity. | `Infinity` |
| **touches** | This object contains references to the touch actions used by the controls. | `{ ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN }` |
| **mouseButtons** | This object contains references to the mouse actions used by the controls. LEFT: Rotate around the target, MIDDLE: Zoom the camera, RIGHT: Pan the camera. | `{ LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN }` |
| **enableZoom** | Whether to enable zooming. | `true` |
| **zoomSpeed** | How fast to zoom in and out. Default is 1. | `1` |
| **enableRotate** | Whether to enable rotating. | `true` |
| **rotateSpeed** | How fast to rotate around the target. Default is 1. | `1` |
| **screenSpacePanning** | Defines how the camera's position is translated when panning. If `true`, the camera pans in screen space. Otherwise, the camera pans in the plane orthogonal to the camera's up direction. | `true` |
## Events
```vue
```
| Event | Description |
| :--------- | :-------------------------------------------- |
| **start** | Dispatched when the control starts to change. |
| **change** | Dispatched when the control changes. |
| **end** | Dispatched when the control ends to change. |
# PointerLock Controls
::scene-controls-wrapper
:controls-pointer-lock-controls
::
[PointerLockControls](https://threejs.org/docs/index.html?q=pointe#examples/en/controls/PointerLockControls){rel=""nofollow""} is a camera controller that allows you to capture the mouse movement and simulate a first person camera. It is a perfect choice for first person 3D games.
::prose-warning
This control uses the [[](https://cientos.tresjs.org/api/controls/orbit-controls){style="color:#f7f7f7;text-decoration:none"}[`Pointer Lock API`](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API){rel=""nofollow""}]{style="background-color:#222;padding:0.25rem;border-radius:4px;"}, the same rules are applied, for example, you need to interact with the browser to "lock" or start the event.
In addition, you need to wait 1 second between canceling and re-starting the event
::
## Usage
```vue {3,10}
```
::prose-warning
Is really important that the Perspective camera is set first in the canvas. Otherwise might break.
::
## Props
| Prop | Description | Default |
| :-------------- | :---------------------------------------------------------------------------------------- | ----------- |
| **makeDefault** | If `true`, the controls will be set as the default controls for the scene. | `false` |
| **camera** | The camera to control. | `undefined` |
| **domElement** | The dom element to listen to. | `undefined` |
| **selector** | Accept an id element as string, if it is set, the new element will be used as the trigger | `undefined` |
## Events
```vue
isActive(state)" />
```
| Event | Description |
| :--------- | :--------------------------------------------------------------- |
| **isLock** | Return `true` if "lock", `false` if "unlock" events are trigger. |
| **change** | Dispatched when the control changes. |
# Transform Controls
The [Transform Controls](https://threejs.org/docs/#examples/en/controls/TransformControls){rel=""nofollow""} are a set of three gizmos that can be used to translate, rotate and scale objects in the scene. It adapts a similar interaction model of DCC tools like Blender
::scene-controls-wrapper
:controls-transform-controls
::
## Usage
To use the Transform Controls, simply add the `TransformControls` component to your scene. You can pass the `templateRef`of the instance you want to control as a prop.
```vue {7-8}
```
::prose-warning
If you are using other controls [[OrbitControls](https://cientos.tresjs.org/api/controls/orbit-controls){style="color:#f7f7f7;text-decoration:none"}]{style="background-color:#222;padding:0.25rem;border-radius:4px;"} they will interfere with each other when dragging. To avoid this, you can set the `makeDefault` prop to `true` on the **OrbitControls**.
::
## Modes
The Transform Controls can be used in three different modes:
### Translate

The default mode allows you to move the object around the scene.
```vue
```
### Rotate

The rotate mode allows you to rotate the object around the scene.
```vue
```
### Scale

The scale mode allows you to scale the object around the scene.
```vue
```
## Props
| Prop | Description | Default |
| :------------------ | :------------------------------------------------------------------------------------------------------------------------ | ----------- |
| **object** | The instance [Object3D](https://threejs.org/docs/index.html#api/en/core/Object3D){rel=""nofollow""} to control. | `null` |
| **mode** | The mode of the controls. Can be `translate`, `rotate` or `scale`. | `translate` |
| **enabled** | If `true`, the controls will be enabled. | `true` |
| **axis** | The axis to use for the controls. Can be `X`, `Y`, `Z`, `XY`, `YZ`, `XZ`, `XYZ`. | `XYZ` |
| **space** | The space to use for the controls. Can be `local` or `world`. | `local` |
| **size** | The size of the controls. | `1` |
| **translationSnap** | The distance to snap to when translating. (World units) | `null` |
| **rotationSnap** | The angle to snap to when rotating. (Radians) | `null` |
| **scaleSnap** | The scale to snap to when scaling. | `null` |
| **showX** | If `true`, the X-axis helper will be shown. | `true` |
| **showY** | If `true`, the Y-axis helper will be shown. | `true` |
| **showZ** | If `true`, the Z-axis helper will be shown. | `true` |
## Events
| Event | Description |
| :--------------- | :------------------------------------------------------------- |
| **dragging** | Fired when the user starts or stops dragging the controls. |
| **change** | Fired when the user changes the controls. |
| **mouseDown** | Fired when the user clicks on the controls. |
| **mouseUp** | Fired when the user releases the mouse button on the controls. |
| **objectChange** | Fired when the user changes the object. |
# useGLTF
::scene-wrapper
:loaders-gltf
::
A composable that allows you to easily load glb/glTF models into your **TresJS** scene.
## Usage
::code-group
```vue [TheModel.vue] {2,5}
```
```vue [app.vue]
```
::
An advantage of using `useGLTF` is that you can pass a `draco` prop to enable [Draco compression](https://threejs.org/docs/index.html?q=drac#examples/en/loaders/DRACOLoader){rel=""nofollow""} for the model. This will reduce the size of the model and improve performance.
```ts
import { useGLTF } from '@tresjs/cientos'
const { state, nodes, materials } = useGLTF('/models/AkuAku.gltf', { draco: true })
```
## Return Values
| Name | Type | Description |
| :------------ | ------------------------------------------------------- | ------------------------------------------- |
| **state** | `Ref` | The loaded GLTF, or `null` until it arrives |
| **nodes** | `ComputedRef` | All nodes in the scene, keyed by name |
| **materials** | `ComputedRef` | All materials in the scene, keyed by name |
| **isLoading** | `Ref` | Whether the model is currently loading |
| **error** | `Ref` | Whatever the loader threw, if anything |
| **progress** | `{ loaded: number, total: number, percentage: number }` | Progress of the current load |
| **load** | `(path: string) => void` | Load a different model into the same state |
| **execute** | `(delay?: number) => Promise` | Re-run the load |
## Options
| Name | Type | Default | Description |
| :-------------- | ---------- | ----------------------------------------------------------- | ---------------------------------------------------------------- |
| **draco** | `boolean` | `false` | Whether to enable Draco compression. |
| **decoderPath** | `string` | `'https://www.gstatic.com/draco/versioned/decoders/1.5.6/'` | Path to the Draco decoder. |
| **traverse** | `Function` | | A traverse function applied to the scene upon loading the model. |
## Accessing Nodes and Materials
The composable provides computed properties to easily access nodes and materials in your scene:
```ts
const { nodes, materials } = useGLTF('/model.glb')
// Access a specific node
const mesh = nodes.value.MeshName
// Access a specific material
const material = materials.value.MaterialName
```
This makes it easier to manipulate specific parts of your model or apply materials programmatically.
## Typing Nodes and Materials
The keys of `nodes` and `materials` come from the file, so by default both are a loose record and
`nodes.value.Body` is an `any`. Pass the shape of your model as generics to get them typed:
```ts
import type { Mesh, MeshStandardMaterial } from 'three'
import { useGLTF } from '@tresjs/cientos'
interface ModelNodes { Body: Mesh }
interface ModelMaterials { Skin: MeshStandardMaterial }
const { nodes, materials } = useGLTF('/models/robot.glb')
nodes.value.Body.geometry // Mesh, not any
```
::prose-note
These interfaces are a claim about the model, not a proof: nothing checks them against the file at
runtime. `tres gltf` reads them off the model and writes them for you, which is the only version
of this that cannot drift.
::
## Generating a Component Instead
For a whole model, writing an element per node by hand does not scale. The
[TresJS CLI](https://docs.tresjs.org/cli/gltf){rel=""nofollow""} generates that component from the model itself,
typed, with a slot for every node so your overrides survive the next export:
```bash
npx @tresjs/cli gltf public/models/robot.glb
# โ src/models/Robot.gen.vue
# 3 slots: Head, Body, Base
```
::read-more{to="https://cientos.tresjs.org/getting-started/loading-models"}
The three ways to load a model, and when to reach for each one.
::
# GLTFModel
::scene-wrapper
:loaders-gltf
::
The `GLTFModel` component is a wrapper around [`useGLTF`](https://cientos.tresjs.org/use-gltf) composable and accepts the same options as props.
## Usage
::code-group
```vue [TheModel.vue] {2,8}
```
```vue [app.vue]
```
::
## Model reference
The component exposes the loaded GLTF as `instance`, so a template ref gets you the parsed model:
```vue
```
## Props
| Prop | Description | Default |
| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------- |
| `path` | Path to the model file. **Required**. | `undefined` |
| `draco` | Enable [Draco compression](https://threejs.org/docs/index.html?q=drac#examples/en/loaders/DRACOLoader){rel=""nofollow""} for the model. | `false` |
| `decoderPath` | Path to a Draco decoder. | `'https://www.gstatic.com/draco/versioned/decoders/1.4.1/'` |
| `castShadow` | Apply `cast-shadow` to all meshes inside your model. | `false` |
| `receiveShadow` | Apply `receive-shadow` to all meshes inside your model. | `false` |
::prose-note
`path` is not reactive: the component reads it once on setup. Use
[`useGLTF`](https://cientos.tresjs.org/use-gltf) with a `ref` path if you need to swap models at runtime.
::
## When to reach for something else
`GLTFModel` renders the model's scene graph as-is, which means there is no element to hang a
material swap, a click handler or a `v-if` on. When you need that, use
[`useGLTF`](https://cientos.tresjs.org/use-gltf) to compose the parts yourself, or let the
[TresJS CLI](https://docs.tresjs.org/cli/gltf){rel=""nofollow""} generate a typed component with a slot per node:
```bash
npx @tresjs/cli gltf public/models/robot.glb
```
::read-more{to="https://cientos.tresjs.org/getting-started/loading-models"}
The three ways to load a model, and when to reach for each one.
::
# useFBX
::scene-wrapper
:loaders-fbx
::
A composable that allows you to easily load FBX models into your **TresJS** scene.
## Usage
::code-group
```vue [TheModel.vue] {2,6}
```
```vue [app.vue]
```
::
## Return Values
| Name | Type | Description |
| :------------ | --------------------- | ----------------------------------------------------- |
| **state** | `Group` | The loaded FBX model state |
| **nodes** | `object` | Computed object containing all nodes in the scene |
| **materials** | `object` | Computed object containing all materials in the scene |
| **isLoading** | `boolean` | Whether the model is currently loading |
| **execute** | `() => Promise` | Function to reload the model |
## Options
| Name | Type | Description |
| :----------- | ---------- | ---------------------------------------------------------------- |
| **traverse** | `Function` | A traverse function applied to the scene upon loading the model. |
## Accessing Nodes and Materials
The composable provides computed properties to easily access nodes and materials in your scene:
```ts
const { nodes, materials } = useFBX('/model.fbx')
// Access a specific node
const mesh = nodes.value.MeshName
// Access a specific material
const material = materials.value.MaterialName
```
This makes it easier to manipulate specific parts of your model or apply materials programmatically.
# FBXModel
::scene-wrapper
:loaders-fbx
::
The `FBXModel` component is a wrapper around [`useFBX`](https://cientos.tresjs.org/use-fbx) composable and accepts the same options as props.
## Usage
::code-group
```vue [TheModel.vue] {2,8}
```
```vue [app.vue]
```
::
## Model reference
You can access the model reference by passing a `ref` to the `FBXModel` component and then using it to get the object.
```vue
```
## Props
| Prop | Description | Default |
| :-------------- | :------------------------------------------------------ | ----------- |
| `path` | Path to the model file. | `undefined` |
| `castShadow` | Apply `cast-shadow` to all meshes inside your model. | `false` |
| `receiveShadow` | Apply `receive-shadow` to all meshes inside your model. | `false` |
# useTexture
::scene-wrapper
:loaders-use-texture
::
A composable that allows you to load textures using the [Three.js texture loader](https://threejs.org/docs/#api/en/loaders/TextureLoader){rel=""nofollow""} into your **TresJS** scene.
## Usage
```vue {2,4,10}
```
## Options
| Name | Type | Default | Description |
| :---------- | ---------------------- | ----------- | ------------------------------------------- |
| **path** | `string` | `undefined` | The path to the texture. |
| **manager** | `THREE.LoadingManager` | `undefined` | The loading manager to use for the texture. |
## Return Values
| Name | Type | Description |
| :---------- | :--------------- | :------------------------------ |
| `state` | `Texture | null` | The loaded texture |
| `isLoading` | `boolean` | Whether the texture is loading |
| `error` | `string | null` | Error message if loading failed |
## Component Usage
You can also use the `UseTexture` component directly in your template:
```vue {2,16-21,26}
```
# useTextures
::scene-wrapper
:loaders-use-textures
::
A composable that allows you to load multiple textures at once using the [Three.js texture loader](https://threejs.org/docs/#api/en/loaders/TextureLoader){rel=""nofollow""} into your **TresJS** scene.
## Usage
```vue {2,12,19-21}
```
## PBR Textures Example
Here's a more advanced example showing how to load and apply PBR (Physically Based Rendering) textures to a material:
```vue [PBRTextures.vue]
```
## API
### Parameters
| Name | Type | Default | Description |
| :-------- | ---------- | ----------- | ------------------------------- |
| **paths** | `string[]` | `undefined` | Array of paths to the textures. |
### Returns
| Name | Type | Description |
| :------------ | ---------------- | ----------------------------------------------- |
| **textures** | `Texture[]` | Array of loaded textures. |
| **isLoading** | `boolean` | Whether any textures are still loading. |
| **error** | `Error[] | null` | Array of errors if any occurred during loading. |
## Benefits
- **Simplified API**: Load multiple textures with a single function call
- **Consolidated loading state**: Track loading state for all textures at once
- **Unified error handling**: Collect and report errors from all texture loads
- **Type safety**: Proper TypeScript typing throughout the implementation
# useSVG
::scene-wrapper
:loaders-use-svg
::
Load and display SVG elements in your **TresJS** scene. This guide covers both the `useSVG` composable for advanced use cases and the `SVG` component for simple declarative rendering.
## useSVG Composable
The `useSVG` composable provides direct access to processed SVG layers, giving you full control over the resulting geometries and materials.
### Usage
::code-group
```vue [TheModel.vue] {2,5-8}
```
```vue [app.vue]
```
::
The `useSVG` composable provides direct access to processed SVG layers, giving you full control over how they're rendered. This is particularly useful when you need to:
- Manually control layer rendering
- Apply custom animations to individual layers
- Access geometry data programmatically
- Implement complex material logic
### SVG Data Sources
The composable accepts both file paths and inline SVG strings:
```ts
import { useSVG } from '@tresjs/cientos'
// From file
const { layers } = useSVG('/path/to/file.svg')
// Inline SVG string
const svgString = ``
const { layers } = useSVG(svgString)
```
### Return Values
| Name | Type | Description |
| :------------ | ------------ | ---------------------------------------------------- |
| **state** | `SVGResult` | The loaded SVG state from SVGLoader |
| **layers** | `SVGLayer[]` | Computed array of processed geometries and materials |
| **isLoading** | `boolean` | Whether the SVG is currently loading |
| **dispose** | `() => void` | Function to dispose of all geometries |
### Options
| Name | Type | Default | Description |
| :----------------- | --------------------------------------------- | --------------- | ----------------------------------------- |
| **skipStrokes** | `boolean` | `false` | Whether to skip rendering strokes |
| **skipFills** | `boolean` | `false` | Whether to skip rendering fills |
| **fillMaterial** | `MeshBasicMaterialParameters` | `{}` | Material properties for fill layers |
| **strokeMaterial** | `MeshBasicMaterialParameters` | `{}` | Material properties for stroke layers |
| **depth** | `'renderOrder' | 'flat' | 'offsetZ' | number` | `'renderOrder'` | How layers should be rendered in 3D space |
### Working with Layers
The `layers` computed property returns an array of processed SVG elements, each containing:
```ts
interface SVGLayer {
geometry: BufferGeometry // Three.js geometry for the layer
material: MeshBasicMaterialParameters // Material properties
isStroke: boolean // Whether this layer is a stroke or fill
}
```
#### Accessing Individual Layers
```vue {2,4}
```
### Depth Handling
The `depth` option controls how SVG layers are rendered in 3D space. It accepts the following values:
#### `'renderOrder'` (Default)
**Use case: Lone SVGs or applications that don't rely on stacked SVGs**
This is the default `depth` option.
This value sets the materials' `depthWrite` to `false` and increments the mesh layers [`renderOrder`](https://threejs.org/docs/?q=mesh#api/en/core/Object3D.renderOrder){rel=""nofollow""}. This makes the SVG layers render dependably regardless of perspective.
**Disadvantage**: Scene objects may render out of order.
SVG layers with higher [`renderOrder`](https://threejs.org/docs/?q=mesh#api/en/core/Object3D.renderOrder){rel=""nofollow""} will be rendered after (i.e., sometimes "on top of") other objects in the scene graph with a lower [`renderOrder`](https://threejs.org/docs/?q=mesh#api/en/core/Object3D.renderOrder){rel=""nofollow""}. Depending on their settings, those other objects may render behind the SVG, even if they are closer to the camera.
```ts
const { layers } = useSVG('/icon.svg', { depth: 'renderOrder' })
```
#### flat
**Use case: simple SVGs**
This option sets the materials [`depthWrite`](https://threejs.org/docs/?q=mesh#api/en/materials/Material.depthWrite){rel=""nofollow""} to `false`.
**Disadvantage**: SVG layers may render out of order.
Overlapping layers in an SVG may be drawn out of order, depending on viewing perspective.
```ts
const { layers } = useSVG('/icon.svg', { depth: 'flat' })
```
#### offsetZ
**Use case: unscaled SVGs seen from the front**
When this value is passed, the result is a 3D "stack" of mesh layers. A small space is added between each mesh layer in the "stack".
**Disadvantage**: "Bottom" of the "stack" is visible; layers may z-fight.
When seen from behind, the "bottom" of the mesh layer "stack" is visible. The space between the layers may be noticeable depending on viewing perspective and scale. The layers may [z-fight](https://en.wikipedia.org/wiki/Z-fighting){rel=""nofollow""}, particularly if the SVG is scaled down.
```ts
const { layers } = useSVG('/icon.svg', { depth: 'offsetZ' })
```
#### `number`
**Use case: SVGs seen from the front**
This is the same as `'offsetZ'` but allows you to specify how much space is added between each layer, in order to eliminate [z-fighting](https://en.wikipedia.org/wiki/Z-fighting){rel=""nofollow""}. For most use cases, this should be a value greater than 0.025 and less than 1.
**Disadvantage**: "Bottom" of the "stack" is visible.
```ts
const { layers } = useSVG('/icon.svg', { depth: 0.1 })
```
### Memory Management
Always dispose of geometries when the component unmounts:
```vue
```
### Advanced Usage
#### Conditional Layer Rendering
```vue
```
#### Material Customization per Layer
```vue
```
## UseSVG Component
For simple, declarative SVG rendering without the need for programmatic control, you can use the `UseSVG` component:
```vue
```
### Props
| Prop | Type | Description | Default |
| :------------------ | --------------------------------------------- | :----------------------------------------------------------------------------------------------------- | ------------- |
| **src** | `string` | Either a path to an SVG *or* an SVG string | |
| **skipStrokes** | `boolean` | If `true`, the SVG strokes will not be rendered. | `false` |
| **skipFills** | `boolean` | If `true`, the SVG fills will not be rendered. | `false` |
| **strokeMaterial** | `MeshBasicMaterialParameters` | Props to assign to the stroke materials of the resulting meshes. | `undefined` |
| **fillMaterial** | `MeshBasicMaterialParameters` | Props to assign to the fill materials of the resulting meshes. | `undefined` |
| **strokeMeshProps** | `TresOptions` | Props to assign to the resulting stroke meshes. | `undefined` |
| **fillMeshProps** | `TresOptions` | Props to assign to the resulting fill meshes. | `undefined` |
| **depth** | `'renderOrder' | 'flat' | 'offsetZ' | number` | Specify how SVG layers are to be rendered. ([See "Depth"](https://cientos.tresjs.org/#depth-handling)) | `renderOrder` |
## Troubleshooting
::alert{type="warning"}
This is not a general-purpose SVG renderer. Many SVG features are unsupported.
::
Here are some things to try if you run into problems:
### Error: "XML Parsing Error: unclosed token"
- In the SVG source, convert hex colors to rgb, e.g., convert `#ff0000` to `rgb(255, 0, 0)`.
### Parts of the SVG render in the wrong order or disappear, depending on viewing angle
- In your `useSVG` options, [change the `depth` option](https://cientos.tresjs.org/#depth-handling).
- In the SVG source, use `fill="none"` rather than `fill-opacity="0"`.
### Parts of the SVG ["z-fight"](https://en.wikipedia.org/wiki/Z-fighting){rel=""nofollow""}
- In your `useSVG` options, [change the `depth` option](https://cientos.tresjs.org/#depth-handling).
- Increase the distance between the SVG and other on-screen elements.
### The SVG is not visible
- If importing an SVG, make sure the path is correct โ check the console for loading errors.
- Try scaling the SVG down, e.g., wrap it in a `TresGroup` with `:scale="0.01"`.
- Try moving the SVG up (+y), e.g., `:position="[0,2,0]"`.
- Check that `layers.length > 0` before rendering.
### Performance issues with many layers
- Use the `dispose()` function when components unmount to clean up geometries.
- Consider using `skipStrokes` or `skipFills` to reduce the number of rendered layers.
- For complex SVGs with many layers, consider simplifying the SVG source.
## When to Use `useSVG` vs `SVG` Component
**Use `useSVG` when you need:**
- Direct access to individual SVG layers
- Custom rendering logic
- Layer-specific animations
- Programmatic geometry manipulation
- Advanced material customization per layer
**Use the `SVG` component when you need:**
- Simple, declarative SVG rendering
- Quick prototyping
- Standard SVG display without custom logic
- Less code and setup
# Loaders
:api-list{list-name="loaders-list"}
# useProgress
A composable to convenience wrap `THREE.DefaultLoadingManager` and returns the progress of the loading assets into the scene.
This comes handy to show an HTML loading bar or a spinner while the assets are being loaded.
## Usage
```ts
import { useProgress } from '@tresjs/cientos'
const { hasFinishLoading, progress, items } = await useProgress()
```
Then you can use the `progress` value to show a loading bar or a spinner:
```vue
Loading... {{ progress }} %
```
::alert{type="warning"}
This component use top level await. Please check the [Suspense API](https://vuejs.org/guide/built-ins/suspense.html#suspense){rel=""nofollow""} for more info
::
## Return Values
| Name | Type | Description |
| :----------------- | :-------- | :--------------------------------------- |
| `hasFinishLoading` | `boolean` | Whether all items have finished loading |
| `progress` | `number` | Loading progress as percentage (0-100) |
| `items` | `Array` | Array of loading items with their status |
::prose-warning
This component use top level await it needs to be wrapped on a [`Suspense`](https://vuejs.org/guide/built-ins/suspense.html#suspense){rel=""nofollow""}. Please check the [`Suspense API`](https://vuejs.org/guide/built-ins/suspense.html#suspense){rel=""nofollow""} for more info
::
# useVideoTexture
::scene-wrapper
:loaders-use-video-texture
::
A composable to easily use videos as textures in your meshes.
This composable is based on the Drei [useVideoTexture](https://github.com/pmndrs/drei/tree/master#usevideotexture){rel=""nofollow""}
## Usage
::code-group
```vue [app.vue]
```
```vue [TheVideoTexture.vue] {3,8,13}
```
::
## Props
| Prop | Description | Default |
| :------------ | :----------------------------------------------------------------------- | ---------------- |
| `src` | Path to the video. | `undefined` |
| `unsuspend` | Path to the model file. | `loadedmetadata` |
| `crossOrigin` | Whether to use CORS to fetch the related video. | `Anonymous` |
| `muted` | Whether to set the audio silenced. | true |
| `loop` | Automatically seek back to the start upon reaching the end of the video. | true |
| `start` | To play to the video once loaded or not. | true |
| `playsInline` | To be play the video inline or not. | true |
- Any other attribute for a `
```
::
## Usage
```vue {3,10-15}
```
## Props
| Prop | Description | Default |
| :--------------- | :----------------------------------------------------------------------------------------------------------------------------------------- | :------------ |
| **lighting** | Lighting setup. Options: `null | undefined | false | 'rembrandt' | 'portrait' | 'upfront' | 'soft' | { main: [x, y, z], fill: [x, y, z] }` | `'rembrandt'` |
| **shadows** | Controls the ground shadows. Options: `boolean | 'contact' | 'accumulative' | StageShadows` | `'contact'` |
| **adjustCamera** | Optionally wraps and thereby centers the models using ``, can also be a camera offset | `true` |
| **environment** | The default environment | `'city'` |
| **intensity** | Lighting intensity, `0` removes lights | `0.5` |
| **align** | To adjust alignment | `undefined` |
### StageShadows Type
When using custom shadow configuration, you can pass an object with the following properties:
| Prop | Description | Default |
| :------------- | :---------------------------------------- | :-------- |
| **type** | Shadow type: `'contact' | 'accumulative'` | - |
| **offset** | Shadow plane offset | `0` |
| **bias** | Shadow bias | `-0.0001` |
| **normalBias** | Shadow normal bias | `0` |
| **size** | Shadow map size | `1024` |
Additionally inherits all props from `AccumulativeShadowsProps`, `RandomizedLightsProps`, and `ContactShadowsProps`.
# Stars
::scene-controls-wrapper
:staging-stars
::
`` is a component that renders a stars in the sky of your scene. It is an abstraction that use Points, PointsMaterial and BufferGeometry to create a beautiful stars effect
## Usage
You can use `` component without passing any props,
```vue {3,9}
```
## Props
| Prop | Description | Default |
| :------------------ | :---------------------------------------------------------- | ------- |
| **size** | The size of the stars | 0.1 |
| **sizeAttenuation** | keep the same size regardless distance. | true |
| **transparent** | show transparency on the stars texture | true |
| **alphaTest** | enables the WebGL to know when not to render the pixeltext. | 0.01 |
| **alphaMap** | texture of the stars | null |
| **count** | number of stars | 5000 |
| **depth** | depth of star's shape | 50 |
| **radius** | Radius of star's shape | 100 |
# AnimatedSprite
::scene-controls-wrapper
:objects-animated-sprite
::
`` displays 2D animations defined in a [texture atlas](https://en.wikipedia.org/wiki/Texture_atlas){rel=""nofollow""}. A typical `` will use:
- An image containing multiple sprites
- A JSON atlas containing the individual sprite coordinates in the image
## Usage
```vue {2,10-14}
```
::prose-warning
`` loads resources asynchronously, so it must be wrapped in a ``.
::
## Compiling an atlas
In typical usage, `` requires both the URL to a texture of compiled sprite images and a JSON atlas containing information about the sprites in the texture.
- [example compiled texture](https://raw.githubusercontent.com/Tresjs/assets/main/textures/animated-sprite/cientosTexture.png){rel=""nofollow""}
- [example JSON atlas](https://raw.githubusercontent.com/Tresjs/assets/main/textures/animated-sprite/cientosAtlas.json){rel=""nofollow""}
Compiling source images into a texture atlas is usually handled by third-party software. You may find [TexturePacker](https://www.codeandweb.com/texturepacker){rel=""nofollow""} useful.
## Without an atlas
There may be cases where you don't want to supply an atlas to the `atlas` prop. To do so:
- Compile your source images into a single image texture.
- Space each sprite into equally sized columns and rows in the compiled image texture.
- Ensure no extra padding has been added to the compiled image texture.
- Set the `atlas` prop to number of columns, number of rows as `[number, number]`.
## Spritesheets in the wild
::prose-warning
In the wild, spritesheets are often distributed without atlases and the images are often compiled by hand. It can be difficult or impossible to use these resources directly with ``. In many cases, it's advisable to recompile the spritesheet.
::
### How to recompile an existing spritesheet image
- Cut individual sprites from the spritesheet and paste them into separate layers in an image editing application, e.g., GIMP.
- Align the layers for animation. Toggling layer visibility on/off will show you how the animation will display, frame to frame.
- Export layers as individual images.
- Name the individual images according to the following pattern: :br`[animation name][frame number].[extension]` :br E.g., walk000.png, walk001.png, idle000.png, idle001.png
- Compile individual images into an image texture and atlas using a texture packing application, like TexturePacker.
## Props
| Name | Description | Default |
| :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------- |
| image | `string` โ URL of the image texture or an image dataURL. This prop is not reactive. | |
| atlas | `string | Atlasish` โ * If `string`, the URL of the JSON atlas.
* If `number`, the number of columns in the texture.
* If `[number, number]`, the number of columns/rows in the texture.
* If `AtlasData`, the atlas as a JS object.:br This prop is not reactive. | |
| definitions | `Record` โ Specify playback frame order and repeated frames (delays). `definitions` is a record where keys are atlas animation names and values are strings containing an animation definition. :br:br A "animation definition" comma-separated string of frame numbers with optional parentheses-surrounded durations. :br:br Here is how various definition strings convert to arrays of frames for playback:* "0,2,1" - [0,2,1], i.e., play frame 0, 2, then 1.
* "2(10)" - [2,2,2,2,2,2,2,2,2,2], i.e., play from 2 10 times.
* "1-4" - [1,2,3,4]
* "10-5(2)" - [10,10,9,9,8,8,7,7,6,6,5,5]
* "1-4(3),10(2)" - [1,1,1,2,2,2,3,3,3,4,4,4,10,10] | |
| fps | `number` โ Desired frames per second of the animation. | `30` |
| loop | `boolean` โ Whether or not the animation should loop. | `true` |
| animation | `string | [number, number] | number` โ If `string`, name of the animation to play. If `[number, number]`, start and end frames of the animation. If `number`, frame number to display. | `0` |
| paused | `boolean` โ Whether the animation is paused. | `false` |
| reversed | `boolean` โ Whether to play the animation in reverse. | `false` |
| flipX | `boolean` โ Whether the sprite should be flipped, left to right. | `false` |
| resetOnEnd | `boolean` โ For a non-looping animation, when the animation ends, whether to display the zeroth frame. | `false` |
| asSprite | `boolean` โ Whether to display the object as a THREE.Sprite. [See THREE.Sprite](https://threejs.org/docs/?q=sprite#api/en/objects/Sprite){rel=""nofollow""} | `true` |
| center | `TresVector2` โ Anchor point of the object. A value of [0.5, 0.5] corresponds to the center. [0, 0] is left, bottom. | `[0.5, 0.5]` |
| alphaTest | `number` โ Alpha test value for the material. [See THREE.Material.alphaTest](https://threejs.org/docs/#api/en/materials/Material.alphaTest){rel=""nofollow""} | `0.0` |
| depthTest | `boolean` โ Depth test value for the material. [See THREE.Material.depthTest](https://threejs.org/docs/#api/en/materials/Material.depthTest){rel=""nofollow""} | `true` |
| depthWrite | `boolean` โ Depth write value for the material. [See THREE.Material.depthWrite](https://threejs.org/docs/#api/en/materials/Material.depthWrite){rel=""nofollow""} | `true` |
## Events
| Event | Description | Argument |
| ------- | ------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `frame` | Emitted when the displayed animation frame changes โ at most once per tick, frames may be dropped | `string` โ Name of the newly displayed frame |
| `end` | Emitted when the animation ends โ `props.loop` must be set to `false` | `string` โ Name of the ending frame |
| `loop` | Emitted when the animation loops โ `props.loop` must be set to `true` | `string` โ Name of the frame at the end of the loop |
## Animation
The `:animation` prop holds either the name of the currently playing animation or a range of frames to play, or a frame number to display.
### Using named animations as animation
When individual files are converted to a spritesheet/atlas, typically the original images' filenames will be included in the atlas.
`` uses those filenames to automatically group images into animations.
Use either of the following naming conventions for your source images ...
- `[animation name][frame number].[file_extension]`
- `[animation name]_[frame number].[file_extension]`
... then `` will automatically make all `[animation name]` available for playback. Just pass `[animation name]` to the component's `:animation` prop.
### Example
For our Cientos heart cartoon character animation, here's how the filenames map to animation names.
| Filenames | Animation name |
| --------------------------------------------- | --------------------------- |
| cientosIdle0000.png, cientosIdle0001.png, ... | cientosIdle |
| cientosIdleToWalkTransition0000.png | cientosIdleToWalkTransition |
| cientosWalk0000.png, cientosWalk0001.png, ... | cientosWalk |
## Definitions
You can supply an object to the `:definitions` prop. Any [named animation](https://cientos.tresjs.org/#animation) can be a key. The value is a string that specifies frame order and delays.
### Demo
In this demo, the 'idle' animation is comprised of six different images. By default, those images will play sequentially when the `:animation` prop is `'idle'`.
But below, we've added a `:definitions` prop with this value for the `idle` key:
```text
'0-5, 0(10), 1-2, 3(20), 4-5, 0-5(3)'
```
So, instead of playing images 0-5 sequentially, this animation will play instead:
- `0-5` โ Play all six images (`0-5`) of the animation normally.
- `0(10), 1-2, 3(20), 4-5` โ Play all six images again with a delay of ten frames at the bottom of the bounce (`0(10)`) and a delay of twenty frames at the top of the bounce (`3(20)`).
- `0-5(3)` โ Finally, play all six images of the animation with a delay of three frames each.
## Center
In addition to being the sprite's anchor point, the `:center` prop also controls how differently sized source images will "grow" and "shrink". Namely, they "grow out from" and "shrink towards" the center.
# CubeCamera
::scene-controls-wrapper
:objects-cube-camera
::
`` creates a `THREE.CubeCamera` and uses it to render an environment map of your scene. The environment map is then applied to component's children.
`` makes its children invisible while rendering to the internal buffer so that they are not included in the reflection.
## Usage
```vue {2,10,15}
```
## Props
| Prop | Description | Default |
| :----------- | :-------------------------------------------------------------------------------------------- | ---------- |
| `frames` | Number of frames to render. Set to `1` for a static scene. `Infinity` to update continuously. | `Infinity` |
| `resolution` | Resolution of the FBO | `255` |
| `near` | Camera near | `0.1` |
| `far` | Camera far | `1000` |
| `envMap` | Custom environment map that is temporarily set as the scene's background | |
| `fog` | Custom fog that is temporarily set as the scene's fog | |
# Fbo
::scene-wrapper
:objects-fbo
::
An FBO (or Frame Buffer Object) is generally used to render to a texture. This is useful for post-processing effects like blurring, or for rendering to a texture that will be used as a texture in a later draw call.
Cientos provides an `` component make it easy to use FBOs in your application.
## Usage
```vue {2,23-26}
```
## Props
| Prop | Description | Default |
| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
| **`width`** | `number` - The width of the FBO. | Width of the canvas |
| **`height`** | `number` - the height of the FBO | Height of the canvas |
| **`depth`** | `boolean` - Whether or not the FBO should render the depth to a [`depthTexture`](https://threejs.org/docs/?q=webglre#api/en/renderers/WebGLRenderTarget.depthTexture){rel=""nofollow""}. | `false` |
| **`settings`** | `WebGLRenderTargetOptions` - Every other configuration property for the [`WebGLRenderTarget` class](https://threejs.org/docs/#api/en/renderers/WebGLRenderTarget){rel=""nofollow""} | `{}` |
| **`autoRender`** | `boolean` - Whether to automatically render the FBO on the default scene. | `true` |
## useFBO
An FBO (or Frame Buffer Object) is generally used to render to a texture. This is useful for post-processing effects like blurring, or for rendering to a texture that will be used as a texture in a later draw call.
Cientos provides a `useFBO` composable to make it easy to use FBOs in your application.
::prose-warning
The `useFBO` composable must be used inside of a child component since it needs the context of TresCanvas.
::
### Usage
```vue {2,4-11,20}
```
### Options
| Prop | Description | Default |
| :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
| **`width`** | `number` - The width of the FBO. | Width of the canvas |
| **`height`** | `number` - the height of the FBO | Height of the canvas |
| **`depth`** | `boolean` - Whether or not the FBO should render the depth to a [`depthTexture`](https://threejs.org/docs/?q=webglre#api/en/renderers/WebGLRenderTarget.depthTexture){rel=""nofollow""}. | `false` |
| **`settings`** | `WebGLRenderTargetOptions` - Every other configuration property for the [`WebGLRenderTarget` class](https://threejs.org/docs/#api/en/renderers/WebGLRenderTarget){rel=""nofollow""} | `{}` |
# GradientTexture
::scene-wrapper
:objects-gradient-texture
::
`` creates a gradient in a THREE.Texture and attaches it to its parent THREE.Material's `map` by default.
## Usage
```vue
```
## Props
| Prop | Description | Default |
| :------------------ | :--------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `stops` | A `number[]` of values between `0` and `1` representing the color positions in the gradient. `stops.length` should match `color.length`. | |
| `colors` | A `THREE.ColorRepresentation[]` representing the colors in the gradient. | |
| `attach` | Where the component should be attached within its parent. | `'map'` |
| `height` | Height of the canvas used to draw the gradient. | `1024` |
| `width` | Width of the canvas used to draw the gradient. | `16` |
| `type` | `'linear' | 'radial'` Type of gradient to draw. | `'linear'` |
| `innerCircleRadius` | Radius of the inner circle of a radial gradient. | `0` |
| `outerCircleRadius` | Radius of the outer circle of a radial gradient. | `'auto'` |
# HTML
This component allows you to project HTML content to any object in your scene. TresJS will automatically update the position of the HTML content to match the position of the object in the scene.
๐ Works seamlessly with both **PerspectiveCamera** and **OrthographicCamera** โ the active camera is automatically detected by the `` component.
::scene-wrapper
:objects-html
::
## Usage
```vue {2,13-18}
I'm a Box ๐ฆ
```
## Occlusion
By default, the HTML content will be visible through other objects in the scene. You can use the `occlude` prop to make the HTML content occlude other objects in the scene.
Html can be hidden behind one or more objects in your scene using the `occlude` prop.
```vue
```
If `occlude`, then `` will be hidden by any objects that pass in front of its position.
::scene-wrapper
:objects-html-occlusion
::
Demo code
```html
Move camera
```
You can also choose which object or objects should occlude the HTML content by passing either a single object ref or an array of object refs to the `occlude` prop:
### Single occluder
```vue
```
::scene-wrapper
:objects-html-single-occluder
::
Demo code
```html
Move camera
```
### Multiple occluders
```vue
```
OR
```vue
```
In the demo below, a `v-for` loop generates multiple spheres around the cube.
All resulting **`Mesh`** instances are collected into an array and passed to the **`occlude`** prop, allowing each sphere to occlude the HTML content.
This demo also uses the **`on-occlude`** event, which is triggered whenever the occlusion state changes.
Here, the event updates a **reactive value** to control element styles โ for example, toggling between *light* and *dark* themes.
::scene-wrapper
:objects-html-occlude-complex-demo
::
Demo code
```html
isOccluded = event"
>
Move camera
```
### Blending Occlusion
`` can hide behind geometry as if it was part of the 3D scene using this mode. It can be enabled by using "blending" as the occlude prop.
```vue
```
The **demo below โฌ๏ธ** *(left black example)* shows a **basic usage example**.
::scene-wrapper
:objects-html-occlude-blending-demo
::
Demo code
```vue {2,32,34-39,62-72,63-72,74-84,86-96,98-108}
BASIC ๐ occlude=blending
CUSTOM CIRCLE GEOMETRY
HTML + Custom material + receive-shadow โฌ๏ธ
```
## Custom Geometry
By default, when using `occlude="blending"`, occlusion works correctly only with **rectangular HTML elements** (using a `PlaneGeometry`).
For *non-rectangular content*, you can use the **`geometry`** prop to provide a matching custom geometry.
In the **demo above โฌ๏ธ** *(middle yellow example)*, a [`CircleGeometry`](https://threejs.org/docs/#api/en/geometries/CircleGeometry){rel=""nofollow""} is used as a **custom geometry**.
::prose-list
- The `geometry` prop only defines the **occlusion shape** in 3D and does not modify your HTML content.
- You can provide any [`BufferGeometry`](https://threejs.org/docs/#api/en/core/BufferGeometry){rel=""nofollow""}, for example to simulate **CSS-like styles** such as `border-radius` using a rounded rectangle or squircle geometry (see [`RoundedRectangle / Squircle geometry`](https://discourse.threejs.org/t/roundedrectangle-squircle/28645){rel=""nofollow""} for example).
::
### Custom Material
You can also assign material properties to the HTML content using the `material` prop.
In the **demo above โฌ๏ธ** *(right red example)*, a **custom material** is used with shadow.
::prose-note
The `material` prop is only available when `occlude="blending"` is **enabled**.
::
::prose-note
Enable shadows using the **`castShadow`** and **`receiveShadow`** props.
Shadows are supported **only** when using a **custom material**. By default, shadows do **not** work with *`MeshBasicMaterial`* or *`ShaderMaterial`*. :br
::
## Using ``
The native Vue [``](https://vuejs.org/guide/built-ins/transition){rel=""nofollow""} component works seamlessly with ``.
This means you can **animate** how your projected HTML content *enters* and *leaves* the scene, exactly as you would in a regular Vue application.
::prose-note
All **standard interactions** are supported just like on a regular HTML element โ **hover effects**, **events**, and *any kind of DOM interaction* are fully possible.
::
::scene-controls-wrapper
:objects-html-transition-demo
::
Demo code
```vue {2,73-92}
TRANSITION + occlude=blending ๐
```
### Using `iframes`
You can achieve pretty cool results with the `Html` component by using iframes. For example, you can use an iframe to display a YouTube video in your scene or a webpage with a 3D model.
::scene-wrapper
:objects-html-iframe-demo
::
Demo code
```html
```
::info
The demos use `:z-index-range="[28, 0]"` simply to ensure the HTML elements stay below the documentation header (which uses `z-index: 30`).
**This value is for the docs only โ you can ignore it or adjust it as needed.**
::
## Props
| Prop | Description | Default |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| **as** | Wrapping *HTML element*. | `'div'` |
| **wrapperClass** | The `className` of the wrapping element. element. | |
| **prepend** | Projects content *behind* the canvas. | `false` |
| **center** | Adds a `transform: translate(-50%, -50%)`. :br โก๏ธ *Ignored in **transform** mode.* | `false` |
| **fullscreen** | Aligns to the upper-left corner and fills the screen. :br โก๏ธ *Ignored in **transform** mode.* | `false` |
| **distanceFactor** | Children are scaled by this factor and also by distance to a `PerspectiveCamera`, or zoom when using an `OrthographicCamera`. | |
| **zIndexRange** | Defines the *Z-order range*. | `[16777271, 0]` |
| **portal** | Reference to a target container (for rendering into a different DOM node). container. | |
| **transform** | If `true`, applies `matrix3d` transformations โ the element appears as if it is inside the 3D scene. | `false` |
| **sprite** | Renders as a *sprite*. :br โก๏ธ *Only in **transform** mode.* | `false` |
| **calculatePosition** | Callback function to override the default positioning logic. :br**Type:** `(object: Object3D, camera: Camera, size: { width: number; height: number }) => [number, number, number]` :br Receives the related 3D object, the active camera, and the current viewport size, and must return `[x, y, z]` pixel coordinates for placing the HTML element. :br โก๏ธ *Ignored in **transform** mode.* | [Default `calculatePosition`](https://github.com/Tresjs/cientos/blob/main/src/core/misc/html/utils.ts#L9-L19){rel=""nofollow""} |
| **occlude** | Enables occlusion. Possible values: :br - `true` โ Occlusion against *all* scene objects :br - `Ref[]` โ Occlusion is enabled only against the specified objects. :br - `'blending'` โ Uses a *blending-based* occlusion method (CSS-like depth blending). | |
| **geometry** | Custom `geometry` to be used. | [`PlaneGeometry`](https://threejs.org/docs/?q=geometry#api/en/geometries/PlaneGeometry){rel=""nofollow""} |
| **material** | **Custom shader *material* used for the occlusion mesh.** :br **Only applies when `occlude="blending"` is enabled** (an occlusion mesh is created). :br *Ignored in raycast occlusion modes (`true`, object refs).* | |
| **transparentMaterial** | **Enables *transparent* rendering for the occlusion material.** :br **Only applies when `occlude="blending"` creates an occlusion mesh.** :br *Ignored in raycast occlusion modes (`true`, object refs).* | `false` |
## Events
| Event | Description |
| --------- | ---------------------------------------- |
| onOcclude | Called when the occlusion state changes. |
## Exposed properties
| Property | Type | Description |
| ----------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| **instance** | `Ref` | Reference to the root **``** used by ``. |
| **isVisible** | `Ref` | Reactive value that indicates whether the HTML content is **currently visible** or **occluded**. |
| **occlusionMesh** | `Ref` | Reference to the **occlusion mesh** created when `occlude="blending"` is **enabled**. Used internally for geometry-based occlusion. |
## Caveats
- โจ When using **``**, if the `` component is **overlapping** or **inside a 3D object**, it will be considered **occluded** and therefore **hidden**. To avoid this, **adjust the position** of the `` component in your scene.
- ๐จ When using **``**, the HTML content is no longer **selectable** because it is rendered **behind the canvas**. This is required to achieve the blending effect.
- โ๏ธ When using a **custom material** with occlusion in `blending` mode, there are a few important requirements to ensure the HTML content renders correctly โฌ๏ธ
See more information
1. If you provide your own material, it must be **transparent** (`transparent: true`) with an **opacity < 1**.
2. If you are not providing a custom material, enable **`transparentMaterial`** so the internal shader becomes transparent.
3. The occlusion mesh requires a **fully transparent canvas background**; otherwise, thin borders or halo artifacts may appear.
4. To compensate for the transparent canvas, you may **reapply your previous clear-color as a CSS background** on the `html`, `body`, or a wrapper `div`.
- ๐ถ When using **`transparentMaterial`**, overlapping `` elements (especially multiple `occlude="blending"` instances) may cause **z-index or depth-order artifacts**.
This happens because the occlusion mesh uses transparency in the WebGL layer while the DOM element uses CSS stacking order.
- ๐ต To avoid thin border artifacts when using `occlude="blending"`, make sure your `` is fully transparent:
```vue
```
| Prop | Description | Default |
| --------------------- | -------------------------------------------------------------------------------------------------------------------- | --------------- |
| **as** | Wrapping html element. | `'div'` |
| **wrapperClass** | The className of the wrapping element. | |
| **prepend** | Project content behind the canvas. | `false` |
| **center** | Adds a -50%/-50% CSS transform. [Ignored in transform mode] | `false` |
| **fullscreen** | Aligns to the upper-left corner, fills the screen. [Ignored in transform mode] | `false` |
| **distanceFactor** | Children will be scaled by this factor, and also by distance to a PerspectiveCamera / zoom by an OrthographicCamera. | |
| **zIndexRange** | Z-order range. | `[16777271, 0]` |
| **portal** | Reference to target container. | |
| **transform** | If true, applies matrix3d transformations. | `false` |
| **sprite** | Renders as sprite, but only in transform mode. | `false` |
| **calculatePosition** | Override default positioning function. [Ignored in transform mode] | |
| **occlude** | Can be `true`, `Ref[]`, `'raycast'`, or `'blending'`. True occludes the entire scene. | |
| **geometry** | Custom `geometry` to be use | `PlaneGeometry` |
| **material** | Custom shader `material` to be use | |
## Events
| Event | Description |
| --------- | ---------------------------------------- |
| onOcclude | Called when the occlusion state changes. |
# Image
::scene-controls-wrapper
:objects-image
::
`` is a shader-based component that optionally loads then displays an image texture on a default plane or on your custom geometry.
## Usage
```vue {3,10-12}
```
## Props
::prose-warning
`` is a THREE.Mesh and most Mesh attributes can be used as props on the component.
::
| Prop | Description | Default |
| :------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `segments` | Number of divisions in the default geometry. | `1` |
| `scale` | Scale of the geometry. `number | [number, number]` | `1` |
| `color` | Color multiplied into the image texture. | `'white'` |
| `zoom` | Shrinks or enlarges the image texture. | `1` |
| `radius` | Border radius applied to the image texture. (Intended for rectangular geometries. Use with `transparent`.) | `0` |
| `grayscale` | Power of grayscale effect. 0 is off. 1 is full grayscale. | `0` |
| `toneMapped` | Whether this material is tone mapped according to the renderers toneMapping settings. [See THREE.material.tonemapped](https://threejs.org/docs/?q=material#api/en/materials/Material.toneMapped){rel=""nofollow""} | `0` |
| `transparent` | Whether the image material should be transparent. [See THREE.material.transparent](https://threejs.org/docs/?q=material#api/en/materials/Material.transparent){rel=""nofollow""} | `false` |
| `transparent` | Whether the image material should be transparent. [See THREE.material.transparent](https://threejs.org/docs/?q=material#api/en/materials/Material.transparent){rel=""nofollow""} | `false` |
| `opacity` | Opacity of the image material. [See THREE.material.transparent](https://threejs.org/docs/?q=material#api/en/materials/Material.transparent){rel=""nofollow""} | `1` |
| `side` | THREE.Side of the image material. [See THREE.material.side](https://threejs.org/docs/?q=material#api/en/materials/Material.side){rel=""nofollow""} | `FrontSide` |
| `texture` | Image texture to display on the geometry. | |
| `url` | Image URL to load and display on the geometry. | |
## Caveats
By default, images loaded via the `url` prop use the rendererโs output color space. For advanced control, pass a `THREE.Texture` via the `texture` prop and set its `colorSpace` (e.g., `THREE.SRGBColorSpace` or `THREE.LinearSRGBColorSpace`).
```vue
```
# Objects
Components for creating 3D objects, sprites, text, and textures in your scene.
:api-list{list-name="objects-list"}
# MarchingCubes
::scene-controls-wrapper
:objects-marching-cubes
::
`` is a wrapper around [THREE's Marching Cubes](https://threejs.org/examples/#webgl_marchingcubes){rel=""nofollow""}.
It includes 3 components:
- `` โ container element for ``s and ``s
- `` - an individual metaball
- `` โ optional bounding plane that interacts with the metaballs
## Usage
```vue {2,15-23}
```
## Props
| Prop | Description | Default |
| :------------- | :----------------------------------------------------------------------------------------------------------------------- | ------- |
| `resolution` | Resolution of the marching cube field. Higher resolution produces smoother meshes at the cost of performance and memory. | `28` |
| `maxPolyCount` | Maximum number of polygons to generate. | `10000` |
| `enableUvs` | Whether UVs are enabled. | `false` |
| `enableColors` | Whether vertex colors are enabled. | `false` |
## MarchingCube Props
| Prop | Description | Default |
| :--------- | :------------------------------------------------------ | ------- |
| `strength` | How strongly this cube affects the marching cube field. | `0.5` |
| `subtract` | How quickly strength moves to `0` over distance. | `12` |
## MarchingPlane Props
| Prop | Description | Default |
| :---------- | :------------------------------------------------------- | ------- |
| `planeType` | Which axis the plane appears on. `'x' | 'y' | 'z'` | `'x'` |
| `strength` | How strongly this plane affects the marching cube field. | `0.5` |
| `subtract` | How quickly strength moves to `0` over distance. | `12` |
# Reflector
::scene-controls-wrapper
:objects-reflector
::
The `cientos` package provides an abstraction of the [Reflector class](https://github.com/mrdoob/three.js/blob/dev/examples/jsm/objects/Reflector.js){rel=""nofollow""}, which creates a Mesh showing a real-time reflection of your scene. This Mesh extends from `Mesh` so all the default props can be passed as well:
## Usage
```vue
```
## Props
| Prop | Description | Default |
| :---------------- | :--------------------------------------------------- | ------------------------- |
| **color** | The base color that's combine with the mirror effect | '#333' |
| **textureWidth** | the width of the texture to render on the mirror | 512 |
| **textureHeight** | the height of the texture to render on the mirror | 512 |
| **clipBias** | to use the clipBias property | 0 |
| **multisample** | how many samplers will be render | 4 |
| **shader** | The texture of the smoke. | Reflector.ReflectorShader |
::prose-warning
All the props except the `color`, are not reactive
::
## Custom mirror effect
You can provide your own shader by passing a full shader object with `uniforms`, `vertexShader`, and `fragmentShader`. The example below adds animated circular ripples emanating from the center of the surface, while preserving the color tint:
```vue
```
The Reflector shader use the following configuration by default:
You can extend, modify or just play with them
### Default shader
```js
const shader = {
name: 'ReflectorShader',
uniforms: {
color: {
value: null
},
tDiffuse: {
value: null
},
textureMatrix: {
value: null
}
},
vertexShader: /* glsl */`
uniform mat4 textureMatrix;
varying vec4 vUv;
#include
#include
void main() {
vUv = textureMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
#include
}`,
fragmentShader: /* glsl */`
uniform vec3 color;
uniform sampler2D tDiffuse;
varying vec4 vUv;
#include
float blendOverlay( float base, float blend ) {
return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
}
vec3 blendOverlay( vec3 base, vec3 blend ) {
return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );
}
void main() {
#include
vec4 base = texture2DProj( tDiffuse, vUv );
gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );
#include
#include
}`
}
```
# Refractor
::scene-controls-wrapper
:objects-refractor
::
The `cientos` package provides an abstraction of the [Refractor class](https://github.com/mrdoob/three.js/blob/dev/examples/jsm/objects/Refractor.js){rel=""nofollow""}, which creates a Mesh that renders what is behind it with a refractive distortion effect โ useful for glass panels, water surfaces, and other transmissive materials. This Mesh extends from `Mesh` so all the default props can be passed as well.
## Usage
```vue
```
## Props
| Prop | Description | Default |
| :---------------- | :--------------------------------------------------- | --------------------------- |
| **color** | Color tint blended with the refracted image | `'#7f7f7f'` |
| **textureWidth** | Width of the internal render target texture | `512` |
| **textureHeight** | Height of the internal render target texture | `512` |
| **clipBias** | Clip bias for the virtual camera projection | `0` |
| **multisample** | Number of MSAA samples for the render target | `4` |
| **shader** | Custom shader object to override the built-in shader | `Refractor.RefractorShader` |
::prose-warning
All the props except `color` are not reactive
::
## Custom refraction effect
You can provide your own shader by passing a full shader object with `uniforms`, `vertexShader`, and `fragmentShader`. The example below adds animated circular ripples emanating from the center of the surface, while preserving the color tint:
```vue
```
The Refractor shader uses the following configuration by default:
### Default shader
```js
const shader = {
uniforms: {
color: {
value: null
},
tDiffuse: {
value: null
},
textureMatrix: {
value: null
}
},
vertexShader: /* glsl */`
uniform mat4 textureMatrix;
varying vec4 vUv;
void main() {
vUv = textureMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`,
fragmentShader: /* glsl */`
uniform vec3 color;
uniform sampler2D tDiffuse;
varying vec4 vUv;
float blendOverlay( float base, float blend ) {
return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
}
vec3 blendOverlay( vec3 base, vec3 blend ) {
return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );
}
void main() {
vec4 base = texture2DProj( tDiffuse, vUv );
gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );
#include
#include
}`
}
```
# Text3D
::scene-controls-wrapper
:objects-text
::
`` is a component that renders text in 3D. It is a wrapper around the [TextGeometry](https://threejs.org/docs/#api/en/geometries/TextGeometry){rel=""nofollow""} class.
## Usage
To use the `` component you need to pass the `font` prop with the URL of the font JSON file you want to use. TextGeometry uses `typeface`.json generated fonts, you can generate yours [here](http://gero3.github.io/facetype.js/){rel=""nofollow""}
```vue
```
Notice that you need to pass the `` component as a child of the `` component. This is because `` is a `Mesh` component, so it needs a material. The geometry is created automatically. Also you can pass the text as a slot or as a prop like this:
```vue
TresJS
```
In addition, you can use the power of Vue to add reactivity, but you need to apply the needUpdates prop, for example you can create a reactive value, apply a v-model and make the bound, the Text3D component will update
```vue
```
## Props
| Prop | Description | Default |
| :----------------- | :--------------------------------------------------------------------- | ------- |
| **font** | The font data or font name to use for the text. | |
| **text** | The text to display. | |
| **size** | The size of the text. | 0.5 |
| **height** | The height of the text. | 0.2 |
| **curveSegments** | The number of curve segments to use when generating the text geometry. | 5 |
| **bevelEnabled** | A flag indicating whether beveling should be enabled for the text. | true |
| **bevelThickness** | The thickness of the beveled edge on the text. | 0.05 |
| **bevelSize** | The size of the beveled edge on the text. | 0.02 |
| **bevelOffset** | The offset of the beveled edge on the text. | 0 |
| **bevelSegments** | The number of bevel segments to use when generating the text geometry. | 4 |
| **center** | To center the text | false |
| **needUpdates** | This props add reactivity | false |
# All
## ๐ฆ Abstraction
:api-list{list-name="abstraction-list" path="/api/abstractions"}
## ๐ฎ Controls
:api-list{list-name="controls-list" path="/api/controls"}
## ๐ Loaders
:api-list{list-name="loaders-list" path="/api/loaders"}
## ๐จ Materials
:api-list{list-name="materials-list" path="/api/materials"}
## ๐ท Shapes
:api-list{list-name="shapes-list" path="/api/shapes"}
## ๐ Debug & Performance
:api-list{list-name="debug-list" path="/api/debug-performance"}
## ๐ก Light & Shadow
:api-list{list-name="light-list" path="/api/light-shadow"}
## ๐ญ Staging
:api-list{list-name="staging-list" path="/api/staging"}
## ๐ฌ Objects
:api-list{list-name="objects-list" path="/api/objects"}
## ๐ ๏ธ Miscellaneous
:api-list{list-name="misc-list" path="/api/miscellaneous"}
# Bounds
::scene-wrapper
:miscellaneous-bounds
::
Calculates a boundary box and centers the camera accordingly. Its `lookAt` method accepts a target to look at imperatively e.g., after a click.
::prose-note
If you are using other camera controls, be sure to make them the 'default'.
```vue
```
::
## Usage
```vue {3,6-7,9-11,18,23}
focusObject()">
```
## Props
| Name | Description | Default |
| :----------- | :----------------------------------------------------------------------------------------- | -------------- |
| `duration` | Duration of the `lookAt` animation in seconds | `1.0` |
| `offset` | Additional distance from the target when using `lookAt` with a `Box3` or `Object3D` | `0.2` |
| `useResize` | Whether to re`lookAt` the last target when the screen is resized | `false` |
| `useMounted` | Whether to `lookAt` the `Bounds` object when the component is mounts | `false` |
| `clip` | Whether to adjust the camera's `near` and `far` settings when using `lookAt` | `false` |
| `easing` | Animation's easing function. `t` and the returned value should be in the interval `[0, 1]` | Cubic ease out |
## lookAt
`` `lookAt` points the camera at its first argument: an `Object3D`, `Box3` or `Vector3`.
### Method Signatures
```text
/**
* Calculates a boundary box around an `Object3D` and centers the camera accordingly.
*/
lookAt(object: Object3D): void
/**
* Calculates a boundary box around an `Object3D` and centers the camera accordingly and animates the camera's `up` vector.
*/
lookAt(object: Object3D, up: VectorFlexibleParams): void
/**
* Centers the camera's viewport on a `Box3`.
*/
lookAt(box3: Box3): void
/**
* Centers the camera's viewport on a `Box3` and animates the camera's `up` vector.
*/
lookAt(box3: Box3, up: VectorFlexibleParams): void
/**
* Look at a `Vector3`.
*/
lookAt(target: VectorFlexibleParams): void
/**
* Look at a `Vector3`, if provided. Move the camera to `position`.
*/
lookAt(target: VectorFlexibleParams | undefined | null, position: VectorFlexibleParams): void
/**
* Look at a `Vector3`, if provided. Move the camera to `position` and animate the camera's `up` vector.
*/
lookAt(target: VectorFlexibleParams | undefined | null, position: VectorFlexibleParams, up: VectorFlexibleParams): void
/**
* Rerun `lookAt` using the prior arguments. If `lookAt` has never been called, uses the `Bounds` object.
*/
lookAt(): void
```
# GlobalAudio
The `cientos` package provides a `` component that serves to easily add a global sound to your scene.
Reference: [Audio](https://threejs.org/docs/index.html?q=audio#api/en/audio/Audio){rel=""nofollow""}
## Usage
```vue {3,9}
```
\*The `src` prop is required
## Props
| Prop | Description | Default |
| :------------- | :------------------------------------------------------- | --------------------- |
| `src` | Path to your audio file | |
| `playTrigger` | Id of the DOM element that triggers the play/pause state | `renderer.domElement` |
| `stopTrigger` | Id of the DOM element that triggers the stop state | |
| `loop` | If the audio must be replayed when ends | `false` |
| `volume` | Volume of the audio | `0.5` |
| `playbackRate` | PlaybackRate of the audio | `1` |
## Events
| Event | Description |
| :---------- | :--------------------------------------------------------------- |
| `isPlaying` | Dispatched when the Audio change its state (play, pause or stop) |
# Miscellaneous
Utility components and composables for audio, animations, intersections, and more.
:api-list{list-name="misc-list"}
# MouseParallax
::scene-controls-wrapper
:miscellaneous-mouse-parallax
::
`` is a component that allows you to easily create a [parallax](https://en.wikipedia.org/wiki/Parallax){rel=""nofollow""} effect. The camera will update automatically according to the mouse position.
## Usage
You only need to import and add it to your template as ``. Additionally, you can pass the following props:
`factor` is a number to increase the movement range of the camera. This could be an array of two values corresponding to the x and y values, in that order: `:factor=[x,y]`.
`ease` is a number that smooths the movement. This could be an array of two values corresponding to the x and y values, in that order: `:ease=[x,y]`.
`local` is a boolean that enables movement based on the position of the mouse on the canvas rather than the window.
```vue {2,12}
```
## Props
| Prop | Description | Default |
| :----------- | :-------------------------------------------------------------------------- | ------- |
| **disabled** | Enable or disable the effect | false |
| **factor** | Increase the range of the parallax | 2.5 |
| **ease** | Increase the camera movement speed | 0.1 |
| **local** | Whether the mouse coordinates are calculated from the element or the window | false |
# PositionalAudio
::scene-controls-wrapper
:miscellaneous-positional-audio
::
The `cientos` package provides an abstraction of the [PositionalAudio](https://threejs.org/docs/index.html?q=posi#api/en/audio/PositionalAudio){rel=""nofollow""}.
`` is an object specifically designed for controlling sounds in a scene graph space. This allows, for the simulation of various audio environments, creating a more immersive user experience.
`` includes a helper ๐ ๏ธ that allows you to view the directional cone of te audio. The helper is based on the [PositionalAudioHelper](https://threejs.org/docs/#examples/en/helpers/PositionalAudioHelper){rel=""nofollow""} class.
## Usage
The `` component is very simple to set up and use, allowing you to bring your 3D scenes to life. All you need to do is call the `` component and set the `url`. It must be wrapped around the `` component to enable it to load your audio asynchronously. ๐ฅ
```vue {2,17-19}
```
::prose-warning
AudioContext is authorized when a user gesture has been made on the page. The property `:autoplay="true"` cannot be activated if no user gesture has been made previously [`read more`](https://goo.gl/7K7WLu){rel=""nofollow""}.
If you are sure that there will be a user gesture before your `` component appears/is created, you can directly add `:ready="true"` and `autoplay="true"` for a direct launch.
::
## How does it work?
{.mx-auto}
## Props
| Prop | Description | Default |
| :------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| **url** | `string` - **required** โ The path or URL to the file. | |
| **helper** | `boolean` โ Selects whether helper mode is enabled. :br *(Useful for visualising the angle of sound propagation)* | `false` |
| **distance** | `number` โ The distance at which the volume reduction starts taking effect. ***A non-negative number.*** | `1` |
| **ready** | `boolean` โ Tells `` that `AudioContext` is authorised because an user gesture has been made on the page. This is imperative, as `autoplay` cannot be activated if no user gesture has been made previously ({rel=""nofollow""}). :br | `false` |
| **autoplay** | `boolean` โ Selects whether the audio is launched automatically. Please refer to the `ready` prop for a better understanding of how to use autoplay. | `false` |
| **loop** | `boolean` โ Specifies whether the audio should loop. | `false` |
| **innerAngle** | `number` โ A parameter for directional audio sources, this is an angle, inside of which there will be no volume reduction. | `360` |
| **outerAngle** | `number` โ A parameter for directional audio sources, this is an angle, outside of which the volume will be reduced to a constant value of `outerGain` prop. | `0` |
| **outerGain** | `number` โ A parameter for directional audio sources, this is the amount of volume reduction outside of the `outerAngle` prop. When the value is `0` no sound can be heard. | `0` |
## Exposed properties
| Event | Description |
| :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `instance` | Instance reference โ Inheritance of [PositionalAudio](https://threejs.org/docs/index.html?q=posi#api/en/audio/PositionalAudio){rel=""nofollow""}. |
| `play()` | Play audio โ *Cannot be fired if audio is already running.* |
| `pause()` | Pause audio โ *Cannot be fired if audio is already paused.* |
| `stop()` | Stop audio โ *Cannot be fired if audio is already stopped.* |
| `dispose()` | Dispose component โ Deletion of the AudioListener in the camera, disconnection of the audio source and deletion of the PositionalAudioHelper (if it exists). |
```typescript
const positionalAudioRef = shallowRef(null)
console.log(positionalAudioRef.value.instance) // instance properties
const handlerAudio = (action: string) => {
if (!positionalAudioRef.value) { return }
const { play, pause, stop } = positionalAudioRef.value
if (action === 'play') { play() }
else if (action === 'pause') { pause() }
else if (action === 'stop') { stop() }
}
```
```vue
```
## Events
| Event | Description |
| :----------- | :---------------------------------------------------------------------------------------------------------------- |
| `is-playing` | Triggered when the audio changes its state (play, pause, or stop) :br `@is-playing="(e) => yourIsPlayingRef = e"` |
# useAnimations
`useAnimations` is a composable that returns a `shallowReactive` with all the models actions based on the animations provided. It is a wrapper around the [AnimationMixer](https://threejs.org/docs/#api/en/animation/AnimationMixer){rel=""nofollow""} class.
## Usage
### Basic Usage (Automatic Updates)
By default, `useAnimations` automatically updates the animation mixer on each frame using the `useLoop` composable:
```ts {1,7}
import { useAnimations, useGLTF } from '@tresjs/cientos'
const { state } = useGLTF('/models/ugly-naked-bunny.gltf')
const animations = computed(() => state.value?.animations || [])
const model = computed(() => state?.value?.scene)
const { actions } = useAnimations(animations, model)
const currentAction = ref()
watch(actions, (newActions) => {
currentAction.value = newActions.Greeting
currentAction.value.play()
})
```
### Manual Updates
To gain finer control over animation mixer updates, enable `manualUpdate: true` and manage the update cycle manually.
```ts {1,8-10,15}
import { useAnimations, useGLTF } from '@tresjs/cientos'
import { useLoop } from '@tresjs/core'
const { state } = useGLTF('/models/ugly-naked-bunny.gltf')
const animations = computed(() => state.value?.animations || [])
const model = computed(() => state?.value?.scene)
const { actions, mixer } = useAnimations(animations, model, {
manualUpdate: true,
})
// Handle updates manually
const { onBeforeRender } = useLoop()
onBeforeRender(({ delta }) => {
mixer.value.update(delta)
})
const currentAction = ref()
watch(actions, (newActions) => {
currentAction.value = newActions.Greeting
currentAction.value.play()
})
```
## Options
- `manualUpdate` (optional): Default is `false`. If set to `true`, disables automatic animation mixer updates. You'll need to call `mixer.value.update(delta)` manually.
# useGLTFExporter
[GLTFExporter](https://threejs.org/docs/index.html?q=expo#examples/en/exporters/GLTFExporter){rel=""nofollow""} is an addon in Three.js that allows you to download any object3D in a [GLTF](https://www.khronos.org/gltf){rel=""nofollow""} format. **TresJS** provides a composable that simplifies this process with just a few lines of code.
## Basic usage
```vue {3,10}
```
## Arguments
| Name | Type | Default | Description |
| :----------- | ---------- | ----------- | ---------------------------------------------------- |
| **Selector** | `Object3D` | Required | The object to download. Could be an array of objects |
| **Options** | `Options` | `undefined` | Description below |
### Options
| Name | Type | Default | Description |
| :-------------------------- | :--------------------- | :------------ | :--------------------------------------------------------------------------- |
| **trs** | `bool` | `false` | Export position, rotation and scale instead of matrix per node |
| **onlyVisible** | `bool` | `true` | Export only visible objects |
| **binary** | `bool` | `false` | Export in binary (.glb) format, returning an ArrayBuffer |
| **maxTextureSize** | `number` | `Infinity` | Restricts the image maximum size (both width and height) to the given value |
| **animations** | `Array` | `undefined` | List of animations to be included in the export |
| **includeCustomExtensions** | `bool` | `false` | Export custom glTF extensions defined on an object's userData.gltfExtensions |
| **fileName** | `string` | `Object name` | Name of the generated file |
# useIntersect
`useIntersect` is a function that returns `intersect`, a `Ref` that's updated when the observed object enters or leaves the screen. This relies on [THREE.Object3D.onBeforeRender](https://threejs.org/docs/#api/en/core/Object3D.onBeforeRender){rel=""nofollow""} so it only works on objects that are effectively rendered, like meshes, lines, sprites. It won't work on other types like group, object3d, bone, etc.
## Usage
::prose-warning
`useIntersect` requires a `TresCanvas` context, so it is only available in `TresCanvas` descendant components' `
```
## Arguments
| Name | Description | Type |
| :----------- | ------------------------------------------------------------------------------------------ | ---------------------------------- |
| **onChange** | Optional callback function triggered when the observed object enters or leaves the screen. | `(isIntersected: boolean) => void` |
## Return
| Name | Description | Type |
| :------------- | --------------------------------------------------------------- | ---------------------- |
| **ref** | Vue `ShallowRef` to pass to the object to be observed. | `ShallowRef` |
| **intersects** | Updates when the observed object's intersect status changes. | `ShallowRef` |
| **off** | Calling this function stops `useIntersect` until `ref` changes. | `() => void` |