跳到主要内容

HDR 渲染

高动态范围(HDR)渲染通过捕获和显示更广的光照与颜色范围,显著提升计算机图形的真实感。最明亮的高光和最深的阴影都能保留细节,让场景更接近真实。HDR 渲染的一大优势是支持基于物理的泛光效果:强光源自然地向周围扩散,模拟真实相机和人眼的行为。此外,它允许光照值超出标准可显示范围,从而实现更准确的反射和折射,产生鲜明而真实的画面。

HDR

相机设置​

相机提供两个处理 HDR 渲染的关键设置:

  • gammaCorrection
  • toneMapping

可以根据渲染模式配置这些设置。

LDR(低动态范围)​

  • toneMapping:LDR 渲染可选择任意色调映射方法,以达到所需视觉风格。色调映射将 HDR 值压缩为可显示的 LDR 值。
  • gammaCorrection:设为 GAMMA_SRGB,表示输出作为颜色,应存储在伽马空间中。
    • 如果输出像素格式是 sRGB,硬件负责伽马校正。
    • 否则,在着色器代码中进行伽马编码。

HDR(高动态范围)​

要进行带泛光等后处理效果的 HDR 渲染,使用 CameraFrame 类(见下文),它会自动处理 HDR 管线。

注意

虽然可以直接在相机上将 gammaCorrection 设为 GAMMA_NONE,但这会直接写入未经伽马编码的线性值,导致整个场景在普通显示器上过暗。仅在高级自定义管线中使用此设置:输出先渲染到中间 HDR 纹理,再在后续通道中进行色调映射和伽马校正。

不使用 CameraFrame 而手动配置 HDR 时:

  • toneMapping:设为 TONEMAP_LINEAR,保留 HDR 颜色。
  • gammaCorrection:仅在渲染到中间 HDR 渲染目标时设为 GAMMA_NONE。
  • 确保使用兼容的 HDR 像素格式。可通过 GraphicsDevice.getRenderableHdrFormat() API 获取。
  • 显示前,在后续通道中应用色调映射和伽马校正。

HDR 显示输出​

在 HDR 模式下渲染时,可将 Application 的 displayFormat 参数设为 DISPLAYFORMAT_HDR,启用 HDR 显示输出。

  • toneMapping:如果支持 HDR 输出,设为 TONEMAP_NONE。
  • gammaCorrection:保持 GAMMA_SRGB,使低强度值的视觉效果与 LDR 渲染相近。
  • 创建设备后,使用 GraphicsDevice.isHdr() 检查是否支持 HDR 显示输出。注意,浏览器必须运行在支持 HDR 输出的显示器上,isHdr() 才可能返回 true。

**注意:**目前仅 WebGPU 支持 HDR 显示输出。在其他平台上,GraphicsDevice.isHdr() 始终返回 false。

PlayCanvas 引擎的 CameraFrame 类​

PlayCanvas 引擎通过 CameraFrame 类提供完整渲染配置,集成高动态范围(HDR)渲染、泛光、屏幕空间环境光遮蔽(SSAO)等高级效果。它通过模拟真实光照和后处理效果,提升视觉保真度。

CameraFrame 的主要功能​

  • 泛光:模拟光散射,在明亮区域周围产生光晕。
  • SSAO:模拟缝隙和角落中的环境光遮蔽,增强深度感。
  • 景深(DoF):模拟相机对焦,模糊焦平面之外的对象。
  • 时间抗锯齿(TAA):通过跨帧平滑锯齿边缘,减少视觉瑕疵。
  • 暗角:压暗图像边角,将注意力引向中心。
  • 颜色分级:调整色彩平衡,塑造视觉风格。
  • 颜色增强:有选择地调整阴影、高光、中间调、自然饱和度和去雾。
  • 体积雾:渲染高度雾,以及平行光、点光源和聚光灯的光束。

完整功能列表、配置建议和示例,参见现代后处理。

在相机上配置 CameraFrame​

const cameraFrame = new pc.CameraFrame(app, cameraEntity.camera);
cameraFrame.rendering.toneMapping = pc.TONEMAP_NEUTRAL;
cameraFrame.rendering.samples = 4;
cameraFrame.bloom.intensity = 0.01;
cameraFrame.update();

在引擎的 CameraFrame 中,正的 bloom.intensity 启用泛光,设为 0 则禁用。此 API 没有 bloom.enabled 标志。编辑器脚本封装另有 Bloom > Enabled(泛光 > 启用)设置。

要让 HDR 泛光有效,场景应包含明亮光源。通常使用高强度自发光材质来实现。例如:

material.emissive = pc.Color.YELLOW;
material.emissiveIntensity = 50;

更多详细信息参见 CameraFrame API 文档。

颜色 LUT​

CameraFrame 支持通过 3D 颜色查找表(LUT)进行颜色分级。LUT 必须是 256×16 的二维“水平条带”纹理,表示按 Unreal Engine 布局展开的 16×16×16 三维 LUT:沿蓝色轴水平排列 16 个切片,每个切片将红色映射到 X 轴、绿色映射到 Y 轴。HALD LUT 和 Unity 风格的 LUT 布局不同,不能兼容。

