Skip to content

全局光照

一般光照系统只考虑光源直接照射到物体表面所产生的效果,不会计算光源经过物体表面反射或折射的光线,即间接光照。全局光照系统能够对间接光照进行建模,实现更加逼真的光线效果。

ts
//初始化引擎
await Engine3D.init({ });

Engine3D.setting.gi.enable = true;
Engine3D.setting.gi.gridYCount = 3;
Engine3D.setting.gi.gridXCount = 4;
Engine3D.setting.gi.gridZCount = 4;
Engine3D.setting.gi.probeSpace = 30;
Engine3D.setting.gi.offsetX = 22;
Engine3D.setting.gi.offsetY = 56;
Engine3D.setting.gi.offsetZ = 23;
Engine3D.setting.gi.indirectIntensity = 2;
Engine3D.setting.gi.probeSize = 64;
Engine3D.setting.gi.octRTSideSize = 128;
Engine3D.setting.gi.autoRenderProbe = true;

let probeObj = new Object3D();
let component = probeObj.addComponent(GlobalIlluminationComponent);
this.scene.addChild(probeObj);

//创建渲染器
let renderJob = new ForwardRenderJob(this.scene);
Engine3D.startRender(renderJob);

Engine3D.setting.gi 配置参数。

参数类型描述
enableboolean开启/关闭
offsetXnumber探针组的注册点在x轴的偏移量
offsetYnumber探针组的注册点在y轴的偏移量
offsetZnumber探针组的注册点在z轴的偏移量
gridXCountnumber探针在x轴的数量
gridYCountnumber探针在y轴的数量
gridZCountnumbe`探针在z轴的数量
ProbeSizenumber每个探针采样到的数据尺寸
probeSpacenumber探针与探针之间的距离
indirectIntensitynumber间接光的光照强度
bounceIntensitynumber反射光的光照强度
octRTMaxSizenumber设置八面体贴图的总尺寸
octRTSideSizenumber设置八面体贴图,每个八面体正方形的尺寸
autoRenderProbeboolean设置探针是否自动更新


Orillusion powered by WebGPU on Chrome/Edge 113+
Please upgrade to latest Chrome/Edge

<
ts
import {
  Camera3D,
  defaultTexture,
  DirectLight,
  Engine3D,
  ForwardRenderJob,
  GLTFParser,
  GUIHelp,
  LitMaterial,
  HoverCameraController,
  KelvinUtil,
  MeshRenderer,
  Object3D,
  PlaneGeometry,
  Scene3D,
  SphereGeometry,
  SSRPost,
  SSR_IS_Kernel,
  Time,
  CameraUtil,
  webGPUContext,
  GTAOPost,
  HDRBloomPost,
  TAAPost,
  GlobalIlluminationComponent,
  PointLight,
  BoxGeometry,
  Color,
} from "@orillusion/core";

export class Sample_GI {
  lightObj: Object3D;
  cameraObj: Camera3D;
  scene: Scene3D;
  hover: HoverCameraController;

  constructor() {}

  async run() {
    await Engine3D.init({});

    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.002;
    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,
      intensity: 0.5,
      brightness: 1.25,
    };
    GUIHelp.init();

    this.scene = new Scene3D();
    Camera3D.mainCamera = CameraUtil.createCamera3DObject(this.scene);
    Camera3D.mainCamera.perspective(60, webGPUContext.aspect, 1, 5000.0);
    let ctrl = Camera3D.mainCamera.object3D.addComponent(HoverCameraController);
    ctrl.setCamera(-60, -25, 150);

    let renderJob = new ForwardRenderJob(this.scene);
    renderJob.debug();
    this.addGIProbes();
    Engine3D.startRender(renderJob);

    await this.initScene();
  }

  private addGIProbes() {
    let probeObj = new Object3D();
    let component = probeObj.addComponent(GlobalIlluminationComponent);
    this.scene.addChild(probeObj);
  }

  async initScene() {
    /******** light *******/
    {
      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 = 18;
      lc.debug();
      this.scene.addChild(this.lightObj);
    }

    {
      let po4 = new Object3D();
      let pl4 = po4.addComponent(PointLight);
      pl4.intensity = 2.5;
      pl4.range = 1000;
      pl4.castShadow = true;
      po4.x = 86;
      po4.y = 23.61;
      po4.z = -23.61;
      this.scene.addChild(po4);
      pl4.debug();
      pl4.debugDraw(true);
    }

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

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

    {
      let chair = (await Engine3D.res.loadGltf(
        "https://cdn.orillusion.com/PBR/SheenChair/SheenChair.gltf",
        {
          onProgress: (e) => this.onLoadProgress(e),
          onComplete: (e) => this.onComplete(e),
        }
      )) 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(
        "https://cdn.orillusion.com/PBR/Duck/Duck.gltf",
        {
          onProgress: (e) => this.onLoadProgress(e),
          onComplete: (e) => this.onComplete(e),
        }
      )) 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);
      GUIHelp.addFolder("Move Duck");
      GUIHelp.add(Duck.transform, "x", -80, 80, 1);
      GUIHelp.add(Duck.transform, "z", -80, 80, 1);
      GUIHelp.endFolder();
    }

    {
      //   let car = await Engine3D.res.loadGltf(
      //     "https://cdn.orillusion.com/gltfs/pbrCar/pbrCar.gltf"
      //   );
      //   car.scaleX = car.scaleY = car.scaleZ = 1.5;
      //   this.scene.addChild(car);
      //   car.x = 20;
    }

    GUIHelp.addButton("Start GI", () => {
      Engine3D.renderJob.probeRenderer.startRenderGI();
    });
  }

  onLoadProgress(e) {
    console.log(e);
  }

  onComplete(e) {
    console.log(e);
  }

  renderUpdate() {}

  public GetSingleCube(
    sizeX: number,
    sizeY: number,
    sizeZ: number,
    r: number,
    g: number,
    b: number
  ) {
    let mat = new LitMaterial();
    mat.baseColor = new Color(r, g, b, 1);

    let obj = new Object3D();
    let mr = obj.addComponent(MeshRenderer);
    mr.castGI = true;
    mr.geometry = new BoxGeometry(sizeX, sizeY, sizeZ);
    mr.material = mat;
    return obj;
  }

  public GetSingleSphere(radius: number, r: number, g: number, b: number) {
    let mat = new LitMaterial();
    mat.baseColor = new Color(r, g, b, 1);

    let obj = new Object3D();
    let mr = obj.addComponent(MeshRenderer);
    mr.castGI = true;
    mr.geometry = new SphereGeometry(radius, 20, 20);
    mr.material = mat;
    return obj;
  }
}

new Sample_GI().run();