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
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


WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

<
ts
import { BoxGeometry, Camera3D, Engine3D, AtmosphericComponent, LitMaterial, HoverCameraController, MeshRenderer, Object3D, Scene3D, DirectLight, Vector3, webGPUContext, View3D } from '@orillusion/core'
import * as dat from 'dat.gui'

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

    async run() {
        await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        })
        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)
        this.initScene(this.scene)

        // add an Atmospheric sky enviroment
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6
        // create a view with target scene and camera
        let view = new View3D()
        view.scene = this.scene
        view.camera = mainCamera
        // start render
        Engine3D.startRenderView(view)
    }

    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
            scene.addChild(dirLight)

            let GUIHelp = new dat.GUI()
            GUIHelp.addFolder('Direct Light')
            GUIHelp.add(dirLight, 'rotationX', -180, 180, 1)
            GUIHelp.add(dirLight, 'rotationY', -180, 180, 1)
            GUIHelp.add(dirLight, 'rotationZ', -180, 180, 1)
            GUIHelp.addColor({ color: Object.values(light.lightColor).map((v) => v * 255) }, 'color').onChange((v) => {
                light.lightColor.copyFromArray(v)
            })
            GUIHelp.add(light, 'intensity', 0, 100, 1)
        }

        let mat = new LitMaterial()
        mat.baseMap = Engine3D.res.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()
import { BoxGeometry, Camera3D, Engine3D, AtmosphericComponent, LitMaterial, HoverCameraController, MeshRenderer, Object3D, Scene3D, DirectLight, Vector3, webGPUContext, View3D } from '@orillusion/core'
import * as dat from 'dat.gui'

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

    async run() {
        await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        })
        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)
        this.initScene(this.scene)

        // add an Atmospheric sky enviroment
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6
        // create a view with target scene and camera
        let view = new View3D()
        view.scene = this.scene
        view.camera = mainCamera
        // start render
        Engine3D.startRenderView(view)
    }

    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
            scene.addChild(dirLight)

            let GUIHelp = new dat.GUI()
            GUIHelp.addFolder('Direct Light')
            GUIHelp.add(dirLight, 'rotationX', -180, 180, 1)
            GUIHelp.add(dirLight, 'rotationY', -180, 180, 1)
            GUIHelp.add(dirLight, 'rotationZ', -180, 180, 1)
            GUIHelp.addColor({ color: Object.values(light.lightColor).map((v) => v * 255) }, 'color').onChange((v) => {
                light.lightColor.copyFromArray(v)
            })
            GUIHelp.add(light, 'intensity', 0, 100, 1)
        }

        let mat = new LitMaterial()
        mat.baseMap = Engine3D.res.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);
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);


WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

<
ts
import { BoxGeometry, Camera3D, Engine3D, AtmosphericComponent, LitMaterial, HoverCameraController, MeshRenderer, Object3D, Scene3D, SphereGeometry, PointLight, Vector3, webGPUContext, View3D } from '@orillusion/core'
import * as dat from 'dat.gui'

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

    async run() {
        await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        })

        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)

        // add an Atmospheric sky enviroment
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6
        // create a view with target scene and camera
        let view = new View3D()
        view.scene = this.scene
        view.camera = mainCamera
        // start render
        Engine3D.startRenderView(view)
    }

    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)

            let GUIHelp = new dat.GUI()
            GUIHelp.addFolder('Direct Light')
            GUIHelp.add(pointLight, 'x', -180, 180, 1)
            GUIHelp.add(pointLight, 'y', -180, 180, 1)
            GUIHelp.add(pointLight, 'z', -180, 180, 1)
            GUIHelp.addColor({ color: Object.values(light.lightColor).map((v) => v * 255) }, 'color').onChange((v) => {
                light.lightColor.copyFromArray(v)
            })
            GUIHelp.add(light, 'intensity', 0, 100, 1)
            GUIHelp.add(light, 'range', 100, 500, 1)
        }

        let mat = new LitMaterial()
        mat.baseMap = Engine3D.res.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()
import { BoxGeometry, Camera3D, Engine3D, AtmosphericComponent, LitMaterial, HoverCameraController, MeshRenderer, Object3D, Scene3D, SphereGeometry, PointLight, Vector3, webGPUContext, View3D } from '@orillusion/core'
import * as dat from 'dat.gui'

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

    async run() {
        await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        })

        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)

        // add an Atmospheric sky enviroment
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6
        // create a view with target scene and camera
        let view = new View3D()
        view.scene = this.scene
        view.camera = mainCamera
        // start render
        Engine3D.startRenderView(view)
    }

    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)

            let GUIHelp = new dat.GUI()
            GUIHelp.addFolder('Direct Light')
            GUIHelp.add(pointLight, 'x', -180, 180, 1)
            GUIHelp.add(pointLight, 'y', -180, 180, 1)
            GUIHelp.add(pointLight, 'z', -180, 180, 1)
            GUIHelp.addColor({ color: Object.values(light.lightColor).map((v) => v * 255) }, 'color').onChange((v) => {
                light.lightColor.copyFromArray(v)
            })
            GUIHelp.add(light, 'intensity', 0, 100, 1)
            GUIHelp.add(light, 'range', 100, 500, 1)
        }

        let mat = new LitMaterial()
        mat.baseMap = Engine3D.res.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;
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;


WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

