# 光照效果(Light)

在不同的应用场景中使用不同的光照模式,可以获得更好的展示效果。在本教程中我们会对所有光照模式进行说明,并提供使用方法示例。

# 教程内容

  • 光照模式说明
  • 添加和控制聚光灯的方法
  • 控制方向光的方法

# 光照模式说明

  • BIMFACE提供了四种光照模式:聚光灯(SpotLight),方向光(DirectionalLight),场景辅助方向光(CSMLight)及场景辅助环境光(FillLight)。
  • 四种光照模式在viewer3D和viewerGIS中均可使用。场景内预设了7盏默认灯光,包括:1盏方向光、1盏场景辅助方向光及5盏场景辅助环境光。默认灯光可以通过光源管理器获取,仅支持控制开关,不支持移除。
// 获取场景中默认创建的光源管理器对象,无需构造,支持Viewer3D和ViewerGIS
let lightManager = viewer.getLightManager();
// 获取管理器内的所有光源对象
lightManager.getAllLights();
# 1 聚光灯(SpotLight)
  • 聚光灯可以向场景中的指定区域集中照射,实现聚焦展示的场景效果,并支持设置阴影效果。
  • 可以通过前端接口在场景中添加和控制聚光灯,具体方法详见“添加和控制聚光灯的方法”。
# 2 方向光(DirectionalLight)
  • 方向光是按特定方向照射的平行光,可以用于太阳光线模拟,投射到物体上可以产生阴影效果。
  • 方向光在大场景中阴影效果不明显,大场景建议使用场景辅助方向光。
  • 由于场景中只能同时开启一个方向光阴影,因此可以通过获取场景中的方向光并对其进行设置来达到预期的光照效果,具体方法详见“控制方向光的方法”。
# 3 场景辅助方向光(CSMLight)
  • 场景辅助方向光用于生成大场景的阴影效果。
  • 预设的场景辅助方向光可以控制开关及阴影状态,不支持新增或移除。
  • 在viewerGIS中,需要对图层设置是否投射和接收阴影。
// 设置模型投射阴影
viewerGIS.getLayerManager().getLayer(layerId).enableCastShadow(true);
// 设置模型接收阴影
viewerGIS.getLayerManager().getLayer(layerId).enableReceiveShadow(true);
// 获取场景中默认创建的光源管理器对象
let lightManager = viewer.getLightManager();
// 获取预设的场景辅助方向光对象
let CSMLight = lightManager.getCSMLight();
// 开启场景辅助方向光的阴影
CSMLight.enableShadow(true)
# 4 场景辅助环境光(FillLight)
  • 场景辅助环境光是场景的基础光源,控制场景的亮度和色调,让物体产生漫反射的效果,但不会产生阴影效果。
  • 在场景中预设了五盏场景辅助环境光,其中三盏为开启状态,两盏为关闭状态。场景辅助环境光可以控制开关,不支持新增或移除。
// 获取场景中默认创建的光源管理器对象
let lightManager = viewer.getLightManager();
// 获取预设的场景辅助环境光对象的数组
let fillLights = lightManager.getAllFillLights()
// 获取第一盏灯
let fillLight = fillLights[0];
// 设置第一盏灯状态为打开
fillLight.enableLight(true);

# 添加和控制聚光灯的方法

# 1 添加聚光灯的方法
  • 在配置聚光灯之前,可以先获取场景中的光源管理器。
  • 然后构造聚光灯的配置项,包括视角范围、颜色及可见距离等,具体配置项要求见SpotLightConfig (opens new window)
  • 最后将聚光灯对象添加到光源管理器中。
// *********************** 创建聚光灯对象 ***********************
let spotLight;
// 获取场景中的光源管理器
let lightManager = viewer3D.getLightManager();

