khora_core/asset/materials/alpha_mode.rs
1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Defines transparency and blending modes for materials.
16
17/// Specifies how a material handles transparency and alpha blending.
18///
19/// This enum is critical for the rendering system to make intelligent decisions about
20/// render pass ordering and pipeline selection. Different alpha modes have significant
21/// performance implications:
22///
23/// - `Opaque`: Fastest, no transparency calculations
24/// - `Mask`: Fast, no sorting required, uses alpha testing
25/// - `Blend`: Slowest, requires depth sorting for correct rendering
26///
27/// # Examples
28///
29/// ```
30/// use khora_core::asset::AlphaMode;
31///
32/// // Opaque material (default for most objects)
33/// let opaque = AlphaMode::Opaque;
34///
35/// // Alpha masking (e.g., foliage, chain-link fences)
36/// let masked = AlphaMode::Mask(0.5); // Discard pixels with alpha < 0.5
37///
38/// // Full blending (e.g., glass, water)
39/// let blended = AlphaMode::Blend;
40/// ```
41#[derive(
42 Debug,
43 Clone,
44 Copy,
45 PartialEq,
46 Default,
47 serde::Serialize,
48 serde::Deserialize,
49 bincode::Encode,
50 bincode::Decode,
51)]
52pub enum AlphaMode {
53 /// The material is fully opaque with no transparency.
54 ///
55 /// This is the default and most performant mode. Fragments are always written
56 /// to the framebuffer without alpha testing or blending.
57 #[default]
58 Opaque,
59
60 /// The material uses alpha testing to create binary transparency.
61 ///
62 /// Fragments with an alpha value below the specified threshold are discarded.
63 /// This mode is useful for rendering vegetation, chain-link fences, or other
64 /// objects with hard transparency edges. It's significantly faster than
65 /// `Blend` because it doesn't require depth sorting.
66 ///
67 /// The f32 value is the alpha cutoff threshold (typically 0.5).
68 Mask(f32),
69
70 /// The material uses full alpha blending.
71 ///
72 /// This mode produces smooth transparency but requires objects to be rendered
73 /// in back-to-front order for correct results. The RenderAgent may choose
74 /// different rendering strategies based on the number of blend-mode objects
75 /// in the scene to balance quality and performance.
76 Blend,
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_alpha_mode_default() {
85 let default_mode = AlphaMode::default();
86 assert_eq!(default_mode, AlphaMode::Opaque);
87 }
88
89 #[test]
90 fn test_alpha_mode_opaque() {
91 let opaque = AlphaMode::Opaque;
92 assert_eq!(opaque, AlphaMode::Opaque);
93 }
94
95 #[test]
96 fn test_alpha_mode_mask() {
97 let masked = AlphaMode::Mask(0.5);
98 match masked {
99 AlphaMode::Mask(cutoff) => assert_eq!(cutoff, 0.5),
100 _ => panic!("Expected AlphaMode::Mask"),
101 }
102 }
103
104 #[test]
105 fn test_alpha_mode_blend() {
106 let blended = AlphaMode::Blend;
107 assert_eq!(blended, AlphaMode::Blend);
108 }
109
110 #[test]
111 fn test_alpha_mode_equality() {
112 assert_eq!(AlphaMode::Opaque, AlphaMode::Opaque);
113 assert_eq!(AlphaMode::Mask(0.5), AlphaMode::Mask(0.5));
114 assert_eq!(AlphaMode::Blend, AlphaMode::Blend);
115
116 assert_ne!(AlphaMode::Opaque, AlphaMode::Blend);
117 assert_ne!(AlphaMode::Mask(0.5), AlphaMode::Mask(0.6));
118 }
119
120 #[test]
121 fn test_alpha_mode_clone() {
122 let original = AlphaMode::Mask(0.75);
123 let cloned = original;
124 assert_eq!(original, cloned);
125 }
126}