后期雾效 - GlobalFog
雾效是一种非常常见的效果,模拟现实环境中人眼观察物体,会被一层具有特定颜色、浓度、体积的半透明的雾覆盖后朦胧的感觉。引擎内模拟实现的过程采用了相机位置、物体位置、物体的高度等参数,提供多种不同的衰减函数来达到不同雾效。
ts
//初始化引擎
await Engine3D.init();
Engine3D.setting.render.postProcessing.globalFog.fogType = 0; //Liner:0, Exp:1, Exp2:2
Engine3D.setting.render.postProcessing.globalFog.start = 400;
Engine3D.setting.render.postProcessing.globalFog.end = 0;
Engine3D.setting.render.postProcessing.globalFog.fogHeightScale = 1;
Engine3D.setting.render.postProcessing.globalFog.density = 0.02;
Engine3D.setting.render.postProcessing.globalFog.ins = 1;
Engine3D.setting.render.postProcessing.globalFog.fogColor = new Color(84,90,239,255);
Engine3D.setting.render.postProcessing.globalFog.skyFactor = 0.5;
Engine3D.setting.render.postProcessing.globalFog.skyRoughness = 0.4;
Engine3D.setting.render.postProcessing.globalFog.overrideSkyFactor = 0.8;
// 添加 GlobalFog
let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(GlobalFog);
//开始渲染
let view = new View3D();
view.scene = this.scene;
view.camera = this.camera;
Engine3D.startRenderView(view);
Engine3D.setting.render.postProcessing.globalFog 配置参数。
参数 | 类型 | 描述 |
---|---|---|
enable | boolean | 开启/关闭。 |
fogColor | Color | 雾的颜色 |
fogType | number | 雾的类型, 线性: 0, 指数: 1, 指数平方: 2 |
start | number | 雾的浓度衰减的起始距离,从 start 到 end 根据类型插值减小到0 |
end | number | 雾的浓度衰减的结束距离,从 start 到 end 根据类型插值减小0 |
density | number | 雾的浓度衰减系数,在指数/指数平方雾类型下,系数会额外加成 |
fogHeightScale | number | 雾的高度影响参数 |
ins | number | 高度影响系数 |
skyFactor | number | 雾的颜色和天空颜色混合系数 |
skyRoughness | number | 天空采样 mipmap 层级 |
overrideSkyFactor | number | 雾覆盖天空系数 |
ts
import { AtmosphericComponent, BoxGeometry, CameraUtil, CylinderGeometry, DirectLight, Engine3D, GlobalFog, HoverCameraController, KelvinUtil, LitMaterial, MeshRenderer, Object3D, PostProcessingComponent, Scene3D, View3D, Color } from '@orillusion/core';
import * as dat from 'dat.gui';
class Sample_Fog {
constructor() {}
lightObj: Object3D;
scene: Scene3D;
async run() {
Engine3D.setting.shadow.shadowSize = 2048;
Engine3D.setting.shadow.shadowBound = 1000;
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, Engine3D.aspect, 1, 5000.0);
let ctrl = mainCamera.object3D.addComponent(HoverCameraController);
ctrl.setCamera(0, -10, 400);
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 fog = postProcessing.addPost(GlobalFog);
let gui = new dat.GUI();
let f = gui.addFolder('GlobalFog');
f.add(fog, 'fogType', {
Liner: 0,
Exp: 1,
Exp2: 2
});
f.add(fog, 'start', -0.0, 1000.0, 0.0001);
f.add(fog, 'end', -0.0, 1000.0, 0.0001);
f.add(fog, 'fogHeightScale', 0.0001, 1.0, 0.0001);
f.add(fog, 'density', 0.0, 1.0, 0.0001);
f.add(fog, 'ins', 0.0, 5.0, 0.0001);
f.add(fog, 'skyFactor', 0.0, 1.0, 0.0001);
f.add(fog, 'skyRoughness', 0.0, 1.0, 0.0001);
f.add(fog, 'overrideSkyFactor', 0.0, 1.0, 0.0001);
f.addColor({ color: Object.values(fog.fogColor).map((v) => v * 255) }, 'color').onChange((v) => {
fog.fogColor = new Color().copyFromArray(v);
});
f.open();
}
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;
this.scene.addChild(this.lightObj);
}
{
let mat = new LitMaterial();
mat.roughness = 0.5;
mat.metallic = 0.5;
let floor = new Object3D();
let mr = floor.addComponent(MeshRenderer);
mr.geometry = new CylinderGeometry(10000, 10000, 1, 20, 20, false);
mr.materials = [mat, mat, mat];
this.scene.addChild(floor);
}
this.createPlane(this.scene);
}
private createPlane(scene: Scene3D) {
let mat = new LitMaterial();
mat.roughness = 1.0;
mat.metallic = 0.0;
const length = 10;
let cubeGeometry = new BoxGeometry(1, 1, 1);
for (let i = 0; i < length; i++) {
for (let j = 0; j < length; j++) {
let building: Object3D = new Object3D();
let mr = building.addComponent(MeshRenderer);
mr.material = mat;
mr.geometry = cubeGeometry;
building.localScale = building.localScale;
building.x = (i - 5) * (Math.random() * 0.5 + 0.5) * 100;
building.z = (j - 5) * (Math.random() * 0.5 + 0.5) * 100;
building.scaleX = 10 * (Math.random() * 0.5 + 0.5) * 2;
building.scaleZ = 10 * (Math.random() * 0.5 + 0.5) * 2;
building.scaleY = 200 * (Math.random() * 0.5 + 0.5);
scene.addChild(building);
}
}
}
}
new Sample_Fog().run();