enigma_3d/postprocessing/
bloom.rs1use glium::{IndexBuffer, Surface, Texture2d, uniform, VertexBuffer};
2use glium::framebuffer::SimpleFrameBuffer;
3use glium::glutin::surface::WindowSurface;
4use glium::texture::DepthTexture2d;
5use crate::geometry::Vertex;
6use crate::postprocessing::PostProcessingEffect;
7use crate::{AppState, postprocessing, resources, shader};
8
9pub struct Bloom {
10 pub threshold: f32,
11 pub iterations: i32,
12 program_extract: glium::Program,
13 program_blur: glium::Program,
14 program_combine: glium::Program,
15 program_copy: glium::Program,
16}
17
18impl Bloom {
19 pub fn new(display: &glium::Display<WindowSurface>, threshold: f32, iterations: i32) -> Self {
20 let extract_shader = shader::Shader::from_strings(resources::post_processing_vertex(), resources::post_processing_bloom_extract_fragment(), None);
21 let blur_shader = shader::Shader::from_strings(resources::post_processing_vertex(), resources::post_processing_bloom_blur_fragment(), None);
22 let combine_shader = shader::Shader::from_strings(resources::post_processing_vertex(), resources::post_processing_bloom_combine_fragment(), None);
23 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");
24 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");
25 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");
26 let program_copy = postprocessing::get_screen_program(&display);
27
28 Self {
29 program_extract,
30 program_blur,
31 program_combine,
32 program_copy,
33 threshold,
34 iterations,
35 }
36 }
37}
38
39impl PostProcessingEffect for Bloom {
40 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>) {
41 let mut work_framebuffer_1 = SimpleFrameBuffer::new(app_state.display.as_ref().unwrap(), &buffer_textures[0]).unwrap();
43 let mut work_framebuffer_2 = SimpleFrameBuffer::new(app_state.display.as_ref().unwrap(), &buffer_textures[1]).unwrap();
44 work_framebuffer_1.clear_color(0.0, 0.0, 0.0, 0.0);
45 work_framebuffer_2.clear_color(0.0, 0.0, 0.0, 0.0);
46
47 let uniforms = uniform! {
49 scene: source.sampled()
50 .wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
51 .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
52 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
53 };
54 work_framebuffer_1.draw(vertex_buffer, index_buffer, &self.program_copy, &uniforms, &Default::default()).unwrap();
55 work_framebuffer_2.draw(vertex_buffer, index_buffer, &self.program_copy, &uniforms, &Default::default()).unwrap();
56
57 let uniforms = uniform! {
59 scene: source.sampled()
60 .wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
61 .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
62 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
63 threshold: self.threshold,
64 };
65 work_framebuffer_1.draw(vertex_buffer, index_buffer, &self.program_extract, &uniforms, &Default::default()).unwrap();
66
67 let uniforms = uniform! {
69 scene: buffer_textures[0].sampled()
70 .wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
71 .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
72 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
73 horizontal: true,
74 iterations: self.iterations,
75 };
76 work_framebuffer_2.draw(vertex_buffer, index_buffer, &self.program_blur, &uniforms, &Default::default()).unwrap();
77 work_framebuffer_1.clear_color(0.0, 0.0, 0.0, 0.0);
78
79 let uniforms = uniform! {
80 scene: buffer_textures[1].sampled()
81 .wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
82 .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
83 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
84 horizontal: false,
85 iterations: self.iterations,
86 };
87 work_framebuffer_1.draw(vertex_buffer, index_buffer, &self.program_blur, &uniforms, &Default::default()).unwrap();
88
89 let uniforms = uniform! {
91 scene: source.sampled()
92 .wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
93 .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
94 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
95 bloomBlur: buffer_textures[0].sampled()
96 .wrap_function(glium::uniforms::SamplerWrapFunction::Clamp)
97 .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear)
98 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear),
99 };
100 target.draw(vertex_buffer, index_buffer, &self.program_combine, &uniforms, &Default::default()).unwrap();
101 }
102}