Skip to content

HDR 屏幕泛光 - BloomPost

一种屏幕后期效果,也叫高光溢出,是一种光学效果;屏幕颜色内亮度高于阈值的部分会表现出扩散到周围像素中,并且随距离的增加而递减,形成一种发光朦胧的效果。

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

Engine3D.setting.render.postProcessing.bloom.downSampleStep = 5;
Engine3D.setting.render.postProcessing.bloom.downSampleBlurSize = 5;
Engine3D.setting.render.postProcessing.bloom.downSampleBlurSigma = 1.0;
Engine3D.setting.render.postProcessing.bloom.upSampleBlurSize = 5;
Engine3D.setting.render.postProcessing.bloom.upSampleBlurSigma = 1.0;
Engine3D.setting.render.postProcessing.bloom.luminanceThreshole = 1.0;
Engine3D.setting.render.postProcessing.bloom.bloomIntensity = 1.0;

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

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

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

参数类型描述
enablebooleanenable
downSampleStepnumber下采样次数
downSampleBlurSizenumber下采样模糊范围
downSampleBlurSigmanumber下采样模糊计算指数
upSampleBlurSizenumber上采样次数
upSampleBlurSigmanumber上采样模糊范围
luminanceThresholenumberBloom高亮区域阈值
bloomIntensitybooleanBloom最终亮度加成系数

一般我们可以通过对物体材质添加发光贴图和颜色来控制物体的发光效果:

ts
let mat = new LitMaterial();
mat.emissiveMap = Engine3D.res.whiteTexture;
mat.emissiveColor = new Color(1.0, 0.0, 0.0);
mat.emissiveIntensity = 3;

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

class Sample_Bloom {
    lightObj: Object3D;
    scene: Scene3D;

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

        await Engine3D.init();

        this.scene = new Scene3D();
        let sky = this.scene.addComponent(AtmosphericComponent);
        sky.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();
        sky.relativeTransform = this.lightObj.transform;

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

        let postProcessing = this.scene.addComponent(PostProcessingComponent);
        let post = postProcessing.addPost(BloomPost);
        this.renderBloom(post, true);
    }

    public renderBloom(bloom: BloomPost, open: boolean = true, name?: string) {
        name ||= 'Bloom';
        let GUIHelp = new dat.GUI();
        GUIHelp.addFolder(name);
        GUIHelp.add(bloom, 'downSampleBlurSize', 3, 15, 1);
        GUIHelp.add(bloom, 'downSampleBlurSigma', 0.01, 1, 0.001);
        GUIHelp.add(bloom, 'upSampleBlurSize', 3, 15, 1);
        GUIHelp.add(bloom, 'upSampleBlurSigma', 0.01, 1, 0.001);
        GUIHelp.add(bloom, 'luminanceThreshole', 0.001, 10.0, 0.001);
        GUIHelp.add(bloom, 'bloomIntensity', 0.001, 10.0, 0.001);
    }

    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 = 3;
            this.scene.addChild(this.lightObj);
        }

        {
            let mat = new LitMaterial();
            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 litMat = new LitMaterial();
                    litMat.emissiveMap = Engine3D.res.whiteTexture;
                    litMat.emissiveColor = new Color(0.0, 0.0, 1.0);
                    litMat.emissiveIntensity = 0.6;
                    let sp = new Object3D();
                    let mr = sp.addComponent(MeshRenderer);
                    mr.geometry = new SphereGeometry(15, 30, 30);
                    mr.material = litMat;
                    sp.x = 68;
                    sp.y = 15;
                    sp.z = -15;
                    this.scene.addChild(sp);
                }

                {
                    let litMat = new LitMaterial();
                    litMat.emissiveMap = Engine3D.res.whiteTexture;
                    litMat.emissiveColor = new Color(1.0, 1.0, 0.0);
                    litMat.emissiveIntensity = 0.8;
                    let sp = new Object3D();
                    let mr = sp.addComponent(MeshRenderer);
                    mr.geometry = new SphereGeometry(15, 30, 30);
                    mr.material = litMat;
                    sp.x = 1;
                    sp.y = 15;
                    sp.z = -8;
                    this.scene.addChild(sp);
                }
            }
        }
    }
}

new Sample_Bloom().run();