scenix_material/
traits.rs1#[derive(Clone, Copy, Debug, PartialEq)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub enum AlphaMode {
5 Opaque,
7 Mask(f32),
9 Blend,
11}
12
13impl AlphaMode {
14 #[inline]
16 pub const fn pipeline_alpha(self) -> PipelineAlphaMode {
17 match self {
18 Self::Opaque => PipelineAlphaMode::Opaque,
19 Self::Mask(_) => PipelineAlphaMode::Mask,
20 Self::Blend => PipelineAlphaMode::Blend,
21 }
22 }
23
24 #[inline]
26 pub const fn is_transparent(self) -> bool {
27 matches!(self, Self::Blend)
28 }
29
30 #[inline]
32 pub const fn cutoff(self) -> Option<f32> {
33 match self {
34 Self::Mask(cutoff) => Some(cutoff),
35 Self::Opaque | Self::Blend => None,
36 }
37 }
38}
39
40impl Default for AlphaMode {
41 #[inline]
42 fn default() -> Self {
43 Self::Opaque
44 }
45}
46
47#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
50#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
51pub enum PipelineAlphaMode {
52 #[default]
54 Opaque,
55 Mask,
57 Blend,
59}
60
61#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
63#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
64pub enum ShaderKind {
65 #[default]
67 Pbr,
68 Physical,
70 Unlit,
72 Lambert,
74 Toon,
76 Normal,
78 Wireframe,
80 Depth,
82 Line,
84 Points,
86 Custom(u64),
88}
89
90#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
92#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
93pub struct PipelineKey {
94 pub shader: ShaderKind,
96 pub alpha: PipelineAlphaMode,
98 pub feature_bits: u64,
100}
101
102impl PipelineKey {
103 #[inline]
105 pub const fn new(shader: ShaderKind, alpha: PipelineAlphaMode, feature_bits: u64) -> Self {
106 Self {
107 shader,
108 alpha,
109 feature_bits,
110 }
111 }
112
113 #[inline]
115 pub const fn with_feature(mut self, feature: u64) -> Self {
116 self.feature_bits |= feature;
117 self
118 }
119
120 #[inline]
122 pub const fn has_feature(self, feature: u64) -> bool {
123 self.feature_bits & feature != 0
124 }
125}
126
127pub const FEATURE_DOUBLE_SIDED: u64 = 1 << 0;
129pub const FEATURE_ALBEDO_TEXTURE: u64 = 1 << 1;
131pub const FEATURE_METALLIC_ROUGHNESS_TEXTURE: u64 = 1 << 2;
133pub const FEATURE_NORMAL_TEXTURE: u64 = 1 << 3;
135pub const FEATURE_OCCLUSION_TEXTURE: u64 = 1 << 4;
137pub const FEATURE_EMISSIVE_TEXTURE: u64 = 1 << 5;
139pub const FEATURE_GRADIENT_TEXTURE: u64 = 1 << 6;
141pub const FEATURE_CLEARCOAT: u64 = 1 << 7;
143pub const FEATURE_SHEEN: u64 = 1 << 8;
145pub const FEATURE_TRANSMISSION: u64 = 1 << 9;
147pub const FEATURE_IRIDESCENCE: u64 = 1 << 10;
149pub const FEATURE_FLAT_SHADING: u64 = 1 << 11;
151pub const FEATURE_WORLD_SPACE: u64 = 1 << 12;
153pub const FEATURE_WIREFRAME: u64 = 1 << 13;
155pub const FEATURE_DASHED: u64 = 1 << 14;
157pub const FEATURE_SIZE_ATTENUATION: u64 = 1 << 15;
159pub const FEATURE_CUSTOM_TEXTURES: u64 = 1 << 16;
161pub const FEATURE_VERTEX_COLORS: u64 = 1 << 17;
163pub const FEATURE_OUTLINE: u64 = 1 << 18;
165
166pub trait Material: Send + Sync + 'static {
168 fn pipeline_key(&self) -> PipelineKey;
170
171 fn is_transparent(&self) -> bool;
173
174 fn double_sided(&self) -> bool;
176
177 fn alpha_cutoff(&self) -> Option<f32>;
179}
180
181#[inline]
182pub(crate) const fn double_sided_bit(double_sided: bool) -> u64 {
183 if double_sided {
184 FEATURE_DOUBLE_SIDED
185 } else {
186 0
187 }
188}
189
190#[inline]
191pub(crate) const fn option_texture_bit<T>(texture: &Option<T>, feature: u64) -> u64 {
192 if texture.is_some() { feature } else { 0 }
193}
194
195#[inline]
197pub(crate) fn stable_shader_id(vertex_wgsl: &str, fragment_wgsl: &str) -> u64 {
198 const OFFSET: u64 = 0xcbf2_9ce4_8422_2325;
199 const PRIME: u64 = 0x0000_0100_0000_01b3;
200
201 let mut hash = OFFSET;
202 for byte in vertex_wgsl.as_bytes() {
203 hash ^= *byte as u64;
204 hash = hash.wrapping_mul(PRIME);
205 }
206 hash ^= 0xff;
207 hash = hash.wrapping_mul(PRIME);
208 for byte in fragment_wgsl.as_bytes() {
209 hash ^= *byte as u64;
210 hash = hash.wrapping_mul(PRIME);
211 }
212 hash
213}