3D Graphics

Three.js

Three.js hace que WebGL sea accesible: un grafo de escena, cámaras, materiales y luces te permiten crear experiencias 3D para el navegador en JavaScript puro.

advanced14 min readUpdated 15 sept 2026
scene.js
js
// scene.js
import * as THREE from "three";

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  innerWidth / innerHeight,
  0.1,
  100,
);
camera.position.z = 3;

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

const cube = new THREE.Mesh(
  new THREE.BoxGeometry(),
  new THREE.MeshStandardMaterial({ color: 0x22c55e }),
);
scene.add(cube);

renderer.setAnimationLoop(() => {
  cube.rotation.y += 0.01;
  renderer.render(scene, camera);
});
Basado en
WebGL
Concepto central
Scene graph
Renderizador
WebGLRenderer
Modelos
glTF / GLTFLoader
React
React Three Fiber
Costo
GPU y peso del bundle

Por que importa

Por qué usar 3D en la web

Un grafo de escena

Añade objetos a una escena y Three.js se encarga de las matemáticas, las transformaciones y las llamadas de dibujo por ti.

Aceleración por hardware

WebGL dibuja con la GPU, por lo que el 3D fluido es posible en dispositivos modernos y teléfonos.

Sistema de materiales rico

Materiales estándar, físicos y personalizados, además de luces, sombras y post-procesamiento, crean visuales convincentes.

La imagen completa

Las tres partes de una app de Three.js

Una escena contiene tus objetos, una cámara decide la vista y un renderizador la dibuja usando WebGL.

La escena

Contenido

Un grafo de mallas, luces, cámaras y grupos posicionados en el espacio 3D.

La cámara

Vista

Perspectiva u ortográfica, definiendo qué es lo que ve el usuario.

El renderizador

Dibujo

WebGLRenderer dibuja la escena en cada frame, y la animación la actualiza a lo largo del tiempo.

Three.js de un vistazo

El núcleo de Three.js

Geometría y material

Una malla (mesh) es una geometría (forma) más un material (superficie).

Cámara

PerspectiveCamera para profundidad realista, Orthographic para vistas planas.

Luces

Luces direccionales, ambientales, puntuales y focales dan forma a la escena.

Texturas y modelos

Carga imágenes y modelos glTF mediante loaders.

Raycaster

Detecta sobre qué objeto está el puntero para permitir la interacción.

Rendimiento

Reutiliza geometrías, limita las luces y libera los recursos.

Una breve historia

De WebGL puro a un 3D accesible

  1. 2011

    Lanzamiento de Three.js

    Ricardo Cabello crea una librería para hacer WebGL accesible.

    11
  2. 2013

    WebGL se generaliza

    El soporte de los navegadores madura y las experiencias 3D se vuelven comunes.

    13
  3. 2017

    Estándar glTF

    Un formato 3D compacto hace que la carga de modelos sea práctica.

    17
  4. 2020

    React Three Fiber

    Un renderizador declarativo de React lleva el 3D al código de componentes.

    20
  5. Hoy

    Web inmersiva

    Configuradores de productos, visualización de datos, juegos y experiencias WebXR.

    Hoy

La guia completa

Three.js: Todo lo que necesitas saber

¿Qué es el 3D en la web?

WebGL permite que el navegador dibuje 3D acelerado por hardware utilizando la GPU. Es potente, pero su API nativa es verbosa: debes gestionar buffers, escribir shaders y encargarte de las matemáticas por tu cuenta. Three.js envuelve WebGL en un grafo de escena amigable para que puedas describir objetos, luces y cámaras, dejando que la librería se encargue del resto.

El resultado es que el 3D en la web es ahora práctico para configuradores de productos, visualización de datos, storytelling interactivo, juegos y experiencias inmersivas de WebXR. No es la opción adecuada para todos los sitios, pero cuando el movimiento y el espacio cuentan la historia mejor que una página plana, Three.js es la herramienta estándar.

