Skip to content

Commit

Permalink
feat(GI): Add GI feature into engine. (#215)
Browse files Browse the repository at this point in the history
Add GI feature into engine.
  • Loading branch information
hellmor committed Jun 10, 2023
1 parent 68ff2ca commit 775ebbc
Show file tree
Hide file tree
Showing 29 changed files with 2,185 additions and 100 deletions.
120 changes: 120 additions & 0 deletions samples/gi/Sample_GI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene";
import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, HDRBloomPost, PostProcessingComponent, TAAPost } from "@orillusion/core";
import { GUIUtil } from "@samples/utils/GUIUtil";
import { GUIHelp } from "@orillusion/debug/GUIHelp";

class Sample_GI {
scene: Scene3D;
async run() {

Engine3D.setting.material.materialChannelDebug = true;
Engine3D.setting.material.materialDebug = false;

Engine3D.setting.gi.enable = true;
Engine3D.setting.gi.debug = true;

Engine3D.setting.gi.probeYCount = 3;
Engine3D.setting.gi.probeXCount = 6;
Engine3D.setting.gi.probeZCount = 6;
Engine3D.setting.gi.probeSpace = 60;
Engine3D.setting.gi.offsetX = 0;
Engine3D.setting.gi.offsetY = 60;
Engine3D.setting.gi.offsetZ = 0;
Engine3D.setting.gi.indirectIntensity = 1;
Engine3D.setting.gi.probeSize = 64;
Engine3D.setting.gi.octRTSideSize = 64;
Engine3D.setting.gi.octRTMaxSize = 2048;
Engine3D.setting.gi.ddgiGamma = 1;
Engine3D.setting.gi.autoRenderProbe = true;

Engine3D.setting.shadow.shadowBound = 200;
Engine3D.setting.shadow.shadowBias = 0.001;
Engine3D.setting.shadow.debug = true;

Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.updateFrameRate = 1;

Engine3D.setting.render.postProcessing.bloom = {
enable: true,
debug: false,
blurX: 4,
blurY: 4,
luminosityThreshold: 0.9,
radius: 4,
strength: 1.2
};

await Engine3D.init({});
GUIHelp.init();
let param = createSceneParam();
param.camera.distance = 200;
let exampleScene = createExampleScene(param);
exampleScene.atmosphericSky.exposure = 0.5;
this.scene = exampleScene.scene;
Engine3D.startRenderViews([exampleScene.view]);
let job = Engine3D.getRenderJob(exampleScene.view);
await this.initScene();
this.addGIProbes();
GUIUtil.renderAtomosphericSky(exampleScene.atmosphericSky);
GUIUtil.renderDirLight(exampleScene.light);

let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(TAAPost);
// postProcessing.addPost(GTAOPost);
postProcessing.addPost(HDRBloomPost);

}

private addGIProbes() {
let probeObj = new Object3D();
let component = probeObj.addComponent(GlobalIlluminationComponent);
this.scene.addChild(probeObj);
setTimeout(() => {
GUIUtil.renderGIComponent(component);
}, 2000);
}

async initScene() {
{
let floorHeight = 20;
let floor = Object3DUtil.GetSingleCube(1000, floorHeight, 1000, 0.6, 0.6, 0.6);
floor.y = -floorHeight;
this.scene.addChild(floor);
}


{
let greenBall = Object3DUtil.GetSingleSphere(30, 0.1, 0.8, 0.2);
this.scene.addChild(greenBall);
greenBall.x = -70;
greenBall.y = 40;
}

{
let chair = await Engine3D.res.loadGltf('PBR/SheenChair/SheenChair.gltf') as Object3D;
chair.scaleX = chair.scaleY = chair.scaleZ = 100;
chair.rotationZ = chair.rotationX = 130;
chair.z = -120;
this.scene.addChild(chair);
}

{
let Duck = await Engine3D.res.loadGltf('PBR/Duck/Duck.gltf') as Object3D;
Duck.scaleX = Duck.scaleY = Duck.scaleZ = 0.3;
Duck.transform.y = 0;
Duck.transform.x = 0;
Duck.transform.z = 80;
this.scene.addChild(Duck);
}


{
let car = await Engine3D.res.loadGltf('gltfs/pbrCar/pbrCar.gltf');
car.scaleX = car.scaleY = car.scaleZ = 1.5;
this.scene.addChild(car);
car.x = 20;
}
}
}

