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(Debug, Clone, Copy, PartialEq, Default)]
42pub enum AlphaMode {
43 /// The material is fully opaque with no transparency.
44 ///
45 /// This is the default and most performant mode. Fragments are always written
46 /// to the framebuffer without alpha testing or blending.
47 #[default]
48 Opaque,
49
50 /// The material uses alpha testing to create binary transparency.
51 ///
52 /// Fragments with an alpha value below the specified threshold are discarded.
53 /// This mode is useful for rendering vegetation, chain-link fences, or other
54 /// objects with hard transparency edges. It's significantly faster than
55 /// `Blend` because it doesn't require depth sorting.
56 ///
57 /// The f32 value is the alpha cutoff threshold (typically 0.5).
58 Mask(f32),
59
60 /// The material uses full alpha blending.
61 ///
62 /// This mode produces smooth transparency but requires objects to be rendered
63 /// in back-to-front order for correct results. The RenderAgent may choose
64 /// different rendering strategies based on the number of blend-mode objects
65 /// in the scene to balance quality and performance.
66 Blend,
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_alpha_mode_default() {
75 let default_mode = AlphaMode::default();
76 assert_eq!(default_mode, AlphaMode::Opaque);
77 }
78
79 #[test]
80 fn test_alpha_mode_opaque() {
81 let opaque = AlphaMode::Opaque;
82 assert_eq!(opaque, AlphaMode::Opaque);
83 }
84
85 #[test]
86 fn test_alpha_mode_mask() {
87 let masked = AlphaMode::Mask(0.5);
88 match masked {
89 AlphaMode::Mask(cutoff) => assert_eq!(cutoff, 0.5),
90 _ => panic!("Expected AlphaMode::Mask"),
91 }
92 }
93
94 #[test]
95 fn test_alpha_mode_blend() {
96 let blended = AlphaMode::Blend;
97 assert_eq!(blended, AlphaMode::Blend);
98 }
99
100 #[test]
101 fn test_alpha_mode_equality() {
102 assert_eq!(AlphaMode::Opaque, AlphaMode::Opaque);
103 assert_eq!(AlphaMode::Mask(0.5), AlphaMode::Mask(0.5));
104 assert_eq!(AlphaMode::Blend, AlphaMode::Blend);
105
106 assert_ne!(AlphaMode::Opaque, AlphaMode::Blend);
107 assert_ne!(AlphaMode::Mask(0.5), AlphaMode::Mask(0.6));
108 }
109
110 #[test]
111 fn test_alpha_mode_clone() {
112 let original = AlphaMode::Mask(0.75);
113 let cloned = original;
114 assert_eq!(original, cloned);
115 }
116}