Skip to content

环境光遮蔽 - GTAO

AO 是用来描绘物体和物体相交或靠近的时候遮挡周围漫反射光线的效果,可以解决或改善漏光、飘和阴影不实等问题,解决或改善场景中缝隙、褶皱与墙角、角线以及细小物体等的表现不清晰问题,综合改善细节尤其是暗部阴影,增强空间的层次感、真实感,同时加强和改善画面明暗对比,增强画面的艺术性。引擎内部通过采样指定屏幕范围内,指定距离范围内的像素点,求积分用于赋值当前像素 AO 系数。

ts
//初始化引擎
await Engine3D.init();

Engine3D.setting.render.postProcessing.gtao.maxDistance = 5;
Engine3D.setting.render.postProcessing.gtao.maxPixel = 50;
Engine3D.setting.render.postProcessing.gtao.darkFactor = 1;
Engine3D.setting.render.postProcessing.gtao.rayMarchSegment = 6;
Engine3D.setting.render.postProcessing.gtao.multiBounce = true;
Engine3D.setting.render.postProcessing.gtao.blendColor = true;

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

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

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

参数类型描述
maxDistancenumber设定ao采样时搜索3D空间周边的最大距离。
maxPixelnumber设定ao采样时搜索周边像素时的最大距离。
darkFactornumber设定ao数值参与输出到屏幕时的系数,1:全部输出,0:不输出。
rayMarchSegmentnumber设定ao采样时的步进的步数,值越大将会获得质量更好的ao效果,同时消耗更多的性能。
multiBounceboolean是否模拟颜色反弹。
blendColorbooleantrue:将与GBuffer的mainColor混合;false:将只输出ao的颜色。

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

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

class Sample_GTAO {
    lightObj: Object3D;
    scene: Scene3D;

    async run() {
        Engine3D.setting.shadow.shadowSize = 2048;
        Engine3D.setting.shadow.shadowBound = 500;
        Engine3D.setting.shadow.shadowBias = 0.05;

        await Engine3D.init();

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

        let mainCamera = CameraUtil.createCamera3DObject(this.scene, 'camera');
        mainCamera.perspective(60, webGPUContext.aspect, 1, 5000.0);
        let ctrl = mainCamera.object3D.addComponent(HoverCameraController);
        ctrl.setCamera(0, -15, 500);
        await this.initScene();

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

        let postProcessing = this.scene.addComponent(PostProcessingComponent);
        let post = postProcessing.addPost(GTAOPost);
        post.maxDistance = 6;
		post.maxPixel = 15;
        this.gui();
    }

    async initScene() {
        {
            this.lightObj = new Object3D();
            this.lightObj.rotationX = 45;
            this.lightObj.rotationY = 110;
            this.lightObj.rotationZ = 0;
            let lc = this.lightObj.addComponent(DirectLight);
            lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
            lc.castShadow = true;
            lc.intensity = 5;
            lc.indirect = 0.3;
            this.scene.addChild(this.lightObj);
        }

        {
            let mat = new LitMaterial();
            mat.roughness = 1.0;
            mat.metallic = 0.0;

            let floor = new Object3D();
            let mr = floor.addComponent(MeshRenderer);
            mr.geometry = new PlaneGeometry(400, 400);
            mr.material = mat;
            this.scene.addChild(floor);

            {
                let wall = new Object3D();
                let mr = wall.addComponent(MeshRenderer);
                mr.geometry = new BoxGeometry(5, 260, 320);
                mr.material = mat;
                wall.x = -320 * 0.5;
                this.scene.addChild(wall);
            }

            {
                let wall = new Object3D();
                let mr = wall.addComponent(MeshRenderer);
                mr.geometry = new BoxGeometry(5, 260, 320);
                mr.material = mat;
                wall.x = 320 * 0.5;
                this.scene.addChild(wall);
            }

            {
                let wall = new Object3D();
                let mr = wall.addComponent(MeshRenderer);
                mr.geometry = new BoxGeometry(320, 260, 5);
                mr.material = mat;
                wall.z = -320 * 0.5;
                this.scene.addChild(wall);
            }

            {
                {
                    let sp = new Object3D();
                    let mr = sp.addComponent(MeshRenderer);
                    mr.geometry = new SphereGeometry(50, 30, 30);
                    mr.material = mat;
                    this.scene.addChild(sp);
                }
            }
        }
    }

    private gui() {
        let postProcessing = this.scene.getComponent(PostProcessingComponent);
        let post = postProcessing.getPost(GTAOPost);

        let GUIHelp = new dat.GUI();
        let f = GUIHelp.addFolder('GTAO');
        f.add(post, 'maxDistance', 0.0, 50, 1);
        f.add(post, 'maxPixel', 0.0, 50, 1);
        f.add(post, 'rayMarchSegment', 4, 10, 0.001);
        f.add(post, 'darkFactor', 0.0, 5, 0.001);
        f.add(post, 'blendColor');
        f.add(post, 'multiBounce');
        f.open();
    }
}

new Sample_GTAO().run();