re_renderer/renderer/
mod.rs

1mod compositor;
2mod debug_overlay;
3mod depth_cloud;
4mod generic_skybox;
5mod lines;
6mod mesh_renderer;
7mod point_cloud;
8mod rectangles;
9mod test_triangle;
10mod world_grid;
11
12pub use self::depth_cloud::{DepthCloud, DepthCloudDrawData, DepthCloudRenderer, DepthClouds};
13pub use debug_overlay::{DebugOverlayDrawData, DebugOverlayError, DebugOverlayRenderer};
14pub use generic_skybox::{GenericSkyboxDrawData, GenericSkyboxType};
15pub use lines::{LineBatchInfo, LineDrawData, LineDrawDataError, LineStripFlags};
16pub use mesh_renderer::{GpuMeshInstance, MeshDrawData};
17pub use point_cloud::{
18    PointCloudBatchFlags, PointCloudBatchInfo, PointCloudDrawData, PointCloudDrawDataError,
19};
20pub use rectangles::{
21    ColorMapper, ColormappedTexture, RectangleDrawData, RectangleOptions, ShaderDecoding,
22    TextureAlpha, TextureFilterMag, TextureFilterMin, TexturedRect,
23};
24pub use test_triangle::TestTriangleDrawData;
25pub use world_grid::{WorldGridConfiguration, WorldGridDrawData, WorldGridRenderer};
26
27pub mod gpu_data {
28    pub use super::lines::gpu_data::{LineStripInfo, LineVertex};
29    pub use super::point_cloud::gpu_data::PositionRadius;
30}
31
32pub(crate) use compositor::CompositorDrawData;
33pub(crate) use mesh_renderer::MeshRenderer;
34
35// ------------
36
37use crate::{
38    Drawable, DrawableCollector, QueueableDrawData,
39    context::RenderContext,
40    draw_phases::DrawPhase,
41    include_shader_module,
42    wgpu_resources::{GpuRenderPipelinePoolAccessor, PoolError},
43};
44
45/// [`DrawData`] specific payload that is injected into the otherwise type agnostic [`crate::Drawable`].
46pub type DrawDataDrawablePayload = u32;
47
48/// A single drawable item within a given [`DrawData`].
49///
50/// The general expectation is that there's a rough one to one relationship between
51/// drawables and drawcalls within a single [`DrawPhase`].
52#[derive(Debug, Clone, Copy)]
53pub struct DrawDataDrawable {
54    /// Used for sorting drawables within a [`DrawPhase`].
55    ///
56    /// Low values mean closer, high values mean further away from the camera.
57    /// This is typically simply the squared scene space distance to the observer,
58    /// but may also be a 2D layer index or similar.
59    ///
60    /// Sorting for NaN is considered undefined.
61    pub distance_sort_key: f32,
62
63    /// Key for identifying the drawable within the [`DrawData`] that produced it..
64    ///
65    /// This is effectively an arbitrary payload whose meaning is dependent on the drawable type
66    /// but typically refers to instances or instance ranges within the draw data.
67    pub draw_data_payload: DrawDataDrawablePayload,
68}
69
70impl DrawDataDrawable {
71    #[inline]
72    pub fn from_affine(
73        view_info: &DrawableCollectionViewInfo,
74        world_from_rdf: &glam::Affine3A,
75        draw_data_payload: DrawDataDrawablePayload,
76    ) -> Self {
77        Self::from_world_position(view_info, world_from_rdf.translation, draw_data_payload)
78    }
79
80    #[inline]
81    pub fn from_world_position(
82        view_info: &DrawableCollectionViewInfo,
83        world_position: glam::Vec3A,
84        draw_data_payload: DrawDataDrawablePayload,
85    ) -> Self {
86        Self {
87            distance_sort_key: world_position.distance_squared(view_info.camera_world_position),
88            draw_data_payload,
89        }
90    }
91}
92
93/// Information about the view for which can be taken into account when collecting drawables.
94pub struct DrawableCollectionViewInfo {
95    /// The position of the camera in world space.
96    pub camera_world_position: glam::Vec3A,
97}
98
99/// GPU sided data used by a [`Renderer`] to draw things to the screen.
100///
101/// Each [`DrawData`] produces one or more [`DrawDataDrawable`]s for each view & phase.
102//
103// TODO(andreas): We're currently not re-using draw across several views & frames.
104// Architecturally there's not much preventing this except for `QueueableDrawData` consuming `DrawData` right now.
105pub trait DrawData {
106    type Renderer: Renderer<RendererDrawData = Self> + Send + Sync;
107
108    /// Collects all drawables for all phases of a specific view.
109    ///
110    /// Draw data implementations targeting several draw phases at once may choose to batch differently for each of them.
111    ///
112    /// Note that depending on the draw phase, drawables may be sorted differently or not at all.
113    // TODO(andreas): This might also be the right place to introduce frustum culling by extending the view info.
114    // on the flip side, we already put quite a bit of work into building up the draw data, not all of which is view-independent today (but it should be).
115    fn collect_drawables(
116        &self,
117        view_info: &DrawableCollectionViewInfo,
118        collector: &mut DrawableCollector<'_>,
119    );
120}
121
122#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
123pub enum DrawError {
124    #[error(transparent)]
125    Pool(#[from] PoolError),
126}
127
128/// A draw instruction specifies which drawables of a given [`DrawData`] should be rendered.
129pub struct DrawInstruction<'a, D> {
130    /// The draw data that produced the [`Self::drawables`].
131    pub draw_data: &'a D,
132
133    /// The drawables to render.
134    ///
135    /// It's guaranteed that all drawables originated from a single call to [`DrawData::collect_drawables`]
136    /// of [`Self::draw_data`] but there are no guarantees on ordering.
137    pub drawables: &'a [Drawable],
138}
139
140/// A Renderer encapsulate the knowledge of how to render a certain kind of primitives.
141///
142/// It is an immutable, long-lived datastructure that only holds onto resources that will be needed
143/// for each of its [`Renderer::draw`] invocations.
144/// Any data that might be different over multiple [`Renderer::draw`] invocations is stored in [`DrawData`].
145pub trait Renderer {
146    type RendererDrawData: DrawData + 'static;
147
148    fn create_renderer(ctx: &RenderContext) -> Self;
149
150    /// Called once per phase if there are any drawables for that phase.
151    ///
152    /// For each draw data reference, there's at most one [`DrawInstruction`].
153    fn draw(
154        &self,
155        render_pipelines: &GpuRenderPipelinePoolAccessor<'_>,
156        phase: DrawPhase,
157        pass: &mut wgpu::RenderPass<'_>,
158        draw_instructions: &[DrawInstruction<'_, Self::RendererDrawData>],
159    ) -> Result<(), DrawError>;
160}
161
162/// Extension trait for [`Renderer`] that allows running draw instructions with type erased draw data.
163pub(crate) trait RendererExt: Send + Sync {
164    fn run_draw_instructions(
165        &self,
166        gpu_resources: &GpuRenderPipelinePoolAccessor<'_>,
167        phase: DrawPhase,
168        pass: &mut wgpu::RenderPass<'_>,
169        type_erased_draw_instructions: &[DrawInstruction<'_, QueueableDrawData>],
170    ) -> Result<(), DrawError>;
171
172    /// Name of the renderer, used for debugging & error reporting.
173    fn name(&self) -> &'static str;
174}
175
176impl<R: Renderer + Send + Sync> RendererExt for R {
177    fn run_draw_instructions(
178        &self,
179        gpu_resources: &GpuRenderPipelinePoolAccessor<'_>,
180        phase: DrawPhase,
181        pass: &mut wgpu::RenderPass<'_>,
182        type_erased_draw_instructions: &[DrawInstruction<'_, QueueableDrawData>],
183    ) -> Result<(), DrawError> {
184        let draw_instructions: Vec<DrawInstruction<'_, R::RendererDrawData>> =
185            type_erased_draw_instructions
186                .iter()
187                .map(|type_erased_draw_instruction| DrawInstruction {
188                    draw_data: type_erased_draw_instruction.draw_data.expect_downcast(),
189                    drawables: type_erased_draw_instruction.drawables,
190                })
191                .collect();
192
193        self.draw(gpu_resources, phase, pass, &draw_instructions)
194    }
195
196    fn name(&self) -> &'static str {
197        std::any::type_name::<R>()
198    }
199}
200
201/// Gets or creates a vertex shader module for drawing a screen filling triangle.
202///
203/// The entry point of this shader is `main`.
204pub fn screen_triangle_vertex_shader(
205    ctx: &RenderContext,
206) -> crate::wgpu_resources::GpuShaderModuleHandle {
207    ctx.gpu_resources.shader_modules.get_or_create(
208        ctx,
209        &include_shader_module!("../../shader/screen_triangle.wgsl"),
210    )
211}