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:
parent
370ec5cbd6
commit
821ab80c5b
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,
|
||||
pipelines::{
|
||||
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},
|
||||
terrain::{Locals as TerrainLocals, TerrainPipeline},
|
||||
ui::{
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub mod figure;
|
||||
pub mod postprocess;
|
||||
pub mod skybox;
|
||||
pub mod terrain;
|
||||
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,
|
||||
mesh::Mesh,
|
||||
model::Model,
|
||||
pipelines::{figure, skybox, terrain, ui, Globals},
|
||||
pipelines::{figure, postprocess, skybox, terrain, ui, Globals},
|
||||
texture::Texture,
|
||||
Pipeline, RenderError,
|
||||
};
|
||||
use gfx::{
|
||||
self,
|
||||
traits::{Device, FactoryExt},
|
||||
handle::Sampler,
|
||||
traits::{Device, Factory, FactoryExt},
|
||||
};
|
||||
use image;
|
||||
use vek::*;
|
||||
@ -24,6 +25,12 @@ pub type TgtColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, Tg
|
||||
/// A handle to a window depth target.
|
||||
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
|
||||
/// 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.
|
||||
@ -32,13 +39,21 @@ pub struct Renderer {
|
||||
encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||
factory: gfx_backend::Factory,
|
||||
|
||||
win_color_view: TgtColorView,
|
||||
win_depth_view: TgtDepthView,
|
||||
|
||||
tgt_color_view: TgtColorView,
|
||||
tgt_depth_view: TgtDepthView,
|
||||
|
||||
tgt_color_res: TgtColorRes,
|
||||
|
||||
sampler: Sampler<gfx_backend::Resources>,
|
||||
|
||||
skybox_pipeline: GfxPipeline<skybox::pipe::Init<'static>>,
|
||||
figure_pipeline: GfxPipeline<figure::pipe::Init<'static>>,
|
||||
terrain_pipeline: GfxPipeline<terrain::pipe::Init<'static>>,
|
||||
ui_pipeline: GfxPipeline<ui::pipe::Init<'static>>,
|
||||
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
@ -47,8 +62,8 @@ impl Renderer {
|
||||
pub fn new(
|
||||
device: gfx_backend::Device,
|
||||
mut factory: gfx_backend::Factory,
|
||||
tgt_color_view: TgtColorView,
|
||||
tgt_depth_view: TgtDepthView,
|
||||
win_color_view: TgtColorView,
|
||||
win_depth_view: TgtDepthView,
|
||||
) -> Result<Self, RenderError> {
|
||||
// Construct a pipeline for rendering skyboxes
|
||||
let skybox_pipeline = create_pipeline(
|
||||
@ -82,29 +97,86 @@ impl Renderer {
|
||||
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 {
|
||||
device,
|
||||
encoder: factory.create_command_buffer().into(),
|
||||
factory,
|
||||
|
||||
win_color_view,
|
||||
win_depth_view,
|
||||
|
||||
tgt_color_view,
|
||||
tgt_depth_view,
|
||||
|
||||
tgt_color_res,
|
||||
sampler,
|
||||
|
||||
skybox_pipeline,
|
||||
figure_pipeline,
|
||||
terrain_pipeline,
|
||||
ui_pipeline,
|
||||
postprocess_pipeline,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get references to the internal render target views that get displayed directly by the window.
|
||||
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.
|
||||
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.
|
||||
@ -120,6 +192,8 @@ impl Renderer {
|
||||
pub fn clear(&mut self, col: Rgba<f32>) {
|
||||
self.encoder.clear(&self.tgt_color_view, col.into_array());
|
||||
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.
|
||||
@ -261,11 +335,31 @@ impl Renderer {
|
||||
h: max.y - min.y,
|
||||
},
|
||||
tex: (tex.srv.clone(), tex.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth: self.tgt_depth_view.clone(),
|
||||
tgt_color: self.win_color_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> {
|
||||
|
@ -10,8 +10,8 @@ use crate::{
|
||||
},
|
||||
mesh::Meshable,
|
||||
render::{
|
||||
create_skybox_mesh, Consts, FigureLocals, Globals, Model, Renderer, SkyboxLocals,
|
||||
SkyboxPipeline,
|
||||
create_pp_mesh, create_skybox_mesh, Consts, FigureLocals, Globals, Model,
|
||||
PostProcessLocals, PostProcessPipeline, Renderer, SkyboxLocals, SkyboxPipeline,
|
||||
},
|
||||
window::Event,
|
||||
};
|
||||
@ -28,11 +28,17 @@ struct Skybox {
|
||||
locals: Consts<SkyboxLocals>,
|
||||
}
|
||||
|
||||
struct PostProcess {
|
||||
model: Model<PostProcessPipeline>,
|
||||
locals: Consts<PostProcessLocals>,
|
||||
}
|
||||
|
||||
pub struct Scene {
|
||||
globals: Consts<Globals>,
|
||||
camera: Camera,
|
||||
|
||||
skybox: Skybox,
|
||||
postprocess: PostProcess,
|
||||
terrain: Terrain,
|
||||
|
||||
figure_cache: FigureCache,
|
||||
@ -51,6 +57,12 @@ impl Scene {
|
||||
model: renderer.create_model(&create_skybox_mesh()).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(),
|
||||
figure_cache: FigureCache::new(),
|
||||
}
|
||||
@ -145,5 +157,11 @@ impl Scene {
|
||||
// Render terrain and figures
|
||||
self.terrain.render(renderer, &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 }) => {
|
||||
let (mut color_view, mut depth_view) = renderer.target_views_mut();
|
||||
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)));
|
||||
}
|
||||
glutin::WindowEvent::ReceivedCharacter(c) => events.push(Event::Char(c)),
|
||||
|
Loading…
Reference in New Issue
Block a user