Programación 3D con JavaScript - parte 2
Tags: webdev, javascript, 3d, threejs
Published: 2023-12-15 14:17:04

> [Primera parte](https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-1-2k95)

## Configurando nuestro entorno 🤓

Bien, lo primero que vamos a hacer es configurar nuestro entorno de trabajo, no importa que editor uses, necesitaremos un archivo HTML como punto de entrada. Luego darle un `margin:0 ` de estilo al `body`. Por último importaremos un script que contendrá nuestro archivo JS.

```
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<title>My first three.js app</title>
		<style>
			body { margin: 0; }
		</style>
	</head>
	<body>
		<script type="module" src="/main.js"></script>
	</body>
</html>
```
Sip, eso es todo el HTML y CSS que necesitaremos 😮.

Bien, ahora depende de donde y como estés trabajando, puedes instalar ThreeJS o por CDN o por npm packages.  [Guía de instalacion](https://threejs.org/docs/index.html#manual/en/introduction/Installation)

## Elementos indispensables de toda escena 3D

Son 5 y veremos uno por uno, la idea es entender bien la función de cada uno, en lugar de solo copiar y pegar (si copias el código de [Creating-a-scene](https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene) de threejs ya tienes el famoso verde cubo girando, pero así ni una gracia).

- **Scene** 🖼️: Contenedor de nuestras instancias
- **Camera** 🎥: Actuará como nuestros ojos en la escena
- **Renderer** 🔩: Motor de renderizado.
- **Mesh** 🔮: Objecto 3D, algo que mostrar
- **Request animation frame API** 💥: Para animar nuestras escenas 

### Scene 🖼️

El elemento `Scene`, va a servir como nuestro contenedor, en él van a vivir todos nuestros elementos, sean luces, cámaras, modelos 3D, etc.

Para crearlo solo debemos importarlo de ThreeJs e instanciarlo de la siguiente forma:

```
import * as THREE from 'three';

const scene = new THREE.Scene();
console.log('scene', scene)
```
**Nota:** acá estamos importando todo como THREE, para mayor flexibilidad. Esto no tiene muy buen rendimiento pero es cómodo. Si quisiéramos pudiéramos importar `Scene` como:
 `import { Scene } from 'three'`

Si prestamos atención a nuestro log veremos algo como:

![Log example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bw61fs9r1bwdfmvntl15.png)

Algo muy útil acerca de ThreeJs es que la gran mayoría de objetos heredan de la clase [Object3D](https://threejs.org/docs/index.html?q=obje#api/en/core/Object3D). Esto significa que muchas propiedades, serán compartidas en otras instancias.

Por ejemplo, una buena práctica es asignarles nombres a nuestro objeto y luego es fácil recorrer toda la escena en busca de él.

Algo particular para prestar atención es nuestra propiedad `children` 👶, allí veremos todos los objetos 3D que forman parte de nuestra escena.

### Camera 🎥

Existen varios tipos de cámaras y para verlas todas en profundidad necesitaríamos un post completo 🙅‍♂️. Por ahora empezaremos usando la `PerspectiveCamera` Es la más fácil de entender por qué simula el ojo humano (los objetos más alejados se ven más pequeños).

Para la [PerspectiveCamera](https://threejs.org/docs/index.html?q=perspe#api/en/cameras/PerspectiveCamera) necesitaremos proporcionar unos parámetros, la gran mayoría serán por ahora estándar, pero veamos que son:
- **fov**: field of view, campo de visión. Me parece que con una imagen se expresa mejor este parámetro.

![Field of view](https://cdn.securityinfowatch.com/files/base/cygnus/siw/image/2019/05/960w/Olsen_1_Camera_FOV.5ce321b430946.jpg)

- **aspect-ratio**: en nuestro caso tomaremos el aspect-ratio de nuestro viewport, que no es más que dividir nuestro window.innerWidth / window.innerHeight

- **near**: Que tan cerca de nosotros la cámara renderizará
- **far**: Que tan lejos nuestra la cámara renderizará

```
// trabajar con un objecto sizes resulta muy comodo
const sizes = {
  width: window.innerWidth,
  height: window.innerHeight
};

const camera = new THREE.PerspectiveCamera(
  45,
  sizes.width / sizes.height,
  1,
  1000
);
console.log('camera', camera)
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mchmqde2rlz3dauc5syf.png)


_Algo_ importante a tener en cuenta es que "si la cámara no lo renderiza, no consume recursos"

Ahora y como último detalle, recordemos añadir nuestra cámara a nuestra escena con la función scene.add():

```
...
scene.add(camera);
```

### Renderer 🔩

Nuestro renderer es el puente entre la WebGL API y ThreeJS, básicamente es el motor que da vida a nuestros increíbles gráficos.

ThreeJs provee varios renderers, nosotros en esta ocasión usaremos el `WebGLRenderer`, lo instanciamos de la siguiente forma:

```
const renderer = new THREE.WebGLRenderer();
renderer.setSize(sizes.width, sizes.height);
document.body.appendChild(renderer.domElement);
renderer.setClearColor("#111");
renderer.render(scene, camera);
```
Entonces veamos paso a paso:

1. Instanciamos nuestro `WebGLRenderer` desde threeJs
2. Indicamos el tamaño que tendrá nuestra escena
3. Acá podemos proporcionarle un elemento HTMLcanvas personalizado o cuando no hemos creado uno manualmente(como es nuestro caso) ThreeJs creará uno automáticamente y vivirá dentro de `renderer.domElement` Entonces lo que hacemos es colocarlo en nuestro body.
4. Como detalle opcional (y muchas veces útil), colocaremos el fondo de la escena, un negro menos intenso
5. Y el último paso es llamar a la función `render` que recibe como parámetros la escena y la cámara anteriormente creados

Si todo ha salido de manera correcta, veremos que nuestra pantalla está negra, esto es una buena señal, significa que tenemos una escena con threeJs corriendo exitosamente :).

Obviamente, no tiene nada que mostrar aún, pero cambiaremos esto y otros detalles en nuestro siguiente post 

Happy 3D coding 😊

> [Tercera parte](https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-3-56cj)