Skip to content

轮廓描边 - Outline

引擎内实现了为指定的物体描绘未被遮挡的部分轮廓的功能。你可以为描边的轮廓线单独设置实线、淡出部分的宽度实现不同样式。

ts
import {Engine3D, View3D, OutlinePost } from '@orillusion/core';
// 初始化引擎
await Engine3D.init();
Engine3D.setting.render.postProcessing.outline.outlinePixel = 2;
Engine3D.setting.render.postProcessing.outline.fadeOutlinePixel = 4;

// 添加 OutlinePost
let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(OutlinePost);

//开始渲染
let view = new View3D();
view.scene = this.scene;
view.camera = this.camera;
Engine3D.startRenderView(view);
import {Engine3D, View3D, OutlinePost } from '@orillusion/core';
// 初始化引擎
await Engine3D.init();
Engine3D.setting.render.postProcessing.outline.outlinePixel = 2;
Engine3D.setting.render.postProcessing.outline.fadeOutlinePixel = 4;

// 添加 OutlinePost
let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(OutlinePost);

//开始渲染
let view = new View3D();
view.scene = this.scene;
view.camera = this.camera;
Engine3D.startRenderView(view);

Engine3D.setting.render.postProcessing.outline 配置参数。

参数类型描述
outlinePixelnumber描边硬边的像素宽度。
fadeOutlinePixelnumber描边淡出像素宽度。

通过 outlinePostManager 指定描边列表。目前 outline 最多指定8组列表,每组可以设置不同的轮廓颜色;单组内的物体可以设置多个对象。分组的先后顺序决定了描边轮廓覆盖的优先级。

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

// 设定 Outline 目标, 分2组,2种颜色
outlinePostManager.setOutlineList([[obj1], [obj2]], [new Color(1, 0.2, 0, 1), new Color(0.2, 1, 0)]);
let obj1 = new Object3D()
let obj2 = new Object3D()

// 设定 Outline 目标, 分2组,2种颜色
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'

export 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 = 10
            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()
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'

export 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 = 10
            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()