EffectComposer — это ключевой инструмент в
Three.js для постобработки сцены, позволяющий
объединять несколько визуальных эффектов в единую цепочку. Вместо того
чтобы напрямую рендерить сцену в WebGLRenderer,
EffectComposer создаёт промежуточные буферы, которые затем
обрабатываются passes. Это открывает возможности для
создания сложных эффектов, таких как размытие, свечение, цветокоррекция,
глубина резкости и множество других визуальных фильтров.
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
const composer = new EffectComposer(renderer);
Главная задача EffectComposer — упорядочивание
passes и контроль их последовательности. Каждый
pass может модифицировать изображение, полученное от
предыдущего, создавая сложные визуальные эффекты без изменения самой
сцены.
RenderPass является основным элементом цепочки и
отвечает за рендеринг сцены в буфер. Обычно он добавляется первым:
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);
Ключевые параметры:
ShaderPass используется для применения пользовательских
или встроенных шейдеров к изображению. Это основной инструмент для
создания фильтров.
import { SepiaShader } from 'three/examples/jsm/shaders/SepiaShader.js';
const sepiaPass = new ShaderPass(SepiaShader);
composer.addPass(sepiaPass);
Особенности ShaderPass:
renderToScreen = true.Three.js поставляется с набором готовых эффектов:
Каждый из этих pass может быть добавлен в EffectComposer
в любой последовательности, но порядок имеет критическое значение, так
как эффекты накапливаются друг на друге.
Эффекты обрабатываются строго по порядку добавления в composer:
Пример цепочки:
composer.addPass(renderPass);
composer.addPass(bloomPass);
composer.addPass(filmPass);
filmPass.renderToScreen = true;
В этом случае сцена сначала рендерится, затем добавляется свечение, и в конце накладывается «кинематографический» фильтр.
MaskPass и ClearMaskPass позволяют
ограничить действие эффектов определёнными объектами сцены. Это полезно
для локальных эффектов, например, свечения только на одном объекте:
import { MaskPass, ClearMaskPass } from 'three/examples/jsm/postprocessing/MaskPass.js';
const maskPass = new MaskPass(scene, camera);
const clearMaskPass = new ClearMaskPass();
composer.addPass(maskPass);
composer.addPass(bloomPass);
composer.addPass(clearMaskPass);
Использование EffectComposer увеличивает нагрузку на
GPU, так как каждый pass требует отдельного рендеринга в текстуру.
Рекомендации для оптимизации:
composer.setSize(width/2, height/2)).Цепочка эффектов обновляется в основном цикле вместо прямого
renderer.render:
function animate() {
requestAnimationFrame(animate);
// Обновление сцены, анимации объектов
composer.render();
}
animate();
Это гарантирует, что все эффекты применяются последовательно и корректно.
EffectComposer использует WebGLRenderTarget
для хранения промежуточного изображения. Для повышения качества можно
использовать multi-sampling, уменьшение артефактов
размытия и сглаживания краёв:
const renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, {
samples: 4
});
const composer = new EffectComposer(renderer, renderTarget);
Ключевой момент: поддержка multi-sampling зависит от
устройства и браузера, поэтому необходимо проверять доступность через
renderer.capabilities.isWebGL2.
Создание собственного эффекта требует написания шейдера с uniforms, vertexShader и fragmentShader. Пример простого эффекта инверсии цвета:
const InvertShader = {
uniforms: { tDiffuse: { value: null } },
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`,
fragmentShader: `
uniform sampler2D tDiffuse;
varying vec2 vUv;
void main() {
vec4 color = texture2D(tDiffuse, vUv);
gl_FragColor = vec4(vec3(1.0) - color.rgb, color.a);
}
`
};
const invertPass = new ShaderPass(InvertShader);
composer.addPass(invertPass);
invertPass.renderToScreen = true;
Такой подход обеспечивает полную свободу в создании визуальных эффектов.
Эффективная цепочка эффектов обычно строится так:
Эта структура обеспечивает гибкость, модульность и позволяет комбинировать любые эффекты для достижения требуемой визуальной стилистики.