Three.js предоставляет мощный набор инструментов для работы с глубиной сцены. Буфер глубины (depth buffer) содержит информацию о расстоянии от камеры до каждого фрагмента в сцене и используется для корректного отображения объектов в 3D-пространстве, особенно при наложении полупрозрачных объектов или при вычислении теней. Управление этим буфером открывает возможности для создания сложных визуальных эффектов, таких как постобработка, глубинное затенение и эффекты SSAO (Screen Space Ambient Occlusion).
Depth Texture — это текстура, которая хранит
значения глубины сцены. В Three.js она создаётся с помощью
THREE.DepthTexture и может быть привязана к
THREE.WebGLRenderTarget для последующего использования.
const renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, {
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
format: THREE.RGBAFormat,
depthTexture: new THREE.DepthTexture(),
depthBuffer: true
});
Ключевые моменты:
depthTexture — объект THREE.DepthTexture,
который будет хранить глубину.depthBuffer: true гарантирует создание буфера глубины
на рендер-таргете.NearestFilter используются для точного чтения
глубины без интерполяции.Depth Texture часто применяется в шейдерах для различных эффектов, например, для создания глубинной размытия (Depth of Field) или эффектов тумана. Основная идея заключается в том, чтобы считывать значения глубины и использовать их для вычислений внутри фрагментного шейдера.
uniform sampler2D depthTexture;
uniform float cameraNear;
uniform float cameraFar;
float readDepth(sampler2D depthSampler, vec2 uv) {
float z_b = texture2D(depthSampler, uv).x;
float z_n = 2.0 * z_b - 1.0;
return (2.0 * cameraNear * cameraFar) / (cameraFar + cameraNear - z_n * (cameraFar - cameraNear));
}
Принцип работы:
z_b) находится в диапазоне
[0, 1].z_n)
для корректных вычислений.Эта функция позволяет применять глубинные эффекты с точным учётом перспективы камеры.
При работе с глубиной важно учитывать параметры камеры. Линейная
интерпретация глубины зависит от near и far
камеры:
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100);
Совет: уменьшение значения near и
увеличение far увеличивает диапазон глубины, но снижает
точность буфера глубины. Для постобработки и эффектов SSAO часто
требуется сбалансированное значение этих параметров.
Рендер сцены в текстуру с глубиной выполняется так:
renderer.setRenderTarget(renderTarget);
renderer.render(scene, camera);
renderer.setRenderTarget(null);
После этого renderTarget.depthTexture готова к
использованию в шейдерах.
Depth Texture идеально подходит для постобработки через
THREE.ShaderPass или кастомные шейдеры:
Пример использования Depth Texture в ShaderMaterial:
const material = new THREE.ShaderMaterial({
uniforms: {
tDiffuse: { value: renderTarget.texture },
tDepth: { value: renderTarget.depthTexture },
cameraNear: { value: camera.near },
cameraFar: { value: camera.far }
},
vertexShader: vertexShaderSource,
fragmentShader: fragmentShaderSource
});
В фрагментном шейдере tDepth используется для
корректного расчёта глубины и создания визуальных эффектов.
При работе с полупрозрачными объектами важно учитывать порядок рендеринга и буфер глубины. Традиционно, объекты с альфа-каналом рендерятся после всех непрозрачных объектов. Для глубоких эффектов можно использовать отдельный рендер-таргет для прозрачных объектов или применять технику depth peeling, где слои прозрачности обрабатываются поочерёдно.
THREE.DepthFormat с
THREE.UnsignedShortType или
THREE.UnsignedIntType уменьшает использование памяти.Depth Texture можно применять не только для постобработки, но и для
взаимодействия с объектами сцены. Например, для выбора объектов по
глубине или создания эффекта «прилипшего света» на ближайших объектах.
Для этого используется чтение значения глубины с помощью
renderer.readRenderTargetPixels или шейдерных вычислений,
что позволяет вычислять точные координаты в 3D-пространстве.
WebGLRenderTarget и может быть
использована в кастомных шейдерах.Работа с Depth Texture открывает возможности для сложных визуальных эффектов и позволяет создавать сцены с реалистичной глубиной и взаимодействием объектов.