Skip to content

Outline

The engine implements the function of drawing the unobstructed parts of a specified object. You can set different styles for the outlined contour line, such as solid line and faded part width.

ts
import {Engine3D, View3D, OutlinePost } from '@orillusion/core';
// Initialize the engine
await Engine3D.init();

// Set the width of the hard edge and the width of the faded edge
Engine3D.setting.render.postProcessing.outline.outlinePixel = 2;
Engine3D.setting.render.postProcessing.outline.fadeOutlinePixel = 4;

// Add OutlinePost
let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(OutlinePost);
//Start rendering
let view = new View3D();
view.scene = this.scene;
view.camera = this.camera;
Engine3D.startRenderView(view);

Engine3D.setting.render.postProcessing.outline configuration parameters:

ParameterTypeDescription
outlinePixelnumberThe pixel width of the hard edge.
fadeOutlinePixelnumberThe pixel width of the faded edge.

Use the outlinePostManager to specify the outline list. Currently, outline can specify up to eight lists, and each list can set a different outline color. Multiple objects can be set within a single group. The order of the groups determines the priority of the outlined contours.

ts
let obj1 = new Object3D()
let obj2 = new Object3D()

// Set the outline target, divide into two groups and two colors
outlinePostManager.setOutlineList([[obj1], [obj2]], [new Color(1, 0.2, 0, 1), new Color(0.2, 1, 0)]);

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

<
ts
import { DirectLight, Engine3D, View3D, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, PostProcessingComponent, CameraUtil, webGPUContext, OutlinePost, outlinePostManager, AtmosphericComponent, Color } from '@orillusion/core';
import * as dat from 'dat.gui';

class Sample_Outline {
    lightObj: Object3D;
    scene: Scene3D;

    constructor() {}

    async run() {
        Engine3D.setting.shadow.enable = false;
        await Engine3D.init({
            canvasConfig: {
                devicePixelRatio: 1
            }
        });

        this.scene = new Scene3D();
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6;

        let mainCamera = CameraUtil.createCamera3DObject(this.scene, 'camera');
        mainCamera.perspective(60, webGPUContext.aspect, 1, 2000.0);
        let ctrl = mainCamera.object3D.addComponent(HoverCameraController);
        ctrl.setCamera(180, -45, 15);

        await this.initScene(this.scene);

        let view = new View3D();
        view.scene = this.scene;
        view.camera = mainCamera;
        Engine3D.startRenderView(view);

        let postProcessing = this.scene.addComponent(PostProcessingComponent);
        let outlinePost = postProcessing.addPost(OutlinePost);

        const GUIHelp = new dat.GUI();
        GUIHelp.addFolder('Outline');
        GUIHelp.add(outlinePost, 'outlinePixel', 0, 5);
        GUIHelp.add(outlinePost, 'fadeOutlinePixel', 0, 5);
        GUIHelp.add(
            {
                Change: () => {
                    this.selectBall();
                }
            },
            'Change'
        );
        this.selectBall();
    }

    private selectBall(): void {
        outlinePostManager.setOutlineList([[this.nextSphere()], [this.nextSphere()], [this.nextSphere()]], [new Color(1, 0.2, 0, 1), new Color(0.2, 1, 0), new Color(0.2, 0, 1)]);
    }

    async initScene(scene: Scene3D) {
        /******** light *******/
        {
            this.lightObj = new Object3D();
            this.lightObj.x = 0;
            this.lightObj.y = 30;
            this.lightObj.z = -40;
            this.lightObj.rotationX = 45;
            this.lightObj.rotationY = 0;
            this.lightObj.rotationZ = 45;
            let lc = this.lightObj.addComponent(DirectLight);
            lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
            lc.intensity = 3;
            scene.addChild(this.lightObj);
        }
        this.createPlane(scene);

        return true;
    }

    private sphereList: Object3D[] = [];
    private sphereIndex = 0;

    private nextSphere(): Object3D {
        this.sphereIndex++;
        if (this.sphereIndex >= this.sphereList.length) {
            this.sphereIndex = 1;
        }

        return this.sphereList[this.sphereIndex];
    }

    private createPlane(scene: Scene3D) {
        let mat = new LitMaterial();
        {
            let debugGeo = new PlaneGeometry(1000, 1000);
            let obj: Object3D = new Object3D();
            let mr = obj.addComponent(MeshRenderer);
            mr.material = mat;
            mr.geometry = debugGeo;
            scene.addChild(obj);
        }

        let sphereGeometry = new SphereGeometry(1, 50, 50);
        for (let i = 0; i < 10; i++) {
            let obj: Object3D = new Object3D();
            let mr = obj.addComponent(MeshRenderer);
            mr.material = mat;
            mr.geometry = sphereGeometry;
            obj.x = 2;
            obj.y = 2;

            let angle = (2 * Math.PI * i) / 10;
            obj.x = Math.sin(angle) * 2;
            obj.z = Math.cos(angle) * 2;
            scene.addChild(obj);
            this.sphereList.push(obj);
        }
    }
}

new Sample_Outline().run();

Released under the MIT License