retrofire_core/render/
ctx.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Rendering context and parameters.

use core::cell::RefCell;
use core::cmp::Ordering;

use crate::math::color::{rgba, Color4};

use super::stats::Stats;

/// Context and parameters used by the renderer.
#[derive(Clone, Debug)]
pub struct Context {
    /// The color with which to fill the color buffer to clear it, if any.
    /// If rendered geometry always fills the entire frame, `color_clear`
    /// can be set to `None`.
    pub color_clear: Option<Color4>,

    /// The value with which to fill the depth buffer to clear it, if any.
    pub depth_clear: Option<f32>,

    /// Whether to cull (discard) faces pointing either away from or towards
    /// the camera. If all geometry drawn is "solid" meshes without holes,
    /// backfaces can usually be culled because they are always occluded by
    /// frontfaces and drawing them would be useless.
    pub face_cull: Option<FaceCull>,

    /// Whether to sort visible faces by their depth. This is important when
    /// rendering overlapping transparent faces, which *have* to be drawn
    /// back-to-front to get correct results. On the other hand, rendering
    /// nontransparent geometry in front-to-back order can improve performance
    /// by reducing overdraw.
    pub depth_sort: Option<DepthSort>,

    /// Whether to do depth testing and which predicate to use. If set to
    /// `Some(Ordering::Less)`, a fragment passes the depth test *iff*
    /// `new_z < old_z` (the default). If set to `None`, depth test is not
    /// performed. This setting has no effect if the render target does not
    /// support z-buffering.
    pub depth_test: Option<Ordering>,

    /// Whether to write color values. If `false`, other fragment processing
    /// is done but there is no color output. This setting has no effect if
    /// the render target does not support color writes.
    pub color_write: bool,

    /// Whether to write depth values. If `false`, other fragment processing
    /// is done but there is no depth output. This setting has no effect if
    /// the render target does not support depth writes.
    pub depth_write: bool,

    /// Collecting rendering statistics.
    pub stats: RefCell<Stats>,
}

/// Whether to sort faces front to back or back to front.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum DepthSort {
    FrontToBack,
    BackToFront,
}

/// Whether to cull frontfaces or backfaces.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum FaceCull {
    Front,
    Back,
}

impl Context {
    /// Compares the reciprocal depth value `new` to `curr` and returns
    /// whether `new` passes the depth test specified by `self.depth_test`.
    /// If `self.depth_test` is `None`, always returns `true`.
    #[inline]
    pub fn depth_test(&self, new: f32, curr: f32) -> bool {
        // Reverse comparison because we're comparing reciprocals
        self.depth_test
            .map_or(true, |ord| curr.partial_cmp(&new) == Some(ord))
    }
}

impl Default for Context {
    fn default() -> Self {
        Self {
            color_clear: Some(rgba(0, 0, 0, 0xFF)),
            depth_clear: Some(f32::INFINITY),
            face_cull: Some(FaceCull::Back),
            depth_sort: None,
            color_write: true,
            depth_test: Some(Ordering::Less),
            depth_write: true,
            stats: Default::default(),
        }
    }
}