How to Use Three.js WebGLRenderTarget
In Three.js, the WebGLRenderTarget class allows you to
render a 3D scene to an off-screen frame buffer instead of directly to
the screen. This technique, commonly known as render-to-texture, is
essential for creating advanced visual effects like dynamic mirrors,
security camera feeds, portal effects, and custom post-processing
passes. This article provides a straightforward, step-by-step guide on
how to set up a WebGLRenderTarget, render a secondary scene
to it, and apply the resulting texture to an object in your main
scene.
Step 1: Create the WebGLRenderTarget
First, instantiate the WebGLRenderTarget. You need to
define the width and height of the off-screen texture in pixels. Higher
resolutions yield sharper textures but require more GPU memory and
processing power.
const rtWidth = 512;
const rtHeight = 512;
const renderTarget = new THREE.WebGLRenderTarget(rtWidth, rtHeight);Step 2: Set Up the Off-Screen Scene
To render something to your target, you need a separate scene and camera setup. This represents the “virtual camera” capturing the off-screen content.
// Create the off-screen scene
const offscreenScene = new THREE.Scene();
offscreenScene.background = new THREE.Color(0x111111);
// Create the off-screen camera
const offscreenCamera = new THREE.PerspectiveCamera(45, rtWidth / rtHeight, 0.1, 100);
offscreenCamera.position.z = 5;
// Add an object to the off-screen scene
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const offscreenCube = new THREE.Mesh(geometry, material);
offscreenScene.add(offscreenCube);Step 3: Use the Render Target Texture in Your Main Scene
The WebGLRenderTarget object contains a
.texture property. You can map this texture directly to a
material used by a mesh in your main visible scene.
// Create your main scene and camera
const mainScene = new THREE.Scene();
const mainCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
mainCamera.position.z = 5;
// Create a plane mesh that will display the off-screen render texture
const displayGeometry = new THREE.PlaneGeometry(3, 3);
const displayMaterial = new THREE.MeshBasicMaterial({ map: renderTarget.texture });
const displayPlane = new THREE.Mesh(displayGeometry, displayMaterial);
mainScene.add(displayPlane);Step 4: Update the Render Loop
In your animation loop, you must perform two render passes. First,
point the renderer to your WebGLRenderTarget and render the
off-screen scene. Then, reset the renderer target to null
(which defaults back to the screen’s canvas) and render the main
scene.
function animate() {
requestAnimationFrame(animate);
// 1. Rotate the off-screen object for visible animation
offscreenCube.rotation.x += 0.01;
offscreenCube.rotation.y += 0.01;
// 2. Direct the renderer to draw to the off-screen render target
renderer.setRenderTarget(renderTarget);
renderer.render(offscreenScene, offscreenCamera);
// 3. Reset the renderer target back to the canvas (screen)
renderer.setRenderTarget(null);
// 4. Render the main scene showing the updated texture
renderer.render(mainScene, mainCamera);
}
animate();Step 5: Clean Up Resources
Because render targets occupy GPU memory, you should properly dispose of them when they are no longer needed to prevent memory leaks.
renderTarget.dispose();