Skip to content

Lighting

Lighting can make the scene more layered, using lighting, you can build a more realistic three-dimensional scene. The lighting system of the Orillusion engine is mainly composed of the following parts:

Light SourceDescription
Light ComponentBasic light source components: direct light, point light and spotlight
Ambient ReflectionSkybox environment light, global exposure
Global IlluminationIndirect light sources reflected or refracted in the scene

Light Component

There are currently three types of classic light sources built into the engine:

Direct Light

Direct Light represents the light that is emitted uniformly from a certain direction and lights between them are parallel. The lights from the sun to the earth can be considered as the parallel light, because the distance between the sun and the earth is far greater than the radius of the earth, so the lights from the sun to the earth can be seen as lights from the same direction, that is, the parallel light. The direct light has 4 main features:

AttributeTypeDescription
lightColorColorThe color of the light, the default is white rgb(1.0,1.0,1.0)
intensityNumberThe intensity of the light, the default value is 1
directionVector3Read-only property, get the direction vector of the parallel light
castShadowBooleanWhether to enable projection, the default false is disabled

Normally, the rotation of the Object3D, where the direct light is located, is used to control the direction of the light.

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

// Add direct light
let dl = lightObj.addComponent(DirectLight);
// Set color
dl.lightColor = new Color(1.0, 0.95, 0.84, 1.0);
// Set intensity
dl.intensity = 20;

// Set the direction of the light source through Object3D
lightObj.rotateX = 45;
lightObj.rotateY = 45;
// You can get the direction vector through 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';

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();

Point Light

Point Light is a point that exists in space, and light is emitted from that point in all directions. The light beyond the effective distance cannot receive the light from the point light, and the intensity of the light will gradually decrease as the light source moves away. It is usually used to simulate the common bulbs in life. The point light has the following main attributes:

AttributeTypeDescription
lightColorColorThe color of the light, the default is white rgb(1.0,1.0,1.0)
intensityNumberThe intensity of the light, the default value is 1
rangeNumberThe farthest distance of the light
ts
let pointLightObj = new Object3D();
// Set the position of the light source Object3D
pointLightObj.x = -10;
pointLightObj.y = 10;
pointLightObj.z = 10;
scene.addChild(pointLightObj);

// Set the radius, intensity, and color of the point light component
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';

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, 200, 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();

Spot Light

Spot Light is similar to the point light, but its light is not emitted in all directions, but in a certain direction range, just like the light emitted by the flashlight in real life. The spotlight has several main features:

AttributeTypeDescription
lightColorColorThe color of the light, the default is white rgb(1.0,1.0,1.0)
intensityNumberThe intensity of the light, the default value is 1
directionVector3Read-only property, get the direction vector of the spotlight
rangeNumberThe farthest distance of the light
innerAngleNumberThe inner angle of the spotlight, the light has light in the range of less than this angle
outerAngleNumberThe outer angle of the spotlight, the light will gradually decrease to 0 in the range from the inner angle to the outer angle
ts
let spotLightObj = new Object3D();
// Set the position of the light source Object3D
spotLightObj.y = 100;
spotLightObj.rotationX = 90;
scene.addChild(spotLightObj);

// Set the attributes of the spotlight component
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';

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, 200, 1);
            GUIHelp.add(light, 'range', 100, 1000, 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 Light Information

The Illuminating Engineering Society(IES) defines a file format that can describe the light intensity distribution of real light in the real world. The IES file describes the light intensity of various types of lamps, attenuation curves, simulating the transmission and refraction of the lamp beads, and finally decoding into a specified 2D data map for 3D space lighting mapping.

IES Light Example

ies_0ies_1ies_2

Load IES Texture

Besides the common light source type settings, the engine also supports setting complex light distribution by loading preset IES textures:

ts
// Load IES texture
let iesTexture = await Engine3D.res.loadTexture("https://cdn.orillusion.com/ies/ies_2.png");
// Create IES object
let iesPofiles = new IESProfiles();
iesPofiles.IESTexture = iesTexture;
let light = new Object3d()
let pointLight = light.addComponent(PointLight);
// Set light IES distribution
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';

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.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();

Get IES Texture

The community has a lot of high-quality IES resources, some lighting equipment manufacturers will also share professional IES files, they are generally free, such as:

The community also has a lot of professional IES preview/conversion software, such as IESviewer, you can also use professional 3D modeling software to convert the IES file to a normal png texture file, and then load it into the engine.

Environment Light

Besides the direct light source, the engine can also render basic environment lighting by setting the Scene3D.evnMap skybox texture, see Skybox for related settings.

Global Illumination

Normal lighting system only considers the effect of light source directly irradiating the surface of the object, and does not calculate the light reflected or refracted by the light source through the surface of the object, that is, indirect lighting. Global illumination system can model indirect lighting to achieve more realistic lighting effects. See Advanced GI for details.

Released under the MIT License