Consejo rápido: cómo renderizar a una textura en Three.js
Spanish (Español) translation by Carlos (you can also view the original English article)
Por defecto, todo lo que renderizas en Three.js es enviado a la pantalla. Después de todo, ¿qué sentido tiene renderizar algo si no puedes verlo? Resulta que hay un punto muy importante: capturar los datos antes de que se envíen a la pantalla (y por consiguiente se pierdan).
Esto facilita la aplicación de efectos de postprocesamiento, como corrección de color, cambio de color o desenfoque, y también es útil para los efectos de sombreado.
Esta técnica es conocida como renderizado a una textura o renderizado a un frame buffer; tu resultado final se almacena en una textura. Que luego puedes renderizar en la pantalla. En este consejo breve, te enseñaré cómo hacerlo, y luego te guiaré a través de un ejemplo práctico de cómo renderizar un cubo en movimiento sobre las superficies de otro cubo en movimiento.
Nota: Este tutorial asume que tienes cierto conocimiento básico de Three.js. Si no, consulta: Cómo aprender Three.js para el desarrollo de juegos.
Implementación básica
Existen muchos ejemplos sobre cómo hacer esto que suelen estar integrados en efectos más complicados. Aquí está lo mínimo que se necesita para renderizar algo en una textura en Three.js:
1 |
// @author Omar Shehata. 2016.
|
2 |
// We are loading the Three.js library from the CDN here:
|
3 |
// https://cdnjs.com/libraries/three.js/
|
4 |
|
5 |
//// This is the basic scene setup ////
|
6 |
|
7 |
var scene = new THREE.Scene(); |
8 |
var width, height = window.innerWidth, window.innerHeight; |
9 |
var camera = new THREE.PerspectiveCamera( 70, width/height, 1, 1000 ); |
10 |
var renderer = new THREE.WebGLRenderer(); |
11 |
renderer.setSize( width,height); |
12 |
document.body.appendChild( renderer.domElement ); |
13 |
|
14 |
//// This is where we create our off-screen render target ////
|
15 |
|
16 |
// Create a different scene to hold our buffer objects
|
17 |
var bufferScene = new THREE.Scene(); |
18 |
// Create the texture that will store our result
|
19 |
var bufferTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter}); |
20 |
|
21 |
////
|
22 |
// Add anything you want to render/capture in bufferScene here //
|
23 |
////
|
24 |
|
25 |
function render() { |
26 |
requestAnimationFrame( render ); |
27 |
// Render onto our off-screen texture
|
28 |
renderer.render(bufferScene, camera, bufferTexture); |
29 |
// Finally, draw to the screen
|
30 |
renderer.render( scene, camera ); |
31 |
}
|
32 |
|
33 |
render(); // Render everything! |
Primero tenemos la configuración básica de la escena. Luego, creamos otra escena, BufferScene
; cualquier objeto que añadamos a esta escena será atraído a nuestro objetivo fuera de la pantalla en vez de a la pantalla.
Después, creamos bufferTexture
, que es un WebGLRenderTarget. Esto es lo que Three.js utiliza para permitirnos renderizar en algo más que la pantalla.
Por último, le decimos a Three.js que renderice bufferScene
:
1 |
renderer.render(bufferScene, camera, bufferTexture); |
Esto es como renderizar una escena normal, excepto que especificamos un tercer argumento: el objetivo de la renderización.
Así que los pasos son:
- Crear una escena para contener tus objetos.
- Crear una textura para almacenar lo que renderizas
- Renderizar tu escena en tu textura
Esto es básicamente lo que necesitamos hacer. Sin embargo, no es muy emocionante, puesto que no podemos ver nada. Aun si has añadido cosas a BufferScene
, seguirás sin ver nada; esto se debe a que de alguna manera tienes que renderizar la textura que has creado en tu escena principal. El siguiente es un ejemplo de cómo hacerlo.
Ejemplo de uso
Vamos a crear un cubo en una escena, dibujarlo en una textura, y ¡luego utilizar eso como una textura para un nuevo cubo!



1. Empieza con una escena básica
Aquí está nuestra escena básica con un cubo rojo girando y un plano azul detrás de él. No hay nada especial aquí, pero puedes revisar el código cambiando a las pestañas CSS o JS en la demostración.
2. Renderiza esta escena en una textura
Ahora vamos a tomar eso y renderizarlo en una textura. Todo lo que debemos hacer es crear un bufferScene
como en la implementación básica anterior, y añadirle nuestros objetos.
Si se ha hecho bien, no veremos nada, ya que ahora no se está proyectando nada en la pantalla. En lugar de ello, nuestra escena se ha renderizado y se ha guardado en BufferTexture
.
3. Renderiza un cubo texturizado
bufferTexture
no es diferente de cualquier otra textura. Podemos simplemente crear un nuevo objeto y utilizarlo como nuestra textura:
1 |
var boxMaterial = new THREE.MeshBasicMaterial({map:bufferTexture}); |
2 |
var boxGeometry2 = new THREE.BoxGeometry( 5, 5, 5 ); |
3 |
var mainBoxObject = new THREE.Mesh(boxGeometry2,boxMaterial); |
4 |
|
5 |
// Move it back so we can see it
|
6 |
mainBoxObject.position.z = -10; |
7 |
// Add it to the main scene
|
8 |
scene.add(mainBoxObject); |
¡Podrías dibujar cualquier cosa en la primera textura, y luego renderizarla en lo que quieras!
Usos potenciales
El uso más simple es cualquier tipo de efecto de postprocesamiento. Si quisieras aplicar algún tipo de corrección o cambio de color a tu escena, en vez de aplicarla a cada uno de los objetos, podrías simplemente renderizar toda la escena en una textura, y luego aplicar el efecto que desees a esa textura final antes de renderizarla en la pantalla.
Cualquier tipo de sombreador que requiera múltiples pasadas (como el desenfoque) hará uso de esta técnica. Explico cómo utilizar frame buffers de para crear un efecto de humo en este tutorial.
¡Esperamos que te haya resultado útil este pequeño consejo ! Si detectas algún error o tienes alguna pregunta, ¡por favor házmelo saber en los comentarios!