Skip to main content

mabda/
blend.rs

1//! Blend state presets for common rendering modes.
2//!
3//! Use [`BlendPreset`] with [`blend_state`] to get a `wgpu::BlendState`
4//! for render pipeline color targets.
5
6/// Common blend mode presets.
7///
8/// # Examples
9///
10/// ```
11/// use mabda::blend::{BlendPreset, blend_state};
12///
13/// let state = blend_state(BlendPreset::AlphaBlend);
14/// let opaque = blend_state(BlendPreset::Opaque);
15/// ```
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17#[non_exhaustive]
18pub enum BlendPreset {
19    /// No blending — source overwrites destination.
20    Opaque,
21    /// Standard alpha blending: `src * src_alpha + dst * (1 - src_alpha)`.
22    AlphaBlend,
23    /// Premultiplied alpha: `src + dst * (1 - src_alpha)`.
24    /// Use when source colors are pre-multiplied by alpha.
25    PremultipliedAlpha,
26    /// Additive blending: `src + dst`. No alpha modulation.
27    /// Good for glow, particles, light accumulation.
28    Additive,
29    /// Multiply blending: `src * dst`.
30    /// Darkens the destination by the source color.
31    Multiply,
32}
33
34/// Convert a blend preset to a `wgpu::BlendState`.
35#[must_use]
36#[inline]
37pub fn blend_state(preset: BlendPreset) -> wgpu::BlendState {
38    match preset {
39        BlendPreset::Opaque => wgpu::BlendState::REPLACE,
40        BlendPreset::AlphaBlend => wgpu::BlendState::ALPHA_BLENDING,
41        BlendPreset::PremultipliedAlpha => wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
42        BlendPreset::Additive => wgpu::BlendState {
43            color: wgpu::BlendComponent {
44                src_factor: wgpu::BlendFactor::One,
45                dst_factor: wgpu::BlendFactor::One,
46                operation: wgpu::BlendOperation::Add,
47            },
48            alpha: wgpu::BlendComponent {
49                src_factor: wgpu::BlendFactor::One,
50                dst_factor: wgpu::BlendFactor::One,
51                operation: wgpu::BlendOperation::Add,
52            },
53        },
54        BlendPreset::Multiply => wgpu::BlendState {
55            color: wgpu::BlendComponent {
56                src_factor: wgpu::BlendFactor::Dst,
57                dst_factor: wgpu::BlendFactor::Zero,
58                operation: wgpu::BlendOperation::Add,
59            },
60            alpha: wgpu::BlendComponent {
61                src_factor: wgpu::BlendFactor::DstAlpha,
62                dst_factor: wgpu::BlendFactor::Zero,
63                operation: wgpu::BlendOperation::Add,
64            },
65        },
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn blend_preset_variants() {
75        let presets = [
76            BlendPreset::Opaque,
77            BlendPreset::AlphaBlend,
78            BlendPreset::PremultipliedAlpha,
79            BlendPreset::Additive,
80            BlendPreset::Multiply,
81        ];
82        assert_eq!(presets.len(), 5);
83    }
84
85    #[test]
86    fn blend_state_opaque() {
87        let state = blend_state(BlendPreset::Opaque);
88        assert_eq!(state, wgpu::BlendState::REPLACE);
89    }
90
91    #[test]
92    fn blend_state_alpha() {
93        let state = blend_state(BlendPreset::AlphaBlend);
94        assert_eq!(state, wgpu::BlendState::ALPHA_BLENDING);
95    }
96
97    #[test]
98    fn blend_state_premultiplied() {
99        let state = blend_state(BlendPreset::PremultipliedAlpha);
100        assert_eq!(state, wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING);
101    }
102
103    #[test]
104    fn blend_state_additive_symmetry() {
105        let state = blend_state(BlendPreset::Additive);
106        assert_eq!(state.color.src_factor, wgpu::BlendFactor::One);
107        assert_eq!(state.color.dst_factor, wgpu::BlendFactor::One);
108    }
109
110    #[test]
111    fn blend_preset_equality() {
112        assert_eq!(BlendPreset::Opaque, BlendPreset::Opaque);
113        assert_ne!(BlendPreset::Opaque, BlendPreset::Additive);
114    }
115
116    #[test]
117    fn blend_preset_debug() {
118        assert_eq!(format!("{:?}", BlendPreset::Multiply), "Multiply");
119    }
120}