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.
//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.
| Parameter | Type | Description |
|---|---|---|
| jitterSeedCount | number | The 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) |
| blendFactor | number | The coefficient for merging the history frame and the current frame. The smaller the parameter, the smaller the proportion of the current frame. |
| sharpFactor | number | Image 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. |
| sharpPreBlurFactor | number | Image sharpening sampling coefficient scaling factor: the scaling of the sampling offset during sharpening. |
| temporalJitterScale | number | The 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. |
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();
