tres-objects.md 6.8 KB


title: Tres Components

description: Learn how TresJS automatically maps Vue components to Three.js objects using a custom renderer and autogenerated catalogue.

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.

Declaring objects

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()

Constructor Arguments with 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 view
  • aspect - Camera frustum aspect ratio
  • near - Camera frustum near plane
  • far - Camera frustum far plane

To 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>

Basic Usage

<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>

Common Patterns

::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>

::

Declarative Properties

Beyond constructor arguments, TresJS allows you to set properties declaratively using Vue props:

Property Mapping

<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>

Shorthand Properties

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>

Set Methods

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>

Extending the Catalogue 🔌

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>