new Sample_GI().run();
84 changes: 84 additions & 0 deletions samples/gi/Sample_GICornellBox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene";
import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Vector3, GTAOPost, PostProcessingComponent, HDRBloomPost } from "@orillusion/core";
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { GUIUtil } from "@samples/utils/GUIUtil";

class Sample_GICornellBox {
scene: Scene3D;
async run() {

Engine3D.setting.material.materialChannelDebug = true;
Engine3D.setting.material.materialDebug = false;

Engine3D.setting.gi.enable = true;
Engine3D.setting.gi.debug = true;
Engine3D.setting.gi.probeYCount = 6;
Engine3D.setting.gi.probeXCount = 6;
Engine3D.setting.gi.probeZCount = 6;
Engine3D.setting.gi.offsetX = 0;
Engine3D.setting.gi.offsetY = 10;
Engine3D.setting.gi.offsetZ = 0;
Engine3D.setting.gi.indirectIntensity = 1;
Engine3D.setting.gi.lerpHysteresis = 0.004;//default value is 0.01
Engine3D.setting.gi.maxDistance = 16;
Engine3D.setting.gi.probeSpace = 6;
Engine3D.setting.gi.normalBias = 0;
Engine3D.setting.gi.probeSize = 32;
Engine3D.setting.gi.octRTSideSize = 16;
Engine3D.setting.gi.octRTMaxSize = 2048;
Engine3D.setting.gi.ddgiGamma = 2.2;
Engine3D.setting.gi.depthSharpness = 1;
Engine3D.setting.gi.autoRenderProbe = true;

Engine3D.setting.shadow.shadowBound = 50;
Engine3D.setting.shadow.shadowBias = 0.001;
Engine3D.setting.shadow.debug = true;

Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.updateFrameRate = 1;

Engine3D.setting.render.debug = true;
Engine3D.setting.render.postProcessing.bloom = {
enable: true,
debug: false,
blurX: 4,
blurY: 4,
luminosityThreshold: 0.9,
radius: 4,
strength: 1.2
};

await Engine3D.init({});
let param = createSceneParam();
param.camera.distance = 40;

let exampleScene = createExampleScene(param);
this.scene = exampleScene.scene;
this.addGIProbes();
Engine3D.startRenderViews([exampleScene.view]);

let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(GTAOPost);
postProcessing.addPost(HDRBloomPost);

await this.initScene();
}

private addGIProbes() {
let probeObj = new Object3D();
GUIHelp.init();
let component = probeObj.addComponent(GlobalIlluminationComponent);
this.scene.addChild(probeObj);
setTimeout(() => {
GUIUtil.renderGIComponent(component);
}, 2000);
}

async initScene() {
let box = await Engine3D.res.loadGltf('gltfs/cornellBox/cornellBox.gltf') as Object3D;
box.localScale = new Vector3(10, 10, 10);
this.scene.addChild(box);
}
}

new Sample_GICornellBox().run();
6 changes: 3 additions & 3 deletions samples/utils/ExampleScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ export function createSceneParam(): ExampleSceneParam {
z: -40,
},
euler: {
x: 0,
y: 200,
z: 135,
x: 20,
y: 160,
z: 0,
},

kelvin: 5355,
Expand Down
96 changes: 95 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, GPUCullMode, PointLight, SpotLight, Transform, UIImage, UIPanel, UIShadow } from "@orillusion/core";
import { AtmosphericComponent, BillboardType, Color, DirectLight, Engine3D, GPUCullMode, GlobalIlluminationComponent, PointLight, SpotLight, Transform, UIImage, UIPanel, UIShadow, View3D } from "@orillusion/core";
import { UVMoveComponent } from "@samples/material/script/UVMoveComponent";

