Skip to content
本页内容

光照

光照使场景更有层次感,使用光照,能建立更真实的三维场景。Orillusion 引擎的光照系统主要由以下几部分组成:

光源说明
灯光组件基础光源组件:平行光,点光源 和 聚光灯
环境反射天空盒环境光,全局曝光
全局光照场景中反射或折射的间接光源

灯光组件

引擎目前内置了3种经典的光源类型:

平行光

平行光 表示的是光线从以某个方向均匀射出,光线之间是平行的,太阳照射在地球表面的光可以认为是平行光,因为太阳和地球距离的远大于地球半径,所以照射在地球的阳光可以看作是来自同一个方向的光,即平行光。平行光4 个主要个特性:

属性类型说明
lightColorColor灯光的颜色, 默认是白色 rgb(1.0,1.0,1.0)
intensityNumber光照强度,默认值为 1
directionVector3只读属性,获取平行光的方向向量
castShadowBoolean是否开启投影, 默认 false 不开启

一般使用平行光所在的 Object3Drotation 控制灯光方向

ts
let lightObj = new Object3D();
scene.addChild(lightObj);

//添加平行光
let dl = lightObj.addComponent(DirectLight);
//设置颜色
dl.lightColor = new Color(1.0, 0.95, 0.84, 1.0);
//设置强度
dl.intensity = 20;

// 通过 Object3D 设置光源的方向
lightObj.rotateX = 45;
lightObj.rotateY = 45;
// 可以通过 direction 获取方向向量
let target = dl.direction


Orillusion powered by WebGPU on Chrome/Edge 113+
Please upgrade to latest Chrome/Edge

<
ts
import {
  BoxGeometry,
  Camera3D,
  defaultTexture,
  Engine3D,
  ForwardRenderJob,
  GUIHelp,
  LitMaterial,
  HoverCameraController,
  MeshRenderer,
  Object3D,
  Scene3D,
  DirectLight,
  Vector3,
  webGPUContext
} from "@orillusion/core";

export class Sample_Light {
  scene: Scene3D;
  hoverCameraController: HoverCameraController;
  lightObj: any;
  constructor() {}

  async run() {
    await Engine3D.init();
    GUIHelp.init()
    this.scene = new Scene3D();
    let cameraObj = new Object3D();
    let mainCamera = cameraObj.addComponent(Camera3D);
    mainCamera.perspective(37, webGPUContext.aspect, 1, 10000.0);

    this.hoverCameraController = mainCamera.object3D.addComponent(
      HoverCameraController
    );
    this.scene.addChild(cameraObj);

    //set camera data
    this.hoverCameraController.setCamera(0, -45, 2000);
    await this.initScene(this.scene);

    let renderJob = new ForwardRenderJob(this.scene);
    Engine3D.startRender(renderJob);
  }

  initScene(scene: Scene3D) {
    {
      let dirLight = new Object3D();
      dirLight.rotationX = 30;
      dirLight.rotationZ = 30;
      let light = dirLight.addComponent(DirectLight);
      light.intensity = 20;
      light.lightColor.r = 255 / 255;
      light.lightColor.g = 157 / 255;
      light.lightColor.b = 5 / 255;
      light.debug()
      scene.addChild(dirLight);
    }

    let mat = new LitMaterial();
    mat.baseMap = defaultTexture.grayTexture;

    let floor = new Object3D();
    let mr = floor.addComponent(MeshRenderer);
    mr.geometry = new BoxGeometry(2000, 1, 2000);
    mr.material = mat;
    this.scene.addChild(floor);

    let box = new BoxGeometry(1, 1, 1);

    let wall_w = new Object3D();
    wall_w.localScale = new Vector3(500, 100, 10);
    wall_w.localPosition = new Vector3(0, 50, 0);
    let mrw = wall_w.addComponent(MeshRenderer);
    mrw.geometry = box;
    mrw.material = mat;
    this.scene.addChild(wall_w);

    let wall_a = new Object3D();
    wall_a.localScale = new Vector3(10, 100, 500);
    wall_a.localPosition = new Vector3(250, 50, 0);
    let mra = wall_a.addComponent(MeshRenderer);
    mra.geometry = box;
    mra.material = mat;
    this.scene.addChild(wall_a);

    let wall_d = new Object3D();
    wall_d.localScale = new Vector3(10, 100, 500);
    wall_d.localPosition = new Vector3(-250, 50, 0);
    let mrd = wall_d.addComponent(MeshRenderer);
    mrd.geometry = box;
    mrd.material = mat;
    this.scene.addChild(wall_d);
  }
}

