Impl ShaderType for LinearRgba (#12137)

# Objective

- LinearRgba is the color type intended for shaders but using it for
shaders is currently not easy because it doesn't implement ShaderType

## Solution

- add encase as a dependency and impl the required traits.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
This commit is contained in:
IceSentry 2024-02-26 17:31:49 -05:00 committed by GitHub
parent 4d325eb3f0
commit abc6f983ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 72 additions and 0 deletions

View file

@ -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

View file

@ -210,6 +210,77 @@ impl From<LinearRgba> 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<Self::ExtraMetadata> = {
let size =
encase::private::SizeValue::from(<f32 as encase::private::ShaderSize>::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<B: encase::private::BufferMut>(&self, writer: &mut encase::private::Writer<B>) {
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<B: encase::private::BufferRef>(
&mut self,
reader: &mut encase::private::Reader<B>,
) {
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<B>(reader: &mut encase::private::Reader<B>) -> 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::*;