Skip to main content

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}