use crate::{
core::{
algebra::{Matrix4, Vector2, Vector3},
math::Rect,
sstorage::ImmutableString,
},
renderer::{
framework::{
error::FrameworkError,
framebuffer::{DrawParameters, FrameBuffer},
geometry_buffer::{GeometryBuffer, GeometryBufferKind},
gpu_program::{GpuProgram, UniformLocation},
gpu_texture::GpuTexture,
state::PipelineState,
},
RenderPassStatistics,
},
scene::mesh::surface::SurfaceData,
};
use std::{cell::RefCell, rc::Rc};
struct FxaaShader {
pub program: GpuProgram,
pub wvp_matrix: UniformLocation,
pub screen_texture: UniformLocation,
pub inverse_screen_size: UniformLocation,
}
impl FxaaShader {
pub fn new(state: &mut PipelineState) -> Result<Self, FrameworkError> {
let fragment_source = include_str!("shaders/fxaa_fs.glsl");
let vertex_source = include_str!("shaders/flat_vs.glsl");
let program = GpuProgram::from_source(state, "FXAAShader", vertex_source, fragment_source)?;
Ok(Self {
wvp_matrix: program
.uniform_location(state, &ImmutableString::new("worldViewProjection"))?,
screen_texture: program
.uniform_location(state, &ImmutableString::new("screenTexture"))?,
inverse_screen_size: program
.uniform_location(state, &ImmutableString::new("inverseScreenSize"))?,
program,
})
}
}
pub struct FxaaRenderer {
shader: FxaaShader,
quad: GeometryBuffer,
}
impl FxaaRenderer {
pub fn new(state: &mut PipelineState) -> Result<Self, FrameworkError> {
Ok(Self {
shader: FxaaShader::new(state)?,
quad: GeometryBuffer::from_surface_data(
&SurfaceData::make_unit_xy_quad(),
GeometryBufferKind::StaticDraw,
state,
),
})
}
pub(in crate) fn render(
&self,
state: &mut PipelineState,
viewport: Rect<i32>,
frame_texture: Rc<RefCell<GpuTexture>>,
frame_buffer: &mut FrameBuffer,
) -> RenderPassStatistics {
let mut statistics = RenderPassStatistics::default();
let frame_matrix = Matrix4::new_orthographic(
0.0,
viewport.w() as f32,
viewport.h() as f32,
0.0,
-1.0,
1.0,
) * Matrix4::new_nonuniform_scaling(&Vector3::new(
viewport.w() as f32,
viewport.h() as f32,
0.0,
));
statistics += frame_buffer.draw(
&self.quad,
state,
viewport,
&self.shader.program,
&DrawParameters {
cull_face: None,
color_write: Default::default(),
depth_write: false,
stencil_test: None,
depth_test: false,
blend: None,
stencil_op: Default::default(),
},
|mut program_binding| {
program_binding
.set_matrix4(&self.shader.wvp_matrix, &frame_matrix)
.set_vector2(
&self.shader.inverse_screen_size,
&Vector2::new(1.0 / viewport.w() as f32, 1.0 / viewport.h() as f32),
)
.set_texture(&self.shader.screen_texture, &frame_texture);
},
);
statistics
}
}