three_d/renderer/
shader_ids.rs

1//!
2//! Each shader is allocated a unique ID within its category so that they can be cached between frames.
3//! If you implement custom shaders, ensure to give them an ID not already allocated here.
4//! Reductions of the public use ID ranges will be considered a breaking change and result in the appropriate version increment.
5//! The allocation of internal use IDs should be considered unstable.
6//!
7
8use crate::texture::{ColorTexture, DepthTexture};
9
10use open_enum::open_enum;
11
12// TODO: Change macros to only take final name and generate base name once concat_idents (rust-lang/rust#29599) becomes stable
13// NOTE: It may be possible to eventually create a proc macro that automatically allocates ID values based on the width of their subfields
14
15///
16/// Recursive macro to assemble multiple booleans into a single bitfield (as a variable width int literal)
17///
18macro_rules! bitfield_bit {
19    ($field:ident << $shift:expr) => {
20        // Base case, unwrapping a boolean into an int literal and shifting by the computed amount
21        ((if $field { 1 } else { 0 }) << $shift)
22    };
23
24    ($field:ident, $($fields:ident),+ << $shift:expr) => {
25        // Recursive case, breaking off the first bit and adding one to the shift of the remainder
26        bitfield_bit!($field << $shift)
27            | bitfield_bit!($($fields),+ << $shift + 1)
28    };
29}
30
31///
32/// Generates a function accepting bit parameters, ordering from least significant bit to most significant bit
33/// bitfield_bit abstracts out the process of converting a tuple of bools into a single int literal
34///
35macro_rules! enum_bitfield {
36    ($base_name:ident, $name:ident($($field:ident),+ $(,)?)) => {
37        #[allow(non_snake_case)]
38        #[inline]
39        pub(crate) fn $name($($field: bool),+) -> Self {
40            Self(
41                Self::$base_name.0
42                    | bitfield_bit!($($field),+ << 0)
43            )
44        }
45    };
46}
47
48///
49/// Generates a function accepting effect parameters, which self-describe which bits they set
50///
51macro_rules! enum_effectfield {
52    ($base_name:ident, $name:ident($($texture:ident: Option<$textureType:ty>),+ $(,)?)) => {
53        // Effect field function taking optional effects, which default to zero if unset
54        #[allow(non_snake_case)]
55        #[inline]
56        pub(crate) fn $name($($texture: Option<$textureType>),*) -> Self {
57            Self(
58                Self::$base_name.0
59                $(  | $texture.map(|t| t.id()).unwrap_or(0))*
60            )
61        }
62    };
63
64    ($base_name:ident, $name:ident(Option<...Default>)) => {
65        // Default for effect field is to accept both color and depth options
66        enum_effectfield!($base_name, $name(color_texture: Option<ColorTexture>, depth_texture: Option<DepthTexture>));
67    };
68
69    ($base_name:ident, $name:ident($($texture:ident: $textureType:ty),+ $(,)?)) => {
70        // Effect field function taking non-optional effects, which have no default
71        #[allow(non_snake_case)]
72        #[inline]
73        pub(crate) fn $name($($texture: $textureType),*) -> Self {
74            Self(
75                Self::$base_name.0
76                $(  | $texture.id())*
77            )
78        }
79    };
80
81    ($base_name:ident, $name:ident(...Default)) => {
82        // Default for effect field is to accept both color and depth options
83        enum_effectfield!($base_name, $name(color_texture: ColorTexture, depth_texture: DepthTexture));
84    };
85}
86
87///
88/// ID Space for geometry shaders
89/// IDs 0x0000 through 0x7FFF are reserved for public use
90///
91#[allow(missing_docs)]
92#[open_enum]
93#[repr(u16)]
94pub enum GeometryId {
95    Screen = 0x8000,
96    Skybox = 0x8001,
97    TerrainPatch = 0x8002,
98    Sprites = 0x8004,
99    WaterPatch = 0x8005,
100    MeshBase = 0x8010,           // To 0x801F
101    ParticleSystemBase = 0x8040, // To 0x807F
102    InstancedMeshBase = 0x8080,  // To 0x80FF
103}
104
105impl GeometryId {
106    enum_bitfield!(MeshBase, Mesh(normal, tangents, uv, color));
107    enum_bitfield!(
108        ParticleSystemBase,
109        ParticleSystem(normal, tangents, uv, color, instance_color, instance_uv)
110    );
111    enum_bitfield!(
112        InstancedMeshBase,
113        InstancedMesh(normal, tangents, uv, color, instance_color, instance_uv)
114    );
115}
116
117///
118/// ID Space for effect and material shaders
119/// IDs 0x0000 through 0x4FFF are reserved for public use
120///
121#[allow(missing_docs)]
122#[open_enum]
123#[repr(u16)]
124pub enum EffectMaterialId {
125    LightingPassEffectBase = 0x5000, // To 0x503F
126    WaterEffectBase = 0x5800,        // To 0x583F
127    CopyEffectBase = 0x6000,         // To 0x603F
128    ScreenEffectBase = 0x6800,       // To 0x683F
129    FogEffectBase = 0x7000,          // To 0x703F
130    FxaaEffectBase = 0x7800,         // To 0x7838 (has holes)
131
132    ColorMaterialBase = 0x8000, // To 0x8001
133    DepthMaterial = 0x8002,
134    PositionMaterial = 0x8003,
135    SkyboxMaterial = 0x8004,
136    UVMaterial = 0x8005,
137    NormalMaterialBase = 0x8006, // To 0x8007
138    IntersectionMaterial = 0x800B,
139    IsosurfaceMaterial = 0x800C,
140    ImpostersMaterial = 0x800D,
141    BrdfMaterial = 0x800E,
142    IrradianceMaterial = 0x800F,
143    ORMMaterialBase = 0x8010,              // To 0x8013
144    PhysicalMaterialBase = 0x8020,         // To 0x803F
145    DeferredPhysicalMaterialBase = 0x8040, // To 0x807F
146    PrefilterMaterial = 0x8080,
147}
148
149impl EffectMaterialId {
150    enum_effectfield!(LightingPassEffectBase, LightingPassEffect(...Default));
151    enum_effectfield!(WaterEffectBase, WaterEffect(...Default));
152    enum_effectfield!(CopyEffectBase, CopyEffect(Option<...Default>));
153    enum_effectfield!(ScreenEffectBase, ScreenEffect(Option<...Default>));
154    enum_effectfield!(FogEffectBase, FogEffect(...Default));
155    enum_effectfield!(FxaaEffectBase, FxaaEffect(color_texture: ColorTexture));
156
157    enum_bitfield!(ColorMaterialBase, ColorMaterial(texture));
158    enum_bitfield!(NormalMaterialBase, NormalMaterial(normal_texture));
159    enum_bitfield!(
160        ORMMaterialBase,
161        ORMMaterial(metallic_roughness_texture, occlusion_texture)
162    );
163    enum_bitfield!(
164        PhysicalMaterialBase,
165        PhysicalMaterial(
166            albedo_texture,
167            metallic_roughness_texture,
168            occlusion_texture,
169            normal_texture,
170            emissive_texture,
171        )
172    );
173    enum_bitfield!(
174        DeferredPhysicalMaterialBase,
175        DeferredPhysicalMaterial(
176            albedo_texture,
177            metallic_roughness_texture,
178            occlusion_texture,
179            normal_texture,
180            emissive_texture,
181            alpha_cutout,
182        )
183    );
184}
185
186///
187/// ID space for lighting shaders
188/// IDs 0x00 through 0x7F are reserved for public use
189///
190#[allow(missing_docs)]
191#[open_enum]
192#[repr(u8)]
193pub enum LightId {
194    AmbientLightBase = 0x80,     // To 0x81
195    DirectionalLightBase = 0x82, // To 0x83
196    PointLight = 0x84,
197    SpotLightBase = 0x86, // To 0x87
198}
199
200impl LightId {
201    enum_bitfield!(AmbientLightBase, AmbientLight(environment));
202    enum_bitfield!(DirectionalLightBase, DirectionalLight(shadow_texture));
203    enum_bitfield!(SpotLightBase, SpotLight(shadow_texture));
204}