畫面中呈現逼真的淺色虛擬物體

瞭解如何在自己的應用程式中使用光線估算

必要條件

請務必先瞭解基本 AR 概念,以及如何設定 ARCore 工作階段,再繼續操作。

每個工作階段設定一次 API,並使用適當模式

針對要使用的模式,每個工作階段設定一次光線估算。

Java

// Configure the session with the Lighting Estimation API in ENVIRONMENTAL_HDR mode.
Config config = session.getConfig();
config.setLightEstimationMode(LightEstimationMode.ENVIRONMENTAL_HDR);
session.configure(config);

// Configure the session with the Lighting Estimation API in AMBIENT_INTENSITY mode.
Config config = session.getConfig();
config.setLightEstimationMode(LightEstimationMode.AMBIENT_INTENSITY);
session.configure(config);

// Configure the session with the Lighting Estimation API turned off.
Config config = session.getConfig();
config.setLightEstimationMode(LightEstimationMode.DISABLED);
session.configure(config);

Kotlin

// Configure the session with the Lighting Estimation API in ENVIRONMENTAL_HDR mode.
Config config = session.config
config.lightEstimationMode = LightEstimationMode.ENVIRONMENTAL_HDR
session.configure(config)

// Configure the session with the Lighting Estimation API in AMBIENT_INTENSITY mode.
Config config = session.config
config.lightEstimationMode = LightEstimationMode.AMBIENT_INTENSITY
session.configure(config)

// Configure the session with the Lighting Estimation API turned off.
Config config = session.config
config.lightEstimationMode = LightEstimationMode.DISABLED
session.configure(config)

設定「ENVIRONMENTAL_HDR」模式

如要設定 ENVIRONMENTAL_HDR 模式,請取得每個影格的光線估計值,然後取得要使用的環境 HDR 照明元件。

Java

void update() {
  // Get the current frame.
  Frame frame = session.update();

  // Get the light estimate for the current frame.
  LightEstimate lightEstimate = frame.getLightEstimate();

  // Get intensity and direction of the main directional light from the current light estimate.
  float[] intensity = lightEstimate.getEnvironmentalHdrMainLightIntensity(); // note - currently only out param.
  float[] direction = lightEstimate.getEnvironmentalHdrMainLightDirection();
  app.setDirectionalLightValues(intensity, direction); // app-specific code.

  // Get ambient lighting as spherical harmonics coefficients.
  float[] harmonics = lightEstimate.getEnvironmentalHdrAmbientSphericalHarmonics();
  app.setAmbientSphericalHarmonicsLightValues(harmonics); // app-specific code.

  // Get HDR environmental lighting as a cubemap in linear color space.
  Image[] lightmaps = lightEstimate.acquireEnvironmentalHdrCubeMap();
  for (int i = 0; i < lightmaps.length /*should be 6*/; ++i) {
    app.uploadToTexture(i, lightmaps[i]);  // app-specific code.
  }
}

Kotlin

fun update() {
  // Get the current frame.
  val frame = session.update()

  // Get the light estimate for the current frame.
  val lightEstimate = frame.lightEstimate

  // Get intensity and direction of the main directional light from the current light estimate.
  val intensity = lightEstimate.environmentalHdrMainLightIntensity
  val direction = lightEstimate.environmentalHdrMainLightDirection
  app.setDirectionalLightValues(intensity, direction) // app-specific code.

  // Get ambient lighting as spherical harmonics coefficients.
  val harmonics = lightEstimate.environmentalHdrAmbientSphericalHarmonics
  app.ambientSphericalHarmonicsLightValues = harmonics // app-specific code.

  // Get HDR environmental lighting as a cubemap in linear color space.
  val lightMaps = lightEstimate.acquireEnvironmentalHdrCubeMap();
  for ((index, lightMap) in lightMaps.withIndex()) { // 6 maps total.
    app.uploadToTexture(index, lightMap); // app-specific code.
  }
}

設定「AMBIENT_INTENSITY」模式

如果您打算使用 AMBIENT_INTENSITY 模式的色彩校正元件,請先重複使用共用配置,避免在每個影格上配置色彩校正。

Java

 // Avoid allocation on every frame.
float[] colorCorrection = new float[4];

Kotlin

val colorCorrection = floatArrayOf(0.0f, 0.0f, 0.0f, 0.0f)

取得每個影格的光線估計值,然後取得要使用的環境強度元件。

Java

void update() {
  // Get the current frame.
  Frame frame = session.update();

  // Get the light estimate for the current frame.
  LightEstimate lightEstimate = frame.getLightEstimate();

  // Get the pixel intensity of AMBIENT_INTENSITY mode.
  float pixelIntensity = lightEstimate.getPixelIntensity();

  // Read the pixel color correction of AMBIENT_INTENSITY mode into colorCorrection.
  lightEstimate.getColorCorrection(colorCorrection, 0);
}

Kotlin

fun update() {
    // Get the current frame.
  val frame = session.update()

  // Get the light estimate for the current frame.
  val lightEstimate = frame.lightEstimate

  // Get the pixel intensity of AMBIENT_INTENSITY mode.
  val pixelIntensity = lightEstimate.pixelIntensity

  // Read the pixel color correction of AMBIENT_INTENSITY mode into colorCorrection.
  lightEstimate.getColorCorrection(colorCorrection, 0)
}

使用 Environmental HDR API 確保節省能源

能量守恆原則是指表面反射的光線強度,絕不會高於光線照射到表面之前的強度。這項規則會在以物理為基礎的算繪中強制執行,但通常會從電玩遊戲和行動應用程式使用的舊版算繪管道中省略。

如果您使用以物理為基礎的算繪管道,並進行環境 HDR 光線估算,只要確保虛擬物件使用以物理為基礎的材質即可。

不過,如果您沒有使用以物理為基礎的管道,則有幾種做法:

  • 最理想的解決方案是遷移至以實體為基礎的管道。

  • 但如果無法這麼做,一個不錯的解決方法是將非實體基礎材質的反射率值乘以能量守恆因子。這可確保至少 BRDF 陰影模型可以轉換為以物理為基礎的模型。每個 BRDF 都有不同的因素,例如漫射反射為 1/Pi。