Skip to content

Lighting ​

Lighting makes 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: directional light, point light, spotlight and rect area light
Ambient ReflectionSkybox environment light, global exposure
Global IlluminationIndirect light sources reflected or refracted in the scene

Light Component ​

The engine currently has four types of light sources built in:

Directional Light ​

Directional Light represents light that is emitted uniformly from a certain direction, with the light rays parallel to each other. The light from the sun shining on the earth's surface can be considered as directional light, because the distance between the sun and the earth is far greater than the radius of the earth, so the sunlight shining on the earth can be regarded as light coming from the same direction, that is, directional light. Directional light has 4 main features:

PropertyTypeDescription
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, gets the direction vector of the directional light
castShadowBooleanWhether to enable shadow casting, the default false is disabled

Generally, the rotation of the Object3D where the directional light is located is used to control the direction of the light.

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

// Add directional 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, View3D } from '@orillusion/core';
import * as dat from 'dat.gui';

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

    async run() {
        this.engine = await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        });
        this.scene = new Scene3D();
        let cameraObj = new Object3D();
        let mainCamera = cameraObj.addComponent(Camera3D);
        mainCamera.perspective(37, this.engine.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
        this.engine.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 = this.engine.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, emitting light from that point in all directions. Places beyond the effective distance cannot receive the light from the point light, and the lighting intensity gradually decreases the farther it is from the light source. It is usually used to simulate common bulbs in life. The point light has the following main properties:

PropertyTypeDescription
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, View3D } from '@orillusion/core';
import * as dat from 'dat.gui';

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

    async run() {
        this.engine = await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        });

        this.scene = new Scene3D();
        let cameraObj = new Object3D();
        let mainCamera = cameraObj.addComponent(Camera3D);
        mainCamera.perspective(37, this.engine.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
        this.engine.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 = this.engine.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();

Spotlight ​

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

PropertyTypeDescription
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, gets the direction vector of the spotlight
rangeNumberThe farthest distance of the light
innerAngleNumberThe inner angle of the light cone, within which the spotlight has light
outerAngleNumberThe outer angle of the light cone, the light gradually attenuates 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 properties 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, View3D } from '@orillusion/core';
import * as dat from 'dat.gui';

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

    async run() {
        this.engine = await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 }
        });

        this.scene = new Scene3D();
        let cameraObj = new Object3D();
        let mainCamera = cameraObj.addComponent(Camera3D);
        mainCamera.perspective(37, this.engine.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
        this.engine.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 = this.engine.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();

Rect Area Light ​

A rect area light is a rectangular emitting panel with a real size that emits from one side only, for windows, softboxes, ceiling panels, screens and the like. Unlike point lights and spotlights, its light comes from a whole area: nearby surfaces receive soft diffuse light that "wraps" around objects, and glossy surfaces show a rectangular highlight. The rect area light has the following main properties:

PropertyTypeDescription
lightColorColorThe color of the light, the default is white rgb(1.0,1.0,1.0)
intensityNumberThe emitted intensity (radiance) of the panel, the default value is 5
widthNumberPanel width (along the object's right axis), the default value is 2
heightNumberPanel height (along the object's up axis), the default value is 1
rangeNumberThe farthest distance of the light, from the panel center to where it fades to 0, the default value is 20

The panel emits toward the object's forward direction. As with the spotlight, its direction is controlled by the rotation of the Object3D, or lookAt can point it straight at a target:

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

// Set the properties of the rect area light component
let rectLight = rectLightObj.addComponent(RectLight);
rectLight.lightColor = new Color(1.0, 0.72, 0.45, 1.0);
rectLight.intensity = 6;
rectLight.width = 5;
rectLight.height = 4;
rectLight.range = 45;

// Place it at (-9, 5, 3), emitting toward (0, 2, 0)
rectLightObj.transform.lookAt(new Vector3(-9, 5, 3), new Vector3(0, 2, 0));

TIP

  • intensity is the emitted intensity per unit area of the panel, so a larger panel lights the scene more, just like a real softbox;
  • rect area lights do not cast shadows; castShadow is ignored;
  • the light itself is invisible. To see the emitting panel, place an UnLitMaterial plane or thin box of the same size at the same position, as in the example below.

The example below is a dark room lit only by three rect area lights: a warm key light on the left, a cool fill light on the right and a magenta strip swinging above the stage. The glossy floor shows a stretched rectangular reflection of each panel, while the back wall and the matte spheres show the soft diffuse light that changes with the panel size; the two rows of spheres go from mirror-like to matte.

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

<
ts
import { BoxGeometry, CameraUtil, Color, ComponentBase, Engine3D, GeometryBase, HoverCameraController, LitMaterial, Material, MeshRenderer, Object3D, RectLight, Scene3D, SphereGeometry, TorusGeometry, UnLitMaterial, Vector3, View3D } from '@orillusion/core';
import * as dat from 'dat.gui';

type Panel = { obj: Object3D; light: RectLight; face: Object3D; mat: UnLitMaterial };

/**
 * RectLight: a dark studio lit only by three rectangular panels.
 * A warm key panel on the left, a cool one on the right and a magenta strip that swings over the stage.
 * The glossy floor shows each panel as a stretched rectangular reflection; the back wall and the matte
 * spheres show the soft, size-dependent diffuse falloff. The sphere rows sweep roughness from mirror-like to matte.
 * The light itself is invisible: each panel carries a thin unlit box so you can see where the emitter is.
 */
class Sample_RectLight {
    private scene: Scene3D;
    private panels: Panel[] = [];

    async run() {
        const engine = await Engine3D.init();
        this.scene = new Scene3D();

        const camera = CameraUtil.createCamera3DObject(this.scene);
        camera.perspective(50, engine.aspect, 0.1, 500);
        camera.object3D.addComponent(HoverCameraController).setCamera(20, -18, 30, new Vector3(0, 3, 0));

        this.buildStage();
        this.addPanel('key (warm)', new Color(1.0, 0.72, 0.45), 6, new Vector3(-9, 5, 3), new Vector3(0, 2, 0), 5, 4);
        this.addPanel('fill (cool)', new Color(0.45, 0.7, 1.0), 5, new Vector3(9, 4, 4), new Vector3(0, 2, 0), 3, 6);
        this.addPanel('strip (magenta)', new Color(1.0, 0.25, 0.8), 8, new Vector3(0, 8, -2), new Vector3(0, 0, -2), 10, 1);

        const swing = this.scene.addComponent(Swing);
        swing.target = this.panels[2].obj;

        const view = new View3D();
        view.scene = this.scene;
        view.camera = camera;
        engine.startRenderView(view);
        this.initGUI(swing);
    }

    private mesh(geo: GeometryBase, mat: Material, x: number, y: number, z: number): Object3D {
        const obj = new Object3D();
        const mr = obj.addComponent(MeshRenderer);
        mr.geometry = geo;
        mr.material = mat;
        obj.x = x;
        obj.y = y;
        obj.z = z;
        this.scene.addChild(obj);
        return obj;
    }

    private lit(r: number, g: number, b: number, roughness: number, metallic = 0): LitMaterial {
        const m = new LitMaterial();
        m.baseColor = new Color(r, g, b, 1);
        m.roughness = roughness;
        m.metallic = metallic;
        return m;
    }

    private buildStage() {
        // Glossy floor and matte back wall
        this.mesh(new BoxGeometry(60, 0.4, 60), this.lit(0.35, 0.35, 0.37, 0.35), 0, -0.2, 0);
        this.mesh(new BoxGeometry(60, 24, 0.4), this.lit(0.7, 0.7, 0.7, 1.0), 0, 12, -12);
        // Two rows of spheres sweeping roughness: metal in front, dielectric behind
        const ball = new SphereGeometry(1.2, 48, 48);
        for (let i = 0; i < 6; i++) {
            this.mesh(ball, this.lit(0.85, 0.85, 0.85, 0.1 + i * 0.18, 1), (i - 2.5) * 3, 1.2, 1);
            this.mesh(ball, this.lit(0.8, 0.8, 0.8, 0.2 + i * 0.16, 0), (i - 2.5) * 3, 1.2, -3);
        }
        const torus = this.mesh(new TorusGeometry(2, 0.6, 48, 64), this.lit(0.9, 0.75, 0.4, 0.4, 1), 0, 3.4, -7);
        torus.rotationX = 70;
    }

    private addPanel(name: string, color: Color, intensity: number, pos: Vector3, target: Vector3, width: number, height: number) {
        const obj = new Object3D();
        obj.name = name;
        const light = obj.addComponent(RectLight);
        light.lightColor = color;
        light.intensity = intensity;
        light.width = width;
        light.height = height;
        light.range = 45;
        this.scene.addChild(obj);
        // The panel emits along the object's forward axis: lookAt points it at the target
        obj.transform.lookAt(pos, target);

        // Visible emitter: a thin unlit box in the light's own plane
        const face = new Object3D();
        const mr = face.addComponent(MeshRenderer);
        mr.geometry = new BoxGeometry(1, 1, 0.05);
        const mat = new UnLitMaterial();
        mr.material = mat;
        mr.castShadow = false;
        obj.addChild(face);
        const panel = { obj, light, face, mat };
        this.panels.push(panel);
        this.syncFace(panel);
    }

    private syncFace(p: Panel) {
        p.face.localScale = new Vector3(p.light.width, p.light.height, 1);
        const c = p.light.lightColor;
        const k = Math.min(p.light.intensity, 12) / 4;
        p.mat.baseColor = new Color(c.r * k, c.g * k, c.b * k, 1);
    }

    private initGUI(swing: Swing) {
        const gui = new dat.GUI();
        for (const p of this.panels) {
            const f = gui.addFolder(p.obj.name);
            const c = p.light.lightColor;
            const proxy = { enable: true, color: [c.r * 255, c.g * 255, c.b * 255] };
            f.add(proxy, 'enable').onChange((v: boolean) => {
                p.light.enable = v;
                p.face.transform.enable = v;
            });
            f.add(p.light, 'intensity', 0, 20, 0.1).onChange(() => this.syncFace(p));
            f.add(p.light, 'width', 0.2, 16, 0.1).onChange(() => this.syncFace(p));
            f.add(p.light, 'height', 0.2, 16, 0.1).onChange(() => this.syncFace(p));
            f.add(p.light, 'range', 5, 80, 1);
            f.addColor(proxy, 'color').onChange((v: number[]) => {
                p.light.lightColor = new Color(v[0] / 255, v[1] / 255, v[2] / 255, 1);
                this.syncFace(p);
            });
        }
        const s = gui.addFolder('strip animation');
        s.add(swing, 'enable').name('swing');
        s.add(swing, 'speed', 0, 3, 0.05);
        // Start collapsed so the panel does not cover the scene
        gui.close();
    }
}

/** Swings the magenta strip light over the stage. */
class Swing extends ComponentBase {
    public target: Object3D;
    public speed = 0.6;
    private time = 0;

    public onUpdate(): void {
        if (!this.target) return;
        this.time += 0.016 * this.speed;
        const x = Math.sin(this.time) * 7;
        this.target.transform.lookAt(new Vector3(x, 8, -2 + Math.cos(this.time * 0.7) * 3), new Vector3(x * 0.3, 0, -2));
    }
}

new Sample_RectLight().run();

IES Light Information ​

The Illuminating Engineering Society (IES) defines a file format that can describe the light intensity distribution of real lights in the real world. IES files describe the light intensity, attenuation curves of various types of luminaires, and simulate light variation behaviors such as the transmission and refraction of the lamp beads, ultimately decoding into a specified 2D data map for lighting mapping in 3D space.

IES Light Examples ​

ies_0ies_1ies_2

Load IES Texture ​

In addition to the regular light source type settings, the engine also supports setting complex light distribution by loading preset IES textures:

ts
// Load IES texture
let iesTexture = await engine.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 the 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, IESProfiles, AtmosphericComponent } from '@orillusion/core';

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

    async run() {
        this.engine = await Engine3D.init({
            canvasConfig: { devicePixelRatio: 1 },
            setting: {
                shadow: {
                    pointShadowBias: 0.0001,
                    type: `HARD`
                }
            }
        });

        this.scene = new Scene3D();
        let cameraObj = new Object3D();
        let mainCamera = cameraObj.addComponent(Camera3D);
        mainCamera.perspective(37, this.engine.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
        this.engine.startRenderView(view);
    }

    async initScene(scene: Scene3D) {
        // load ies texture
        let iesTexture = await this.engine.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 Textures ​

There are many high-quality IES resource sharing communities, and some lighting equipment manufacturers also share professional IES files, which are generally free, such as:

The community also has many professional IES preview/conversion software, such as IESviewer. You can also use professional 3D modeling software to convert IES files into ordinary png texture files, and finally load them into the engine.

Environment Light ​

In addition to direct light sources, the engine performs basic environment lighting rendering by setting the Scene3D.evnMap skybox texture. For details, refer to the related Skybox introduction.

Global Illumination ​

A general lighting system only considers the effect produced by the light source directly shining on the surface of the object, and does not calculate the light reflected or refracted by the surface of the object, that is, indirect lighting. The global illumination system can model indirect lighting to achieve more realistic light effects. For details, refer to Advanced GI

Released under the MIT License