mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add post-process pipeline
Former-commit-id: aed1fff25f7fd95fe040b0877011cbe57e77eba3
This commit is contained in:
30
voxygen/shaders/postprocess.frag
Normal file
30
voxygen/shaders/postprocess.frag
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
uniform sampler2D src_color;
|
||||||
|
|
||||||
|
in vec2 f_pos;
|
||||||
|
|
||||||
|
layout (std140)
|
||||||
|
uniform u_locals {
|
||||||
|
vec4 nul;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (std140)
|
||||||
|
uniform u_globals {
|
||||||
|
mat4 view_mat;
|
||||||
|
mat4 proj_mat;
|
||||||
|
vec4 cam_pos;
|
||||||
|
vec4 focus_pos;
|
||||||
|
vec4 view_distance;
|
||||||
|
vec4 time_of_day;
|
||||||
|
vec4 tick;
|
||||||
|
};
|
||||||
|
|
||||||
|
out vec4 tgt_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Uncomment to invert colors
|
||||||
|
//tgt_color = vec4(vec3(1.0, 1.0, 1.0) - texture2D(src_color, (f_pos + 1.0) / 2.0).xyz, 1.0);
|
||||||
|
tgt_color = texture2D(src_color, (f_pos + 1.0) / 2.0);
|
||||||
|
|
||||||
|
}
|
27
voxygen/shaders/postprocess.vert
Normal file
27
voxygen/shaders/postprocess.vert
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec2 v_pos;
|
||||||
|
|
||||||
|
layout (std140)
|
||||||
|
uniform u_locals {
|
||||||
|
vec4 nul;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (std140)
|
||||||
|
uniform u_globals {
|
||||||
|
mat4 view_mat;
|
||||||
|
mat4 proj_mat;
|
||||||
|
vec4 cam_pos;
|
||||||
|
vec4 focus_pos;
|
||||||
|
vec4 view_distance;
|
||||||
|
vec4 time_of_day;
|
||||||
|
vec4 tick;
|
||||||
|
};
|
||||||
|
|
||||||
|
out vec2 f_pos;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
f_pos = v_pos;
|
||||||
|
|
||||||
|
gl_Position = vec4(v_pos, 0.0, 1.0);
|
||||||
|
}
|
@ -13,6 +13,9 @@ pub use self::{
|
|||||||
model::Model,
|
model::Model,
|
||||||
pipelines::{
|
pipelines::{
|
||||||
figure::{BoneData as FigureBoneData, FigurePipeline, Locals as FigureLocals},
|
figure::{BoneData as FigureBoneData, FigurePipeline, Locals as FigureLocals},
|
||||||
|
postprocess::{
|
||||||
|
create_mesh as create_pp_mesh, Locals as PostProcessLocals, PostProcessPipeline,
|
||||||
|
},
|
||||||
skybox::{create_mesh as create_skybox_mesh, Locals as SkyboxLocals, SkyboxPipeline},
|
skybox::{create_mesh as create_skybox_mesh, Locals as SkyboxLocals, SkyboxPipeline},
|
||||||
terrain::{Locals as TerrainLocals, TerrainPipeline},
|
terrain::{Locals as TerrainLocals, TerrainPipeline},
|
||||||
ui::{
|
ui::{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
pub mod figure;
|
pub mod figure;
|
||||||
|
pub mod postprocess;
|
||||||
pub mod skybox;
|
pub mod skybox;
|
||||||
pub mod terrain;
|
pub mod terrain;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
71
voxygen/src/render/pipelines/postprocess.rs
Normal file
71
voxygen/src/render/pipelines/postprocess.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Library
|
||||||
|
use gfx::{
|
||||||
|
self,
|
||||||
|
gfx_constant_struct_meta,
|
||||||
|
// Macros
|
||||||
|
gfx_defines,
|
||||||
|
gfx_impl_struct_meta,
|
||||||
|
gfx_pipeline,
|
||||||
|
gfx_pipeline_inner,
|
||||||
|
gfx_vertex_struct_meta,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Local
|
||||||
|
use super::{
|
||||||
|
super::{Mesh, Pipeline, TgtColorFmt, TgtDepthFmt, Tri},
|
||||||
|
Globals,
|
||||||
|
};
|
||||||
|
|
||||||
|
gfx_defines! {
|
||||||
|
vertex Vertex {
|
||||||
|
pos: [f32; 2] = "v_pos",
|
||||||
|
}
|
||||||
|
|
||||||
|
constant Locals {
|
||||||
|
nul: [f32; 4] = "nul",
|
||||||
|
}
|
||||||
|
|
||||||
|
pipeline pipe {
|
||||||
|
vbuf: gfx::VertexBuffer<Vertex> = (),
|
||||||
|
|
||||||
|
locals: gfx::ConstantBuffer<Locals> = "u_locals",
|
||||||
|
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||||
|
|
||||||
|
src_sampler: gfx::TextureSampler<<TgtColorFmt as gfx::format::Formatted>::View> = "src_color",
|
||||||
|
|
||||||
|
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
|
||||||
|
tgt_depth: gfx::DepthTarget<TgtDepthFmt> = gfx::preset::depth::PASS_TEST,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Locals {
|
||||||
|
pub fn default() -> Self {
|
||||||
|
Self { nul: [0.0; 4] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PostProcessPipeline;
|
||||||
|
|
||||||
|
impl Pipeline for PostProcessPipeline {
|
||||||
|
type Vertex = Vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_mesh() -> Mesh<PostProcessPipeline> {
|
||||||
|
let mut mesh = Mesh::new();
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
mesh.push_tri(Tri::new(
|
||||||
|
Vertex { pos: [ 1.0, -1.0] },
|
||||||
|
Vertex { pos: [-1.0, 1.0] },
|
||||||
|
Vertex { pos: [-1.0, -1.0] },
|
||||||
|
));
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
mesh.push_tri(Tri::new(
|
||||||
|
Vertex { pos: [1.0, -1.0] },
|
||||||
|
Vertex { pos: [1.0, 1.0] },
|
||||||
|
Vertex { pos: [-1.0, 1.0] },
|
||||||
|
));
|
||||||
|
|
||||||
|
mesh
|
||||||
|
}
|
@ -3,13 +3,14 @@ use super::{
|
|||||||
gfx_backend,
|
gfx_backend,
|
||||||
mesh::Mesh,
|
mesh::Mesh,
|
||||||
model::Model,
|
model::Model,
|
||||||
pipelines::{figure, skybox, terrain, ui, Globals},
|
pipelines::{figure, postprocess, skybox, terrain, ui, Globals},
|
||||||
texture::Texture,
|
texture::Texture,
|
||||||
Pipeline, RenderError,
|
Pipeline, RenderError,
|
||||||
};
|
};
|
||||||
use gfx::{
|
use gfx::{
|
||||||
self,
|
self,
|
||||||
traits::{Device, FactoryExt},
|
handle::Sampler,
|
||||||
|
traits::{Device, Factory, FactoryExt},
|
||||||
};
|
};
|
||||||
use image;
|
use image;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -24,6 +25,12 @@ pub type TgtColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, Tg
|
|||||||
/// A handle to a window depth target.
|
/// A handle to a window depth target.
|
||||||
pub type TgtDepthView = gfx::handle::DepthStencilView<gfx_backend::Resources, TgtDepthFmt>;
|
pub type TgtDepthView = gfx::handle::DepthStencilView<gfx_backend::Resources, TgtDepthFmt>;
|
||||||
|
|
||||||
|
/// A handle to a render color target as a resource.
|
||||||
|
pub type TgtColorRes = gfx::handle::ShaderResourceView<
|
||||||
|
gfx_backend::Resources,
|
||||||
|
<TgtColorFmt as gfx::format::Formatted>::View,
|
||||||
|
>;
|
||||||
|
|
||||||
/// A type that encapsulates rendering state. `Renderer` is central to Voxygen's rendering
|
/// A type that encapsulates rendering state. `Renderer` is central to Voxygen's rendering
|
||||||
/// subsystem and contains any state necessary to interact with the GPU, along with pipeline state
|
/// subsystem and contains any state necessary to interact with the GPU, along with pipeline state
|
||||||
/// objects (PSOs) needed to renderer different kinds of models to the screen.
|
/// objects (PSOs) needed to renderer different kinds of models to the screen.
|
||||||
@ -32,13 +39,21 @@ pub struct Renderer {
|
|||||||
encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||||
factory: gfx_backend::Factory,
|
factory: gfx_backend::Factory,
|
||||||
|
|
||||||
|
win_color_view: TgtColorView,
|
||||||
|
win_depth_view: TgtDepthView,
|
||||||
|
|
||||||
tgt_color_view: TgtColorView,
|
tgt_color_view: TgtColorView,
|
||||||
tgt_depth_view: TgtDepthView,
|
tgt_depth_view: TgtDepthView,
|
||||||
|
|
||||||
|
tgt_color_res: TgtColorRes,
|
||||||
|
|
||||||
|
sampler: Sampler<gfx_backend::Resources>,
|
||||||
|
|
||||||
skybox_pipeline: GfxPipeline<skybox::pipe::Init<'static>>,
|
skybox_pipeline: GfxPipeline<skybox::pipe::Init<'static>>,
|
||||||
figure_pipeline: GfxPipeline<figure::pipe::Init<'static>>,
|
figure_pipeline: GfxPipeline<figure::pipe::Init<'static>>,
|
||||||
terrain_pipeline: GfxPipeline<terrain::pipe::Init<'static>>,
|
terrain_pipeline: GfxPipeline<terrain::pipe::Init<'static>>,
|
||||||
ui_pipeline: GfxPipeline<ui::pipe::Init<'static>>,
|
ui_pipeline: GfxPipeline<ui::pipe::Init<'static>>,
|
||||||
|
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
@ -47,8 +62,8 @@ impl Renderer {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
device: gfx_backend::Device,
|
device: gfx_backend::Device,
|
||||||
mut factory: gfx_backend::Factory,
|
mut factory: gfx_backend::Factory,
|
||||||
tgt_color_view: TgtColorView,
|
win_color_view: TgtColorView,
|
||||||
tgt_depth_view: TgtDepthView,
|
win_depth_view: TgtDepthView,
|
||||||
) -> Result<Self, RenderError> {
|
) -> Result<Self, RenderError> {
|
||||||
// Construct a pipeline for rendering skyboxes
|
// Construct a pipeline for rendering skyboxes
|
||||||
let skybox_pipeline = create_pipeline(
|
let skybox_pipeline = create_pipeline(
|
||||||
@ -82,29 +97,86 @@ impl Renderer {
|
|||||||
include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/ui.frag")),
|
include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/ui.frag")),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// Construct a pipeline for rendering our post-processing
|
||||||
|
let postprocess_pipeline = create_pipeline(
|
||||||
|
&mut factory,
|
||||||
|
postprocess::pipe::new(),
|
||||||
|
include_bytes!(concat!(
|
||||||
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
|
"/shaders/postprocess.vert"
|
||||||
|
)),
|
||||||
|
include_bytes!(concat!(
|
||||||
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
|
"/shaders/postprocess.frag"
|
||||||
|
)),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let dims = win_color_view.get_dimensions();
|
||||||
|
let d_dims = win_depth_view.get_dimensions();
|
||||||
|
|
||||||
|
let (_, tgt_color_res, tgt_color_view) = factory
|
||||||
|
.create_render_target::<TgtColorFmt>(dims.0, dims.1)
|
||||||
|
.map_err(RenderError::CombinedError)?;
|
||||||
|
let (_, _, tgt_depth_view) = factory
|
||||||
|
.create_depth_stencil(d_dims.0, d_dims.1)
|
||||||
|
.map_err(RenderError::CombinedError)?;
|
||||||
|
|
||||||
|
let sampler = factory.create_sampler_linear();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
device,
|
device,
|
||||||
encoder: factory.create_command_buffer().into(),
|
encoder: factory.create_command_buffer().into(),
|
||||||
factory,
|
factory,
|
||||||
|
|
||||||
|
win_color_view,
|
||||||
|
win_depth_view,
|
||||||
|
|
||||||
tgt_color_view,
|
tgt_color_view,
|
||||||
tgt_depth_view,
|
tgt_depth_view,
|
||||||
|
|
||||||
|
tgt_color_res,
|
||||||
|
sampler,
|
||||||
|
|
||||||
skybox_pipeline,
|
skybox_pipeline,
|
||||||
figure_pipeline,
|
figure_pipeline,
|
||||||
terrain_pipeline,
|
terrain_pipeline,
|
||||||
ui_pipeline,
|
ui_pipeline,
|
||||||
|
postprocess_pipeline,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get references to the internal render target views that get displayed directly by the window.
|
/// Get references to the internal render target views that get displayed directly by the window.
|
||||||
pub fn target_views(&self) -> (&TgtColorView, &TgtDepthView) {
|
pub fn target_views(&self) -> (&TgtColorView, &TgtDepthView) {
|
||||||
(&self.tgt_color_view, &self.tgt_depth_view)
|
(&self.win_color_view, &self.win_depth_view)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get mutable references to the internal render target views that get displayed directly by the window.
|
/// Get mutable references to the internal render target views that get displayed directly by the window.
|
||||||
pub fn target_views_mut(&mut self) -> (&mut TgtColorView, &mut TgtDepthView) {
|
pub fn target_views_mut(&mut self) -> (&mut TgtColorView, &mut TgtDepthView) {
|
||||||
(&mut self.tgt_color_view, &mut self.tgt_depth_view)
|
(&mut self.win_color_view, &mut self.win_depth_view)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_resize(&mut self) -> Result<(), RenderError> {
|
||||||
|
let dims = self.win_color_view.get_dimensions();
|
||||||
|
let d_dims = self.win_depth_view.get_dimensions();
|
||||||
|
|
||||||
|
if dims.0 > 0 && dims.1 > 0 {
|
||||||
|
let (_, tgt_color_res, tgt_color_view) = self
|
||||||
|
.factory
|
||||||
|
.create_render_target::<TgtColorFmt>(dims.0, dims.1)
|
||||||
|
.map_err(RenderError::CombinedError)?;
|
||||||
|
self.tgt_color_res = tgt_color_res;
|
||||||
|
self.tgt_color_view = tgt_color_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
if d_dims.0 > 0 && d_dims.1 > 0 {
|
||||||
|
let (_, _, tgt_depth_view) = self
|
||||||
|
.factory
|
||||||
|
.create_depth_stencil(d_dims.0, d_dims.1)
|
||||||
|
.map_err(RenderError::CombinedError)?;
|
||||||
|
self.tgt_depth_view = tgt_depth_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the resolution of the render target.
|
/// Get the resolution of the render target.
|
||||||
@ -120,6 +192,8 @@ impl Renderer {
|
|||||||
pub fn clear(&mut self, col: Rgba<f32>) {
|
pub fn clear(&mut self, col: Rgba<f32>) {
|
||||||
self.encoder.clear(&self.tgt_color_view, col.into_array());
|
self.encoder.clear(&self.tgt_color_view, col.into_array());
|
||||||
self.encoder.clear_depth(&self.tgt_depth_view, 1.0);
|
self.encoder.clear_depth(&self.tgt_depth_view, 1.0);
|
||||||
|
self.encoder.clear(&self.win_color_view, col.into_array());
|
||||||
|
self.encoder.clear_depth(&self.win_depth_view, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform all queued draw calls for this frame and clean up discarded items.
|
/// Perform all queued draw calls for this frame and clean up discarded items.
|
||||||
@ -261,11 +335,31 @@ impl Renderer {
|
|||||||
h: max.y - min.y,
|
h: max.y - min.y,
|
||||||
},
|
},
|
||||||
tex: (tex.srv.clone(), tex.sampler.clone()),
|
tex: (tex.srv.clone(), tex.sampler.clone()),
|
||||||
tgt_color: self.tgt_color_view.clone(),
|
tgt_color: self.win_color_view.clone(),
|
||||||
tgt_depth: self.tgt_depth_view.clone(),
|
tgt_depth: self.win_depth_view.clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render_post_process(
|
||||||
|
&mut self,
|
||||||
|
model: &Model<postprocess::PostProcessPipeline>,
|
||||||
|
globals: &Consts<Globals>,
|
||||||
|
locals: &Consts<postprocess::Locals>,
|
||||||
|
) {
|
||||||
|
self.encoder.draw(
|
||||||
|
&model.slice,
|
||||||
|
&self.postprocess_pipeline.pso,
|
||||||
|
&postprocess::pipe::Data {
|
||||||
|
vbuf: model.vbuf.clone(),
|
||||||
|
locals: locals.buf.clone(),
|
||||||
|
globals: globals.buf.clone(),
|
||||||
|
src_sampler: (self.tgt_color_res.clone(), self.sampler.clone()),
|
||||||
|
tgt_color: self.win_color_view.clone(),
|
||||||
|
tgt_depth: self.win_depth_view.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GfxPipeline<P: gfx::pso::PipelineInit> {
|
struct GfxPipeline<P: gfx::pso::PipelineInit> {
|
||||||
|
@ -10,8 +10,8 @@ use crate::{
|
|||||||
},
|
},
|
||||||
mesh::Meshable,
|
mesh::Meshable,
|
||||||
render::{
|
render::{
|
||||||
create_skybox_mesh, Consts, FigureLocals, Globals, Model, Renderer, SkyboxLocals,
|
create_pp_mesh, create_skybox_mesh, Consts, FigureLocals, Globals, Model,
|
||||||
SkyboxPipeline,
|
PostProcessLocals, PostProcessPipeline, Renderer, SkyboxLocals, SkyboxPipeline,
|
||||||
},
|
},
|
||||||
window::Event,
|
window::Event,
|
||||||
};
|
};
|
||||||
@ -28,11 +28,17 @@ struct Skybox {
|
|||||||
locals: Consts<SkyboxLocals>,
|
locals: Consts<SkyboxLocals>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PostProcess {
|
||||||
|
model: Model<PostProcessPipeline>,
|
||||||
|
locals: Consts<PostProcessLocals>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
globals: Consts<Globals>,
|
globals: Consts<Globals>,
|
||||||
camera: Camera,
|
camera: Camera,
|
||||||
|
|
||||||
skybox: Skybox,
|
skybox: Skybox,
|
||||||
|
postprocess: PostProcess,
|
||||||
terrain: Terrain,
|
terrain: Terrain,
|
||||||
|
|
||||||
figure_cache: FigureCache,
|
figure_cache: FigureCache,
|
||||||
@ -51,6 +57,12 @@ impl Scene {
|
|||||||
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
|
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
|
||||||
locals: renderer.create_consts(&[SkyboxLocals::default()]).unwrap(),
|
locals: renderer.create_consts(&[SkyboxLocals::default()]).unwrap(),
|
||||||
},
|
},
|
||||||
|
postprocess: PostProcess {
|
||||||
|
model: renderer.create_model(&create_pp_mesh()).unwrap(),
|
||||||
|
locals: renderer
|
||||||
|
.create_consts(&[PostProcessLocals::default()])
|
||||||
|
.unwrap(),
|
||||||
|
},
|
||||||
terrain: Terrain::new(),
|
terrain: Terrain::new(),
|
||||||
figure_cache: FigureCache::new(),
|
figure_cache: FigureCache::new(),
|
||||||
}
|
}
|
||||||
@ -145,5 +157,11 @@ impl Scene {
|
|||||||
// Render terrain and figures
|
// Render terrain and figures
|
||||||
self.terrain.render(renderer, &self.globals);
|
self.terrain.render(renderer, &self.globals);
|
||||||
self.figure_cache.render(renderer, client, &self.globals);
|
self.figure_cache.render(renderer, client, &self.globals);
|
||||||
|
|
||||||
|
renderer.render_post_process(
|
||||||
|
&self.postprocess.model,
|
||||||
|
&self.globals,
|
||||||
|
&self.postprocess.locals,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,7 @@ impl Window {
|
|||||||
glutin::WindowEvent::Resized(glutin::dpi::LogicalSize { width, height }) => {
|
glutin::WindowEvent::Resized(glutin::dpi::LogicalSize { width, height }) => {
|
||||||
let (mut color_view, mut depth_view) = renderer.target_views_mut();
|
let (mut color_view, mut depth_view) = renderer.target_views_mut();
|
||||||
gfx_window_glutin::update_views(&window, &mut color_view, &mut depth_view);
|
gfx_window_glutin::update_views(&window, &mut color_view, &mut depth_view);
|
||||||
|
renderer.on_resize().unwrap();
|
||||||
events.push(Event::Resize(Vec2::new(width as u32, height as u32)));
|
events.push(Event::Resize(Vec2::new(width as u32, height as u32)));
|
||||||
}
|
}
|
||||||
glutin::WindowEvent::ReceivedCharacter(c) => events.push(Event::Char(c)),
|
glutin::WindowEvent::ReceivedCharacter(c) => events.push(Event::Char(c)),
|
||||||
|
Reference in New Issue
Block a user