use glium::{IndexBuffer, Surface, Texture2d, uniform, VertexBuffer};
use glium::framebuffer::SimpleFrameBuffer;
use glium::glutin::surface::WindowSurface;
use glium::texture::DepthTexture2d;
use crate::geometry::Vertex;
use crate::postprocessing::PostProcessingEffect;
use crate::{AppState, postprocessing, resources, shader};
pub struct Bloom {
pub threshold: f32,
pub iterations: i32,
program_extract: glium::Program,
program_blur: glium::Program,
program_combine: glium::Program,
program_copy: glium::Program,
}
impl Bloom {
pub fn new(display: &glium::Display<WindowSurface>, threshold: f32, iterations: i32) -> Self {
let extract_shader = shader::Shader::from_strings(resources::post_processing_vertex(), resources::post_processing_bloom_extract_fragment(), None);
let blur_shader = shader::Shader::from_strings(resources::post_processing_vertex(), resources::post_processing_bloom_blur_fragment(), None);
let combine_shader = shader::Shader::from_strings(resources::post_processing_vertex(), resources::post_processing_bloom_combine_fragment(), None);
let program_extract = glium::Program::from_source(display, &extract_shader.get_vertex_shader(), &extract_shader.get_fragment_shader(), None).expect("Failed to compile shader program");
let program_blur = glium::Program::from_source(display, &blur_shader.get_vertex_shader(), &blur_shader.get_fragment_shader(), None).expect("Failed to compile shader program");
let program_combine = glium::Program::from_source(display, &combine_shader.get_vertex_shader(), &combine_shader.get_fragment_shader(), None).expect("Failed to compile shader program");
let program_copy = postprocessing::get_screen_program(&display);
Self {
program_extract,
program_blur,
program_combine,
program_copy,
threshold,
iterations,
}
}
}
impl PostProcessingEffect for Bloom {
fn render(&self, app_state: &AppState, vertex_buffer: &VertexBuffer<Vertex>, index_buffer: &IndexBuffer<u32>, target: &mut SimpleFrameBuffer, source: &Texture2d, _depth_texture: &DepthTexture2d, buffer_textures: &Vec<Texture2d>) {
let mut work_framebuffer_1 = SimpleFrameBuffer::new(app_state.display.as_ref().unwrap(), &buffer_textures[0]).unwrap();
let mut work_framebuffer_2 = SimpleFrameBuffer::new(app_state.display.as_ref().unwrap(), &buffer_textures[1]).unwrap();
work_framebuffer_1.clear_color(0.0, 0.0, 0.0, 0.0);
work_framebuffer_2.clear_color(0.0, 0.0, 0.0, 0.0);
let uniforms = uniform! {
scene: source.sampled()
.wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
.minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
.magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
};
work_framebuffer_1.draw(vertex_buffer, index_buffer, &self.program_copy, &uniforms, &Default::default()).unwrap();
work_framebuffer_2.draw(vertex_buffer, index_buffer, &self.program_copy, &uniforms, &Default::default()).unwrap();
let uniforms = uniform! {
scene: source.sampled()
.wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
.minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
.magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
threshold: self.threshold,
};
work_framebuffer_1.draw(vertex_buffer, index_buffer, &self.program_extract, &uniforms, &Default::default()).unwrap();
let uniforms = uniform! {
scene: buffer_textures[0].sampled()
.wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
.minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
.magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
horizontal: true,
iterations: self.iterations,
};
work_framebuffer_2.draw(vertex_buffer, index_buffer, &self.program_blur, &uniforms, &Default::default()).unwrap();
work_framebuffer_1.clear_color(0.0, 0.0, 0.0, 0.0);
let uniforms = uniform! {
scene: buffer_textures[1].sampled()
.wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
.minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
.magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
horizontal: false,
iterations: self.iterations,
};
work_framebuffer_1.draw(vertex_buffer, index_buffer, &self.program_blur, &uniforms, &Default::default()).unwrap();
let uniforms = uniform! {
scene: source.sampled()
.wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
.minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
.magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
bloomBlur: buffer_textures[0].sampled()
.wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
.minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
.magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
};
target.draw(vertex_buffer, index_buffer, &self.program_combine, &uniforms, &Default::default()).unwrap();
}
}