addRenderStep method

Registration addRenderStep(
  1. RuntimeRenderStep step,
  2. RendererSteps into
)

Adds step to into — the renderer's steps as the same plugin sees them — with a pass that draws once its stage for this backend is loaded.

A backend step has no stage for adds the step anyway, switched off, with the reason in statuses: FrameResult.skipped names it, and a plugin list can say why.

Implementation

Registration addRenderStep(RuntimeRenderStep step, RendererSteps into) {
  final needs = <RenderStep>{
    for (final name in step.needs) _builtInStep(name, step.name),
  };
  final renderStep = RenderStep(step.name, needs: needs);
  final node = _RuntimeEffectNode(step.name, present: step.present);
  final registrations = <Registration>[
    into.addStep(renderStep),
    into.addNode(
      node,
      at: step.anchor,
      step: renderStep,
      after: step.after,
      before: step.before,
    ),
  ];
  final backend = _store.backend;
  final source = backend == null ? null : step.shaders[backend];
  final material = step.shaders[RuntimeRenderStep.materialStage];
  if (material != null && backend != null) {
    _materialStep(step, material, node);
  } else if (source == null) {
    _store.statuses[step.name] = backend == null
        ? 'this engine draws nothing'
        : 'it has a stage for ${step.shaders.keys.join(', ')} and this '
              'engine draws with $backend';
  } else if (backend != RuntimeBackends.webgl) {
    _store.statuses[step.name] =
        'a raw stage is compiled at run time on '
        '${RuntimeBackends.webgl} only; this engine draws with $backend';
  } else {
    _store.statuses[step.name] = null;
    final bundle = ShaderBundle(
      name: step.name,
      sdk: runtimeShaderSdk,
      stages: <ShaderBundleStage>[
        ShaderBundleStage(step.name, fragment: true),
      ],
      sections: <String, ByteData>{
        ShaderBundle.webglSection: encodeWebGlSection(
          vertex: const <String, String>{},
          fragment: <String, String>{step.name: source},
        ),
      },
    );
    _store.load(bundle, step.name, (library) {
      final shader = library[step.name];
      if (shader == null) {
        _store.statuses[step.name] =
            'the loaded library has no stage named '
            '"${step.name}"';
        return;
      }
      node.effect = step.present
          ? FullscreenEffect.present(name: step.name, shader: shader)
          : FullscreenEffect.overlay(name: step.name, shader: shader);
    });
  }
  return _tracked(
    Registration(() {
      node.effect = null;
      for (final registration in registrations.reversed) {
        registration.cancel();
      }
      _store.statuses.remove(step.name);
    }),
  );
}