diff --git a/crates/bevy_color/Cargo.toml b/crates/bevy_color/Cargo.toml index 4997436e19..fa88cc611d 100644 --- a/crates/bevy_color/Cargo.toml +++ b/crates/bevy_color/Cargo.toml @@ -16,6 +16,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [ serde = "1.0" thiserror = "1.0" wgpu = { version = "0.19.1", default-features = false } +encase = { version = "0.7", default-features = false } [lints] workspace = true diff --git a/crates/bevy_color/src/linear_rgba.rs b/crates/bevy_color/src/linear_rgba.rs index 9a682b2ac9..85b3c2f094 100644 --- a/crates/bevy_color/src/linear_rgba.rs +++ b/crates/bevy_color/src/linear_rgba.rs @@ -210,6 +210,77 @@ impl From for wgpu::Color { } } +// [`LinearRgba`] is intended to be used with shaders +// So it's the only color type that implements [`ShaderType`] to make it easier to use inside shaders +impl encase::ShaderType for LinearRgba { + type ExtraMetadata = (); + + const METADATA: encase::private::Metadata = { + let size = + encase::private::SizeValue::from(::SHADER_SIZE) + .mul(4); + let alignment = encase::private::AlignmentValue::from_next_power_of_two_size(size); + + encase::private::Metadata { + alignment, + has_uniform_min_alignment: false, + min_size: size, + extra: (), + } + }; + + const UNIFORM_COMPAT_ASSERT: fn() = || {}; +} + +impl encase::private::WriteInto for LinearRgba { + fn write_into(&self, writer: &mut encase::private::Writer) { + for el in &[self.red, self.green, self.blue, self.alpha] { + encase::private::WriteInto::write_into(el, writer); + } + } +} + +impl encase::private::ReadFrom for LinearRgba { + fn read_from( + &mut self, + reader: &mut encase::private::Reader, + ) { + let mut buffer = [0.0f32; 4]; + for el in &mut buffer { + encase::private::ReadFrom::read_from(el, reader); + } + + *self = LinearRgba { + red: buffer[0], + green: buffer[1], + blue: buffer[2], + alpha: buffer[3], + } + } +} + +impl encase::private::CreateFrom for LinearRgba { + fn create_from(reader: &mut encase::private::Reader) -> Self + where + B: encase::private::BufferRef, + { + // These are intentionally not inlined in the constructor to make this + // resilient to internal Color refactors / implicit type changes. + let red: f32 = encase::private::CreateFrom::create_from(reader); + let green: f32 = encase::private::CreateFrom::create_from(reader); + let blue: f32 = encase::private::CreateFrom::create_from(reader); + let alpha: f32 = encase::private::CreateFrom::create_from(reader); + LinearRgba { + red, + green, + blue, + alpha, + } + } +} + +impl encase::ShaderSize for LinearRgba {} + #[cfg(test)] mod tests { use super::*;