retrofire_core/render/
ctx.rs

1//! Rendering context and parameters.
2
3use core::cell::RefCell;
4use core::cmp::Ordering;
5
6use crate::math::color::{rgba, Color4};
7
8use super::stats::Stats;
9
10/// Context and parameters used by the renderer.
11#[derive(Clone, Debug)]
12pub struct Context {
13    /// The color with which to fill the color buffer to clear it, if any.
14    /// If rendered geometry always fills the entire frame, `color_clear`
15    /// can be set to `None`.
16    pub color_clear: Option<Color4>,
17
18    /// The value with which to fill the depth buffer to clear it, if any.
19    pub depth_clear: Option<f32>,
20
21    /// Whether to cull (discard) faces pointing either away from or towards
22    /// the camera. If all geometry drawn is "solid" meshes without holes,
23    /// backfaces can usually be culled because they are always occluded by
24    /// frontfaces and drawing them would be useless.
25    pub face_cull: Option<FaceCull>,
26
27    /// Whether to sort visible faces by their depth. This is important when
28    /// rendering overlapping transparent faces, which *have* to be drawn
29    /// back-to-front to get correct results. On the other hand, rendering
30    /// nontransparent geometry in front-to-back order can improve performance
31    /// by reducing overdraw.
32    pub depth_sort: Option<DepthSort>,
33
34    /// Whether to do depth testing and which predicate to use. If set to
35    /// `Some(Ordering::Less)`, a fragment passes the depth test *iff*
36    /// `new_z < old_z` (the default). If set to `None`, depth test is not
37    /// performed. This setting has no effect if the render target does not
38    /// support z-buffering.
39    pub depth_test: Option<Ordering>,
40
41    /// Whether to write color values. If `false`, other fragment processing
42    /// is done but there is no color output. This setting has no effect if
43    /// the render target does not support color writes.
44    pub color_write: bool,
45
46    /// Whether to write depth values. If `false`, other fragment processing
47    /// is done but there is no depth output. This setting has no effect if
48    /// the render target does not support depth writes.
49    pub depth_write: bool,
50
51    /// Collecting rendering statistics.
52    pub stats: RefCell<Stats>,
53}
54
55/// Whether to sort faces front to back or back to front.
56#[derive(Copy, Clone, Debug, Eq, PartialEq)]
57pub enum DepthSort {
58    FrontToBack,
59    BackToFront,
60}
61
62/// Whether to cull frontfaces or backfaces.
63#[derive(Copy, Clone, Debug, Eq, PartialEq)]
64pub enum FaceCull {
65    Front,
66    Back,
67}
68
69impl Context {
70    /// Compares the reciprocal depth value `new` to `curr` and returns
71    /// whether `new` passes the depth test specified by `self.depth_test`.
72    /// If `self.depth_test` is `None`, always returns `true`.
73    #[inline]
74    pub fn depth_test(&self, new: f32, curr: f32) -> bool {
75        // Reverse comparison because we're comparing reciprocals
76        self.depth_test
77            .map_or(true, |ord| curr.partial_cmp(&new) == Some(ord))
78    }
79}
80
81impl Default for Context {
82    fn default() -> Self {
83        Self {
84            color_clear: Some(rgba(0, 0, 0, 0xFF)),
85            depth_clear: Some(f32::INFINITY),
86            face_cull: Some(FaceCull::Back),
87            depth_sort: None,
88            color_write: true,
89            depth_test: Some(Ordering::Less),
90            depth_write: true,
91            stats: Default::default(),
92        }
93    }
94}