Escena, cámara y renderizador

Cada aplicación de Three.js tiene tres objetos fundamentales.

// setup.js
import * as THREE from "three";

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 100);
camera.position.set(0, 0, 3);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

La scene es el contenedor. La camera define la vista; PerspectiveCamera aporta una profundidad realista, mientras que OrthographicCamera es útil para vistas planas o isométricas. El renderer dibuja la escena en un canvas. Limitar el pixel ratio evita que las pantallas de alta densidad rendericen más píxeles de los necesarios.

Meshes, geometría y materiales

Un objeto visible es un mesh: una geometría para su forma y un material para su superficie.

// mesh.js
const cube = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  new THREE.MeshStandardMaterial({ color: 0x22c55e, roughness: 0.4 }),
);
cube.position.set(0, 0, 0);
scene.add(cube);

Three.js incluye muchas geometrías integradas (box, sphere, plane, torus y más) y materiales para lograr diferentes apariencias. MeshStandardMaterial responde a las luces y es una buena opción por defecto; MeshBasicMaterial ignora la iluminación y es más ligero. Los meshes pueden agruparse y anidarse, formando el grafo de la escena a través del cual se heredan las transformaciones.

Luces y sombras

Sin luz, la mayoría de los materiales se renderizan en negro.

// lights.js
const ambient = new THREE.AmbientLight(0xffffff, 0.4);
const key = new THREE.DirectionalLight(0xffffff, 2.5);
key.position.set(2, 3, 2);

scene.add(ambient, key);

Las luces son objetos en la escena, por lo que su posición y tipo son fundamentales. Las sombras requieren activar renderer.shadowMap y marcar la luz, el objeto y la superficie; además, son relativamente costosas, así que úsalas con moderación. Cada luz añade carga al rendimiento, por lo que es recomendable mantener el número de luces al mínimo.

Modelos y texturas

En los proyectos reales, lo habitual es cargar assets en lugar de construir la geometría a mano. glTF es el formato estándar de 3D para la web.

// load.js
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";

const loader = new GLTFLoader();
loader.load("/models/robot.glb", (gltf) => {
  scene.add(gltf.scene);
});

Las texturas se cargan de forma similar con TextureLoader, y RGBELoader o PMREMGenerator pueden proporcionar mapas de entorno para lograr reflejos realistas. Mantén el tamaño de los modelos y las texturas en niveles razonables, ya que son los elementos que más afectan al tiempo de carga y al uso de memoria.

El bucle de animación

La animación actualiza la escena y la vuelve a renderizar en cada frame.

// loop.js
const clock = new THREE.Clock();

renderer.setAnimationLoop(() => {
  const delta = clock.getDelta();
  cube.rotation.y += delta;
  renderer.render(scene, camera);
});

El uso de delta mantiene la velocidad del movimiento constante, independientemente de la tasa de refresco (frame rate). Cuando la escena es estática, renderiza bajo demanda en lugar de hacerlo continuamente: renderiza después de un cambio, una interacción con los controles o una animación, y detente cuando no esté ocurriendo nada. Esto ahorra batería y recursos de la GPU en dispositivos móviles.

Interacción

Para hacer que los objetos sean clickeables o reaccionen al pasar el cursor, utiliza un Raycaster.

// pick.js
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();

addEventListener("pointerdown", (event) => {
  pointer.x = (event.clientX / innerWidth) * 2 - 1;
  pointer.y = -(event.clientY / innerHeight) * 2 + 1;

  raycaster.setFromCamera(pointer, camera);
  const hit = raycaster.intersectObjects(scene.children)[0];
  if (hit) hit.object.material.color.set(0xf97316);
});

El raycasting desde la cámara a través del puntero devuelve los objetos que se encuentran debajo, lo cual es suficiente para la selección, el resaltado e interacciones sencillas.

Rendimiento y limpieza

