Skip to main content

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    Wireframe = 0x8006,
101    MeshBase = 0x8010,           // To 0x801F
102    ParticleSystemBase = 0x8040, // To 0x807F
103    InstancedMeshBase = 0x8080,  // To 0x80FF
104}
105
106impl GeometryId {
107    enum_bitfield!(MeshBase, Mesh(normal, tangents, uv, color));
108    enum_bitfield!(
109        ParticleSystemBase,
110        ParticleSystem(normal, tangents, uv, color, instance_color, instance_uv)
111    );
112    enum_bitfield!(
113        InstancedMeshBase,
114        InstancedMesh(normal, tangents, uv, color, instance_color, instance_uv)
115    );
116}
117
118///
119/// ID Space for effect and material shaders
120/// IDs 0x0000 through 0x4FFF are reserved for public use
121///
122#[allow(missing_docs)]
123#[open_enum]
124#[repr(u16)]
125pub enum EffectMaterialId {
126    LightingPassEffectBase = 0x5000, // To 0x503F
127    WaterEffectBase = 0x5800,        // To 0x583F
128    CopyEffectBase = 0x6000,         // To 0x603F
129    ScreenEffectBase = 0x6800,       // To 0x683F
130    FogEffectBase = 0x7000,          // To 0x703F
131    FxaaEffectBase = 0x7800,         // To 0x7838 (has holes)
132
133    ColorMaterialBase = 0x8000, // To 0x8001
134    DepthMaterial = 0x8002,
135    PositionMaterial = 0x8003,
136    SkyboxMaterial = 0x8004,
137    UVMaterial = 0x8005,
138    NormalMaterialBase = 0x8006, // To 0x8007
139    IntersectionMaterial = 0x800B,
140    IsosurfaceMaterial = 0x800C,
141    ImpostersMaterial = 0x800D,
142    BrdfMaterial = 0x800E,
143    IrradianceMaterial = 0x800F,
144    ORMMaterialBase = 0x8010,              // To 0x8013
145    PhysicalMaterialBase = 0x8020,         // To 0x803F
146    DeferredPhysicalMaterialBase = 0x8040, // To 0x807F
147    PrefilterMaterial = 0x8080,
148    WireframeMaterial = 0x8081,
149}
150
151impl EffectMaterialId {
152    enum_effectfield!(LightingPassEffectBase, LightingPassEffect(...Default));
153    enum_effectfield!(WaterEffectBase, WaterEffect(...Default));
154    enum_effectfield!(CopyEffectBase, CopyEffect(Option<...Default>));
155    enum_effectfield!(ScreenEffectBase, ScreenEffect(Option<...Default>));
156    enum_effectfield!(FogEffectBase, FogEffect(...Default));
157    enum_effectfield!(FxaaEffectBase, FxaaEffect(color_texture: ColorTexture));
158
159    enum_bitfield!(ColorMaterialBase, ColorMaterial(texture));
160    enum_bitfield!(NormalMaterialBase, NormalMaterial(normal_texture));
161    enum_bitfield!(
162        ORMMaterialBase,
163        ORMMaterial(metallic_roughness_texture, occlusion_texture)
164    );
165    enum_bitfield!(
166        PhysicalMaterialBase,
167        PhysicalMaterial(
168            albedo_texture,
169            metallic_roughness_texture,
170            occlusion_texture,
171            normal_texture,
172            emissive_texture,
173        )
174    );
175    enum_bitfield!(
176        DeferredPhysicalMaterialBase,
177        DeferredPhysicalMaterial(
178            albedo_texture,
179            metallic_roughness_texture,
180            occlusion_texture,
181            normal_texture,
182            emissive_texture,
183            alpha_cutout,
184        )
185    );
186}
187
188///
189/// ID space for lighting shaders
190/// IDs 0x00 through 0x7F are reserved for public use
191///
192#[allow(missing_docs)]
193#[open_enum]
194#[repr(u8)]
195pub enum LightId {
196    AmbientLightBase = 0x80,     // To 0x81
197    DirectionalLightBase = 0x82, // To 0x83
198    PointLight = 0x84,
199    SpotLightBase = 0x86, // To 0x87
200}
201
202impl LightId {
203    enum_bitfield!(AmbientLightBase, AmbientLight(environment));
204    enum_bitfield!(DirectionalLightBase, DirectionalLight(shadow_texture));
205    enum_bitfield!(SpotLightBase, SpotLight(shadow_texture));
206}