Skip to content

Anti-Aliasing - TAAPost

A 3D rendering anti-aliasing implementation. During the rasterization process of 3D rendering, the displayed objects are stored in the form of a two-dimensional array of dots, and the edges of objects in the resulting raw image inevitably have aliasing. The method adopted by TAA is to slightly apply some offset values to the camera according to a certain strategy, so that objects produce slightly different results during rasterization due to the different camera offset values. This is especially noticeable at the edges. The color finally output to the screen uses the interpolation of the history frame and the current frame as the result, and this result is used for the next interpolation.

ts
//Initialize the engine (global engine configuration is merged into init)
let engine = await Engine3D.init({
    setting: {
        render: {
            postProcessing: {
                taa: {
                    jitterSeedCount: 8,
                    blendFactor: 0.1,
                    sharpFactor: 0.6,
                    sharpPreBlurFactor: 0.5,
                    temporalJitterScale: 0.6
                }
            }
        }
    }
});

// Add the post-processing component
let postProcessing = this.scene.addComponent(PostProcessingComponent);

// Add TAAPost
let taaPost = postProcessing.addPost(TAAPost);

// Set via the taaPost object (the global engine configuration and the settings based on the taaPost object here are equivalent)
taaPost.jitterSeedCount = 8;
taaPost.blendFactor = 0.1;
taaPost.sharpFactor = 0.6;
taaPost.sharpPreBlurFactor = 0.5;
taaPost.temporalJitterScale = 0.6;

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

engine.setting.render.postProcessing.taa configuration parameters.

ParameterTypeDescription
jitterSeedCountnumberThe number of random seeds used for jittering the camera, default 8. (Reducing the number can solve some problems where the jitter is too obvious, but the aliasing will become more obvious)
blendFactornumberThe coefficient for merging the history frame and the current frame. The smaller the parameter, the smaller the proportion of the current frame.
sharpFactornumberImage sharpening coefficient [0.1,1.9]: The smaller the coefficient, the weaker the sharpening effect and the better the anti-aliasing effect; conversely, the stronger the sharpening, the weaker the anti-aliasing effect.
sharpPreBlurFactornumberImage sharpening sampling coefficient scaling factor: the scaling of the sampling offset during sharpening.
temporalJitterScalenumberThe scaling factor of the random offset value of the jittered camera [0,1]: The smaller the coefficient, the weaker the anti-aliasing effect, and the weaker the pixel jitter.

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

class Sample_TAA {
    lightObj: Object3D;
    scene: Scene3D;

    async run() {
        let engine = await Engine3D.init({
            canvasConfig: {
                devicePixelRatio: 1
            },
            setting: {
                shadow: {
                    enable: true,
                    shadowSize: 2048,
                    shadowBound: 40,
                    shadowBias: 0.005
                }
            }
        });

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

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

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

        let postProcessing = this.scene.addComponent(PostProcessingComponent);
        let taa = postProcessing.addPost(TAAPost);

        const gui = new dat.GUI();
        let f = gui.addFolder('TAA')
        f.add(taa, "jitterSeedCount", 2, 16, 1);
        f.add(taa, "blendFactor", 0.0, 1.0, 0.01);
        f.add(taa, "sharpFactor", 0.1, 0.9, 0.01);
        f.add(taa, "sharpPreBlurFactor", 0.1, 0.9, 0.01);
        f.add(taa, "temporalJitterScale", 0.0, 1.0, 0.01);
        f.open()
    }

    async initScene() {
        {
            this.lightObj = new Object3D();
            this.lightObj.rotationX = 15;
            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 = 4;
            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(2000, 2000);
            mr.material = mat;
            this.scene.addChild(floor);
        }

        this.createPlane(this.scene);
    }

    private createPlane(scene: Scene3D) {
        let mat = new LitMaterial();
        mat.roughness = 0.5;
        mat.metallic = 0.2;
        {
            let sphereGeometry = new SphereGeometry(1, 50, 50);
            let obj: Object3D = new Object3D();
            let mr = obj.addComponent(MeshRenderer);
            mr.material = mat;
            mr.geometry = sphereGeometry;
            obj.x = 10;
            obj.y = 2;
            scene.addChild(obj);
        }

        const length = 5;
        for (let i = 0; i < length; i++) {
            let cubeGeometry = new BoxGeometry(1, 10, 1);
            for (let j = 0; j < length; j++) {
                let obj: Object3D = new Object3D();
                let mr = obj.addComponent(MeshRenderer);
                mr.material = mat;
                mr.geometry = cubeGeometry;
                obj.localScale = obj.localScale;
                obj.x = (i - 2.5) * 4;
                obj.z = (j - 2.5) * 4;
                obj.y = 5;
                obj.rotationX = (Math.random() - 0.5) * 90;
                obj.rotationY = (Math.random() - 0.5) * 90;
                obj.rotationZ = (Math.random() - 0.5) * 90;
                scene.addChild(obj);
            }
        }
    }
}

new Sample_TAA().run();

Released under the MIT License