在使用Cesium进行三维地理可视化时,经常需要根据时间变化来调整场景的渲染效果,例如模拟一天的白天和黑夜。这个过程不仅能让场景的光照效果更真实,还能提供动态的视觉体验。本文将通过一个示例代码,讲解如何在Cesium中实现动态渲染白天与黑夜,并根据一天不同时间调整曝光值,模拟白天和夜晚的不同光照效果。

背景

在Cesium中,场景的渲染可以通过“后处理阶段”(Post-Process Stages)来调整。曝光(exposure)是影响光照和画面亮度的重要参数。白天和夜晚的曝光差异较大:白天时阳光强烈,曝光值应较高;而在夜晚,曝光值应较低,甚至接近零。

核心思路

我们将通过监听时间的变化,根据当前时间动态调整Cesium中的曝光值,从而模拟一天中的不同光照变化。具体来说,白天(9:00 AM 到 3:00 PM)的曝光值较高,而在傍晚(3:00 PM 到 7:00 PM)时,曝光值逐渐过渡到夜晚(7:00 PM 到 6:00 AM)的低曝光值。

示例代码讲解

以下是实现动态曝光调整的代码示例:

javascript
// 曝光控制
viewer.scene.postProcessStages.exposure = 1.0;
gui.add(viewer.scene.postProcessStages, 'exposure', 0.0, 3.0).step(0.01).name('曝光');

// 设置时间为每秒钟模拟3600秒(即1小时)
viewer.clock.multiplier = 3600;
viewer.clock.shouldAnimate = true;

// 每次时间更新时触发
viewer.clock.onTick.addEventListener((clock) => {
  // 当前时间
  const currentTime = viewer.clock.currentTime;
  const h = Cesium.JulianDate.toDate(currentTime).getHours();
  const m = Cesium.JulianDate.toDate(currentTime).getMinutes();
  let hour = h + m / 60;

  // 设置曝光值,根据时间调整:白天曝光较高,晚上曝光较低
  if (hour >= 9 && hour <= 15) {
    // 白天时(9:00 AM 到 3:00 PM),曝光较高
    viewer.scene.postProcessStages.exposure = 2.0;
  } else if (hour > 15 && hour < 19) {
    // 傍晚时(3:00 PM 到 7:00 PM),曝光逐渐降低
    let exposure = Cesium.Math.lerp(2.0, 0.01, (hour - 15) / 4);
    viewer.scene.postProcessStages.exposure = exposure;
  } else if (hour < 9 && hour > 6) {
    // 早晨时(6:00 AM 到 9:00 AM),曝光逐渐增高
    let exposure = Cesium.Math.lerp(0.01, 2.0, (hour - 6) / 3);
    viewer.scene.postProcessStages.exposure = exposure;
  } else {
    // 夜晚时(7:00 PM 到 6:00 AM),曝光较低
    viewer.scene.postProcessStages.exposure = 0.01;
  }
});

javascript

代码解释

1. 曝光控制

javascript
viewer.scene.postProcessStages.exposure = 1.0;
gui.add(viewer.scene.postProcessStages, 'exposure', 0.0, 3.0).step(0.01).name('曝光');
  • 通过viewer.scene.postProcessStages.exposure来控制曝光值的初始状态。默认曝光值为1.0。
  • 通过gui.add()方法,允许我们在调试面板中手动调整曝光值范围,便于测试不同的曝光效果。

2. 设置时间速率


viewer.clock.multiplier = 3600;
viewer.clock.shouldAnimate = true;
  • viewer.clock.multiplier = 3600将时间速率设定为每秒钟模拟1小时。这意味着每1秒钟的实际时间,场景中时间会推进1小时。
  • viewer.clock.shouldAnimate = true启用动画,使得场景会根据时间的变化自动更新。

3. 时间更新与曝光调整

】
viewer.clock.onTick.addEventListener((clock) => {
  const currentTime = viewer.clock.currentTime;
  const h = Cesium.JulianDate.toDate(currentTime).getHours();
  const m = Cesium.JulianDate.toDate(currentTime).getMinutes();
  let hour = h + m / 60;
  • 每当时间更新时,onTick事件触发,我们获取当前的时间,并将其转换为小时(hour)。
  • 使用Cesium.JulianDate.toDate()方法将Cesium的时间格式转换为JavaScript的Date对象,从而获取小时和分钟。

4. 根据时间动态调整曝光


if (hour >= 9 && hour <= 15) {
  viewer.scene.postProcessStages.exposure = 2.0;
} else if (hour > 15 && hour < 19) {
  let exposure = Cesium.Math.lerp(2.0, 0.01, (hour - 15) / 4);
  viewer.scene.postProcessStages.exposure = exposure;
} else if (hour < 9 && hour > 6) {
  let exposure = Cesium.Math.lerp(0.01, 2.0, (hour - 6) / 3);
  viewer.scene.postProcessStages.exposure = exposure;
} else {
  viewer.scene.postProcessStages.exposure = 0.01;
}

  • 白天(9:00 AM 到 3:00 PM):曝光值为2.0,模拟强烈的阳光。
  • 傍晚(3:00 PM 到 7:00 PM):使用线性插值Cesium.Math.lerp()逐渐降低曝光值,从2.0降到0.01。
  • 早晨(6:00 AM 到 9:00 AM):曝光值逐渐增高,从0.01增至2.0,模拟太阳升起的过程。
  • 夜晚(7:00 PM 到 6:00 AM):曝光值保持在最低,模拟夜晚或无光照的情况。

结论

通过上述代码实现,我们能够根据一天内的时间变化,动态地调整Cesium中的曝光值,从而模拟白天与夜晚的光照效果。这种方式可以增强三维场景的真实感,尤其在需要动态显示全天候变化的地理信息系统(GIS)应用中非常有用。

随着时间的推移,我们可以继续优化和扩展这个基础,实现更多的效果,如太阳高度角变化、天气变化等,进一步提升可视化的真实性和互动性。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注