WebGLRenderTarget: рендеринг в текстуру

WebGLRenderTarget — это объект, который позволяет рендерить сцену не на экран, а в текстуру. Полученная текстура может использоваться для последующего отображения на объектах сцены, для постобработки, создания эффектов отражений, теней и многого другого. Это мощный инструмент для реализации сложных визуальных эффектов в WebGL через Three.js.

В отличие от стандартного рендеринга в канвас, WebGLRenderTarget хранит framebuffer, в который происходит отрисовка сцены. После рендеринга его можно использовать как обычную текстуру.

const renderTarget = new THREE.WebGLRenderTarget(width, height, {
    minFilter: THREE.LinearFilter,
    magFilter: THREE.LinearFilter,
    format: THREE.RGBAFormat
});

Параметры minFilter, magFilter и format управляют качеством и форматом текстуры. Обычно используется THREE.LinearFilter для сглаживания и THREE.RGBAFormat для поддержки прозрачности.


Рендеринг сцены в текстуру

Для рендеринга сцены в текстуру используется метод renderer.setRenderTarget и renderer.render. Сначала создается сцена и камера, затем создается WebGLRenderTarget, после чего сцена рендерится в текстуру:

const sceneRTT = new THREE.Scene();
const cameraRTT = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);

const renderTarget = new THREE.WebGLRenderTarget(1024, 1024);
renderer.setRenderTarget(renderTarget);
renderer.render(sceneRTT, cameraRTT);
renderer.setRenderTarget(null); // возвращаем рендеринг на экран

После этого renderTarget.texture можно использовать в качестве материала на любом объекте:

const material = new THREE.MeshBasicMaterial({ map: renderTarget.texture });
const quad = new THREE.Mesh(new THREE.PlaneGeometry(5, 5), material);
scene.add(quad);

Такой подход позволяет создавать эффекты зеркал, порталов, динамических экранов.


Постобработка и эффекты

WebGLRenderTarget является основой для постобработки через ShaderPass. Обычно создается несколько render target для ping-pong рендеринга, где текстуры чередуются для применения нескольких эффектов:

const renderTarget1 = new THREE.WebGLRenderTarget(width, height);
const renderTarget2 = new THREE.WebGLRenderTarget(width, height);

// пример простого эффекта: размытие
shaderMaterial.uniforms['tDiffuse'].value = renderTarget1.texture;
renderer.setRenderTarget(renderTarget2);
renderer.render(postProcessScene, postProcessCamera);

Использование нескольких рендер-таргетов позволяет комбинировать эффекты bloom, motion blur, depth of field без необходимости постоянного рендеринга основной сцены.


Глубина, stencil и мультисемплинг

WebGLRenderTarget поддерживает опции глубины и stencil, что важно для сложных эффектов, таких как тени и отражения:

const renderTarget = new THREE.WebGLRenderTarget(width, height, {
    depthBuffer: true,
    stencilBuffer: false,
    samples: 4 // включение мультисемплинга
});
  • depthBuffer: true — создается буфер глубины, необходимый для корректного наложения объектов.
  • stencilBuffer: true — используется для масок и сложных эффектов рендеринга.
  • samples — количество сэмплов для мультисемплинга, уменьшает aliasing.

Использование Multiple Render Targets (MRT)

Three.js поддерживает несколько render target одновременно через WebGLMultipleRenderTargets, что позволяет рендерить несколько текстур за один проход шейдера. Это полезно для deferred shading и G-buffer.

const mrt = new THREE.WebGLMultipleRenderTargets(width, height, 3);
mrt.texture[0].name = "color";
mrt.texture[1].name = "normal";
mrt.texture[2].name = "position";

Каждая текстура сохраняет разные данные, которые потом используются в шейдере для освещения или постобработки.


Практические советы

  • Размер WebGLRenderTarget влияет на производительность. Оптимально использовать степени двойки: 512x512, 1024x1024.
  • Не забывать возвращать renderer.setRenderTarget(null) после рендеринга в текстуру, иначе следующий рендер будет направлен в текстуру, а не на экран.
  • Для динамических текстур, обновляющихся каждый кадр, лучше создавать WebGLRenderTarget один раз и переиспользовать его.
  • Можно комбинировать WebGLRenderTarget с CubeCamera для создания реалистичных отражений окружающей среды.

Пример динамического зеркала

const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);
const cubeCamera = new THREE.CubeCamera(1, 1000, cubeRenderTarget);

function animate() {
    cubeCamera.update(renderer, scene); // рендеринг сцены в кубическую текстуру
    mirrorMaterial.map = cubeRenderTarget.texture; // использование текстуры в зеркале
    renderer.render(scene, camera);
}

Такой подход позволяет создавать реалистичные отражения объектов, которые реагируют на изменения сцены в реальном времени.


WebGLRenderTarget является ключевым инструментом для создания сложных визуальных эффектов, позволяя рендерить сцену в текстуру, управлять буферами глубины и stencil, использовать мультисемплинг и multiple render targets. Его гибкость открывает возможности для реалистичных отражений, динамических экранов, постобработки и deferred shading в Three.js.