<
ts
import { BoxGeometry, Camera3D, Engine3D, AtmosphericComponent, LitMaterial, HoverCameraController, MeshRenderer, Object3D, Scene3D, SphereGeometry, SpotLight, Vector3, webGPUContext, View3D } from '@orillusion/core'
import * as dat from 'dat.gui'

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

    async run() {
        await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        })

        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)
        this.initScene(this.scene)

        // add an Atmospheric sky enviroment
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6
        // create a view with target scene and camera
        let view = new View3D()
        view.scene = this.scene
        view.camera = mainCamera
        // start render
        Engine3D.startRenderView(view)
    }

    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)

            let GUIHelp = new dat.GUI()
            GUIHelp.addFolder('Direct Light')
            GUIHelp.add(spotLight, 'x', -180, 180, 1)
            GUIHelp.add(spotLight, 'y', -180, 180, 1)
            GUIHelp.add(spotLight, 'z', -180, 180, 1)
            GUIHelp.add(spotLight, 'rotationX', -180, 180, 1)
            GUIHelp.add(spotLight, 'rotationY', -180, 180, 1)
            GUIHelp.add(spotLight, 'rotationZ', -180, 180, 1)
            GUIHelp.addColor({ color: Object.values(light.lightColor).map((v) => v * 255) }, 'color').onChange((v) => {
                light.lightColor.copyFromArray(v)
            })
            GUIHelp.add(light, 'intensity', 0, 100, 1)
            GUIHelp.add(light, 'range', 100, 500, 1)
            GUIHelp.add(light, 'outerAngle', 0, 180, 1)
            GUIHelp.add(light, 'innerAngle', 0, 100, 1)
        }

        let mat = new LitMaterial()
        mat.baseMap = Engine3D.res.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()
import { BoxGeometry, Camera3D, Engine3D, AtmosphericComponent, LitMaterial, HoverCameraController, MeshRenderer, Object3D, Scene3D, SphereGeometry, SpotLight, Vector3, webGPUContext, View3D } from '@orillusion/core'
import * as dat from 'dat.gui'

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

    async run() {
        await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        })

        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)
        this.initScene(this.scene)

        // add an Atmospheric sky enviroment
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6
        // create a view with target scene and camera
        let view = new View3D()
        view.scene = this.scene
        view.camera = mainCamera
        // start render
        Engine3D.startRenderView(view)
    }

    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)

            let GUIHelp = new dat.GUI()
            GUIHelp.addFolder('Direct Light')
            GUIHelp.add(spotLight, 'x', -180, 180, 1)
            GUIHelp.add(spotLight, 'y', -180, 180, 1)
            GUIHelp.add(spotLight, 'z', -180, 180, 1)
            GUIHelp.add(spotLight, 'rotationX', -180, 180, 1)
            GUIHelp.add(spotLight, 'rotationY', -180, 180, 1)
            GUIHelp.add(spotLight, 'rotationZ', -180, 180, 1)
            GUIHelp.addColor({ color: Object.values(light.lightColor).map((v) => v * 255) }, 'color').onChange((v) => {
                light.lightColor.copyFromArray(v)
            })
            GUIHelp.add(light, 'intensity', 0, 100, 1)
            GUIHelp.add(light, 'range', 100, 500, 1)
            GUIHelp.add(light, 'outerAngle', 0, 180, 1)
            GUIHelp.add(light, 'innerAngle', 0, 100, 1)
        }

        let mat = new LitMaterial()
        mat.baseMap = Engine3D.res.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;
// 加载 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;


WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

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

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

    async run() {
        Engine3D.setting.shadow.pointShadowBias = 0.0001
        Engine3D.setting.shadow.type = `HARD`

        await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        })

        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)

        // add an Atmospheric sky enviroment
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6
        // create a view with target scene and camera
        let view = new View3D()
        view.scene = this.scene
        view.camera = mainCamera
        // start render
        Engine3D.startRenderView(view)
    }

    async initScene(scene: Scene3D) {
        // load ies texture
        let iesTexture = await Engine3D.res.loadTexture('https://cdn.orillusion.com/ies/ies_2.png')
        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.iesProfiles = iesPofiles
            po.x = 0
            po.y = 22
            po.z = 15
            this.scene.addChild(po)
        }

        let ball: Object3D
        {
            let mat = new LitMaterial()
            mat.baseMap = Engine3D.res.whiteTexture
            mat.normalMap = Engine3D.res.normalTexture
            mat.aoMap = Engine3D.res.whiteTexture
            mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1)
            mat.emissiveMap = Engine3D.res.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()
import { BoxGeometry, Camera3D, Engine3D, View3D, LitMaterial, HoverCameraController, BitmapTexture2D, MeshRenderer, Object3D, Scene3D, SphereGeometry, PointLight, Vector3, webGPUContext, IESProfiles, AtmosphericComponent } from '@orillusion/core'

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

    async run() {
        Engine3D.setting.shadow.pointShadowBias = 0.0001
        Engine3D.setting.shadow.type = `HARD`

        await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        })

        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)

        // add an Atmospheric sky enviroment
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6
        // create a view with target scene and camera
        let view = new View3D()
        view.scene = this.scene
        view.camera = mainCamera
        // start render
        Engine3D.startRenderView(view)
    }

    async initScene(scene: Scene3D) {
        // load ies texture
        let iesTexture = await Engine3D.res.loadTexture('https://cdn.orillusion.com/ies/ies_2.png')
        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.iesProfiles = iesPofiles
            po.x = 0
            po.y = 22
            po.z = 15
            this.scene.addChild(po)
        }

        let ball: Object3D
        {
            let mat = new LitMaterial()
            mat.baseMap = Engine3D.res.whiteTexture
            mat.normalMap = Engine3D.res.normalTexture
            mat.aoMap = Engine3D.res.whiteTexture
            mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1)
            mat.emissiveMap = Engine3D.res.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