Skip to content

轮廓描边 - Outline

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

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

// 创建渲染器
let renderJob = new ForwardRenderJob(scene);
renderJob.addPost(new OutlinePost());
Engine3D.startRender(renderJob);

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


Orillusion powered by WebGPU on Chrome/Edge 113+
Please upgrade to latest Chrome/Edge

<
ts
import {
	Camera3D,
	defaultTexture,
	DirectLight,
	Engine3D,
	ForwardRenderJob,
	GUIHelp,
	LitMaterial,
	HoverCameraController,
	KelvinUtil,
	MeshRenderer,
	Object3D,
	PlaneGeometry,
	Scene3D,
	SphereGeometry,
	Time,
	CameraUtil,
	webGPUContext,
	BoxGeometry,
	GTAOPost,
	Vector3,
	TAAPost,
	SSRPost,
	OutlinePost,
	outlinePostManager,
	Color,
} from '@orillusion/core';

export class Sample_Outline {
	lightObj: Object3D;
	scene: Scene3D;

	constructor() { }

	async run() {
		Engine3D.setting.gi.enable = true;
		Engine3D.setting.gi.indirectIntensity = 5;
		Engine3D.setting.shadow.debug = false;
		Engine3D.setting.shadow.enable = false;
		Engine3D.setting.shadow.shadowBias = 0.002;
		Engine3D.setting.render.postProcessing.taa.debug = false;
		Engine3D.setting.render.postProcessing.gtao.debug = false;
		await Engine3D.init();

		GUIHelp.init();

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

		await this.initScene(this.scene);

		let renderJob = new ForwardRenderJob(this.scene);
		renderJob.addPost(new TAAPost());
		renderJob.addPost(new GTAOPost());
		renderJob.addPost(new OutlinePost());
		Engine3D.startRender(renderJob);

		GUIHelp.addButton('Outline Button (click me)', () => {
			this.selectBall();
		});

		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();
		mat.baseMap = defaultTexture.whiteTexture;
		mat.normalMap = defaultTexture.normalTexture;
		mat.aoMap = defaultTexture.whiteTexture;
		mat.emissiveMap = defaultTexture.blackTexture;
		mat.roughness = 0.5;
		mat.roughness_max = 0.1;
		mat.metallic = 0.5;

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