use crate::renderer::QualitySettings;
use crate::{
core::{math::Rect, ImmutableString},
graphics::{
error::FrameworkError,
framebuffer::{Attachment, GpuFrameBuffer},
gpu_texture::{GpuTexture, PixelKind},
server::GraphicsServer,
},
renderer::{
bloom::blur::GaussianBlur,
cache::{
shader::{binding, property, PropertyGroup, RenderMaterial},
uniform::UniformBufferCache,
},
make_viewport_matrix,
resources::RendererResources,
RenderPassStatistics,
},
};
mod blur;
pub struct BloomRenderer {
framebuffer: GpuFrameBuffer,
blur: GaussianBlur,
width: usize,
height: usize,
}
impl BloomRenderer {
pub fn new(
server: &dyn GraphicsServer,
width: usize,
height: usize,
) -> Result<Self, FrameworkError> {
Ok(Self {
blur: GaussianBlur::new(server, width, height, PixelKind::RGB10A2)?,
framebuffer: server.create_frame_buffer(
None,
vec![Attachment::color(server.create_2d_render_target(
"Bloom",
PixelKind::RGB10A2,
width,
height,
)?)],
)?,
width,
height,
})
}
fn glow_texture(&self) -> &GpuTexture {
&self.framebuffer.color_attachments()[0].texture
}
pub fn result(&self) -> &GpuTexture {
self.blur.result()
}
pub(crate) fn render(
&self,
server: &dyn GraphicsServer,
hdr_scene_frame: &GpuTexture,
uniform_buffer_cache: &mut UniformBufferCache,
renderer_resources: &RendererResources,
settings: &QualitySettings,
) -> Result<RenderPassStatistics, FrameworkError> {
let _debug_scope = server.begin_scope("Bloom");
let mut stats = RenderPassStatistics::default();
let viewport = Rect::new(0, 0, self.width as i32, self.height as i32);
let wvp = make_viewport_matrix(viewport);
let properties = PropertyGroup::from([
property("worldViewProjection", &wvp),
property("threshold", &settings.hdr_settings.bloom_settings.threshold),
]);
let material = RenderMaterial::from([
binding(
"hdrSampler",
(hdr_scene_frame, &renderer_resources.nearest_clamp_sampler),
),
binding("properties", &properties),
]);
stats += renderer_resources.shaders.bloom.run_pass(
1,
&ImmutableString::new("Primary"),
&self.framebuffer,
&renderer_resources.quad,
viewport,
&material,
uniform_buffer_cache,
Default::default(),
None,
)?;
stats += self.blur.render(
server,
&renderer_resources.quad,
self.glow_texture(),
uniform_buffer_cache,
renderer_resources,
)?;
Ok(stats)
}
}