loadTexture function Assets and loading
- String sourcePath, {
- String? package,
- AssetBundle? bundle,
- TextureSampling? sampling,
Loads a cooked compressed texture by its source path relative to the owning
package's root (for example assets/shadow_plane.png), ready to assign to
a material texture slot.
The texture must have been cooked by the buildTextures build hook in a
DataAssets mode. The payload transcodes to a device-supported block format
(or decodes to rgba8) off the main isolate, uploads with its full mip
chain, and is cached, so repeated loads of the same source share one GPU
texture. In debug builds the texture hot reloads: editing the source image
re-cooks it and the next hot reload swaps the new texture into every bound
material in place.
The default sampling is trilinear repeat; pass sampling to override it
(the underlying GPU texture stays shared). Prefer sampling over wrapping
the returned source's raw texture yourself, which would pin the texture
handle and stop hot reload from reaching that holder. Pass package to
disambiguate when the same source path is provided by more than one
package.
Implementation
Future<TextureSource> loadTexture(
String sourcePath, {
String? package,
AssetBundle? bundle,
TextureSampling? sampling,
}) async {
final assetBundle = bundle ?? rootBundle;
Future<Uint8List> loadBytes(String key) async {
final data = await assetBundle.load(key);
return data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
}
final registry = await TextureRegistry.load(bundle: bundle);
final key = registry.resolveKey(sourcePath, package: package);
final future = _textureCache.putIfAbsent(key, () async {
final source = _ReloadableTextureSource(
await gpuTextureFromKtx2Async(await loadBytes(key)),
);
HotReloadCoordinator.instance.registerTexture(
source,
assetKey: key,
bundle: assetBundle,
onReload: () async =>
source._swap(await gpuTextureFromKtx2Async(await loadBytes(key))),
);
return source;
});
final _ReloadableTextureSource source;
try {
source = await future;
} catch (_) {
// Do not pin a failed load; the next call retries it.
if (identical(_textureCache[key], future)) {
_textureCache.remove(key);
}
rethrow;
}
if (sampling == null) return source;
return _SampledTextureView(source, sampling.toSamplerOptions());
}