Upscaling support

This commit is contained in:
Joshua Barretto 2020-11-15 22:18:35 +00:00
parent 7ffb3b91fa
commit 171ef1d7b9
12 changed files with 418 additions and 34 deletions

View File

@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Saving of the last selected character in the character selection screen
- Autoselecting the newly created character
- Deselecting when the selected character is deleted
- Upscaling support
### Changed

View File

@ -337,6 +337,7 @@ magically infused items?"#,
"hud.settings.gamma": "Gamma",
"hud.settings.ambiance": "Ambiance Brightness",
"hud.settings.antialiasing_mode": "AntiAliasing Mode",
"hud.settings.upscale_factor": "Upscale Factor",
"hud.settings.cloud_rendering_mode": "Cloud Rendering Mode",
"hud.settings.fluid_rendering_mode": "Fluid Rendering Mode",
"hud.settings.fluid_rendering_mode.cheap": "Cheap",

View File

@ -0,0 +1,74 @@
#version 330 core
#include <constants.glsl>
#define LIGHTING_TYPE (LIGHTING_TYPE_TRANSMISSION | LIGHTING_TYPE_REFLECTION)
#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR
#if (FLUID_MODE == FLUID_MODE_CHEAP)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE
#elif (FLUID_MODE == FLUID_MODE_SHINY)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE
#endif
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
#include <globals.glsl>
// Note: The sampler uniform is declared here because it differs for MSAA
#include <anti-aliasing.glsl>
#include <srgb.glsl>
#include <cloud.glsl>
uniform sampler2D src_depth;
in vec2 f_pos;
layout (std140)
uniform u_locals {
mat4 proj_mat_inv;
mat4 view_mat_inv;
};
out vec4 tgt_color;
float depth_at(vec2 uv) {
float buf_depth = texture(src_depth, uv).x;
vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0);
vec4 view_space = proj_mat_inv * clip_space;
view_space /= view_space.w;
return -view_space.z;
}
vec3 wpos_at(vec2 uv) {
float buf_depth = texture(src_depth, uv).x * 2.0 - 1.0;
mat4 inv = view_mat_inv * proj_mat_inv;//inverse(all_mat);
vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0);
vec4 view_space = inv * clip_space;
view_space /= view_space.w;
if (buf_depth == 1.0) {
vec3 direction = normalize(view_space.xyz);
return direction.xyz * 100000.0 + cam_pos.xyz;
} else {
return view_space.xyz;
}
}
void main() {
vec2 uv = (f_pos + 1.0) * 0.5;
vec4 color = texture(src_color, uv);
// Apply clouds to `aa_color`
#if (CLOUD_MODE != CLOUD_MODE_NONE)
vec3 wpos = wpos_at(uv);
float dist = distance(wpos, cam_pos.xyz);
vec3 dir = (wpos - cam_pos.xyz) / dist;
color.rgb = get_cloud_color(color.rgb, dir, cam_pos.xyz, time_of_day.x, dist, 1.0);
#endif
tgt_color = vec4(color.rgb, 1);
}

View File

@ -0,0 +1,29 @@
#version 330 core
#include <constants.glsl>
#define LIGHTING_TYPE (LIGHTING_TYPE_TRANSMISSION | LIGHTING_TYPE_REFLECTION)
#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR
#if (FLUID_MODE == FLUID_MODE_CHEAP)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE
#elif (FLUID_MODE == FLUID_MODE_SHINY)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE
#endif
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
#include <globals.glsl>
in vec2 v_pos;
out vec2 f_pos;
void main() {
f_pos = v_pos;
gl_Position = vec4(v_pos, -1.0, 1.0);
}

View File

