title: Tres Components
The core idea of TresJS is to provide an autogenerated catalogue of all the Three.js elements. This catalogue is generated based on the Three.js source code, so it's always up to date.
When using plain Three.js, you need to import the elements you want to use. For example, if you want to use a PerspectiveCamera
, you need to import it from the three
package:
import { PerspectiveCamera } from 'three'
const camera = new PerspectiveCamera(45, width / height, 1, 1000)
::tip{icon="i-ph-lightbulb-duotone"} With Tres you don't need to import anything, that's because Tres automatically generates a Vue Component based of the Three Object you want to use in PascalCase with a Tres prefix. ::
For example, if you want to use a PerspectiveCamera
you would use the <TresPerspectiveCamera />
component.
<template>
<TresCanvas>
<TresPerspectiveCamera />
<!-- Your scene goes here -->
</TresCanvas>
</template>
This means that you can rely on the same documentation as you would when using plain Three.js, but with the power of Vue.
If we follow this argument, you should be able to lay out an instance like this: ❌
<template>
<TresCanvas>
<TresPerspectiveCamera visible :position="new THREE.Vector3(1, 2, 3)" />
<!-- Your scene goes here -->
</TresCanvas>
</template>
But with Tres this is not needed, you can define properties declaratively like this: ✅
<template>
<TresCanvas>
<TresPerspectiveCamera visible :position="[1, 2, 3]" />
<!-- Your scene goes here -->
</TresCanvas>
</template>
TresJS follows a simple naming convention: any component prefixed with Tres
is automatically mapped to its Three.js counterpart. Some examples:
Vue Component | Instance |
---|---|
<TresPerspectiveCamera /> |
new THREE.PerspectiveCamera() |
<TresMesh /> |
new THREE.Mesh() |
<TresBoxGeometry /> |
new THREE.BoxGeometry() |
<TresMeshBasicMaterial /> |
new THREE.MeshBasicMaterial() |
args
Many Three.js objects require constructor arguments. TresJS provides the args
prop as an array of constructor arguments that are passed directly to the Three.js constructor:
For example, the PerspectiveCamera
constructor has the following arguments:
fov
- Camera frustum vertical field of viewaspect
- Camera frustum aspect rationear
- Camera frustum near planefar
- Camera frustum far planeTo pass these arguments to the <TresPerspectiveCamera />
component, you can use the args
prop:
<template>
<TresCanvas>
<!-- Creates: new THREE.PerspectiveCamera(45, 1, 0.1, 1000) -->
<TresPerspectiveCamera :args="[45, 1, 0.1, 1000]" />
<!-- Your scene goes here -->
</TresCanvas>
</template>
<template>
<TresCanvas>
<!-- Creates: new THREE.PerspectiveCamera(45, 1, 0.1, 1000) -->
<TresPerspectiveCamera :args="[45, 1, 0.1, 1000]" />
<!-- Creates: new THREE.BoxGeometry(1, 2, 3) -->
<TresBoxGeometry :args="[1, 2, 3]" />
<!-- Creates: new THREE.MeshBasicMaterial({ color: 'red' }) -->
<TresMeshBasicMaterial :args="[{ color: 'red' }]" />
</TresCanvas>
</template>
::code-group
<template>
<!-- Box: width, height, depth -->
<TresBoxGeometry :args="[2, 2, 2]" />
<!-- Sphere: radius, widthSegments, heightSegments -->
<TresSphereGeometry :args="[1, 32, 32]" />
<!-- Plane: width, height, widthSegments, heightSegments -->
<TresPlaneGeometry :args="[10, 10, 1, 1]" />
</template>
<template>
<!-- PerspectiveCamera: fov, aspect, near, far -->
<TresPerspectiveCamera :args="[75, window.innerWidth / window.innerHeight, 0.1, 1000]" />
<!-- OrthographicCamera: left, right, top, bottom, near, far -->
<TresOrthographicCamera :args="[-5, 5, 5, -5, 0.1, 1000]" />
</template>
<template>
<!-- DirectionalLight: color, intensity -->
<TresDirectionalLight :args="['#ffffff', 1]" />
<!-- PointLight: color, intensity, distance, decay -->
<TresPointLight :args="['#ff0000', 2, 100, 2]" />
</template>
::
Beyond constructor arguments, TresJS allows you to set properties declaratively using Vue props:
<template>
<!-- Three.js equivalent:
const mesh = new THREE.Mesh()
mesh.position.set(0, 1, 0)
mesh.rotation.set(0, Math.PI, 0)
mesh.visible = true
-->
<TresMesh
:position="[0, 1, 0]"
:rotation="[0, Math.PI, 0]"
:visible="true"
>
<TresBoxGeometry />
<TresMeshBasicMaterial color="blue" />
</TresMesh>
</template>
TresJS provides convenient shorthands for common transformations:
<template>
<!-- Individual axis manipulation -->
<TresMesh
:position-x="1"
:position-y="2"
:position-z="3"
:rotation-x="Math.PI / 4"
:scale-y="2"
/>
<!-- Color properties -->
<TresMeshBasicMaterial
:color-r="0.8"
:color-g="0.2"
:color-b="0.1"
/>
</template>
Properties with .set()
methods can accept arrays:
<template>
<!-- Automatically calls position.set(1, 2, 3) -->
<TresMesh :position="[1, 2, 3]" />
<!-- Automatically calls scale.set(2, 2, 2) -->
<TresMesh :scale="2" />
<!-- Automatically calls lookAt(0, 0, 0) -->
<TresPerspectiveCamera :look-at="[0, 0, 0]" />
</template>
Tres offers bare bones functionality, but it's easy to add third-party elements and extend
them into its internal catalogue.
Most of 3D experience uses OrbitControls
which is not part of the core threejs library. You can add it to your project by importing it from the three/addons/controls/OrbitControls module.
import { OrbitControls } from 'three/addons/controls/OrbitControls'
Then you can extend the catalogue with the extend
function:
<script setup lang="ts">
import { extend } from '@tresjs/core'
import { OrbitControls } from 'three/addons/controls/OrbitControls'
import { TextGeometry } from 'three/addons/geometries/TextGeometry'
// Add the element to the catalogue
extend({ TextGeometry, OrbitControls })
</script>
<template>
<TresCanvas shadows alpha>
<TresPerspectiveCamera :position="[5, 5, 5]" />
<TresOrbitControls v-if="state.renderer" :args="[state.camera, state.renderer?.domElement]" />
<TresMesh>
<TresTextGeometry :args="['TresJS', { font, ...fontOptions }]" center />
<TresMeshMatcapMaterial :matcap="matcapTexture" />
</TresMesh>
</TresCanvas>
</template>