Make bloom intensity configurable, make whether less blurred layers are added in toggleable, hold onto copy of pipeline modes instead of returning it from pipeline creation

This commit is contained in:
Imbris 2021-08-01 18:50:09 -04:00
parent 147e4f00f6
commit a1026c36f5
8 changed files with 126 additions and 51 deletions

View File

@ -24,9 +24,6 @@
#define SHADOW_MODE_CHEAP 1
#define SHADOW_MODE_MAP 2
#define BLOOM_DISABLED 0
#define BLOOM_ENABLED 1
/* Unlike the other flags (for now anyway), these are bitmask values */
#define LIGHTING_TYPE_REFLECTION 0x01
#define LIGHTING_TYPE_TRANSMISSION 0x02

View File

@ -35,7 +35,7 @@ uniform u_locals {
mat4 view_mat_inv;
};
#if (BLOOM == BLOOM_ENABLED)
#ifdef BLOOM_FACTOR
layout(set = 1, binding = 3)
uniform texture2D t_src_bloom;
#endif
@ -187,11 +187,13 @@ void main() {
vec4 aa_color = aa_apply(t_src_color, s_src_color, uv * screen_res.xy, screen_res.xy);
// Bloom
#if (BLOOM == BLOOM_ENABLED)
// divide by 4.0 to account for adding blurred layers together
vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0) / 4.0;
float bloom_factor = 0.10;
aa_color = mix(aa_color, bloom, bloom_factor);
#ifdef BLOOM_FACTOR
vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0);
#if (BLOOM_UNIFORM_BLUR == false)
// divide by 4.0 to account for adding blurred layers together
bloom /= 4.0;
#endif
aa_color = mix(aa_color, bloom, BLOOM_FACTOR);
#endif
// Tonemapping

View File