export class GUIUtil {
Expand Down Expand Up @@ -102,6 +102,100 @@ export class GUIUtil {
GUIHelp.endFolder();
}

public static renderGIComponent(component: GlobalIlluminationComponent): void {
let volume = component['_volume'];
let giSetting = volume.setting;
let view: View3D = Engine3D.views[0];
let renderJob = Engine3D.getRenderJob(view);

function onProbesChange(): void {
component['changeProbesPosition']();
}

function debugProbeRay(probeIndex: number, array: Float32Array): void {
component['debugProbeRay'](probeIndex, array);
}

GUIHelp.addFolder('GI');
GUIHelp.add(giSetting, `lerpHysteresis`, 0.001, 10, 0.0001).onChange(() => {
onProbesChange();
});
GUIHelp.add(giSetting, `depthSharpness`, 1.0, 100.0, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(giSetting, `normalBias`, -100.0, 100.0, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(giSetting, `irradianceChebyshevBias`, -100.0, 100.0, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(giSetting, `rayNumber`, 0, 512, 1).onChange(() => {
onProbesChange();
});
GUIHelp.add(giSetting, `irradianceDistanceBias`, 0.0, 200.0, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(giSetting, `indirectIntensity`, 0.0, 100.0, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(giSetting, `bounceIntensity`, 0.0, 1.0, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(giSetting, `probeRoughness`, 0.0, 1.0, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(giSetting, `ddgiGamma`, 0.0, 4.0, 0.001).onChange(() => {
onProbesChange();
});

GUIHelp.add(giSetting, 'autoRenderProbe');
GUIHelp.endFolder();

GUIHelp.addFolder('probe volume');
GUIHelp.add(volume.setting, 'probeSpace', 0.1, volume.setting.probeSpace * 5, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(volume.setting, 'offsetX', -100, 100, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(volume.setting, 'offsetY', -100, 100, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.add(volume.setting, 'offsetZ', -100, 100, 0.001).onChange(() => {
onProbesChange();
});
GUIHelp.addButton('show', () => {
component.object3D.transform.enable = true;
});
GUIHelp.addButton('hide', () => {
component.object3D.transform.enable = false;
});

let ddgiProbeRenderer = renderJob.ddgiProbeRenderer;
GUIHelp.addButton('showRays', () => {
let array = ddgiProbeRenderer.irradianceComputePass['depthRaysBuffer'].readBuffer();
let count = Engine3D.setting.gi.probeXCount * Engine3D.setting.gi.probeYCount * Engine3D.setting.gi.probeZCount
for (let j = 0; j < count; j++) {
let probeIndex = j;
debugProbeRay(probeIndex, array);
}
debugProbeRay(0, array);
});

GUIHelp.addButton('hideRays', () => {
let count = Engine3D.setting.gi.probeXCount * Engine3D.setting.gi.probeYCount * Engine3D.setting.gi.probeZCount
for (let j = 0; j < count; j++) {
let probeIndex = j;
const rayNumber = Engine3D.setting.gi.rayNumber;
for (let i = 0; i < rayNumber; i++) {
let id = `showRays${probeIndex}${i}`;
view.graphic3D.Clear(id);
}
}
});
GUIHelp.endFolder();
}

//render uv move component
public static renderUVMove(component: UVMoveComponent, open: boolean = true, name?: string) {
name ||= 'UV Move';
Expand Down
29 changes: 29 additions & 0 deletions src/Engine3D.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,35 @@ export class Engine3D {
updateFrameRate: 2,
debug: false,
},
gi: {
enable: false,
offsetX: 0,
offsetY: 0,
offsetZ: 0,
probeSpace: 64,
probeXCount: 4,
probeYCount: 2,
probeZCount: 4,
probeSize: 32,
probeSourceTextureSize: 2048,
octRTMaxSize: 2048,
octRTSideSize: 16,
maxDistance: 64 * 1.73,
normalBias: 0.25,
depthSharpness: 1,
hysteresis: 0.98,
lerpHysteresis: 0.01,//The smaller the value, the slower the reaction, which can counteract flickering
irradianceChebyshevBias: 0.01,
rayNumber: 144,
irradianceDistanceBias: 32,
indirectIntensity: 1.0,
ddgiGamma: 2.2,
bounceIntensity: 0.025,
probeRoughness: 1,
realTimeGI: false,
debug: false,
autoRenderProbe: false,
},
sky: {
type: 'HDRSKY',
sky: null,
Expand Down

0 comments on commit 775ebbc

Please sign in to comment.