use crate::{
core::{
algebra::{Matrix4, Vector3},
color::Color,
math::Rect,
sstorage::ImmutableString,
},
graphics::{
buffer::BufferUsage,
error::FrameworkError,
framebuffer::GpuFrameBuffer,
geometry_buffer::{
AttributeDefinition, AttributeKind, ElementsDescriptor, GpuGeometryBuffer,
GpuGeometryBufferDescriptor, VertexBufferData, VertexBufferDescriptor,
},
server::GraphicsServer,
},
renderer::{
cache::{
shader::{binding, property, PropertyGroup, RenderMaterial},
uniform::UniformBufferCache,
},
resources::RendererResources,
RenderPassStatistics,
},
scene::debug::Line,
};
use bytemuck::{Pod, Zeroable};
#[repr(C)]
#[derive(Copy, Pod, Zeroable, Clone)]
struct Vertex {
position: Vector3<f32>,
color: u32,
}
pub struct DebugRenderer {
geometry: GpuGeometryBuffer,
vertices: Vec<Vertex>,
line_indices: Vec<[u32; 2]>,
}
pub fn draw_rect(rect: &Rect<f32>, lines: &mut Vec<Line>, color: Color) {
for (a, b) in [
(rect.left_top_corner(), rect.right_top_corner()),
(rect.right_top_corner(), rect.right_bottom_corner()),
(rect.right_bottom_corner(), rect.left_bottom_corner()),
(rect.left_bottom_corner(), rect.left_top_corner()),
] {
lines.push(Line {
begin: a.to_homogeneous(),
end: b.to_homogeneous(),
color,
});
}
}
impl DebugRenderer {
pub(crate) fn new(server: &dyn GraphicsServer) -> Result<Self, FrameworkError> {
let desc = GpuGeometryBufferDescriptor {
name: "DebugGeometryBuffer",
elements: ElementsDescriptor::Lines(&[]),
buffers: &[VertexBufferDescriptor {
usage: BufferUsage::DynamicDraw,
attributes: &[
AttributeDefinition {
location: 0,
divisor: 0,
kind: AttributeKind::Float,
component_count: 3,
normalized: false,
},
AttributeDefinition {
location: 1,
kind: AttributeKind::UnsignedByte,
component_count: 4,
normalized: true,
divisor: 0,
},
],
data: VertexBufferData::new::<Vertex>(None),
}],
usage: BufferUsage::DynamicDraw,
};
Ok(Self {
geometry: server.create_geometry_buffer(desc)?,
vertices: Default::default(),
line_indices: Default::default(),
})
}
pub fn set_lines(&mut self, lines: &[Line]) {
self.vertices.clear();
self.line_indices.clear();
let mut i = 0;
for line in lines.iter() {
let color = line.color.into();
self.vertices.push(Vertex {
position: line.begin,
color,
});
self.vertices.push(Vertex {
position: line.end,
color,
});
self.line_indices.push([i, i + 1]);
i += 2;
}
self.geometry.set_buffer_data_of_type(0, &self.vertices);
self.geometry.set_lines(&self.line_indices);
}
pub(crate) fn render(
&mut self,
server: &dyn GraphicsServer,
uniform_buffer_cache: &mut UniformBufferCache,
viewport: Rect<i32>,
framebuffer: &GpuFrameBuffer,
view_projection: Matrix4<f32>,
renderer_resources: &RendererResources,
) -> Result<RenderPassStatistics, FrameworkError> {
let _debug_scope = server.begin_scope("DebugRendering");
let mut statistics = RenderPassStatistics::default();
let properties = PropertyGroup::from([property("worldViewProjection", &view_projection)]);
let material = RenderMaterial::from([binding("properties", &properties)]);
statistics += renderer_resources.shaders.debug.run_pass(
1,
&ImmutableString::new("Primary"),
framebuffer,
&self.geometry,
viewport,
&material,
uniform_buffer_cache,
Default::default(),
None,
)?;
Ok(statistics)
}
}