Your First Scene
What You'll Build
By the end of this guide, you'll have created:
- A 3D scene with a rotating donut
- A reusable component structure
- Animation using TresJS composables
Step 1: Set Up the Canvas Component
First, let's create the main canvas component that will host our 3D scene. This component will contain the TresCanvas
and handle the overall scene setup.
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import FirstExperience from './components/FirstExperience.vue'
</script>
<template>
<TresCanvas
clear-color="#82DBC5"
window-size
>
<FirstExperience />
</TresCanvas>
</template>
TresCanvas
component is the root container for your 3D scene. The clear-color
prop sets the background color, and window-size
makes the canvas automatically fill the entire window without needing a parent container.Step 2: Set Up the Camera
Let's start by creating the experience component with just a camera. This will allow us to see the clear background color of our canvas.
TresCanvas
component from your 3D experience. This pattern helps with organization, reusability, and makes your code easier to maintain.<script setup lang="ts">
// No imports needed! TresJS components are available globally
</script>
<template>
<!-- Camera Setup -->
<TresPerspectiveCamera
:position="[7, 7, 7]"
:look-at="[0, 0, 0]"
/>
</template>
What you should see: A solid turquoise background (#82DBC5
) filling your entire window.
[0, 0, 0]
(the center of the scene). Always position your camera away from the origin to have a proper viewpoint of your 3D objects.The camera defines the viewpoint of your scene:
position="[7, 7, 7]"
places the camera at coordinates X=7, Y=7, Z=7 in 3D spacelook-at="[0, 0, 0]"
points the camera toward the center of the scene
Step 3: Add Visual Helpers
Before adding our donut, let's add some visual helpers to better understand the 3D space. These helpers will show us the coordinate axes and a grid.
<script setup lang="ts">
// No imports needed! TresJS components are available globally
</script>
<template>
<!-- Camera Setup -->
<TresPerspectiveCamera
:position="[7, 7, 7]"
:look-at="[0, 0, 0]"
/>
<!-- Visual Helpers -->
<TresAxesHelper />
<TresGridHelper />
</template>
What you should see: A turquoise background with red, green, and blue arrows showing the X, Y, Z axes, plus a grid on the ground plane.
Understanding the Helpers
TresAxesHelper
: Shows the coordinate system with colored arrows- Red arrow: X-axis (left/right)
- Green arrow: Y-axis (up/down)
- Blue arrow: Z-axis (forward/backward)
TresGridHelper
: Shows a grid on the XZ plane (ground)- Helps visualize object positioning and scale
- The grid center is at the origin (0, 0, 0)
Step 4: Add the Donut
Now let's add our 3D donut to the scene. In TresJS, 3D objects are created using a TresMesh
component with geometry and material as children.
<script setup lang="ts">
// No imports needed! TresJS components are available globally
</script>
<template>
<!-- Camera Setup -->
<TresPerspectiveCamera
:position="[7, 7, 7]"
:look-at="[0, 0, 0]"
/>
<!-- The Donut -->
<TresMesh :position="[0, 2, 0]">
<TresTorusGeometry :args="[1, 0.4, 16, 32]" />
<TresMeshBasicMaterial color="#ff6b35" />
</TresMesh>
<!-- Visual Helpers -->
<TresAxesHelper />
<TresGridHelper />
</template>
What you should see: A bright orange donut shape in the center of your scene!
Understanding the Mesh Structure
In TresJS, 3D objects follow a slot-based pattern:
TresMesh
is the container that represents a 3D object- The first child defines the geometry (shape)
- The second child defines the material (appearance)
Geometry Parameters:
TresTorusGeometry
creates the donut shape with an array of parameters[radius, tube, radialSegments, tubularSegments]
:radius: 1
- Overall size of the donuttube: 0.4
- Thickness of the donut tuberadialSegments: 16
- How smooth the donut curve istubularSegments: 32
- How smooth the tube surface is
Material Types:
TresMeshBasicMaterial
- Simple material that doesn't require lighting- Perfect for beginners and solid colors
Step 5: Add Animation
Finally, let's make our donut rotate! We'll use TresJS's useLoop
composable to create smooth animations.
<script setup lang="ts">
import { useLoop } from '@tresjs/core'
import { ref } from 'vue'
// Reference to our donut mesh for animation
const donutRef = ref()
// Animation loop
const { onBeforeRender } = useLoop()
onBeforeRender(({ elapsed }) => {
if (donutRef.value) {
// Rotate the donut on both X and Y axes
donutRef.value.rotation.x = elapsed * 0.5
donutRef.value.rotation.y = elapsed * 0.3
}
})
</script>
<template>
<!-- Camera Setup -->
<TresPerspectiveCamera
:position="[4, 4, 4]"
:look-at="[0, 0, 0]"
/>
<!-- The Donut -->
<TresMesh ref="donutRef">
<TresTorusGeometry :args="[1, 0.4, 16, 32]" />
<TresMeshBasicMaterial color="#ff6b35" />
</TresMesh>
</template>
What you should see: Your donut now rotates smoothly on both the X and Y axes!
Understanding Animation
The animation (system) consists of:
- Template Ref:
ref="donutRef"
creates a reference to the mesh object - useLoop Hook: Provides access to the render loop
- onBeforeRender: Runs before each frame is rendered
- Elapsed Time:
elapsed
parameter gives us the total time since animation started
onBeforeRender(({ elapsed }) => {
if (donutRef.value) {
donutRef.value.rotation.x = elapsed * 0.5 // Rotates on X-axis
donutRef.value.rotation.y = elapsed * 0.3 // Rotates on Y-axis (different speed)
}
})
elapsed
time creates smooth, time-based animations that run consistently regardless of frame rate. The multipliers (0.5 and 0.3) control the rotation speed on each axis.Step 6: Running Your Scene
Your scene is now complete! Since we've set up everything in app.vue
, your 3D scene will automatically render when you start your application. The window-size
prop ensures the canvas fills the entire viewport automatically.
Final Project Structure
Here's the complete file structure and code for your first TresJS scene:
<script setup lang="ts">
import { useLoop } from '@tresjs/core'
import { ref } from 'vue'
// Reference to our donut mesh for animation
const donutRef = ref()
// Animation loop
const { onBeforeRender } = useLoop()
onBeforeRender(({ elapsed }) => {
if (donutRef.value) {
// Rotate the donut on both X and Y axes
donutRef.value.rotation.x = elapsed * 0.5
donutRef.value.rotation.y = elapsed * 0.3
}
})
</script>
<template>
<!-- Camera Setup -->
<TresPerspectiveCamera
:position="[7, 7, 7]"
:look-at="[0, 0, 0]"
/>
<!-- The Donut -->
<TresMesh ref="donutRef" :position="[0, 2, 0]">
<TresTorusGeometry :args="[1, 0.4, 16, 32]" />
<TresMeshBasicMaterial color="#ff6b35" />
</TresMesh>
<!-- Visual Helpers -->
<TresAxesHelper />
<TresGridHelper />
</template>
Key Concepts Learned
Component Separation
Separating TresCanvas
from your 3D experience improves code organization and reusability.
Objects and Materials
In TresJS, 3D objects are created using a TresMesh
component with geometry and material as children.
Animation Loop
Using useLoop
provides a clean way to handle animations and updates in your 3D scene.
Template Refs
Using Vue's template refs allows you to directly manipulate 3D objects in your animations.
Next Steps
Now that you have your first scene running, you can:
- Extract the donut into its own component - Create a
TheDonut.vue
component to practice component composition - Experiment with different geometries and materials
- Add more objects to your scene (Get inspired by Three.js's Geometries and Materials)
- Try different camera positions and angles
- Explore more complex animations