@ -22,7 +22,7 @@
#include <srgb.glsl>
#include <cloud.glsl>
uniform sampler2D src_depth;
//uniform sampler2D src_depth;
in vec2 f_pos;
@ -145,6 +145,7 @@ vec3 _illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitte
// return /*srgb_to_linear*/(/*0.5*//*0.125 * */vec3(pow(color.x, gamma), pow(color.y, gamma), pow(color.z, gamma)));
}
/*
float depth_at(vec2 uv) {
float buf_depth = texture(src_depth, uv).x;
vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0);
@ -166,6 +167,7 @@ vec3 wpos_at(vec2 uv) {
return view_space.xyz;
}
}
*/
void main() {
vec2 uv = (f_pos + 1.0) * 0.5;
@ -202,6 +204,7 @@ void main() {
vec4 aa_color = aa_apply(src_color, uv * screen_res.xy, screen_res.xy);
/*
// Apply clouds to `aa_color`
#if (CLOUD_MODE != CLOUD_MODE_NONE)
vec3 wpos = wpos_at(uv);
@ -210,6 +213,7 @@ void main() {
aa_color.rgb = get_cloud_color(aa_color.rgb, dir, cam_pos.xyz, time_of_day.x, dist, 1.0);
#endif
*/
// aa_color.rgb = (wpos + focus_off.xyz) / vec3(32768, 32768, /*view_distance.w*/2048);
// aa_color.rgb = mod((wpos + focus_off.xyz), vec3(32768, 32768, view_distance.w)) / vec3(32768, 32768, view_distance.w);// / vec3(32768, 32768, view_distance.w);

View File

@ -6,7 +6,10 @@ use super::{
use crate::{
hud::BuffPosition,
i18n::{list_localizations, LanguageMetadata, Localization},
render::{AaMode, CloudMode, FluidMode, LightingMode, RenderMode, ShadowMapMode, ShadowMode},
render::{
AaMode, CloudMode, FluidMode, LightingMode, RenderMode, ShadowMapMode, ShadowMode,
UpscaleMode,
},
ui::{fonts::Fonts, ImageSlider, ScaleMode, ToggleButton},
window::{FullScreenSettings, FullscreenMode, GameInput},
GlobalState,
@ -126,6 +129,8 @@ widget_ids! {
ambiance_value,
aa_mode_text,
aa_mode_list,
upscale_factor_text,
upscale_factor_list,
cloud_mode_text,
cloud_mode_list,
fluid_mode_text,
@ -2060,13 +2065,55 @@ impl<'a> Widget for SettingsWindow<'a> {
})));
}
// Upscaling factor
Text::new(&self.localized_strings.get("hud.settings.upscale_factor"))
.down_from(state.ids.aa_mode_list, 8.0)
.font_size(self.fonts.cyri.scale(14))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.upscale_factor_text, ui);
let upscale_factors = [
// Upscaling
0.15, 0.2, 0.25, 0.35, 0.5, 0.65, 0.75, 0.85, 1.0,
// Downscaling (equivalent to SSAA)
1.25, 1.5, 1.75, 2.0,
];
// Get which upscale factor is currently active
let selected = upscale_factors
.iter()
.position(|factor| (*factor - render_mode.upscale_mode.factor).abs() < 0.001);
if let Some(clicked) = DropDownList::new(
&upscale_factors
.iter()
.map(|factor| format!("{n:.*}", 2, n = factor))
.collect::<Vec<String>>(),
selected,
)
.w_h(400.0, 22.0)
.color(MENU_BG)
.label_color(TEXT_COLOR)
.label_font_id(self.fonts.cyri.conrod_id)
.down_from(state.ids.upscale_factor_text, 8.0)
.set(state.ids.upscale_factor_list, ui)
{
events.push(Event::ChangeRenderMode(Box::new(RenderMode {
upscale_mode: UpscaleMode {
factor: upscale_factors[clicked],
},
..render_mode.clone()
})));
}
// CloudMode
Text::new(
&self
.localized_strings
.get("hud.settings.cloud_rendering_mode"),
)
.down_from(state.ids.aa_mode_list, 8.0)
.down_from(state.ids.upscale_factor_list, 8.0)
.font_size(self.fonts.cyri.scale(14))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)

View File