new Sample_Light().run();

点光源

点光源 是存在于空间中的一个点,由该点向四面八方发射光线,超过有效距离的地方将无法接受到点光源的光线,并且离光源越远光照强度也会逐渐降低。通常用来模拟生活中常见的灯泡。点光源有主要以下属性:

属性类型说明
lightColorColor灯光的颜色, 默认是白色 rgb(1.0,1.0,1.0)
intensityNumber光照强度,默认值为 1
rangeNumber光照最远距离
ts
let pointLightObj = new Object3D();
// 设置光源 Object3D 的位置
pointLightObj.x = -10;
pointLightObj.y = 10;
pointLightObj.z = 10;
scene.addChild(pointLightObj);

// 设置点光源组件的半径,强度和颜色
let pointLight = pointLightObj.addComponent(PointLight);
pointLight.range = 20;
pointLight.intensity = 10;
pointLight.lightColor = new Color(1.0, 0.95, 0.84, 1.0);


Orillusion powered by WebGPU on Chrome/Edge 113+
Please upgrade to latest Chrome/Edge

<
ts
import { BoxGeometry, Camera3D, defaultTexture, Engine3D, ForwardRenderJob, GUIHelp, LitMaterial, HoverCameraController, MeshRenderer, Object3D, Scene3D, SphereGeometry, PointLight, Vector3, webGPUContext } from '@orillusion/core';

export class Sample_Light {
  scene: Scene3D;
  hoverCameraController: HoverCameraController;
  lightObj: any;
  constructor() { }

  async run() {
    await Engine3D.init();
    GUIHelp.init();

    this.scene = new Scene3D();
    let cameraObj = new Object3D();
    let mainCamera = cameraObj.addComponent(Camera3D);
    mainCamera.perspective(37, webGPUContext.aspect, 1, 5000.0);

    this.hoverCameraController = mainCamera.object3D.addComponent(HoverCameraController);
    this.scene.addChild(cameraObj);

    //set camera data
    this.hoverCameraController.setCamera(0, -45, 1200);
    await this.initScene(this.scene);

    let renderJob = new ForwardRenderJob(this.scene);
    Engine3D.startRender(renderJob);
  }

  initScene(scene: Scene3D) {
    {
      let sp = new SphereGeometry(5, 30, 30);
      let pointLight = new Object3D();
      pointLight.y = 200;
      let mr = pointLight.addComponent(MeshRenderer);
      mr.geometry = sp;
      mr.material = new LitMaterial();

      let light = pointLight.addComponent(PointLight);
      light.intensity = 100;
      light.range = 300;
      light.lightColor.r = 255 / 255;
      light.lightColor.g = 157 / 255;
      light.lightColor.b = 5 / 255;
      scene.addChild(pointLight);

      light.debug();
    }

    let mat = new LitMaterial();
    mat.baseMap = defaultTexture.grayTexture;

    let floor = new Object3D();
    let mr = floor.addComponent(MeshRenderer);
    mr.geometry = new BoxGeometry(2000, 1, 2000);
    mr.material = mat;
    this.scene.addChild(floor);

    let box = new BoxGeometry(1, 1, 1);
    let wall_w = new Object3D();
    wall_w.localScale = new Vector3(500, 100, 10);
    wall_w.localPosition = new Vector3(0, 50, 0);
    let mrw = wall_w.addComponent(MeshRenderer);
    mrw.geometry = box;
    mrw.material = mat;
    this.scene.addChild(wall_w);

    let wall_a = new Object3D();
    wall_a.localScale = new Vector3(10, 100, 500);
    wall_a.localPosition = new Vector3(250, 50, 0);
    let mra = wall_a.addComponent(MeshRenderer);
    mra.geometry = box;
    mra.material = mat;
    this.scene.addChild(wall_a);

    let wall_d = new Object3D();
    wall_d.localScale = new Vector3(10, 100, 500);
    wall_d.localPosition = new Vector3(-250, 50, 0);
    let mrd = wall_d.addComponent(MeshRenderer);
    mrd.geometry = box;
    mrd.material = mat;
    this.scene.addChild(wall_d);
  }
}

new Sample_Light().run()

聚光灯

聚光灯点光源 类似,但是它的光线不是朝四面八方发射,而是朝某个方向范围,就像现实生活中的手电筒发出的光。聚光灯有几个主要特性:

