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}