Cesium PBR增强(一)

介绍

Cesium 1.123的更新引入了一种全新的“程序化”光照系统,基于 CesiumJS 的图像基照明(Image-Based Lighting,IBL)方法,旨在显著提升默认光照环境的真实感和视觉质量。通过动态生成环境贴图和相关光照值,该系统能够实时响应场景中的位置和光源变化,为模型和 3D 瓦片(3D Tilesets)提供更加真实的渲染效果。

DynamicEnvironmentMapManager

DynamicEnvironmentMapManager 是本次更新的核心组件,用于动态生成与当前场景光照条件匹配的环境贴图,并计算多种反射和漫反射参数。以下是对其主要功能和参数的详细描述:

功能

  1. 环境贴图生成
    • 使用场景中的当前位置和太阳位置动态生成一组环境贴图。
    • 基于环境贴图,生成多个高光贴图(Specular Maps),涵盖不同表面粗糙度的反射。
  2. 光照值计算
    • 球面谐波漫反射光照:通过计算球面谐波(Spherical Harmonics)系数,提升光扩散的真实感。
    • 辐射贴图(Radiance Map)和辐照贴图(Irradiance Map):分别表示高分辨率的镜面反射效果和环境光的整体分布。
  3. 动态更新
    • 根据场景中位置变化或时间变化(如太阳运动)自动更新环境贴图。
    • 内置多个更新触发条件,包括位置阈值(maximumPositionEpsilon)和时间阈值(maximumSecondsDifference)。
  4. 性能优化
    • 使用延迟更新机制,仅在需要时重新生成贴图和计算参数。
    • 支持多层级的高光贴图生成(mipmapLevels),以适配不同渲染需求。

主要参数

以下是 DynamicEnvironmentMapManager 的重要构造参数及其作用:

  • enabled: 是否启用动态环境贴图更新,默认为 true
  • mipmapLevels: 高光贴图生成的层级数,默认为 10,层级越多,反射效果越精细。
  • maximumSecondsDifference: 更新环境贴图的最大时间间隔,默认为 3600 秒。
  • maximumPositionEpsilon: 更新环境贴图的最大位置变化阈值,单位为米,默认为 1000
  • atmosphereScatteringIntensity: 大气散射光的强度,默认为 2.0,可以根据场景光源亮度调整。
  • gamma: 环境光的伽马校正值,默认为 1.0
  • brightness: 环境光的亮度校正值,默认为 1.0
  • saturation: 环境光的饱和度校正值,默认为 1.0
  • groundColor: 地面的固有颜色,默认值为地球的平均地面色(#717145)。
  • groundAlbedo: 地面的反射率,默认为 0.31,反映地球的平均反照率。

实现细节

  1. 贴图更新逻辑

    • 通过 ComputeCommand 创建计算命令,将辐射贴图结果更新到 CubeMap 的每个面。
    • 支持多层级卷积计算,用于生成不同粗糙度的高光贴图。
  2. 光照计算

    • 在 GPU 上使用片段着色器(如 ComputeRadianceMapFSComputeIrradianceFS)高效完成辐射和辐照的卷积计算。
    • 利用球面谐波计算漫反射系数,结合大气散射提升光照真实性。
  3. 重置与销毁

    • 提供 reset 方法以便在条件改变时清理未完成的计算命令并标记更新状态。

      /**
       * 取消所有正在进行的命令,并将环境贴图标记为“脏”状态。
       * 这意味着当前的计算命令会被中断,并且环境贴图需要重新计算。
       * 
       * @private
       * @function
       */
      DynamicEnvironmentMapManager.prototype.reset = function () {
        // 获取当前辐射贴图计算命令的数量
        let length = this._radianceMapComputeCommands.length;
        
        // 遍历并清除辐射贴图计算命令
        for (let i = 0; i < length; ++i) {
          this._radianceMapComputeCommands[i] = undefined;
        }
      
        // 获取当前卷积计算命令的数量
        length = this._convolutionComputeCommands.length;
        
        // 遍历并清除卷积计算命令
        for (let i = 0; i < length; ++i) {
          this._convolutionComputeCommands[i] = undefined;
        }
      
        // 如果辐射照射计算命令已定义,则清除它
        if (defined(this._irradianceComputeCommand)) {
          this._irradianceComputeCommand = undefined;
        }
      
        // 将辐射贴图状态标记为“脏”以指示需要重新计算
        this._radianceMapDirty = true;
        
        // 将辐射命令状态标记为“脏”
        this._radianceCommandsDirty = true;
      };
      
      
    • 提供 destroy 方法以销毁所有 WebGL 资源,确保资源管理的高效性。

      /**
       * 销毁该对象所持有的WebGL资源。销毁对象允许我们有确定性的方式释放WebGL资源,
       * 而不是依赖垃圾回收器来销毁该对象。
       * <br /><br />
       * 一旦对象被销毁,就不应再使用它;调用任何除了 <code>isDestroyed</code> 之外的函数将会
       * 导致抛出 {@link DeveloperError} 异常。因此,应将返回值(<code>undefined</code>)重新赋值给对象,
       * 如示例所示。
       * 
       * @throws {DeveloperError} 当对象已被销毁(即调用了 destroy())时抛出。
       * @example
       * mapManager = mapManager && mapManager.destroy();
       * @see DynamicEnvironmentMapManager#isDestroyed
       */
      DynamicEnvironmentMapManager.prototype.destroy = function () {
        // 取消所有正在进行的辐射贴图计算命令
        let length = this._radianceMapComputeCommands.length;
        for (let i = 0; i < length; ++i) {
          this._radianceMapComputeCommands[i] = undefined;
        }
      
        // 取消所有正在进行的卷积计算命令
        length = this._convolutionComputeCommands.length;
        for (let i = 0; i < length; ++i) {
          this._convolutionComputeCommands[i] = undefined;
        }
      
        // 清除辐射照射贴图计算命令
        this._irradianceMapComputeCommand = undefined;
      
        // 销毁所有辐射贴图纹理
        length = this._radianceMapTextures.length;
        for (let i = 0; i < length; ++i) {
          this._radianceMapTextures[i] =
            this._radianceMapTextures[i] && this._radianceMapTextures[i].destroy();
        }
      
        // 销毁所有高光贴图纹理
        length = this._specularMapTextures.length;
        for (let i = 0; i < length; ++i) {
          this._specularMapTextures[i] =
            this._specularMapTextures[i] && this._specularMapTextures[i].destroy();
        }
      
        // 销毁辐射立方体贴图
        this._radianceCubeMap =
          this._radianceCubeMap && this._radianceCubeMap.destroy();
      
        // 销毁辐射照射贴图
        this._irradianceMapTexture =
          this._irradianceMapTexture && this._irradianceMapTexture.destroy();
      
        // 销毁当前对象,并释放其所有资源
        return destroyObject(this);
      };
      
      

使用示例

以下是 DynamicEnvironmentMapManager 的典型使用场景:

// 在场景中启用动态环境贴图
scene.atmosphere.dynamicLighting = Cesium.DynamicAtmosphereLightingType.SUNLIGHT;

// 调整光源和环境贴图的光照强度
scene.light.intensity = 0.5;
const environmentMapManager = tileset.environmentMapManager;
environmentMapManager.atmosphereScatteringIntensity = 3.0;

// 设置环境贴图的地面颜色为森林绿
environmentMapManager.groundColor = Cesium.Color.fromCssColorString("#203b34");

更详细的解析后面再更新

TilesBuilderTilesBuilder提供一个高效、兼容、优化的数据转换工具,一站式完成数据转换、数据发布、数据预览操作。

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值