属性类型说明
lightColorColor灯光的颜色, 默认是白色 rgb(1.0,1.0,1.0)
intensityNumber光照强度,默认值为 1
directionVector3只读属性,获取聚光的方向向量
rangeNumber光照最远距离
innerAngleNumber光锥内切角,聚光在小于这个角度的范围内有光线
outerAngleNumber光锥外切角,光线会在内切角到外切角的范围内逐步衰减到0
ts
let spotLightObj = new Object3D();
// 设置光源 Object3D 的位置
spotLightObj.y = 100;
spotLightObj.rotationX= 90;
scene.addChild(spotLightObj);

// 设置聚光灯组件的属性
let spotLight = spotLightObj.addComponent(SpotLight);
spotLight.lightColor = new Color(1.0, 0.95, 0.84, 1.0);
spotLight.intensity = 20;
spotLight.range = 200;
spotLight.innerAngle = 20;
spotLight.outerAngle = 35;


Orillusion powered by WebGPU on Chrome/Edge 113+
Please upgrade to latest Chrome/Edge

<
ts
import { BoxGeometry, Camera3D, defaultTexture, Engine3D, ForwardRenderJob, GUIHelp, LitMaterial, HoverCameraController, MeshRenderer, Object3D, Scene3D, SphereGeometry, SpotLight, Vector3, webGPUContext } from '@orillusion/core';

export class Sample_Light {
  scene: Scene3D;
  hoverCameraController: HoverCameraController;
  lightObj: any;
  constructor() { }

  async run() {
    await Engine3D.init({});
    GUIHelp.init();

    this.scene = new Scene3D();
    let cameraObj = new Object3D();
    let mainCamera = cameraObj.addComponent(Camera3D);
    mainCamera.perspective(37, webGPUContext.aspect, 1, 5000.0);

    this.hoverCameraController = mainCamera.object3D.addComponent(HoverCameraController);
    this.scene.addChild(cameraObj);

    //set camera data
    this.hoverCameraController.setCamera(0, -45, 1000);
    await this.initScene(this.scene);
    let renderJob = new ForwardRenderJob(this.scene);
    Engine3D.startRender(renderJob);
  }

  initScene(scene: Scene3D) {
    {
      let sp = new SphereGeometry(5, 30, 30);
      let spotLight = new Object3D();
      let mr = spotLight.addComponent(MeshRenderer);
      mr.geometry = sp;
      mr.material = new LitMaterial();

      let light = spotLight.addComponent(SpotLight);
      spotLight.y = 200;
      spotLight.z = 50
      spotLight.rotationX = 120;
      light.lightColor.r = 255 / 255;
      light.lightColor.g = 157 / 255;
      light.lightColor.b = 5 / 255;
      light.intensity = 100;
      light.range = 500;
      light.outerAngle = 110;
      light.innerAngle = 30;
      scene.addChild(spotLight);

      light.debug();
    }

    let mat = new LitMaterial();
    mat.baseMap = defaultTexture.grayTexture;

    let floor = new Object3D();
    let mr = floor.addComponent(MeshRenderer);
    mr.geometry = new BoxGeometry(2000, 1, 2000);
    mr.material = mat;
    this.scene.addChild(floor);

    let box = new BoxGeometry(1, 1, 1);
    let wall_w = new Object3D();
    wall_w.localScale = new Vector3(500, 100, 10);
    wall_w.localPosition = new Vector3(0, 50, 0);
    let mrw = wall_w.addComponent(MeshRenderer);
    mrw.geometry = box;
    mrw.material = mat;
    this.scene.addChild(wall_w);

    let wall_a = new Object3D();
    wall_a.localScale = new Vector3(10, 100, 500);
    wall_a.localPosition = new Vector3(250, 50, 0);
    let mra = wall_a.addComponent(MeshRenderer);
    mra.geometry = box;
    mra.material = mat;
    this.scene.addChild(wall_a);

    let wall_d = new Object3D();
    wall_d.localScale = new Vector3(10, 100, 500);
    wall_d.localPosition = new Vector3(-250, 50, 0);
    let mrd = wall_d.addComponent(MeshRenderer);
    mrd.geometry = box;
    mrd.material = mat;
    this.scene.addChild(wall_d);
  }
}

new Sample_Light().run()

IES 灯光信息

照明工程学会(IES)定义了一种文件格式,可以描述真实灯光在现实世界的光照强度分布情况。IES 文件描述了各种类型的灯具的光线强弱度,衰减曲线,模拟灯珠的透射,折射等光线变化行为,最终解码成指定的2D数据图进行3D空间的灯光映射。

IES 灯光示例

ies_0ies_1ies_2

加载 IES 贴图