El 3D es lo más costoso que la mayoría de los sitios llegarán a renderizar, por lo que la disciplina es fundamental.

  • Libera (Dispose) geometrías, materiales y texturas cuando elimines objetos; estos residen en la memoria de la GPU.
  • Reutiliza geometrías y materiales entre instancias en lugar de crear nuevos.
  • Fusiona (Merge) geometrías estáticas y utiliza instancing para objetos repetidos.
  • Limita las luces y los objetos que proyectan sombras.
  • Reduce el pixel ratio en pantallas de alta densidad.
  • Renderiza bajo demanda para escenas estáticas.
  • Pausa el renderizado cuando el canvas esté fuera de la pantalla.
// dispose.js
mesh.geometry.dispose();
mesh.material.dispose();
scene.remove(mesh);

Olvidar liberar la memoria es la causa más común de que una aplicación de Three.js consuma lentamente toda la memoria disponible.

React Three Fiber

Con React, React Three Fiber renderiza Three.js de forma declarativa, por lo que la escena se describe mediante componentes y se integra con el estado y el ciclo de vida de React.

// Scene.jsx
import { Canvas } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";

export function Scene() {
  return (
    <Canvas>
      <ambientLight intensity={0.4} />
      <directionalLight position={[2, 3, 2]} intensity={2.5} />
      <mesh>
        <boxGeometry />
        <meshStandardMaterial color="#22c55e" />
      </mesh>
      <OrbitControls />
    </Canvas>
  );
}

Los helpers de drei proporcionan controles, entornos y abstracciones comunes. Es la forma recomendada de utilizar Three.js en React.

Mejores prácticas

  • Limita el pixel ratio y ajusta el tamaño del renderer según la ventana.
  • Reutiliza geometrías y materiales; utiliza instanciado para objetos repetidos.
  • Libera los recursos de la GPU al eliminar objetos.
  • Mantén al mínimo el número de luces y emisores de sombras.
  • Renderiza bajo demanda en escenas estáticas.
  • Realiza pruebas en dispositivos móviles reales de gama media.
  • Proporciona una alternativa (fallback) cuando WebGL no esté disponible.

Errores comunes

  • Olvidar hacer el dispose y provocar fugas de memoria de la GPU.
  • Renderizar continuamente cuando nada ha cambiado.
  • Crear nuevas geometrías o materiales en cada frame.
  • Añadir demasiadas luces y sombras sin realizar mediciones.
  • Cargar modelos y texturas enormes y sin optimizar.
  • Probar únicamente en un ordenador rápido y desplegar en dispositivos móviles.

Próximos pasos

Three.js abre una dimensión completamente nueva para la web. Añade movimiento coreografiado con la guía de Animación Avanzada, construye con React Three Fiber si utilizas React, y mantén el rendimiento optimizado con la guía de Rendimiento Web. Después, crea la escena más sencilla posible —un cubo iluminado alrededor del cual puedas orbitar— y ve expandiéndola concepto a concepto.

Gestión de recursos de la GPU

Las geometrías, materiales y texturas residen en la memoria de la GPU. Libéralos (dispose) cuando elimines un objeto, o la escena tendrá fugas de memoria.

Preferir
function remove(mesh) {
  mesh.geometry.dispose();
  mesh.material.dispose();
  mesh.material.map?.dispose();
  scene.remove(mesh);
}
Evitar
scene.remove(mesh);
// geometry and textures
// stay in GPU memory

Renderizado de frames

Renderiza continuamente solo cuando la escena cambie. Para escenas estáticas, renderiza bajo demanda para ahorrar batería y GPU.

Preferir
// render when needed
controls.addEventListener("change", () => {
  renderer.render(scene, camera);
});
Evitar
renderer.setAnimationLoop(() => {
  renderer.render(scene, camera);
});
// runs at 60fps forever,
// even when nothing moves

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender Three.js / WebGL?

Nuestro tutorial interactivo te guia a traves de Three.js / WebGL paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.