UNPKG

@realsee/five

Version:

Realsee Renderer SDK

262 lines (199 loc) • 9.65 kB
# 后处理 (Post Processing) - **Summary**: Five 提供了基于 EffectComposer 的后处理机制,默认挂载了自适应亮度 (Auto Exposure) 和眼球穹顶光照 (EDL) 两种效果,同时提供多种可选内置 Pass,并支持开发者编写自定义 Pass。 - **Schema**: `FivePass` 类及 `Pass` 接口。 - **Concepts**: EffectComposer, G-Buffer, Pass, AdaptiveLuminance, EyeDomeLighting。 - **Configuration**: 开启内置 Pass 的开关及参数配置。 - **Examples**: 开启内置 Pass 示例,自定义黑白滤镜 Pass 示例。 ## Schema > **Definition**: [FivePass](../../five/renderer/postprocessing/passes/pass.d.ts) ```typescript /** * Pass 接口 (兼容 three.js EffectComposer) */ export interface Pass { enabled: boolean; needsSwap: boolean; clear: boolean; renderToScreen: boolean; setSize(width: number, height: number): void; render( renderer: THREE.WebGLRenderer, writeBuffer: THREE.WebGLRenderTarget, readBuffer: THREE.WebGLRenderTarget, deltaTime?: number, maskActive?: boolean ): void; } /** * FivePass 基类 * 支持 G-Buffer 注入 (depth, normal, color) */ export class FivePass implements Pass { public enabled: boolean = true; public needsSwap: boolean = true; public clear: boolean = false; public renderToScreen: boolean = true; public dependencies: ('depth' | 'normal' | 'color')[]; // 由 EffectComposer 在 render 时注入 public gbuffer!: Map<'depth' | 'normal' | 'color', THREE.Texture>; constructor(dependencies?: ('depth' | 'normal' | 'color')[]); // ... render method implementation } ``` ## Concepts - **EffectComposer**: 后处理管理器,负责按顺序执行 Pass,管理渲染目标 (RenderTarget) 和 G-Buffer。 - **FivePass**: Five 引擎优化的 Pass 基类。相比普通 Pass,它声明了 `dependencies`,Five 会在渲染 Pass 之前准备好所需的 G-Buffer (如深度图、法线图),避免在每个 Pass 中重复渲染场景。 - **AdaptiveLuminancePass (自适应亮度)**: 模拟人眼对光线的适应过程。当场景亮度变化时,会自动平滑调整曝光度,使画面保持在舒适的亮度范围内。 - **EyeDomeLightingPass (EDL)**: 一种非真实感渲染技术,主要用于增强点云模型的深度感知。通过屏幕空间的深度差计算遮蔽效果,让点云看起来更有轮廓感。 ## Built-in Passes (内置 Pass) Five 默认挂载了两个 Pass 实例,挂载在 `five` 实例上,默认是关闭状态。 ### 1. AdaptiveLuminancePass 位于 `five.adaptiveLuminancePass`。 * **作用**: 自动调整画面曝光。 * **开启方式**: `five.adaptiveLuminancePass.enabled = true`。 * **配置项**: * `luminanceScale` (number): 亮度缩放系数,影响最终画面的整体亮度。 * `luminanceStep` (number): 亮度适应步长,影响适应速度。 ### 2. EyeDomeLightingPass 位于 `five.eyeDomeLightingPass`。 * **作用**: 增强点云的轮廓和深度感。 * **开启方式**: `five.eyeDomeLightingPass.enabled = true`。 * **配置项**: * `strength` (number): 增强强度,值越大轮廓越明显。 * `radius` (number): 采样半径,影响阴影的范围。 * **注意**: 这是一个基于屏幕空间深度的算法,依赖 Depth Buffer。 ### 3. Optional Built-in Passes (可选内置 Pass) Five 新增了多个可选使用的内置 Pass,这些 Pass 没有预先挂载在 `five` 实例上,需手动导入并添加到渲染链中: * **[GaussianBlurPass](gaussian-blur-pass.md)**: 高斯模糊效果。 * **[FlowingLight2DPass](flowing-light-2d-pass.md)**: 2D 流光效果(通常用于平面路线流光)。 * **[FlowingLight3DPass](flowing-light-3d-pass.md)**: 3D 流光效果(通常用于空间路径流光)。 * **[FlowingFireworks3DPass](flowing-fireworks-3d-pass.md)**: 在 3D 流光尾部喷射烟花粒子的配套特效。 #### GaussianBlurPass 使用示例 ```typescript import { GaussianBlurPass } from '@realsee/five'; // 1. 创建 GaussianBlurPass 实例 (需要传入 camera) const gaussianBlurPass = new GaussianBlurPass(five.camera); // 2. 配置参数 // 设置模糊半径 (默认 4.0) gaussianBlurPass.setRadius(6); // 3. 将 Pass 添加到渲染链 five.addPass(gaussianBlurPass); // 4. (可选) 动态开关 // gaussianBlurPass.enabled = false; // 5. (可选) 移除 Pass // five.removePass(gaussianBlurPass); ``` ## Custom Pass (自定义 Pass) 如果需要实现自定义的后处理效果(如景深、色彩校正、描边等),建议继承 `FivePass`。 ### 步骤 1. **创建类**: 继承 `FivePass`。 2. **声明依赖**: 在 `super()` 中传入需要的 G-Buffer 依赖 (如 `['depth']`)。 3. **实现 render**: 使用 `readBuffer` 作为输入,将结果渲染到 `writeBuffer` (或直接渲染到屏幕)。 4. **挂载**: 使用 `five.addPass(pass)` 将其实例添加到渲染链中。 ## Examples ### 开启内置 Pass ```typescript import { Five } from '@realsee/five'; const five = new Five(); // 开启自适应亮度 five.adaptiveLuminancePass.enabled = true; five.adaptiveLuminancePass.luminanceScale = 0.5; // 调整目标亮度 // 开启 EDL (通常用于点云模式) five.eyeDomeLightingPass.enabled = true; five.eyeDomeLightingPass.strength = 1.5; // 增强轮廓感 five.needsRender = true; ``` ### 自定义 Pass (黑白滤镜) ```typescript import * as THREE from 'three'; import { Five, FivePass } from '@realsee/five'; import { FullScreenQuad } from '@realsee/five/lib/five/tools/full-screen-quad'; // 需根据实际路径引用 // 1. 定义 Shader const grayscaleVertexShader = ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; const grayscaleFragmentShader = ` uniform sampler2D tDiffuse; varying vec2 vUv; void main() { vec4 color = texture2D(tDiffuse, vUv); float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114)); gl_FragColor = vec4(vec3(gray), color.a); } `; // 2. 创建 Pass 类 class GrayscalePass extends FivePass { private material: THREE.ShaderMaterial; private fsQuad: FullScreenQuad; constructor() { super(); // 不需要额外的 G-Buffer 依赖,只需要前一个 Pass 的颜色结果 this.material = new THREE.ShaderMaterial({ uniforms: { tDiffuse: { value: null } }, vertexShader: grayscaleVertexShader, fragmentShader: grayscaleFragmentShader }); this.fsQuad = new FullScreenQuad(this.material); } render(renderer, writeBuffer, readBuffer) { // 将上一个 Pass 的结果 (readBuffer) 传给 Shader this.material.uniforms.tDiffuse.value = readBuffer.texture; if (this.renderToScreen) { // 如果是最后一个 Pass,直接渲染到屏幕 renderer.setRenderTarget(null); this.fsQuad.render(renderer); } else { // 否则渲染到 writeBuffer,供下一个 Pass 使用 renderer.setRenderTarget(writeBuffer); if (this.clear) renderer.clear(); this.fsQuad.render(renderer); } } } // 3. 挂载到 Five const grayPass = new GrayscalePass(); five.addPass(grayPass); // 触发重绘 five.needsRender = true; ``` ### 使用 G-Buffer (深度图示例) 如果你的 Pass 需要使用场景的深度信息(例如雾效),可以在构造函数中声明依赖。 ```typescript class FogPass extends FivePass { constructor() { super(['depth']); // 声明需要深度图 } render(renderer, writeBuffer, readBuffer) { // 获取深度图 const depthTexture = this.gbuffer.get('depth'); // 在 Shader 中使用 depthTexture ... // this.material.uniforms.tDepth.value = depthTexture; // ... 渲染逻辑 } } ``` ## Debugging * **查看 Pass 列表**: 检查 `five.fiveRenderer.composer.passes` 数组,确认 Pass 是否已添加以及顺序是否正确。 * **检查 Enabled 状态**: 确保 Pass 实例的 `.enabled` 属性为 `true`。 * **G-Buffer 调试**: 如果自定义 Pass 依赖 G-Buffer 但效果不对,检查 `this.gbuffer` 是否包含预期的纹理。 ## Common Pitfalls 1. **Pass 顺序**: 后处理是按顺序执行的。如果添加了多个 Pass,要注意它们的添加顺序。`addPass` 会添加到末尾,`insertPass` 可以插入到指定位置。 2. **renderToScreen**: 只有链中的最后一个 Pass (且 `renderToScreen` 为 true) 才会渲染到屏幕。EffectComposer 会自动管理这个标志,但自定义 Pass 必须在 `render` 方法中正确处理 `this.renderToScreen` 逻辑。 3. **Performance**: 过多的后处理 Pass 会显著降低帧率,尤其是在高分辨率屏幕上。尽量合并 Shader 逻辑,避免频繁的 Buffer 拷贝。 4. **Dependencies**: 只有继承 `FivePass` 并声明了 `dependencies`,`this.gbuffer` 才会有值。普通 `Pass` 实现无法自动获取 G-Buffer。 ## Related * [Gaussian Blur Pass](gaussian-blur-pass.md): 高斯模糊 Pass 文档。 * [Flowing Light 2D Pass](flowing-light-2d-pass.md): 2D 流光 Pass 文档。 * [Flowing Light 3D Pass](flowing-light-3d-pass.md): 3D 流光 Pass 文档。 * [Flowing Fireworks 3D Pass](flowing-fireworks-3d-pass.md): 流光烟花粒子 Pass 文档。 * [five.ts](../../five/application/five.d.ts): 查看 `addPass` 方法的实现。 * [pass.ts](../../five/renderer/postprocessing/passes/pass.d.ts): 查看 `FivePass` 基类定义。 --- ```yaml tags: [后处理, 特效, 自定义shader, 滤镜, 描边, 景深, 色彩校正, 渲染管线, postprocessing, shader, effect, adaptive-luminance, edl, effect-composer, addPass] ```