Skip to content

HDR Screen Bloom - BloomPost

A screen post-processing effect, also known as highlight overflow, that creates an optical effect; parts of the screen with brightness higher than a threshold value will diffuse into surrounding pixels and gradually decrease with distance, creating a glowing and hazy effect.

ts
//Initialize the engine
let engine = await Engine3D.init();

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

// Add a BloomPost
let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(BloomPost);

//Start rendering
let view = new View3D();
view.scene = this.scene;
view.camera = this.camera;
engine.startRenderView(view);

Configuration parameters for engine.setting.render.postProcessing.bloom.

ParameterTypeDescription
enablebooleanenable
downSampleStepnumberNumber of downsampling passes
downSampleBlurSizenumberDownsampling blur range
downSampleBlurSigmanumberDownsampling blur computation exponent
upSampleBlurSizenumberNumber of upsampling passes
upSampleBlurSigmanumberUpsampling blur range
luminanceThresholenumberThreshold for the Bloom highlight region
bloomIntensitybooleanFinal bloom brightness boost factor

Generally, we can control the object's bloom effect by adding an emissive texture and color to its material:

ts
let mat = new LitMaterial();
mat.emissiveMap = engine.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, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color, BloomPost } from '@orillusion/core';
import * as dat from 'dat.gui';

class Sample_Bloom {
    lightObj: Object3D;
    scene: Scene3D;
    engine: Engine3D;

    async run() {
        this.engine = await Engine3D.init({
            setting: {
                shadow: {
                    shadowSize: 2048,
                    shadowBound: 500
                }
            }
        });

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

        let mainCamera = CameraUtil.createCamera3DObject(this.scene, 'camera');
        mainCamera.perspective(60, this.engine.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;
        this.engine.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 = this.engine.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 = this.engine.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();

Released under the MIT License