@ -265,6 +265,66 @@ impl From<PresentMode> for wgpu::PresentMode {
}
}
/// Bloom factor
/// Controls fraction of output image luminosity that is blurred bloom
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub enum BloomFactor {
Low,
High,
/// Max valid value is 1.0
Custom(f32),
// other variant has to be placed last
#[serde(other)]
Standard,
}
impl Default for BloomFactor {
fn default() -> Self { Self::Standard }
}
impl BloomFactor {
/// Fraction of output image luminosity that is blurred bloom
pub fn fraction(self) -> f32 {
match self {
Self::Low => 0.05,
Self::Standard => 0.10,
Self::High => 0.25,
Self::Custom(val) => val.max(0.0).min(1.0),
}
}
}
/// Bloom settings
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct BloomConfig {
/// Controls fraction of output image luminosity that is blurred bloom
///
/// Defaults to `Standard`
factor: BloomFactor,
/// Turning this on make the bloom blur less sharply concentrated around the
/// high intensity phenomena (removes adding in less blurred layers to the
/// final blur)
///
/// Defaults to `false`
uniform_blur: bool,
// TODO: allow configuring the blur radius and/or the number of passes
}
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub enum BloomMode {
On(BloomConfig),
#[serde(other)]
Off,
}
impl Default for BloomMode {
fn default() -> Self { Self::Off }
}
impl BloomMode {
fn is_on(&self) -> bool { matches!(self, BloomMode::On(_)) }
}
/// Render modes
#[derive(PartialEq, Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
@ -274,7 +334,7 @@ pub struct RenderMode {
pub fluid: FluidMode,
pub lighting: LightingMode,
pub shadow: ShadowMode,
pub bloom: bool,
pub bloom: BloomMode,
pub upscale_mode: UpscaleMode,
pub present_mode: PresentMode,
@ -310,7 +370,7 @@ pub struct PipelineModes {
fluid: FluidMode,
lighting: LightingMode,
pub shadow: ShadowMode,
bloom: bool,
bloom: BloomMode,
}
/// Other render modes that don't effect pipelines

View File

@ -2,7 +2,7 @@
//!
//! See additional details in the [NUM_SIZES] docs
use super::super::Consts;
use super::super::{BloomConfig, Consts};
use bytemuck::{Pod, Zeroable};
use vek::*;
@ -152,6 +152,7 @@ impl BloomPipelines {
upsample_fs_module: &wgpu::ShaderModule,
target_format: wgpu::TextureFormat,
layout: &BloomLayout,
bloom_config: &BloomConfig,
) -> Self {
common_base::span!(_guard, "BloomPipelines::new");
let render_pipeline_layout =
@ -207,18 +208,14 @@ impl BloomPipelines {
let upsample_pipeline = create_pipeline(
"Bloom upsample pipeline",
upsample_fs_module,
Some(wgpu::BlendState {
(!bloom_config.uniform_blur).then(|| wgpu::BlendState {
color: wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::One,
dst_factor: wgpu::BlendFactor::One,
operation: wgpu::BlendOperation::Add,
},
// we don't really use this, but... we need something here
alpha: wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::One,
dst_factor: wgpu::BlendFactor::One,
operation: wgpu::BlendOperation::Add,
},
// We don't reaaly use this but we need something here..
alpha: wgpu::BlendComponent::REPLACE,
}),
);

View File

@ -66,7 +66,7 @@ impl PostProcessLayout {
},
];
if pipeline_modes.bloom {
if pipeline_modes.bloom.is_on() {
bind_entries.push(
// src bloom
wgpu::BindGroupLayoutEntry {

View File

@ -111,19 +111,19 @@ enum State {
Complete {
pipelines: Pipelines,
shadow: Shadow,
recreating: Option<
recreating: Option<(
PipelineModes,
PipelineCreation<
Result<
(
Pipelines,
ShadowPipelines,
PipelineModes,
Arc<postprocess::PostProcessLayout>,
),
RenderError,
>,
>,
>,
)>,
},
}
@ -522,7 +522,7 @@ impl Renderer {
/// Returns `Some((total, complete))` if in progress
pub fn pipeline_recreation_status(&self) -> Option<(usize, usize)> {
if let State::Complete { recreating, .. } = &self.state {
recreating.as_ref().map(|r| r.status())
recreating.as_ref().map(|(_, c)| c.status())
} else {
None
}
@ -765,6 +765,7 @@ impl Renderer {
let bloom_tgt_views = pipeline_modes
.bloom
.is_on()
.then(|| bloom_sizes.map(|size| color_view(size.x, size.y)));
let tgt_depth_tex = device.create_texture(&wgpu::TextureDescriptor {
@ -964,11 +965,11 @@ impl Renderer {
} else if let State::Complete {
pipelines,
mut shadow,
recreating: Some(recreating),
recreating: Some((new_pipeline_modes, pipeline_creation)),
} = state
{
match recreating.try_complete() {
Ok(Ok((pipelines, shadow_pipelines, new_pipeline_modes, postprocess_layout))) => {
match pipeline_creation.try_complete() {
Ok(Ok((pipelines, shadow_pipelines, postprocess_layout))) => {
if let (
Some(point_pipeline),
Some(terrain_directed_pipeline),
@ -1007,10 +1008,10 @@ impl Renderer {
}
},
// Not complete
Err(recreating) => State::Complete {
Err(pipeline_creation) => State::Complete {
pipelines,
shadow,
recreating: Some(recreating),
recreating: Some((new_pipeline_modes, pipeline_creation)),
},
}
} else {
@ -1080,16 +1081,20 @@ impl Renderer {
State::Complete {
recreating, shadow, ..
} => {
*recreating = Some(pipeline_creation::recreate_pipelines(
Arc::clone(&self.device),
Arc::clone(&self.layouts.immutable),
self.shaders.read().clone(),
self.pipeline_modes.clone(),
// NOTE: if present_mode starts to be used to configure pipelines then it needs
// to become a part of the pipeline modes (note here since the present mode is
// accessible through the swap chain descriptor)
self.sc_desc.clone(), // Note: cheap clone
shadow.map.is_enabled(),
*recreating = Some((
pipeline_modes.clone(),
pipeline_creation::recreate_pipelines(
Arc::clone(&self.device),
Arc::clone(&self.layouts.immutable),
self.shaders.read().clone(),
pipeline_modes,
// NOTE: if present_mode starts to be used to configure pipelines then it
// needs to become a part of the pipeline modes
// (note here since the present mode is accessible
// through the swap chain descriptor)
self.sc_desc.clone(), // Note: cheap clone
shadow.map.is_enabled(),
),
));
},
State::Interface { .. } => {

View File

@ -4,7 +4,8 @@ use super::{
blit, bloom, clouds, debug, figure, fluid, lod_terrain, particle, postprocess, shadow,
skybox, sprite, terrain, ui,
},
AaMode, CloudMode, FluidMode, LightingMode, PipelineModes, RenderError, ShadowMode,
AaMode, BloomMode, CloudMode, FluidMode, LightingMode, PipelineModes, RenderError,
ShadowMode,
},
shaders::Shaders,
ImmutableLayouts, Layouts,
@ -151,7 +152,6 @@ impl ShaderModules {
#define CLOUD_MODE {}
#define LIGHTING_ALGORITHM {}
#define SHADOW_MODE {}
#define BLOOM {}
"#,
&constants.0,
@ -179,13 +179,26 @@ impl ShaderModules {
ShadowMode::Map(_) if has_shadow_views => "SHADOW_MODE_MAP",
ShadowMode::Cheap | ShadowMode::Map(_) => "SHADOW_MODE_CHEAP",
},
if pipeline_modes.bloom {
"BLOOM_ENABLED"
} else {
"BLOOM_DISABLED"
},
);
let constants = match pipeline_modes.bloom {
BloomMode::Off => constants,
BloomMode::On(config) => {
format!(
r#"
{}
#define BLOOM_FACTOR {}
#define BLOOM_UNIFORM_BLUR {}
"#,
constants,
config.factor.fraction(),
config.uniform_blur,
)
},
};
let anti_alias = shaders
.get(match pipeline_modes.aa {
AaMode::None => "antialias.none",
@ -558,7 +571,11 @@ fn create_ingame_and_shadow_pipelines(
let create_bloom = || {
bloom_task.run(
|| {
pipeline_modes.bloom.then(|| {
match &pipeline_modes.bloom {
BloomMode::Off => None,
BloomMode::On(config) => Some(config),
}
.map(|bloom_config| {
bloom::BloomPipelines::new(
device,
&shaders.blit_vert,
@ -567,6 +584,7 @@ fn create_ingame_and_shadow_pipelines(
&shaders.dual_upsample_frag,
wgpu::TextureFormat::Rgba16Float,
&layouts.bloom,
bloom_config,
)
})
},
@ -797,7 +815,6 @@ pub(super) fn recreate_pipelines(
(
Pipelines,
ShadowPipelines,
PipelineModes,
Arc<postprocess::PostProcessLayout>,
),
RenderError,
@ -871,7 +888,6 @@ pub(super) fn recreate_pipelines(
.send(Ok((
Pipelines::consolidate(interface, ingame),
shadow,
pipeline_modes,
layouts.postprocess,
)))
.expect("Channel disconnected");

View File

@ -43,7 +43,6 @@ pub struct GraphicsSettings {
pub window_size: [u16; 2],
pub fullscreen: FullScreenSettings,
pub lod_detail: u32,
pub bloom_enabled: bool,
}
impl Default for GraphicsSettings {
@ -63,7 +62,6 @@ impl Default for GraphicsSettings {
window_size: [1280, 720],
fullscreen: FullScreenSettings::default(),
lod_detail: 250,
bloom_enabled: false,
}
}
}