除了常规的光源类型设置,引擎还支持通过加载预设的 IES 贴图来设置复杂的光线分布:

ts
// 加载 IES 贴图
let iesTexture = await Engine3D.res.loadTexture("https://cdn.orillusion.com/ies/ies_2.png");
// 创建 IES 对象
let iesPofiles = new IESProfiles();
iesPofiles.IESTexture = iesTexture;
let light = new Object3d()
let pointLight = light.addComponent(PointLight);
// 设置灯光 IES 分布
pointLight.iesPofile = iesPofiles;


Orillusion powered by WebGPU on Chrome/Edge 113+
Please upgrade to latest Chrome/Edge

<
ts
import { BoxGeometry, Camera3D, defaultTexture, Engine3D, ForwardRenderJob, GUIHelp, LitMaterial, HoverCameraController,BitmapTexture2D, MeshRenderer, Object3D, Scene3D, SphereGeometry, PointLight, Vector3, webGPUContext , IESProfiles} from '@orillusion/core';

export class Sample_LightIES {
  scene: Scene3D;
  hoverCameraController: HoverCameraController;
  lightObj: any;
  constructor() { }

  async run() {
    Engine3D.setting.shadow.pointShadowBias = 0.6;
    Engine3D.setting.shadow.type = `HARD`;
    
    await Engine3D.init();
    GUIHelp.init();

    this.scene = new Scene3D();
    let cameraObj = new Object3D();
    let mainCamera = cameraObj.addComponent(Camera3D);
    mainCamera.perspective(37, webGPUContext.aspect, 1, 5000.0);

    this.hoverCameraController = mainCamera.object3D.addComponent(HoverCameraController);
    this.scene.addChild(cameraObj);

    //set camera data
    this.hoverCameraController.setCamera(0, -45, 200);
    await this.initScene(this.scene);

    let renderJob = new ForwardRenderJob(this.scene);
    Engine3D.startRender(renderJob);
  }

  async initScene(scene: Scene3D) {

    let iesTexture = await Engine3D.res.loadTexture("https://cdn.orillusion.com/ies/ies_2.png") as BitmapTexture2D;
    var iesPofiles = new IESProfiles();
    iesPofiles.IESTexture = iesTexture;

    {
        let po = new Object3D();
        let pl = po.addComponent(PointLight);
        pl.intensity = 10;
        pl.range = 100;
        pl.castShadow = true;
        pl.realTimeShadow = true;
        pl.iesPofile = iesPofiles;
        po.x = 0;
        po.y = 22;
        po.z = 15 ;
        this.scene.addChild(po);
        pl.debug();
        pl.debugDraw(true);
    }
    
    let ball: Object3D;
    {
        let mat = new LitMaterial();
        mat.baseMap = defaultTexture.whiteTexture;
        mat.normalMap = defaultTexture.normalTexture;
        mat.aoMap = defaultTexture.whiteTexture;
        mat.maskMap = defaultTexture.createTexture(32, 32, 255.0, 255.0, 0.0, 1);
        mat.emissiveMap = defaultTexture.blackTexture;
        mat.roughness = 0.5;
        mat.metallic = 0.2;

        ball = new Object3D();
        let mr = ball.addComponent(MeshRenderer);
        mr.geometry = new SphereGeometry(6, 20, 20);
        mr.material = mat;
        this.scene.addChild(ball);
        ball.transform.x = -17;
        ball.transform.y = 10;
        ball.transform.z = 10;

        //wall
        let back_wall =  new Object3D();
        let mr2 = back_wall.addComponent(MeshRenderer);
        mr2.geometry = new BoxGeometry(500,500,10);
        mr2.material = mat;
        this.scene.addChild(back_wall);       
    }
  }
}

new Sample_LightIES().run()

获取 IES 贴图

社区中有大量优质的 IES 资源分享社区,一些灯光设备厂商也会分享专业的 IES 文件,它们一般都是免费的,比如:

社区中同样有很多专业的 IES 预览/转换的软件,比如 IESviewer,您也可以使用专业的3D建模软件来将 IES 文件转换到普通的 png 贴图文件,最后加载到引擎中来。

环境光

除了直接的光源,引擎通过设置 Scene3D.evnMap 天空盒贴图进行基本的环境光渲染,详情参考 天空盒 相关设置

全局光照

一般光照系统只考虑光源直接照射到物体表面所产生的效果,不会计算光源经过物体表面反射或折射的光线,即间接光照。全局光照系统能够对间接光照进行建模,实现更加逼真的光线效果。详情参考 高级 GI