diff --git a/assets/voxygen/i18n/en.ron b/assets/voxygen/i18n/en.ron index fd223268cc..5697bccacc 100644 --- a/assets/voxygen/i18n/en.ron +++ b/assets/voxygen/i18n/en.ron @@ -335,6 +335,7 @@ magically infused items?"#, "hud.settings.maximum_fps": "Maximum FPS", "hud.settings.fov": "Field of View (deg)", "hud.settings.gamma": "Gamma", + "hud.settings.exposure": "Exposure", "hud.settings.ambiance": "Ambiance Brightness", "hud.settings.antialiasing_mode": "AntiAliasing Mode", "hud.settings.upscale_factor": "Upscale Factor", diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index c67e1044eb..eecfddd1c9 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -21,7 +21,7 @@ float emission_strength = clamp((sin(time_of_day.x / (3600 * 24)) - 0.8) / 0.1, vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { // Natural attenuation of air (air naturally attenuates light that passes through it) // Simulate the atmosphere thinning above 3000 metres down to nothing at 5000 metres - float air = 0.00015 * clamp((10000.0 - pos.z) / 7000, 0, 1); + float air = 0.00035 * clamp((10000.0 - pos.z) / 7000, 0, 1); // Mist sits close to the ground in valleys (TODO: use base_alt to put it closer to water) float mist_min_alt = 0.5; @@ -106,7 +106,7 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission) { #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) emission_nz *= (1.0 + (noise_3d(vec3(wind_pos.xy * 0.05, time_of_day.x * 0.15) * 0.004) - 0.5) * 4.0); #endif - emission = emission_col * emission_nz * emission_strength * max(sun_dir.z, 0) * 50; + emission = emission_col * emission_nz * emission_strength * max(sun_dir.z, 0) * 20; } // We track vapor density and air density separately. Why? Because photons will ionize particles in air @@ -194,8 +194,7 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of (1.0 - surf_color) * net_light * sky_color * density_integrals.y * RAYLEIGH + // Add the directed light light scattered into the camera by the clouds get_sun_color() * sun_scatter * sun_access * scatter_factor * get_sun_brightness() + - // Really we should multiple by just moon_brightness here but this just looks better given that we lack HDR - get_moon_color() * moon_scatter * moon_access * scatter_factor * get_moon_brightness() * 4.0 + + get_moon_color() * moon_scatter * moon_access * scatter_factor * get_moon_brightness() + emission * density_integrals.y + // Global illumination (uniform scatter from the sky) sky_color * sun_access * scatter_factor * get_sun_brightness() + diff --git a/assets/voxygen/shaders/include/globals.glsl b/assets/voxygen/shaders/include/globals.glsl index 11ed591a19..6b3c8373be 100644 --- a/assets/voxygen/shaders/include/globals.glsl +++ b/assets/voxygen/shaders/include/globals.glsl @@ -16,7 +16,7 @@ uniform u_globals { vec4 shadow_proj_factors; uvec4 medium; ivec4 select_pos; - vec4 gamma; + vec4 gamma_exposure; float ambiance; // 0 - FirstPerson // 1 - ThirdPerson diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index ee5a597836..e89ff0a48c 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -22,7 +22,7 @@ const vec3 SUN_HALO_DAY = vec3(0.35, 0.35, 0.05); const vec3 SKY_DUSK_TOP = vec3(0.06, 0.1, 0.20); const vec3 SKY_DUSK_MID = vec3(0.35, 0.1, 0.15); const vec3 SKY_DUSK_BOT = vec3(0.0, 0.1, 0.23); -const vec3 DUSK_LIGHT = vec3(9.0, 0.5, 0.15); +const vec3 DUSK_LIGHT = vec3(5.0, 0.5, 0.15); const vec3 SUN_HALO_DUSK = vec3(1.2, 0.15, 0.01); const vec3 SKY_NIGHT_TOP = vec3(0.001, 0.001, 0.0025); @@ -100,7 +100,7 @@ float get_sun_brightness(/*vec3 sun_dir*/) { } float get_moon_brightness(/*vec3 moon_dir*/) { - return max(-moon_dir.z + 0.6, 0.0) * 0.1; + return max(-moon_dir.z + 0.6, 0.0) * 0.2; } vec3 get_sun_color(/*vec3 sun_dir*/) { diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index d481ba35cd..f006981e4e 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -205,10 +205,12 @@ void main() { vec4 aa_color = aa_apply(src_color, uv * screen_res.xy, screen_res.xy); // Tonemapping - float exposure = 1.0; - aa_color.rgb = vec3(1.0) - exp(-aa_color.rgb * exposure); + float exposure_offset = 1.5; + // Adding an in-code offset to gamma and explosure let us have more precise control over the game's look + float gamma_offset = 0.35; + aa_color.rgb = vec3(1.0) - exp(-aa_color.rgb * (gamma_exposure.y + exposure_offset)); // gamma correction - aa_color.rgb = pow(aa_color.rgb, vec3(gamma)); + aa_color.rgb = pow(aa_color.rgb, vec3(gamma_exposure.x + gamma_offset)); /* // Apply clouds to `aa_color` diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 4198c4abe5..1a9a4c1a2e 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -325,6 +325,7 @@ pub enum Event { ChangeMaxFPS(u32), ChangeFOV(u16), ChangeGamma(f32), + ChangeExposure(f32), ChangeAmbiance(f32), MapZoom(f64), MapDrag(Vec2), @@ -2162,6 +2163,9 @@ impl Hud { settings_window::Event::AdjustGamma(new_gamma) => { events.push(Event::ChangeGamma(new_gamma)); }, + settings_window::Event::AdjustExposure(new_exposure) => { + events.push(Event::ChangeExposure(new_exposure)); + }, settings_window::Event::AdjustAmbiance(new_ambiance) => { events.push(Event::ChangeAmbiance(new_ambiance)); }, diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index a38a1b4980..08b6ccbe3c 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -124,6 +124,9 @@ widget_ids! { gamma_slider, gamma_text, gamma_value, + exposure_slider, + exposure_text, + exposure_value, ambiance_slider, ambiance_text, ambiance_value, @@ -284,6 +287,7 @@ pub enum Event { AdjustFOV(u16), AdjustLodDetail(u32), AdjustGamma(f32), + AdjustExposure(f32), AdjustAmbiance(f32), AdjustWindowSize([u16; 2]), ChangeFullscreenMode(FullScreenSettings), @@ -1900,6 +1904,38 @@ impl<'a> Widget for SettingsWindow<'a> { .color(TEXT_COLOR) .set(state.ids.gamma_value, ui); + // Exposure + if let Some(new_val) = ImageSlider::discrete( + (self.global_state.settings.graphics.exposure * 16.0) as i32, + 0, + 32, + self.imgs.slider_indicator, + self.imgs.slider, + ) + .w_h(104.0, 22.0) + .right_from(state.ids.gamma_slider, 50.0) + .track_breadth(12.0) + .slider_length(10.0) + .pad_track((5.0, 5.0)) + .set(state.ids.exposure_slider, ui) + { + events.push(Event::AdjustExposure(new_val as f32 / 16.0)); + } + + Text::new(&self.localized_strings.get("hud.settings.exposure")) + .up_from(state.ids.exposure_slider, 8.0) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.exposure_text, ui); + + Text::new(&format!("{:.2}", self.global_state.settings.graphics.exposure)) + .right_from(state.ids.exposure_slider, 8.0) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.exposure_value, ui); + //Ambiance Brightness // 320.0 = maximum brightness in shaders let min_ambiance = 10.0; @@ -1912,7 +1948,7 @@ impl<'a> Widget for SettingsWindow<'a> { self.imgs.slider, ) .w_h(104.0, 22.0) - .right_from(state.ids.gamma_slider, 50.0) + .right_from(state.ids.exposure_slider, 50.0) .track_breadth(12.0) .slider_length(10.0) .pad_track((5.0, 5.0)) diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index eb25e93c2e..43e6424076 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -152,6 +152,7 @@ impl PlayState for CharSelectionState { thread_pool: client.thread_pool(), body: humanoid_body, gamma: global_state.settings.graphics.gamma, + exposure: global_state.settings.graphics.exposure, ambiance: global_state.settings.graphics.ambiance, mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable, figure_lod_render_distance: global_state diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 28bf1954b4..9338250bab 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -46,7 +46,7 @@ gfx_defines! { shadow_proj_factors: [f32; 4] = "shadow_proj_factors", medium: [u32; 4] = "medium", select_pos: [i32; 4] = "select_pos", - gamma: [f32; 4] = "gamma", + gamma_exposure: [f32; 4] = "gamma_exposure", ambiance: f32 = "ambiance", cam_mode: u32 = "cam_mode", sprite_render_distance: f32 = "sprite_render_distance", @@ -84,6 +84,7 @@ impl Globals { medium: BlockKind, select_pos: Option>, gamma: f32, + exposure: f32, ambiance: f32, cam_mode: CameraMode, sprite_render_distance: f32, @@ -124,7 +125,7 @@ impl Globals { .map(|sp| Vec4::from(sp) + Vec4::unit_w()) .unwrap_or(Vec4::zero()) .into_array(), - gamma: [gamma; 4], + gamma_exposure: [gamma, exposure, 0.0, 0.0], ambiance, cam_mode: cam_mode as u32, sprite_render_distance, @@ -168,6 +169,7 @@ impl Default for Globals { None, 1.0, 1.0, + 1.0, CameraMode::ThirdPerson, 250.0, ) diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index aae6b08720..538874319b 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -47,7 +47,7 @@ use specs::{Entity as EcsEntity, Join, LazyUpdate, WorldExt}; use treeculler::{BVol, BoundingSphere}; use vek::*; -const DAMAGE_FADE_COEFFICIENT: f64 = 5.0; +const DAMAGE_FADE_COEFFICIENT: f64 = 15.0; const MOVING_THRESHOLD: f32 = 0.7; const MOVING_THRESHOLD_SQR: f32 = MOVING_THRESHOLD * MOVING_THRESHOLD; @@ -665,7 +665,7 @@ impl FigureMgr { let col = health .map(|h| { vek::Rgba::broadcast(1.0) - + vek::Rgba::new(2.0, 2.0, 2., 0.00).map(|c| { + + vek::Rgba::new(10.0, 10.0, 10.0, 0.0).map(|c| { (c / (1.0 + DAMAGE_FADE_COEFFICIENT * h.last_change.0)) as f32 }) }) diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 63b7d25289..d0f4337edc 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -115,6 +115,7 @@ pub struct SceneData<'a> { pub tick: u64, pub thread_pool: &'a uvth::ThreadPool, pub gamma: f32, + pub exposure: f32, pub ambiance: f32, pub mouse_smoothing: bool, pub sprite_render_distance: f32, @@ -659,6 +660,7 @@ impl Scene { .unwrap_or(BlockKind::Air), self.select_pos.map(|e| e - focus_off.map(|e| e as i32)), scene_data.gamma, + scene_data.exposure, scene_data.ambiance, self.camera.get_mode(), scene_data.sprite_render_distance as f32 - 20.0, diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index aff2f577c8..224f45a6fc 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -95,6 +95,7 @@ pub struct SceneData<'a> { pub thread_pool: &'a uvth::ThreadPool, pub body: Option, pub gamma: f32, + pub exposure: f32, pub ambiance: f32, pub figure_lod_render_distance: f32, pub mouse_smoothing: bool, @@ -281,6 +282,7 @@ impl Scene { BlockKind::Air, None, scene_data.gamma, + scene_data.exposure, scene_data.ambiance, self.camera.get_mode(), 250.0, diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index f1aaf633c9..bac31b11b8 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -972,6 +972,10 @@ impl PlayState for SessionState { global_state.settings.graphics.gamma = new_gamma; global_state.settings.save_to_file_warn(); }, + HudEvent::ChangeExposure(new_exposure) => { + global_state.settings.graphics.exposure = new_exposure; + global_state.settings.save_to_file_warn(); + }, HudEvent::ChangeAmbiance(new_ambiance) => { global_state.settings.graphics.ambiance = new_ambiance; global_state.settings.save_to_file_warn(); @@ -1065,6 +1069,7 @@ impl PlayState for SessionState { tick: client.get_tick(), thread_pool: client.thread_pool(), gamma: global_state.settings.graphics.gamma, + exposure: global_state.settings.graphics.exposure, ambiance: global_state.settings.graphics.ambiance, mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable, sprite_render_distance: global_state.settings.graphics.sprite_render_distance @@ -1131,6 +1136,7 @@ impl PlayState for SessionState { tick: client.get_tick(), thread_pool: client.thread_pool(), gamma: settings.graphics.gamma, + exposure: settings.graphics.exposure, ambiance: settings.graphics.ambiance, mouse_smoothing: settings.gameplay.smooth_pan_enable, sprite_render_distance: settings.graphics.sprite_render_distance as f32, diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 3da82fd38a..a810ed5dd3 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -622,6 +622,7 @@ pub struct GraphicsSettings { pub max_fps: u32, pub fov: u16, pub gamma: f32, + pub exposure: f32, pub ambiance: f32, pub render_mode: RenderMode, pub window_size: [u16; 2], @@ -639,6 +640,7 @@ impl Default for GraphicsSettings { max_fps: 60, fov: 50, gamma: 1.0, + exposure: 1.0, ambiance: 20.0, render_mode: RenderMode::default(), window_size: [1920, 1080],