DepthOfField: размытие вне фокуса (BokehPass)

Глубина резкости (Depth of Field, DoF) — это визуальный эффект, позволяющий симулировать оптическое поведение камеры, когда объекты вне зоны фокуса становятся размытыми. В Three.js этот эффект реализуется через постобработку, чаще всего с использованием BokehPass из модуля postprocessing. Этот подход позволяет создавать реалистичное размытие заднего и переднего плана, акцентируя внимание на ключевых объектах сцены.

Эффект DoF основан на двух основных компонентах:

  1. Карта глубины (depth texture) — хранит информацию о расстоянии каждого пикселя до камеры.
  2. Bokeh-шейдер — использует карту глубины для расчёта степени размытия каждого пикселя, создавая мягкий эффект боке.

Настройка сцены для DoF

Для работы с BokehPass необходимо:

  • Иметь сцену (THREE.Scene) с камерой (THREE.PerspectiveCamera) и объектами.
  • Настроить WebGLRenderer с включённым depthTexture через WebGLRenderTarget.
  • Добавить EffectComposer для постобработки.

Пример настройки:

import * as THREE from 'three';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { BokehPass } from 'three/examples/jsm/postprocessing/BokehPass.js';

// Сцена и камера
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 5;

// Рендерер
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Composer и RenderPass
const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);

// Настройка BokehPass
const bokehPass = new BokehPass(scene, camera, {
    focus: 2.0,         // расстояние до фокуса
    aperture: 0.025,    // размер апертуры, влияет на степень размытия
    maxblur: 0.01,      // максимальная величина размытия
    width: window.innerWidth,
    height: window.innerHeight
});
composer.addPass(bokehPass);

Основные параметры BokehPass

  • focus — расстояние до объекта, который должен оставаться резким. Все объекты ближе или дальше от этого расстояния будут размыты.
  • aperture — апертура камеры; чем больше значение, тем сильнее размытие вне фокуса.
  • maxblur — максимальная величина размытия, контролирует “сильность” эффекта.
  • width / height — размеры текстуры для постобработки; обычно совпадают с размером рендерера.

Использование этих параметров позволяет точно настроить эффект в зависимости от композиции сцены.


Важные нюансы работы DoF в Three.js

  1. Карта глубины Для корректного размытия необходимо, чтобы камера и сцена поддерживали рендеринг глубины. Включение renderer.capabilities.isWebGL2 позволяет использовать depthTexture с THREE.FloatType, что повышает точность размытия.

  2. Производительность Эффект DoF затратен, особенно при высокой maxblur и большом разрешении. Рекомендуется уменьшать разрешение BokehPass через renderTarget с меньшим размером и масштабировать результат.

  3. Комбинация с другими эффектами BokehPass можно использовать вместе с другими postprocessing-пассами, например, BloomPass или FilmPass. Важно соблюдать порядок, так как размытие вне фокуса должно применяться после основного рендера сцены.


Практическое применение

Глубина резкости особенно полезна в следующих случаях:

  • Архитектурная визуализация — фокус на переднем плане, задний план слегка размытый.
  • Игровая графика — выделение цели или персонажа на фоне.
  • Визуальные эффекты для анимации — реалистичное имитация работы объектива камеры.

Оптимизация и дополнительные приёмы

  1. Адаптивное размытие Можно динамически изменять aperture или focus в зависимости от позиции камеры или объекта для интерактивных сцен.

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

  3. Использование LOD Для больших сцен объекты с дальнего плана можно заменять на упрощённые модели, что снижает нагрузку при вычислении размытия.


Интеграция с пользовательским интерфейсом

Параметры focus, aperture и maxblur удобно связывать с dat.GUI или любым другим инструментом управления, чтобы менять степень размытия в реальном времени. Это полезно для настройки композиции и тестирования визуальных решений.

import { GUI } from 'dat.gui';
const gui = new GUI();
gui.add(bokehPass.materialBokeh.uniforms.focus, 'value', 0.1, 10).name('Focus');
gui.add(bokehPass.materialBokeh.uniforms.aperture, 'value', 0, 0.1).name('Aperture');
gui.add(bokehPass.materialBokeh.uniforms.maxblur, 'value', 0, 0.05).name('Max Blur');

Итоговая структура рендера

В цикле анимации сцены renderer.render заменяется на composer.render, чтобы эффект постобработки применялся ко всей сцене:

function animate() {
    requestAnimationFrame(animate);
    composer.render();
}
animate();

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