TresJS v2 First steps with 3D on Vue
Tags: webdev, vue, threejs, 3d
Published: 2023-06-20 12:50:35

The TresJS team released [v2 of TresJS](https://twitter.com/tresjs_dev/status/1657051544901042177?s=20) on stage at [VueJS Live London 2023](https://vuejslive.com/) and we made the repo public for the community live on stage.

![TresJS live at Vuejs Live London](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mxxgidjoygezs5mdbuxa.jpg)

This version came with a lot of improvements, including some breaking changes (😜 TresJS is now based on [Custom Render API](https://vuejs.org/api/custom-renderer.html#createrenderer)), so the first content of the series became obsolete.

{% youtube https://youtu.be/k2ntrRtR8wc %}

So today, we are going to start fresh with the v2 and explain some of the core concepts. The video above is the updated version.

This will be the first article of a series with Basics of TresJS. 

It doesn't matter if you don't have previous experience with 3D or ThreeJS, this article will guide you on your first steps using a familiar ecosystem like Vue.

You can follow the series code available on this repository https://github.com/alvarosabu/tresjs-basics

## Basic parts of a 3D scene

![Parts of a 3D scene](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2fleubs8hokd855h15bd.png)

Before jumping to the code, let me quickly explain the parts that make up a 3D scene

- **Objects**, could be a sphere, a plane, lights, a 3D model of you favorite character (slide show 3D scene examples resembling the words, make pauses )
- Then we need a **Camera** to see those objects, to capture them.
- We wrap all in a **Scene** and then
- We tell the **Renderer** to render everything into a DOM Canvas element.

## Installing

To get started we are going to take a Vue app made with Vite, we are going to install the library by using:

```bash
pnpm add @tresjs/core three
```

If we want to have typescript support, we also need to install the latest types using `pnpm add @types/three -D` . This will ensure that your IDE gets the proper Intellisense.

## Usage

Now let’s open our `App.vue` and remove the default code and leave the `script` tag and the `template` tag empty

Next we import the `TresCanvas` component from the `@tresjs/core` package:

```html
<script lang="ts" setup>
import { TresCanvas } from '@tresjs/core'
</script>

<template>
  <TresCanvas>
		
  </TresCanas>
</template>
```

Something really important to know is that `<TresCanvas />` component will create a `<canvas />` DOM element which size (width and height) is exactly the one of it's parent. So if you don't see your scene, it's probably because it has a height of 0px.

To avoid that mistake, we are going to add some minimal css into our App.

```css
html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
}
#app {
  height: 100%;
  width: 100%;
}
```

## TresCanvas Props

As we would do with normal Vue, you can pass props to your `TresCanvas` component. Here is the list of props available for the [renderer](https://tresjs.org/api/renderer.html#props) 

```html
<TresCanvas :clear-color="'#82DBC5">
		
</TresCanas>
```

This will set the background color of the scene to a fun one, however, we still see only a blank page right 🤔?

That's because we haven't add a **Camera** yet.


## Perspective Camera

To be able to see (render) our scene, we need a camera, specifically a [Perspective Camera](https://threejs.org/docs/#api/en/cameras/PerspectiveCamera) which is the most similar to how camera works on videos or cinema. 

```html
<TresCanvas :clear-color="'#82DBC5">
 <TresPerspectiveCamera />	
</TresCanas>
```
Now you should be seeing something like this on your browser.

![Empty scene with background](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hshzafl2r7x4amozc0df.png)

Psst 🙊, this is gonna be improved on upcoming `v2.2` where there is a default PerspectiveCamera added by default.

## Adding an object

So now that we have "something" render on the browser, let's add a 3D Object.

A **Mesh** (a.k.a your object) is the rendering result of combining:

- **Geometry**: the structure composed of points (vertices), lines (edges) and polygons (faces).
- **Material**: are the visual properties of that object, it's color, texture, how reflective it is, if it shines etc.

![Mesh is the combination of a Geometry and a Material](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5knt4x4za6vxqdpofkod.png)

All we need to add to our template is a `<TresMesh />` component.

```vue
<TresMesh>
   <TresBoxGeometry/>
   <TresMeshNormalMaterial />
</TresMesh>
```

Notice how we pass 2 more components via **slots**, the `TresBoxGeometry` and the `TresMeshNormalMaterial`, both custom render components based on [`THREE.BoxGeometry`](https://threejs.org/docs/index.html?q=BoxG#api/en/geometries/BoxGeometry) and [`THREE.MeshNormalMaterial`](https://threejs.org/docs/index.html?q=MeshNor#api/en/materials/MeshNormalMaterial) from ThreeJS. 


![Cube Mesh with NormalMaterial](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mjv5sxs95m961xx30nqv.png)

For now, we are going to use a cube with a normal material that resembles the RGB colors (looks pretty cool). In the follow up series we are going to go deeper in **Geometries** and **Materials**.

## Initialise instances with `args`

In the previous example we created a Cube of `1x1x1`. How can we tell TresJS to create a wider box? We can use `args` prop to initialise the instance with different arguments.

```vue
<TresMesh>
   <TresBoxGeometry :args="[2,1,1]"/>
   <TresMeshNormalMaterial />
</TresMesh>
```

The result should be something like this:

![Box with args](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8lk5y339h93txihe0vnc.png)

To check what arguments the component expect, you can easily search for the constructor arguments [available on the ThreeJS docs](https://threejs.org/docs/index.html?q=boxge#api/en/geometries/BoxGeometry)

## Transform the object

Transforming your mesh is easier that you would imagine. You just need to set a prop for:

- Position
- Rotation
- Scale

You can pass an array of numbers `[1, 2, 3]` where `[x,y,z]`, or a `new THREE.Vector(1,2,3)` vector. TresJS will format it for you.


![Intellisense showing position prop type](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6ef6bm22x7iv9zy1322.png)

### Position

To change the position of an object relative to the world origin `[0,0,0]` just pass a value to the prop like this:

```vue
<TresMesh :position="[1,2,-1]">
   <TresBoxGeometry/>
   <TresMeshNormalMaterial />
</TresMesh>
```

![Box moved to new position](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7vdzd34tbf7mf4ahoxiu.png)

### Rotation

In addition to changing the position of an object, you may also want to adjust the rotation. This is typically done using Euler angles in the x, y, and z dimensions. The rotation values are given in radians.

For instance, if you want to rotate an object 90 degrees about the Y axis, you will use `Math.PI/2` as the value. You may specify the rotation of the object with the `rotation` prop, which also takes an array of three values or a Vector3, representing rotations along the x, y, and z axis respectively. Here's an example:

```vue
<TresMesh :rotation="[Math.PI/4, Math.PI/2, 0]">
   <TresBoxGeometry/>
   <TresMeshNormalMaterial />
</TresMesh>
```

![Box rotated in X and Y axis](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2phkcgq46o3z8br0t13w.png)

In this example, the mesh is rotated 90 degrees around the Y axis and 45 degrees on the X axis. Notice that we didn't rotate it around Z (values are 0).

### Scale
The scale of an object determines its size in the 3D world. It's specified in terms of the `scale` prop. By default, the scaling factor of an object is 1 in all directions.

You can use the scale prop to make an object larger or smaller. For instance, if you want to make an object twice as wide and half as tall, you could pass `[2,0.5,1]` as the value to the scale prop, like so:

```vue
<TresMesh :scale="[2, 0.5, 1]">
   <TresBoxGeometry/>
   <TresMeshNormalMaterial />
</TresMesh>
```

![Box scaled twice as wide and half as tall](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d16if6h1hv6miu2hs3c1.png)

### Transform the Camera

Just like other objects in the 3D world, the camera in a 3D scene can also be manipulated in terms of its position and rotation. In Vue, this can be done using the `TresPerspectiveCamera` component. This is particularly useful to frame the view of your scene to fit your specific needs.

Unlike other objects, though, the camera also has the ability to "look at" a particular point in the scene. This is not equivalent to rotation, as rotation for the camera involves changing the direction it's facing. Instead, "look at" sets the direction the camera is facing to point directly at a specific point.

Here's an example of how you might change the position of the camera and have it look at the center of the scene:

```vue
<TresPerspectiveCamera 
    :position="[10,10,10]"
    :lookAt="[0,0,0]"
/>
```

In this example, the camera is positioned at the coordinates `[10,10,10]`, which would place it in the top right front corner of the scene when looking from the origin. The `lookAt` prop is used to direct the camera towards the center of the scene, `[0,0,0]`. 

The "look at" functionality is extremely useful for focusing the camera on specific areas of a 3D scene, especially when used in combination with adjusting the camera's position. By manipulating these properties, you can achieve an ideal perspective for your particular 3D scene.

### Conclusion

In this article, we've explored the core aspects of creating 3D scenes using Tres.js v2 in a Vue application. We started off with the installation process of Tres.js, leading into a basic understanding of 3D scenes, and how to setup the TresCanvas.

We discussed the perspective camera, which is a critical component of a 3D scene. This sets the viewpoint from which your scene will be observed. We also covered how to add objects (meshes) to the scene, which require a geometry and a material. The geometry determines the shape of the object, while the material defines its appearance.

From there, we explored transformation properties, including position, rotation, and scale, which allow you to control where your object is, how it's oriented, and what size it is in the scene. Furthermore, we've seen that not only meshes, but any object in the 3D world, including the camera itself, can be transformed and manipulated to fit the needs of your scene.

This provides a solid basis for getting started with 3D scenes in Vue using Tres.js. Remember, this is just the beginning - there's a whole world of complex and beautiful 3D scenes you can create from here!

As always, if you have any questions, comments, or insights you'd like to share, please feel free to leave them below. Your feedback is not only welcomed, but highly appreciated as it helps us all learn and grow. And remember to stay tuned for more articles in this series as we dive deeper into the fascinating world of 3D modeling with Tres.js and Vue!

Happy coding 😊✌️