// 创建聚光灯对象
function createSpotLight(){
  // 构造聚光灯配置项
  let spotLightConfig = new Glodon.Bimface.Light.SpotLightConfig();
  // 配置聚光灯位置
  spotLightConfig.position = {'x': 27.038391046237017, 'y': -1614.4351043688982, 'z': 9753.098173741395};
  // 配置聚光灯照射方向
  spotLightConfig.target = {'x': 27.038391046237017, 'y': -1614.4351043688982, 'z': 0};
  // 配置聚光灯光线强度
  spotLightConfig.intensity = 3;
  // 配置聚光灯可见距离
  spotLightConfig.distance = 10000;
  // 配置聚光灯衰减的半影范围
  spotLightConfig.penumbra = 0.1;
  // 配置聚光灯光线颜色
  spotLightConfig.color = new Glodon.Web.Graphics.Color(255, 215, 0, 1);
  // 配置聚光灯视角范围
  spotLightConfig.angle = Math.PI/6;
  // 配置聚光灯开启阴影
  spotLightConfig.shadow = true;
  // 构造聚光灯对象
  spotLight = new Glodon.Bimface.Light.SpotLight(spotLightConfig);
  // 将聚光灯添加到光源管理器中
  lightManager.addLight(spotLight);
}
# 2 前端控制聚光灯的方法
  • 在创建聚光灯后,就可以调用spotLight中的接口对聚光灯进行控制,这里以如何控制聚光灯开关为例。
  • 首先,我们新建一个按钮。
<button class="button" id="btnSpotLight" onclick="enableSpotLight()">开启聚光灯</button>    
  • 其次,在script标签中构造函数enableSpotLight。
// *********************** 控制聚光灯开关 ***********************
let isSpotLightEnabled = false;

// 控制聚光灯开关
function enableSpotLight() {
  if (isSpotLightEnabled) {
    // 关闭聚光灯
    spotLight.enableLight(false);
    // 更新光源效果
    lightManager.update();
    setButtonText('btnSpotLight', '开启聚光灯');
  } else {
    // 开启聚光灯
    spotLight.enableLight(true);
    // 更新光源效果
    lightManager.update();
    setButtonText('btnSpotLight', '关闭聚光灯');
  }
  isSpotLightEnabled = !isSpotLightEnabled;
};   
  • 到此,我们就可以运用按钮控制聚光灯的开关了。

# 控制方向光的方法

# 1 获取预设方向光的方法
  • 由于场景中只能同时开启一个方向光阴影,因此可以通过获取场景中的方向光并对其进行设置来达到预期的光照效果。
// *********************** 获取场景中的方向光并开启阴影 ***********************
let directionalLight;
// 获取场景中的光源管理器
let lightManager = viewer3D.getLightManager();

// 开启场景中预设的方向光对象
function getDirectionalLight(){
  // 获取场景中预设的方向光对象
  directionalLight = lightManager.getAllDirectionalLights()[0];
  // 开启方向光阴影效果
  directionalLight.enableShadow(true);
}
# 2 更新方向光的方法
  • 在获取场景中预设的方向光对象后,可以调用接口对方向光进行控制,具体接口详见DirectionalLight (opens new window)

  • 首先,我们新建一个按钮。

<button class="button" id="btnDirectionalLight" onclick="updateDirectionalLight()">更新方向光</button> 
  • 其次,在script标签中构造函数updateDirectionalLight,可以直接设置方向光的投影方向,也可以根据经纬度及时间设置方向光的投影方向。
// *********************** 更新方向光投影方向 ***********************
let isDirectionalLightUpdated = false;

// 更新方向光投影方向
function updateDirectionalLight() { 
  if (isDirectionalLightUpdated) {
    // 设置方向光投影方向
    directionalLight.setDirection({x: 30, y: 50, z: 20});
  } else {
    // 设置经纬度及时间
    let date = new Date(2020, 07, 31, 16, 00, 00);
    let latLon = {
      lat: 31.0,
      lon: 120.0
    }
    // 根据经纬度及时间设置方向光的投影方向
    directionalLight.setDirectionByCondition(latLon, date);
  }
  isDirectionalLightUpdated = !isDirectionalLightUpdated;
};
  • 到此,我们就可以运用按钮更新方向光的方向了。

