Realistycznie oświetlone wirtualne obiekty w scenie

Dowiedz się, jak używać Oszacowania oświetlenia w swoich aplikacjach.

Wymagania wstępne

Zanim przejdziesz dalej, upewnij się, że znasz podstawowe pojęcia związane z AR i wiesz, jak skonfigurować sesję ARCore.

Skonfiguruj interfejs API raz na sesję z użyciem odpowiedniego trybu

Skonfiguruj szacowanie oświetlenia raz na sesję w przypadku wybranego trybu.

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)

Skonfiguruj tryb ENVIRONMENTAL_HDR

Aby skonfigurować tryb ENVIRONMENTAL_HDR, pobierz oszacowanie natężenia światła dla każdej klatki, a następnie kup komponenty oświetleniowe HDR, których chcesz użyć.

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.
  }
}

Skonfiguruj tryb AMBIENT_INTENSITY

Jeśli zamierzasz użyć komponentu korekcji kolorów w trybie AMBIENT_INTENSITY, najpierw unikaj przypisania korekcji kolorów w każdej klatce przez ponowne wykorzystanie wspólnego przydziału.

Java

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

Kotlin

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

Uzyskaj szacunkową ilość światła dla każdej klatki i uzyskaj komponenty natężenia światła otoczenia, których chcesz użyć.

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)
}

Zapewnianie oszczędzania energii dzięki interfejsom API Environmental HDR API

Oszczędność energii to zasada, że światło odbite od powierzchni nigdy nie będzie silniejsze niż przed uderzeniem na tę powierzchnię. Ta reguła jest egzekwowana w przypadku renderowania fizycznego, ale zwykle jest pomijana w starszych potokach renderowania używanych w grach wideo i aplikacjach mobilnych.

Jeśli używasz fizycznego potoku renderowania z oszacowaniem światła HDR środowiskowego, upewnij się, że w obiektach wirtualnych używane są materiały fizyczne.

Jeśli jednak nie używasz fizycznie potoku, masz kilka możliwości:

  • Najlepszym rozwiązaniem w tym przypadku jest migracja do potoku fizycznie.

  • Jeśli jednak nie jest to możliwe, dobrym obejściem jest pomnożenie wartości albedo materiału niefizycznego przez współczynnik oszczędzania energii. W ten sposób mamy pewność, że przynajmniej model cieniowania BRDF można przekształcić w fizycznie modelowany. Każdy BRDF ma inny czynnik – na przykład w przypadku rozproszonego odbicia wynosi on 1/Pi.