From ae73181466c7e32b0e5e9e814f5170310c20f263 Mon Sep 17 00:00:00 2001 From: Jochum van der Ploeg Date: Sat, 14 Dec 2024 13:35:46 +0100 Subject: [PATCH] feat!: Allow for custom shaders and materials (#3384) Allows for custom materials and shaders. --- .../resources/material/spatial_material.dart | 10 ++-- .../lib/src/resources/shader/shader.dart | 52 +++++++++++-------- .../shader/uniform_binding_test.dart | 1 + 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/packages/flame_3d/lib/src/resources/material/spatial_material.dart b/packages/flame_3d/lib/src/resources/material/spatial_material.dart index eb3b088dfda..b15022767f0 100644 --- a/packages/flame_3d/lib/src/resources/material/spatial_material.dart +++ b/packages/flame_3d/lib/src/resources/material/spatial_material.dart @@ -12,8 +12,9 @@ class SpatialMaterial extends Material { this.roughness = 0.6, }) : albedoTexture = albedoTexture ?? Texture.standard, super( - vertexShader: Shader( - name: 'TextureVertex', + vertexShader: Shader.vertex( + asset: + 'packages/flame_3d/assets/shaders/spatial_material.shaderbundle', slots: [ UniformSlot.value('VertexInfo', { 'model', @@ -26,8 +27,9 @@ class SpatialMaterial extends Material { ), ], ), - fragmentShader: Shader( - name: 'TextureFragment', + fragmentShader: Shader.fragment( + asset: + 'packages/flame_3d/assets/shaders/spatial_material.shaderbundle', slots: [ UniformSlot.sampler('albedoTexture'), UniformSlot.value('Material', { diff --git a/packages/flame_3d/lib/src/resources/shader/shader.dart b/packages/flame_3d/lib/src/resources/shader/shader.dart index a7e1bd5f4fa..30e645130e5 100644 --- a/packages/flame_3d/lib/src/resources/shader/shader.dart +++ b/packages/flame_3d/lib/src/resources/shader/shader.dart @@ -6,49 +6,53 @@ import 'package:flame_3d/graphics.dart'; import 'package:flame_3d/resources.dart'; import 'package:flutter_gpu/gpu.dart' as gpu; -/// {@template shader} +/// {@template shader_resource} /// /// {@endtemplate} class ShaderResource extends Resource { - final Shader shader; + /// {@macro shader_resource} + factory ShaderResource.createFromAsset({ + required String asset, + required String shaderName, + required List slots, + }) { + final library = gpu.ShaderLibrary.fromAsset(asset)!; - /// {@macro shader} - ShaderResource( - super.resource, { - required String name, - List slots = const [], - }) : shader = Shader(name: name, slots: slots) { - for (final slot in slots) { - slot.resource = resource.getUniformSlot(slot.name); + final shader = library[shaderName]; + if (shader == null) { + throw StateError('Shader "$shaderName" not found in library "$asset"'); } + return ShaderResource._(shader, slots: slots); } - factory ShaderResource.create({ - required String name, - required List slots, + ShaderResource._( + super.resource, { + List slots = const [], }) { - final shader = _library[name]; - if (shader == null) { - throw StateError('Shader "$name" not found in library'); + for (final slot in slots) { + slot.resource = resource.getUniformSlot(slot.name); } - return ShaderResource(shader, name: name, slots: slots); } - - static final _library = gpu.ShaderLibrary.fromAsset( - 'packages/flame_3d/assets/shaders/spatial_material.shaderbundle', - )!; } class Shader { + final String asset; final String name; final List slots; final Map instances = {}; Shader({ + required this.asset, required this.name, required this.slots, }); + Shader.vertex({required String asset, required List slots}) + : this(asset: asset, name: 'TextureVertex', slots: slots); + + Shader.fragment({required String asset, required List slots}) + : this(asset: asset, name: 'TextureFragment', slots: slots); + /// Set a [Texture] at the given [key] on the buffer. void setTexture(String key, Texture texture) => _setTypedValue(key, texture); @@ -140,6 +144,10 @@ class Shader { } ShaderResource compile() { - return ShaderResource.create(name: name, slots: slots); + return ShaderResource.createFromAsset( + asset: asset, + shaderName: name, + slots: slots, + ); } } diff --git a/packages/flame_3d/test/resources/shader/uniform_binding_test.dart b/packages/flame_3d/test/resources/shader/uniform_binding_test.dart index f628a34df6e..151dc97a24a 100644 --- a/packages/flame_3d/test/resources/shader/uniform_binding_test.dart +++ b/packages/flame_3d/test/resources/shader/uniform_binding_test.dart @@ -107,6 +107,7 @@ void main() { Shader _createShader(List slots) { return Shader( + asset: 'none', name: '-test-', slots: slots, );