# 完整代码

<!DOCTYPE html>
<html lang="en">

<!-- 本DEMO中将展示如何使用光源管理器控制光照效果 -->

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>spotLight</title>
  <style type="text/css">
    * {
      margin: 0;
      padding: 0;
    }

    html,
    body {
      height: 100%;
    }

    .buttons {
      font-size: 0;
    }

    .button {
      margin: 5px 0 5px 5px;
      width: 100px;
      height: 30px;
      border-radius: 3px;
      border: none;
      background: #32D3A6;
      color: #FFFFFF;
    }

    .main {
      display: flex;
      flex-direction: column;
      overflow: hidden;
      height: 100%;
    }

    #domId {
      flex: 1;
    }
  </style>
  <script src="https://static.bimface.com/api/BimfaceSDKLoader/BimfaceSDKLoader@latest-release.js"></script>
</head>

<body>
  <div class='main'>
    <div class='buttons'>
      <button class="button" id="btnSpotLight" onclick="enableSpotLight()">关闭聚光灯</button>
      <button class="button" id="btnDirectionalLight" onclick="updateDirectionalLight()">更新方向光</button>
    </div>
    <!-- 定义DOM元素,用于在该DOM元素中显示模型或图纸 -->
    <div id="domId"></div>
  </div>
  <script type="text/javascript">

    let viewToken = '<yourViewToken>';
    // 声明Viewer及App
    let viewer3D;
    let app;
    let lightManager;
    let viewAdded = false;

    // 配置JSSDK加载项
    window.onload = function () {
      let loaderConfig = new BimfaceSDKLoaderConfig();
      loaderConfig.viewToken = viewToken;
      BimfaceSDKLoader.load(loaderConfig, successCallback, failureCallback);
    }

    // 加载成功回调函数
    function successCallback(viewMetaData) {
      let dom4Show = document.getElementById('domId');
      // 设置WebApplication3D的配置项
      let webAppConfig = new Glodon.Bimface.Application.WebApplication3DConfig();
      webAppConfig.domElement = dom4Show;
      // 创建WebApplication3D,用以显示模型
      app = new Glodon.Bimface.Application.WebApplication3D(webAppConfig);
      app.addView(viewToken);
      viewer3D = app.getViewer();
      // 增加加载完成监听事件
      viewer3D.addEventListener(Glodon.Bimface.Viewer.Viewer3DEvent.ViewAdded, function () {
        //自适应屏幕大小
        window.onresize = function () {
          viewer3D.resize(document.documentElement.clientWidth, document.documentElement.clientHeight - 40)
        }
        // 获取场景中的光源管理器
        lightManager = viewer3D.getLightManager();
        // 设置模型初始状态
        setState();
        // 创建聚光灯对象
        createSpotLight();
        // 开启场景中预设的方向光对象
        getDirectionalLight();
        // 渲染场景
        viewer3D.render();
        viewAdded = true;
      });
    }

    // 加载失败回调函数
    function failureCallback(error) {
      console.log(error);
    }


    // *********************** 设置相机视角及剖切盒状态 ***********************
    let cameraStatus = {
      "name": "persp",
      "position": {
        "x": 10358.883279512556,
        "y": -1624.294865164534,
        "z": 8690.363880331972
      },
      "target": {
        "x": -29193.15382728242,
        "y": -1624.2639685000165,
        "z": -5.7151716988510595
      },
      "up": {
        "x": -0.2147353202214749,
        "y": -0.000003593195528526761,
        "z": 0.9766722798546449
      },
      "fov": 45
    };
    let box = {
      "min": {
        "x": -20087.900059516865,
        "y": -17672.78598070529,
        "z": -588.1997356465587
      },
      "max": {
        "x": 2040.2224631616114,
        "y": 14379.286068563284,
        "z": 13508.199600463586
      }
    };

    // 设置模型初始状态
    function setState() {
      viewer3D.getCamera().setStatus(cameraStatus);
      let sectionBoxConfig = new Glodon.Bimface.Plugins.Section.SectionBoxConfig();
      sectionBoxConfig.viewer = viewer3D;
      let sectionBox = new Glodon.Bimface.Plugins.Section.SectionBox(sectionBoxConfig);
      sectionBox.setSectionBox(box);
      sectionBox.hideBox();
    }


    // *********************** 创建聚光灯对象 ***********************
    let spotLight;

    // 创建聚光灯对象
    function createSpotLight() {
      // 构造聚光灯配置项
      let spotLightConfig = new Glodon.Bimface.Light.SpotLightConfig();
      // 配置聚光灯位置
      spotLightConfig.position = { 'x': 27.038391046237017, 'y': -1614.4351043688982, 'z': 9753.098173741395 };
      // 配置聚光灯照射方向
      spotLightConfig.target = { 'x': 27.038391046237017, 'y': -1614.4351043688982, 'z': 0 };
      // 配置聚光灯光线强度
      spotLightConfig.intensity = 3;
      // 配置聚光灯可见距离
      spotLightConfig.distance = 10000;
      // 配置聚光灯衰减的半影范围
      spotLightConfig.penumbra = 0.1;
      // 配置聚光灯光线颜色
      spotLightConfig.color = new Glodon.Web.Graphics.Color(255, 215, 0, 1);
      // 配置聚光灯视角范围
      spotLightConfig.angle = Math.PI / 6;
      // 配置聚光灯开启阴影
      spotLightConfig.shadow = true;
      // 构造聚光灯对象
      spotLight = new Glodon.Bimface.Light.SpotLight(spotLightConfig);
      // 将聚光灯添加到光源管理器中
      lightManager.addLight(spotLight);
    }


    // *********************** 控制聚光灯开关 ***********************
    let isSpotLightEnabled = true;

    // 控制聚光灯开关
    function enableSpotLight() {
      if (isSpotLightEnabled) {
        // 关闭聚光灯
        spotLight.enableLight(false);
        // 更新光源效果
        lightManager.update();
        setButtonText('btnSpotLight', '开启聚光灯');
      } else {
        // 开启聚光灯
        spotLight.enableLight(true);
        // 更新光源效果
        lightManager.update();
        setButtonText('btnSpotLight', '关闭聚光灯');
      }
      isSpotLightEnabled = !isSpotLightEnabled;
    };


    // *********************** 获取场景中的方向光并开启阴影 ***********************
    let directionalLight;

    // 开启场景中预设的方向光对象
    function getDirectionalLight() {
      // 获取场景中预设的方向光对象
      directionalLight = lightManager.getAllDirectionalLights()[0];
      // 开启方向光阴影效果
      directionalLight.enableShadow(true);
    }


    // *********************** 更新方向光投影方向 ***********************
    let isDirectionalLightUpdated = false;

    // 更新方向光投影方向
    function updateDirectionalLight() {
      if (isDirectionalLightUpdated) {
        // 设置方向光投影方向
        directionalLight.setDirection({ x: 30, y: 50, z: 20 });
      } else {
        // 设置经纬度及时间
        let date = new Date(2020, 07, 31, 16, 00, 00);
        let latLon = {
          lat: 31.0,
          lon: 120.0
        }
        // 根据经纬度及时间设置方向光的投影方向
        directionalLight.setDirectionByCondition(latLon, date);
      }
      isDirectionalLightUpdated = !isDirectionalLightUpdated;
    };


    // *********************** 按钮文字 ***********************
    function setButtonText(btnId, text) {
      let dom = document.getElementById(btnId);
      if (dom != null && dom.nodeName == "BUTTON") {
        dom.innerText = text;
      }
    }
  </script>
</body>

</html>

至此,你已经完成了进阶模式的学习,如需要运用BIMFACE的其他功能,可查看API的介绍及文档,或是查看示例DEMO来完成具体功能的实现。