addMaterial method
Compiles source for this engine's backend and adds it to the
renderer's materials once loaded. from names it in every message.
The registration takes it out of the renderer again.
Implementation
Registration addMaterial(String source, {required String from}) {
final String name;
final ShaderBundle bundle;
try {
final program = parseMaterial(source);
name = program.name;
if (program.kind != MaterialStageKind.surface) {
throw PluginException(
'${_owner()} brought "$name", a ${program.kind} stage, as a '
'material: a full-screen stage is a render step\'s, under its '
'"shaders" as "material"',
);
}
} on MaterialSyntaxException catch (error) {
// A source that does not parse is the author's mistake on every
// backend, so it fails the install rather than switching anything off.
throw PluginException(
'${_owner()} brought a material that does not parse: '
'$from:${error.line}:${error.column}: ${error.message}',
);
}
if (_store.backend == RuntimeBackends.impeller) {
return _prebuiltMaterial(source, name);
}
try {
bundle = runtimeMaterialBundle(
source,
backend: _store.backend,
from: from,
engineSources: _store.engineSources,
webGpuHost: _store.webGpuHost,
webGpuFullscreenUvLocation: _store.webGpuFullscreenUvLocation,
compilers: _store.compilers,
);
} on RuntimeShadersException catch (refused) {
_store.statuses[name] = refused.message;
return _tracked(Registration(() => _store.statuses.remove(name)));
}
_store.statuses[name] = null;
Registration? added;
var cancelled = false;
_store.load(bundle, name, (library) {
if (cancelled) return;
added = _store.addMaterials(library);
_store.lighting[name] = describeMaterial(
parseMaterial(source),
).lightingModel(label: name, shaderName: name);
});
return _tracked(
Registration(() {
cancelled = true;
added?.cancel();
_store.lighting.remove(name);
_store.statuses.remove(name);
}),
);
}