@ -16,6 +16,7 @@ pub use self::{
mesh::{Mesh, Quad, Tri},
model::{DynamicModel, Model},
pipelines::{
clouds::{create_mesh as create_clouds_mesh, CloudsPipeline, Locals as CloudsLocals},
figure::{
BoneData as FigureBoneData, BoneMeshes, FigureModel, FigurePipeline,
Locals as FigureLocals,
@ -257,6 +258,17 @@ impl ShadowMode {
pub fn is_map(&self) -> bool { matches!(self, Self::Map(_)) }
}
/// Upscale mode settings.
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct UpscaleMode {
// Determines non-UI graphics upscaling. 0.25 to 2.0.
pub factor: f32,
}
impl Default for UpscaleMode {
fn default() -> Self { Self { factor: 1.0 } }
}
/// Render modes
#[derive(PartialEq, Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
@ -266,4 +278,5 @@ pub struct RenderMode {
pub fluid: FluidMode,
pub lighting: LightingMode,
pub shadow: ShadowMode,
pub upscale_mode: UpscaleMode,
}

View File

@ -0,0 +1,77 @@
use super::{
super::{Mesh, Pipeline, TgtColorFmt, TgtDepthStencilFmt, Tri},
Globals,
};
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta,
};
use vek::*;
gfx_defines! {
vertex Vertex {
pos: [f32; 2] = "v_pos",
}
constant Locals {
proj_mat_inv: [[f32; 4]; 4] = "proj_mat_inv",
view_mat_inv: [[f32; 4]; 4] = "view_mat_inv",
}
pipeline pipe {
vbuf: gfx::VertexBuffer<Vertex> = (),
locals: gfx::ConstantBuffer<Locals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
map: gfx::TextureSampler<[f32; 4]> = "t_map",
alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
color_sampler: gfx::TextureSampler<<TgtColorFmt as gfx::format::Formatted>::View> = "src_color",
depth_sampler: gfx::TextureSampler<<TgtDepthStencilFmt as gfx::format::Formatted>::View> = "src_depth",
noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
}
}
impl Default for Locals {
fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
}
impl Locals {
pub fn new(proj_mat_inv: Mat4<f32>, view_mat_inv: Mat4<f32>) -> Self {
Self {
proj_mat_inv: proj_mat_inv.into_col_arrays(),
view_mat_inv: view_mat_inv.into_col_arrays(),
}
}
}
pub struct CloudsPipeline;
impl Pipeline for CloudsPipeline {
type Vertex = Vertex;
}
pub fn create_mesh() -> Mesh<CloudsPipeline> {
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
}

View File

@ -1,3 +1,4 @@
pub mod clouds;
pub mod figure;
pub mod fluid;
pub mod lod_terrain;

View File

@ -5,8 +5,8 @@ use super::{
mesh::Mesh,
model::{DynamicModel, Model},
pipelines::{
figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, ui,
GlobalModel, Globals,
clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain,
ui, GlobalModel, Globals,
},
texture::Texture,
AaMode, CloudMode, FilterMethod, FluidMode, LightingMode, Pipeline, RenderError, RenderMode,
@ -148,9 +148,11 @@ pub struct Renderer {
tgt_color_view: TgtColorView,
tgt_depth_stencil_view: TgtDepthStencilView,
tgt_color_view_pp: TgtColorView,
tgt_color_res: TgtColorRes,
tgt_depth_res: TgtDepthRes,
tgt_color_res_pp: TgtColorRes,
sampler: Sampler<gfx_backend::Resources>,
@ -164,6 +166,7 @@ pub struct Renderer {
particle_pipeline: GfxPipeline<particle::pipe::Init<'static>>,
ui_pipeline: GfxPipeline<ui::pipe::Init<'static>>,
lod_terrain_pipeline: GfxPipeline<lod_terrain::pipe::Init<'static>>,
clouds_pipeline: GfxPipeline<clouds::pipe::Init<'static>>,
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
player_shadow_pipeline: GfxPipeline<figure::pipe::Init<'static>>,
@ -213,6 +216,7 @@ impl Renderer {
particle_pipeline,
ui_pipeline,
lod_terrain_pipeline,
clouds_pipeline,
postprocess_pipeline,
player_shadow_pipeline,
point_shadow_pipeline,
@ -225,8 +229,14 @@ impl Renderer {
&mut shader_reload_indicator,
)?;
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_res, tgt_depth_res) =
Self::create_rt_views(&mut factory, (dims.0, dims.1), &mode)?;
let (
tgt_color_view,
tgt_depth_stencil_view,
tgt_color_view_pp,
tgt_color_res,
tgt_depth_res,
tgt_color_res_pp,
) = Self::create_rt_views(&mut factory, (dims.0, dims.1), &mode)?;
let shadow_map = if let (
Some(point_pipeline),
@ -266,7 +276,10 @@ impl Renderer {
None
};
let sampler = factory.create_sampler_linear();
let sampler = factory.create_sampler(gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Clamp,
));
let noise_tex = Texture::new(
&mut factory,
@ -286,9 +299,11 @@ impl Renderer {
tgt_color_view,
tgt_depth_stencil_view,
tgt_color_view_pp,
tgt_color_res,
tgt_depth_res,
tgt_color_res_pp,
sampler,
@ -302,6 +317,7 @@ impl Renderer {
particle_pipeline,
ui_pipeline,
lod_terrain_pipeline,
clouds_pipeline,
postprocess_pipeline,
player_shadow_pipeline,
@ -363,12 +379,20 @@ impl Renderer {
// Avoid panics when creating texture with w,h of 0,0.
if dims.0 != 0 && dims.1 != 0 {
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_res, tgt_depth_res) =
Self::create_rt_views(&mut self.factory, (dims.0, dims.1), &self.mode)?;
let (
tgt_color_view,
tgt_depth_stencil_view,
tgt_color_view_pp,
tgt_color_res,
tgt_depth_res,
tgt_color_res_pp,
) = Self::create_rt_views(&mut self.factory, (dims.0, dims.1), &self.mode)?;
self.tgt_color_res = tgt_color_res;
self.tgt_depth_res = tgt_depth_res;
self.tgt_color_res_pp = tgt_color_res_pp;
self.tgt_color_view = tgt_color_view;
self.tgt_depth_stencil_view = tgt_depth_stencil_view;
self.tgt_color_view_pp = tgt_color_view_pp;
if let (Some(shadow_map), ShadowMode::Map(mode)) =
(self.shadow_map.as_mut(), self.mode.shadow)
{
@ -403,42 +427,66 @@ impl Renderer {
factory: &mut gfx_device_gl::Factory,
size: (u16, u16),
mode: &RenderMode,
) -> Result<(TgtColorView, TgtDepthStencilView, TgtColorRes, TgtDepthRes), RenderError> {
) -> Result<
(
TgtColorView,
TgtDepthStencilView,
TgtColorView,
TgtColorRes,
TgtDepthRes,
TgtColorRes,
),
RenderError,
> {
let upscaled = Vec2::from(size)
.map(|e: u16| (e as f32 * mode.upscale_mode.factor) as u16)
.into_tuple();
let kind = match mode.aa {
AaMode::None | AaMode::Fxaa => {
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Single)
gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Single)
},
// TODO: Ensure sampling in the shader is exactly between the 4 texels
AaMode::SsaaX4 => {
// TODO: Figure out how to do upscaling correctly with SSAA
gfx::texture::Kind::D2(size.0 * 2, size.1 * 2, gfx::texture::AaMode::Single)
},
AaMode::MsaaX4 => {
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Multi(4))
gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Multi(4))
},
AaMode::MsaaX8 => {
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Multi(8))
gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Multi(8))
},
AaMode::MsaaX16 => {
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Multi(16))
gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Multi(16))
},
};
let levels = 1;
let color_cty = <<TgtColorFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped
>::get_channel_type();
let tgt_color_tex = factory.create_texture(
kind,
levels,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::RENDER_TARGET,
gfx::memory::Usage::Data,
Some(color_cty),
)?;
let tgt_color_res = factory.view_texture_as_shader_resource::<TgtColorFmt>(
&tgt_color_tex,
(0, levels - 1),
gfx::format::Swizzle::new(),
)?;
let mut color_tex = || {
factory.create_texture(
kind,
levels,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::RENDER_TARGET,
gfx::memory::Usage::Data,
Some(color_cty),
)
};
let tgt_color_tex = color_tex()?;
let tgt_color_tex_pp = color_tex()?;
let mut color_res = |tex| {
factory.view_texture_as_shader_resource::<TgtColorFmt>(
tex,
(0, levels - 1),
gfx::format::Swizzle::new(),
)
};
let tgt_color_res = color_res(&tgt_color_tex)?;
let tgt_color_res_pp = color_res(&tgt_color_tex_pp)?;
let tgt_color_view = factory.view_texture_as_render_target(&tgt_color_tex, 0, None)?;
let tgt_color_view_pp =
factory.view_texture_as_render_target(&tgt_color_tex_pp, 0, None)?;
let depth_stencil_cty = <<TgtDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
let tgt_depth_stencil_tex = factory.create_texture(
@ -459,8 +507,10 @@ impl Renderer {
Ok((
tgt_color_view,
tgt_depth_stencil_view,
tgt_color_view_pp,
tgt_color_res,
tgt_depth_res,
tgt_color_res_pp,
))
}
@ -763,6 +813,7 @@ impl Renderer {
particle_pipeline,
ui_pipeline,
lod_terrain_pipeline,
clouds_pipeline,
postprocess_pipeline,
player_shadow_pipeline,
point_shadow_pipeline,
@ -777,6 +828,7 @@ impl Renderer {
self.particle_pipeline = particle_pipeline;
self.ui_pipeline = ui_pipeline;
self.lod_terrain_pipeline = lod_terrain_pipeline;
self.clouds_pipeline = clouds_pipeline;
self.postprocess_pipeline = postprocess_pipeline;
self.player_shadow_pipeline = player_shadow_pipeline;
if let (
@ -1645,6 +1697,37 @@ impl Renderer {
);
}
pub fn render_clouds(
&mut self,
model: &Model<clouds::CloudsPipeline>,
globals: &Consts<Globals>,
locals: &Consts<clouds::Locals>,
lod: &lod_terrain::LodData,
) {
self.encoder.draw(
&gfx::Slice {
start: model.vertex_range().start,
end: model.vertex_range().end,
base_vertex: 0,
instances: None,
buffer: gfx::IndexBuffer::Auto,
},
&self.clouds_pipeline.pso,
&clouds::pipe::Data {
vbuf: model.vbuf.clone(),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
map: (lod.map.srv.clone(), lod.map.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
color_sampler: (self.tgt_color_res.clone(), self.sampler.clone()),
depth_sampler: (self.tgt_depth_res.clone(), self.sampler.clone()),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view_pp.clone(),
},
)
}
pub fn render_post_process(
&mut self,
model: &Model<postprocess::PostProcessPipeline>,
@ -1668,7 +1751,7 @@ impl Renderer {
map: (lod.map.srv.clone(), lod.map.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
color_sampler: (self.tgt_color_res.clone(), self.sampler.clone()),
color_sampler: (self.tgt_color_res_pp.clone(), self.sampler.clone()),
depth_sampler: (self.tgt_depth_res.clone(), self.sampler.clone()),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.win_color_view.clone(),
@ -1698,6 +1781,7 @@ fn create_pipelines(
GfxPipeline<particle::pipe::Init<'static>>,
GfxPipeline<ui::pipe::Init<'static>>,
GfxPipeline<lod_terrain::pipe::Init<'static>>,
GfxPipeline<clouds::pipe::Init<'static>>,
GfxPipeline<postprocess::pipe::Init<'static>>,
GfxPipeline<figure::pipe::Init<'static>>,
Option<GfxPipeline<shadow::pipe::Init<'static>>>,
@ -1908,6 +1992,16 @@ fn create_pipelines(
gfx::state::CullFace::Back,
)?;
// Construct a pipeline for rendering our clouds (a kind of post-processing)
let clouds_pipeline = create_pipeline(
factory,
clouds::pipe::new(),
&Glsl::load_watched("voxygen.shaders.clouds-vert", shader_reload_indicator).unwrap(),
&Glsl::load_watched("voxygen.shaders.clouds-frag", shader_reload_indicator).unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
// Construct a pipeline for rendering our post-processing
let postprocess_pipeline = create_pipeline(
factory,
@ -2019,6 +2113,7 @@ fn create_pipelines(
particle_pipeline,
ui_pipeline,
lod_terrain_pipeline,
clouds_pipeline,
postprocess_pipeline,
player_shadow_pipeline,
point_shadow_pipeline,

View File

@ -16,9 +16,9 @@ pub use self::{
use crate::{
audio::{music::MusicMgr, sfx::SfxMgr, AudioFrontend},
render::{
create_pp_mesh, create_skybox_mesh, Consts, GlobalModel, Globals, Light, LodData, Model,
PostProcessLocals, PostProcessPipeline, Renderer, Shadow, ShadowLocals, SkyboxLocals,
SkyboxPipeline,
create_clouds_mesh, create_pp_mesh, create_skybox_mesh, CloudsLocals, CloudsPipeline,
Consts, GlobalModel, Globals, Light, LodData, Model, PostProcessLocals,
PostProcessPipeline, Renderer, Shadow, ShadowLocals, SkyboxLocals, SkyboxPipeline,
},
settings::Settings,
window::{AnalogGameInput, Event},
@ -71,6 +71,11 @@ struct Skybox {
locals: Consts<SkyboxLocals>,
}
struct Clouds {
model: Model<CloudsPipeline>,
locals: Consts<CloudsLocals>,
}
struct PostProcess {
model: Model<PostProcessPipeline>,
locals: Consts<PostProcessLocals>,
@ -83,6 +88,7 @@ pub struct Scene {
event_lights: Vec<EventLight>,
skybox: Skybox,
clouds: Clouds,
postprocess: PostProcess,
terrain: Terrain<TerrainChunk>,
pub lod: Lod,
@ -283,6 +289,10 @@ impl Scene {
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
locals: renderer.create_consts(&[SkyboxLocals::default()]).unwrap(),
},
clouds: Clouds {
model: renderer.create_model(&create_clouds_mesh()).unwrap(),
locals: renderer.create_consts(&[CloudsLocals::default()]).unwrap(),
},
postprocess: PostProcess {
model: renderer.create_model(&create_pp_mesh()).unwrap(),
locals: renderer
@ -664,6 +674,12 @@ impl Scene {
scene_data.sprite_render_distance as f32 - 20.0,
)])
.expect("Failed to update global constants");
renderer
.update_consts(&mut self.clouds.locals, &[CloudsLocals::new(
proj_mat_inv,
view_mat_inv,
)])
.expect("Failed to update cloud locals");
renderer
.update_consts(&mut self.postprocess.locals, &[PostProcessLocals::new(
proj_mat_inv,
@ -1075,6 +1091,14 @@ impl Scene {
// Render particle effects.
self.particle_mgr.render(renderer, scene_data, global, lod);
// Render clouds (a post-processing effect)
renderer.render_clouds(
&self.clouds.model,
&global.globals,
&self.clouds.locals,
self.lod.get_data(),
);
renderer.render_post_process(
&self.postprocess.model,
&global.globals,

View File

@ -1,9 +1,10 @@
use crate::{
mesh::{greedy::GreedyMesh, Meshable},
render::{
create_pp_mesh, create_skybox_mesh, BoneMeshes, Consts, FigureModel, FigurePipeline,
GlobalModel, Globals, Light, Mesh, Model, PostProcessLocals, PostProcessPipeline, Renderer,
Shadow, ShadowLocals, SkyboxLocals, SkyboxPipeline, TerrainPipeline,
create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals,
CloudsPipeline, Consts, FigureModel, FigurePipeline, GlobalModel, Globals, Light, Mesh,
Model, PostProcessLocals, PostProcessPipeline, Renderer, Shadow, ShadowLocals,
SkyboxLocals, SkyboxPipeline, TerrainPipeline,
},
scene::{
camera::{self, Camera, CameraMode},
@ -61,11 +62,17 @@ struct PostProcess {
locals: Consts<PostProcessLocals>,
}
struct Clouds {
model: Model<CloudsPipeline>,
locals: Consts<CloudsLocals>,
}
pub struct Scene {
data: GlobalModel,
camera: Camera,
skybox: Skybox,
clouds: Clouds,
postprocess: PostProcess,
lod: LodData,
map_bounds: Vec2<f32>,
@ -123,6 +130,10 @@ impl Scene {
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
locals: renderer.create_consts(&[SkyboxLocals::default()]).unwrap(),
},
clouds: Clouds {
model: renderer.create_model(&create_clouds_mesh()).unwrap(),
locals: renderer.create_consts(&[CloudsLocals::default()]).unwrap(),
},
postprocess: PostProcess {
model: renderer.create_model(&create_pp_mesh()).unwrap(),
locals: renderer
@ -377,6 +388,13 @@ impl Scene {
);
}
renderer.render_clouds(
&self.clouds.model,
&self.data.globals,
&self.clouds.locals,
&self.lod,
);
renderer.render_post_process(
&self.postprocess.model,
&self.data.globals,