use crate::{
core::{math::Rect, ImmutableString},
graphics::{
error::FrameworkError,
framebuffer::{Attachment, DrawCallStatistics, GpuFrameBuffer},
gpu_texture::{GpuTexture, PixelKind},
server::GraphicsServer,
},
renderer::{
cache::{
shader::{binding, property, PropertyGroup, RenderMaterial},
uniform::UniformBufferCache,
},
make_viewport_matrix,
resources::RendererResources,
},
};
pub struct Blur {
framebuffer: GpuFrameBuffer,
width: usize,
height: usize,
}
impl Blur {
pub fn new(
server: &dyn GraphicsServer,
width: usize,
height: usize,
) -> Result<Self, FrameworkError> {
let frame =
server.create_2d_render_target("BlurTexture", PixelKind::R32F, width, height)?;
Ok(Self {
framebuffer: server.create_frame_buffer(None, vec![Attachment::color(frame)])?,
width,
height,
})
}
pub fn result(&self) -> GpuTexture {
self.framebuffer.color_attachments()[0].texture.clone()
}
pub(crate) fn render(
&self,
server: &dyn GraphicsServer,
input: GpuTexture,
uniform_buffer_cache: &mut UniformBufferCache,
renderer_resources: &RendererResources,
) -> Result<DrawCallStatistics, FrameworkError> {
let _debug_scope = server.begin_scope("BoxBlur");
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)]);
let material = RenderMaterial::from([
binding(
"inputTexture",
(&input, &renderer_resources.nearest_clamp_sampler),
),
binding("properties", &properties),
]);
renderer_resources.shaders.box_blur.run_pass(
1,
&ImmutableString::new("Primary"),
&self.framebuffer,
&renderer_resources.quad,
viewport,
&material,
uniform_buffer_cache,
Default::default(),
None,
)
}
}