可从下面的中性恒等 LUT 开始:应用到场景时不会产生变化。在图像编辑器中修改它,即可创建自己的调色效果:

中性恒等 LUT(256x16)

下面是大幅修改的例子:强烈增强红色,大幅降低绿色和蓝色:

樱桃色 LUT 示例(256x16)

加载 LUT 纹理时必须使用以下设置。LUT 在 sRGB 显示空间中制作,引擎依赖硬件 sRGB 采样,因此错误配置会导致明显的颜色偏差:

  • srgb: true:LUT 采用 sRGB 编码。
  • mipmaps: false:仅采样 LOD 0。
  • minfilter: 'linear'、magfilter: 'linear':在 LUT 条目间进行双线性滤波,避免色带。
const lutAsset = new pc.Asset(
'colorLut',
'texture',
{ url: 'path/to/lut.png' },
{
srgb: true,
mipmaps: false,
minfilter: 'linear'
}
);
app.assets.add(lutAsset);
lutAsset.ready(() => {
cameraFrame.colorLUT.texture = lutAsset.resource;
cameraFrame.colorLUT.intensity = 1.0;
cameraFrame.update();
});
app.assets.load(lutAsset);

如果上述纹理设置有误,引擎的调试构建会发出警告,指出需要修改的具体属性;发布构建会移除此检查。

制作 LUT 时,可截取场景画面,在 Photoshop 等图像编辑器中调整颜色,将这些调整拖到中性恒等 LUT 上,再导出为 PNG。在 PlayCanvas 编辑器中,开启纹理资源的 sRGB,关闭 Mipmaps,将 Filter(滤波)设为 Linear(线性)。

两个 LUT 之间的交叉淡化​

在两种调色风格之间过渡(白天到夜晚、地点 A 到地点 B 等)时,LUT 插槽支持可选的第二张纹理和混合系数。两个 LUT 同时采样,调色结果在线性空间中交叉淡化:

cameraFrame.colorLUT.texture = lutDayAsset.resource;
cameraFrame.colorLUT.texture2 = lutNightAsset.resource;
cameraFrame.colorLUT.intensity = 1; // strength of LUT 1 against the original
cameraFrame.colorLUT.intensity2 = 1; // strength of LUT 2 against the original
cameraFrame.colorLUT.blend = 0; // 0 = only LUT 1, 1 = only LUT 2, animate this for a fade
cameraFrame.update();

第二张纹理必须满足与第一张相同的尺寸和滤波要求。当 texture2 为 null 时,使用单 LUT 路径,忽略 intensity2 和 blend 值。

编辑器中的 CameraFrame​

camera-frame.mjs 脚本将引擎的 CameraFrame 设置暴露到编辑器检查器。其类名为 CameraFrame,注册名为 cameraFrame。

使用步骤​

  1. 将 camera-frame.mjs 添加到项目并解析。
  2. 将 cameraFrame 脚本添加到具有相机组件的实体。
  3. 使用检查器配置相机的渲染设置,例如色调映射、泛光、SSAO 等效果。

这种集成简化了复杂相机效果的配置,改善了 PlayCanvas 编辑器中的整体工作流。

CameraFrame 脚本

效果脚本​

未内置于 CameraFrame 的效果各自拥有独立脚本。每个脚本会将效果添加到所在相机实体的 CameraFrame,因此应将它们与 cameraFrame 脚本添加到同一实体:

脚本文件添加的效果
autoExposureEffectauto-exposure.mjs自动曝光
smaaEffectsmaa.mjsSMAA 抗锯齿
lensFlareEffectlens-flare.mjs带形状库的镜头光晕效果。同一文件中的 lensFlare 脚本为所在实体添加光晕。
dynamicSkyEffectdynamic-sky.mjs动态天空

这些脚本导入 camera-frame-effect.mjs,因此也要将它添加到项目中,与这些脚本放在一起。它还是自定义效果脚本的基类,参见编辑器中的效果。

脚本效果随脚本的启用状态变化,并随脚本销毁而从 CameraFrame 移除。脚本的 Debug(调试)属性显示其效果的调试视图。它与 cameraFrame 脚本的调试设置相互覆盖,以最后更改的设置为准。

CameraFrame 使用建议​

  • HDR 泛光至少需要一种可渲染的浮点格式(例如 RG11B10、RGBA16F 或 RGBA32F)。如果设备均不支持,HDR 泛光会自动禁用。
  • StandardMaterial 的 toneMapping 属性会被忽略。色调映射作为全屏后处理通道应用,因此无法逐网格控制。
  • 使用 CameraFrame 时,有两个属性控制色调映射:
    • CameraFrame.rendering.toneMapping:控制 CameraFrame 内渲染的 3D 场景的色调映射。
    • CameraComponent.toneMapping:控制包含后处理的 3D 场景渲染完成后应用的色调映射,通常影响叠加在上方的 UI 元素。
  • 使用 CameraFrame 时,alpha 混合几何体的强度可能有所不同。原因是混合在线性 HDR 空间中进行,比伽马空间混合更符合物理规律。因此,可能需要调整与 alpha 混合相关的材质属性。