realizeStage function

Future<void> realizeStage(
  1. SceneDocument document,
  2. Scene scene, {
  3. AssetBundle? bundle,
})

Applies document's stage render settings to scene: environment, environment intensity, exposure, tone mapping, skybox, and sky lighting.

When the stage binds sky lighting (skyEnvironment), the binding owns Scene.environment and the stage's environment is not applied. A skybox and a sky-lighting binding whose sources describe the same sky share one live source, so mutating it (or hot reloading its .fmat) updates both.

GPU-bound and async (an asset environment decodes its image, an fmat sky loads by source path from bundle, default the root bundle).

Implementation

Future<void> realizeStage(
  SceneDocument document,
  Scene scene, {
  AssetBundle? bundle,
}) async {
  final stage = document.stage;
  scene.environmentIntensity = stage.environmentIntensity;
  scene.exposure = stage.exposure;
  scene.toneMapping = _toneMapping(stage.toneMapping);
  scene.antiAliasingMode = _byName(
    AntiAliasingMode.values,
    stage.antiAliasingMode,
    AntiAliasingMode.auto,
  );
  scene.renderScale = stage.renderScale;
  scene.filterQuality = _byName(
    ui.FilterQuality.values,
    stage.filterQuality,
    ui.FilterQuality.medium,
  );

  // Realize each distinct sky source once so a skybox and sky lighting
  // describing the same sky share one live source.
  final realized = <String, SkySource?>{};
  Future<SkySource?> sourceFor(SkySourceSpec spec) async =>
      realized[canonicalJson(encodeSkySource(spec))] ??=
          await _realizeSkySource(spec, bundle);

  final skyEnvironmentSpec = stage.skyEnvironment;
  if (skyEnvironmentSpec == null) {
    scene.skyEnvironment = null;
    await _applyEnvironment(stage.environment, scene, bundle);
  } else {
    final source = await sourceFor(skyEnvironmentSpec.source);
    if (source is ShaderSkySource) {
      scene.skyEnvironment = SkyEnvironment(
        source,
        refresh: _refresh(skyEnvironmentSpec.refresh),
        interval: Duration(
          microseconds: (skyEnvironmentSpec.intervalSeconds * 1e6).round(),
        ),
        faceResolution: skyEnvironmentSpec.faceResolution,
        equirectWidth: skyEnvironmentSpec.equirectWidth,
      );
    } else {
      if (source != null) {
        debugPrint(
          'fscene: skyEnvironment needs a shader sky (fmat, gradient, or '
          'physical); skipping the binding',
        );
      }
      scene.skyEnvironment = null;
      await _applyEnvironment(stage.environment, scene, bundle);
    }
  }

  final skyboxSpec = stage.skybox;
  if (skyboxSpec == null) {
    scene.skybox = null;
  } else {
    final source = await sourceFor(skyboxSpec.source);
    scene.skybox = source == null
        ? null
        : Skybox(source, intensity: skyboxSpec.intensity);
  }
}