Skip to content

Commit

Permalink
perf(globalFog): Optimize the fog effect to add fog color to the ambi… (
Browse files Browse the repository at this point in the history
#223)

Update the fog effect to add atmospheric diffuse reflection to the final effect
chore(fog): revert heightFactor to distance.
revert heightFactor to distance.
The color of fog can affect the sky
  • Loading branch information
hellmor committed Jun 21, 2023
1 parent f128ae5 commit fab97a5
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 37 deletions.
28 changes: 16 additions & 12 deletions samples/post/Sample_Fog.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { AtmosphericComponent, BoxGeometry, CameraUtil, CylinderGeometry, DirectLight, Engine3D, GlobalFog, HoverCameraController, KelvinUtil, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, PostProcessingComponent, Scene3D, View3D, webGPUContext } from '@orillusion/core';
import { GUIHelp } from '@orillusion/debug/GUIHelp';
import { GUIUtil } from '@samples/utils/GUIUtil';

class Sample_Fog {
constructor() { }
Expand All @@ -7,27 +9,29 @@ class Sample_Fog {

async run() {
Engine3D.setting.shadow.shadowSize = 2048
Engine3D.setting.shadow.shadowBound = 500;
Engine3D.setting.shadow.shadowBias = 0.0002;
Engine3D.setting.shadow.shadowBound = 1000;
Engine3D.setting.shadow.shadowBias = 0.0005;

await Engine3D.init();

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

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, -20, 150);
ctrl.setCamera(0, -10, 400);
await this.initScene();

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

GUIHelp.init();
GUIUtil.renderAtomosphericSky(sky, false);
let postProcessing = this.scene.addComponent(PostProcessingComponent);
let fog = postProcessing.addPost(GlobalFog);
GUIUtil.renderGlobalFog(fog, true);
}

async initScene() {
Expand Down Expand Up @@ -55,7 +59,7 @@ class Sample_Fog {

let floor = new Object3D();
let mr = floor.addComponent(MeshRenderer);
mr.geometry = new CylinderGeometry(2000, 2000, 1, 20, 20, false);
mr.geometry = new CylinderGeometry(10000, 10000, 1, 20, 20, false);
mr.materials = [mat, mat, mat];
this.scene.addChild(floor);
}
Expand All @@ -82,11 +86,11 @@ class Sample_Fog {
mr.material = mat;
mr.geometry = cubeGeometry;
building.localScale = building.localScale;
building.x = (i - 5) * (Math.random() * 0.5 + 0.5) * 50;
building.z = (j - 5) * (Math.random() * 0.5 + 0.5) * 50;
building.scaleX = 10 * (Math.random() * 0.5 + 0.5);
building.scaleZ = 10 * (Math.random() * 0.5 + 0.5);
building.scaleY = 50 * (Math.random() * 0.5 + 0.5);
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);
}
}
Expand Down
23 changes: 22 additions & 1 deletion samples/utils/GUIUtil.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { AtmosphericComponent, BillboardType, Color, DirectLight, Engine3D, GPUCullMode, GlobalIlluminationComponent, PointLight, SpotLight, Transform, UIImage, UIPanel, UIShadow, View3D } from "@orillusion/core";
import { AtmosphericComponent, BillboardType, Color, DirectLight, Engine3D, GPUCullMode, GlobalFog, GlobalIlluminationComponent, PointLight, SpotLight, Transform, UIImage, UIPanel, UIShadow, View3D } from "@orillusion/core";
import { UVMoveComponent } from "@samples/material/script/UVMoveComponent";

export class GUIUtil {
Expand All @@ -20,6 +20,27 @@ export class GUIUtil {
GUIHelp.endFolder();
}

public static renderGlobalFog(fog: GlobalFog, open: boolean = true, name?: string) {
name ||= 'GlobalFog';
GUIHelp.addFolder(name);
GUIHelp.add(fog, 'fogType', {
Liner: 0,
Exp: 1,
Exp2: 2,
});
GUIHelp.add(fog, 'start', -0.0, 1000.0, 0.0001);
GUIHelp.add(fog, 'end', -0.0, 1000.0, 0.0001);
GUIHelp.add(fog, 'height', -1000.0, 1000.0, 0.0001);
GUIHelp.add(fog, 'density', 0.0, 1.0, 0.0001);
GUIHelp.add(fog, 'ins', 0.0, 5.0, 0.0001);
GUIHelp.add(fog, 'skyFactor', 0.0, 1.0, 0.0001);
GUIHelp.add(fog, 'skyRoughness', 0.0, 1.0, 0.0001);
GUIHelp.add(fog, 'overrideSkyFactor', 0.0, 1.0, 0.0001);
GUIHelp.addColor(fog, 'fogColor');
open && GUIHelp.open();
GUIHelp.endFolder();
}

//render transform
public static renderTransform(transform: Transform, open: boolean = true, name?: string) {
name ||= 'Transform';
Expand Down
11 changes: 7 additions & 4 deletions src/Engine3D.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,14 @@ export class Engine3D {
enable: false,
fogType: 0.0,
height: 100,
start: 400,
end: 0,
start: 800,
end: 200,
density: 0.02,
ins: 1,
fogColor: new Color(84 / 255, 90 / 255, 239 / 255, 1),
skyFactor: 0.5,
skyRoughness: 0.4,
overrideSkyFactor: 0.8,
fogColor: new Color(112 / 255, 61 / 255, 139 / 255, 1),
},
ssao: {
enable: false,
Expand Down Expand Up @@ -262,7 +265,7 @@ export class Engine3D {
type: 'HDRSKY',
sky: null,
skyExposure: 1.0,
defaultFar: 1000000,
defaultFar: 65536,//can't be to big
defaultNear: 1,
},
light: {
Expand Down
98 changes: 78 additions & 20 deletions src/assets/shader/post/GlobalFog_shader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ struct UniformData {
end: f32,
density : f32 ,
ins : f32 ,
skyFactor: f32,
skyRoughness: f32,
overrideSkyFactor: f32,
isSkyHDR: f32
};
@group(1) @binding(0)
Expand All @@ -37,39 +41,93 @@ var normalMapSampler: sampler;
@group(1) @binding(5)
var normalMap: texture_2d<f32>;
@group(1) @binding(6)
var prefilterMapSampler: sampler;
@group(1) @binding(7)
var prefilterMap: texture_cube<f32>;
@group(2) @binding(0)
var<uniform> global : UniformData;
var<private> varying_uv: vec2<f32>;
fn LinearToGammaSpace(linRGB: vec3<f32>) -> vec3<f32> {
var linRGB1 = max(linRGB, vec3<f32>(0.0));
linRGB1 = pow(linRGB1, vec3<f32>(0.4166666567325592));
return max(((1.0549999475479126 * linRGB1) - vec3<f32>(0.054999999701976776)), vec3<f32>(0.0));
}
fn getSkyColor(worldPosition:vec3<f32>, skyRoughness:f32, isHDRTexture:bool) -> vec3<f32>{
let cameraPosition = vec3<f32>(globalUniform.cameraWorldMatrix[3].xyz);
let rayDirection = normalize(vec3<f32>(worldPosition.xyz - cameraPosition));
let calcRoughness = clamp(skyRoughness, 0.0, 1.0);
let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ;
var prefilterColor = textureSampleLevel(prefilterMap, prefilterMapSampler, rayDirection, calcRoughness * MAX_REFLECTION_LOD);
if(isHDRTexture){
prefilterColor = vec4<f32>(LinearToGammaSpace(vec3<f32>(prefilterColor.xyz)), prefilterColor.w);
}
return prefilterColor.xyz * globalUniform.skyExposure;
}
var<private> texPosition: vec4<f32>;
var<private> texNormal: vec4<f32>;
var<private> texColor: vec4<f32>;
@fragment
fn main(@location(0) fragUV: vec2<f32>,
@builtin(position) coord: vec4<f32>) -> FragmentOutput {
var texCoord = fragUV ;
texCoord.y = 1.0 - texCoord.y ;
var texCoord = vec2<f32>(fragUV.x, 1.0 - fragUV.y);
texPosition = textureSample(positionMap, positionMapSampler, texCoord) ;
texNormal = textureSample(normalMap, normalMapSampler, texCoord) ;
texColor = textureSample(colorMap, colorMapSampler, texCoord) ;
var opColor = vec3<f32>(0.0);
if(texNormal.w <= 0.5){
//for sky
if(global.overrideSkyFactor > 0.01){
opColor = blendSkyColor();
}else{
opColor = texColor.xyz;
}
}else{
//for ground
var fogFactor = calcFogFactor();
if(global.skyFactor > 0.01 || global.overrideSkyFactor > 0.01){
opColor = blendGroundColor(fogFactor);
}else{
opColor = mix(texColor.rgb, global.fogColor.xyz, fogFactor);
}
}
return FragmentOutput(vec4<f32>(opColor.xyz, texColor.a));
}
fn calcFogFactor() -> f32{
var cameraPos = globalUniform.cameraWorldMatrix[3].xyz ;
var texPosition = textureSample(positionMap, positionMapSampler ,texCoord) ;
var texNormal = textureSample(normalMap, normalMapSampler,texCoord) ;
var texColor = textureSample(colorMap, colorMapSampler ,texCoord) ;
let dis = texNormal.w * distance(cameraPos,texPosition.xyz);
let height = texPosition.y ;
// var heightFactor = computeFog((dis + height) / 2.0 );
//var heightFactor = computeFog((dis + height) / 2.0 );
var heightFactor = computeFog((dis));
// visible test
if(texNormal.w<=0.5){
return FragmentOutput(vec4<f32>(texColor.rgb,texColor.a));
}else{
// var emissive = mix( global.fogColor.rgb , texColor.rgb , global.ins * heightFactor );
var emissive = mix( texColor.rgb , global.fogColor.rgb , clamp(global.ins * heightFactor,0.0,1.0) );
return FragmentOutput(vec4<f32>(emissive.rgb,texColor.a));
}
}
return clamp(global.ins * heightFactor,0.0,1.0);
}
fn computeFog(z:f32) -> f32 {
fn blendGroundColor(fogFactor:f32) -> vec3<f32>
{
var skyColorBlur = getSkyColor(texPosition.xyz, global.skyRoughness, global.isSkyHDR > 0.5);
let skyFactor = clamp(global.skyFactor - global.overrideSkyFactor * 0.5, 0.0, 1.0);
var fogColor = mix(global.fogColor.xyz, skyColorBlur, skyFactor);
return mix(texColor.rgb, fogColor.rgb, fogFactor);
}
fn blendSkyColor() -> vec3<f32>
{
let overrideSkyFactor = sqrt(global.overrideSkyFactor);
var skyColorBlur = getSkyColor(texPosition.xyz, overrideSkyFactor * 0.3, global.isSkyHDR > 0.5);
return mix(global.fogColor.xyz, skyColorBlur, 1.0 - overrideSkyFactor);
}
fn computeFog(z:f32) -> f32 {
var fog = 0.0;
if( global.fogType == 0.0 ){
fog = (global.end - z) / (global.end - global.start);
Expand All @@ -80,5 +138,5 @@ fn main(@location(0) fragUV: vec2<f32>,
fog = exp2(-fog * fog);
}
return max(fog,0.0);
}
}
`;
34 changes: 34 additions & 0 deletions src/gfx/renderJob/post/GlobalFog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { webGPUContext } from '../../graphics/webGpu/Context3D';
import { PostBase } from './PostBase';
import { View3D } from '../../../core/View3D';
import { GBufferFrame } from '../frame/GBufferFrame';
import { SkyRenderer } from '../../../components/renderer/SkyRenderer';
import { EntityCollect } from '../collect/EntityCollect';
import { Texture } from '../../..';
/**
* screen space fog
* @group Post Effects
Expand Down Expand Up @@ -40,6 +43,10 @@ export class GlobalFog extends PostBase {
end: new UniformNode(globalFog.end),
density: new UniformNode(globalFog.density),
ins: new UniformNode(globalFog.ins),
skyFactor: new UniformNode(globalFog.skyFactor),
skyRoughness: new UniformNode(globalFog.skyRoughness),
overrideSkyFactor: new UniformNode(globalFog.overrideSkyFactor),
isSkyHDR: new UniformNode(0),
};

this.rtTexture = this.createRTTexture(`GlobalFog`, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float);
Expand Down Expand Up @@ -104,6 +111,26 @@ export class GlobalFog extends PostBase {
public get density() {
return this.viewQuad.uniforms['density'].value;
}
public set skyRoughness(v: number) {
this.viewQuad.uniforms['skyRoughness'].value = v;
}
public get skyRoughness() {
return this.viewQuad.uniforms['skyRoughness'].value;
}
public set skyFactor(v: number) {
this.viewQuad.uniforms['skyFactor'].value = v;
}
public get skyFactor() {
return this.viewQuad.uniforms['skyFactor'].value;
}

public set overrideSkyFactor(v: number) {
this.viewQuad.uniforms['overrideSkyFactor'].value = v;
}
public get overrideSkyFactor() {
return this.viewQuad.uniforms['overrideSkyFactor'].value;
}

/**
* @internal
*/
Expand All @@ -125,13 +152,20 @@ export class GlobalFog extends PostBase {
const renderShader = this.viewQuad.material.renderShader;
renderShader.setTexture('positionMap', positionMap);
renderShader.setTexture('normalMap', normalMap);
let skyTexture: Texture = Engine3D.res.defaultSky;
if (EntityCollect.instance.sky instanceof SkyRenderer) {
skyTexture = EntityCollect.instance.sky.map;
}
renderShader.setTexture(`prefilterMap`, skyTexture);
}

/**
* @internal
*/
render(view: View3D, command: GPUCommandEncoder) {
const renderShader = this.viewQuad.material.renderShader;
renderShader.setTexture('colorMap', this.getOutTexture());
renderShader.setUniformFloat('isSkyHDR', renderShader.getTexture('prefilterMap').isHDRTexture ? 1 : 0);
this.viewQuad.renderTarget(view, this.viewQuad, command);
}

Expand Down
12 changes: 12 additions & 0 deletions src/setting/post/GlobalFogSetting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ export type GlobalFogSetting = {
* The effect of setting height on fog (working together with height)
*/
ins: number;
/**
* mix fog color with sky color
*/
skyFactor: number;
/**
* use mipmap level
*/
skyRoughness: number,
/**
* factor effect the sky
*/
overrideSkyFactor: number,
/**
* fog color
*/
Expand Down

0 comments on commit fab97a5

Please sign in to comment.