Added configurable sprite view distance, minor bug fixes

This commit is contained in:
Joshua Barretto 2020-04-25 14:04:30 +01:00
parent 8bf5709ddf
commit c05f4fe009
12 changed files with 71 additions and 62 deletions

View File

@ -16,6 +16,7 @@ uniform u_globals {
// 0 - FirstPerson
// 1 - ThirdPerson
uint cam_mode;
float sprite_render_distance;
};
// Specifies the pattern used in the player dithering
@ -26,4 +27,4 @@ mat4 threshold_matrix = mat4(
vec4(16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0)
);
float distance_divider = 2;
float shadow_dithering = 0.5;
float shadow_dithering = 0.5;

View File

@ -13,7 +13,6 @@ out vec4 tgt_color;
#include <sky.glsl>
#include <light.glsl>
const float RENDER_DIST = 180.0;
const float FADE_DIST = 32.0;
void main() {
@ -35,5 +34,5 @@ void main() {
vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x, cam_pos.xyz, f_pos, 0.5, true, clouds);
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
tgt_color = vec4(color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (RENDER_DIST - FADE_DIST)) / FADE_DIST, 0, 1));
tgt_color = vec4(color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (sprite_render_distance - FADE_DIST)) / FADE_DIST, 0, 1));
}

View File

@ -32,6 +32,7 @@ void main() {
vec3 sprite_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz;
f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz;
f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
// Wind waving
f_pos += inst_wind_sway * vec3(

View File

@ -210,6 +210,7 @@ pub enum Event {
ToggleMouseYInvert(bool),
ToggleSmoothPan(bool),
AdjustViewDistance(u32),
AdjustSpriteRenderDistance(u32),
AdjustMusicVolume(f32),
AdjustSfxVolume(f32),
ChangeAudioDevice(String),
@ -1801,6 +1802,9 @@ impl Hud {
settings_window::Event::AdjustViewDistance(view_distance) => {
events.push(Event::AdjustViewDistance(view_distance));
},
settings_window::Event::AdjustSpriteRenderDistance(view_distance) => {
events.push(Event::AdjustSpriteRenderDistance(view_distance));
},
settings_window::Event::CrosshairTransp(crosshair_transp) => {
events.push(Event::CrosshairTransp(crosshair_transp));
},

View File

@ -212,6 +212,7 @@ pub enum Event {
ToggleMouseYInvert(bool),
ToggleSmoothPan(bool),
AdjustViewDistance(u32),
AdjustSpriteRenderDistance(u32),
AdjustFOV(u16),
AdjustGamma(f32),
AdjustWindowSize([u16; 2]),
@ -1617,9 +1618,9 @@ impl<'a> Widget for SettingsWindow<'a> {
.set(state.ids.gamma_value, ui);
// Sprites VD
if let Some(new_val) = ImageSlider::discrete(
self.global_state.settings.graphics.view_distance,
1,
65,
self.global_state.settings.graphics.sprite_render_distance,
50,
500,
self.imgs.slider_indicator,
self.imgs.slider,
)
@ -1630,7 +1631,7 @@ impl<'a> Widget for SettingsWindow<'a> {
.pad_track((5.0, 5.0))
.set(state.ids.sprite_dist_slider, ui)
{
events.push(Event::AdjustViewDistance(new_val));
events.push(Event::AdjustSpriteRenderDistance(new_val));
}
Text::new(
&self
@ -1645,7 +1646,7 @@ impl<'a> Widget for SettingsWindow<'a> {
Text::new(&format!(
"{}",
self.global_state.settings.graphics.view_distance
self.global_state.settings.graphics.sprite_render_distance
))
.right_from(state.ids.sprite_dist_slider, 8.0)
.font_size(self.fonts.cyri.scale(14))

View File

@ -29,6 +29,7 @@ gfx_defines! {
select_pos: [i32; 4] = "select_pos",
gamma: [f32; 4] = "gamma",
cam_mode: u32 = "cam_mode",
sprite_render_distance: f32 = "sprite_render_distance",
}
constant Light {
@ -58,6 +59,7 @@ impl Globals {
select_pos: Option<Vec3<i32>>,
gamma: f32,
cam_mode: CameraMode,
sprite_render_distance: f32,
) -> Self {
Self {
view_mat: arr_to_mat(view_mat.into_col_array()),
@ -77,6 +79,7 @@ impl Globals {
.into_array(),
gamma: [gamma; 4],
cam_mode: cam_mode as u32,
sprite_render_distance,
}
}
}
@ -98,6 +101,7 @@ impl Default for Globals {
None,
1.0,
CameraMode::ThirdPerson,
250.0,
)
}
}

View File

@ -76,6 +76,7 @@ pub struct SceneData<'a> {
pub thread_pool: &'a uvth::ThreadPool,
pub gamma: f32,
pub mouse_smoothing: bool,
pub sprite_render_distance: f32,
}
impl Scene {
@ -353,6 +354,7 @@ impl Scene {
self.select_pos,
scene_data.gamma,
self.camera.get_mode(),
scene_data.sprite_render_distance as f32 - 20.0,
)])
.expect("Failed to update global constants");
@ -385,6 +387,7 @@ impl Scene {
state: &State,
player_entity: EcsEntity,
tick: u64,
scene_data: &SceneData,
) {
// Render terrain and figures.
self.terrain.render(
@ -425,6 +428,7 @@ impl Scene {
&self.lights,
&self.shadows,
self.camera.get_focus_pos(),
scene_data.sprite_render_distance,
);
renderer.render_post_process(

View File

@ -183,6 +183,7 @@ impl Scene {
None,
scene_data.gamma,
self.camera.get_mode(),
250.0,
)]) {
error!("Renderer failed to update: {:?}", err);
}

View File

@ -330,10 +330,12 @@ impl<V: RectRasterableVol> Terrain<V> {
let scaled = [1.0, 0.6, 0.4, 0.2];
scaled
.iter()
.map(|lod_scale| if *lod_scale == 1.0 {
Vec3::broadcast(1.0)
} else {
lod_axes * *lod_scale + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 })
.map(|lod_scale| {
if *lod_scale == 1.0 {
Vec3::broadcast(1.0)
} else {
lod_axes * *lod_scale + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 })
}
})
.map(|lod_scale| {
renderer
@ -2229,6 +2231,7 @@ impl<V: RectRasterableVol> Terrain<V> {
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
focus_pos: Vec3<f32>,
sprite_render_distance: f32,
) {
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
(e as i32).div_euclid(sz as i32)
@ -2252,22 +2255,21 @@ impl<V: RectRasterableVol> Terrain<V> {
// Terrain sprites
for (pos, chunk) in chunk_iter.clone() {
if chunk.visible {
const SPRITE_RENDER_DISTANCE: f32 = 200.0;
const SPRITE_DETAIL_LOW_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.65;
const SPRITE_DETAIL_MID_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.4;
const SPRITE_DETAIL_HIGH_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.25;
let sprite_detail_low_distance = sprite_render_distance * 0.65;
let sprite_detail_mid_distance = sprite_render_distance * 0.4;
let sprite_detail_high_distance = sprite_render_distance * 0.25;
let chunk_center =
pos.map2(V::RECT_SIZE, |e, sz: u32| (e as f32 + 0.5) * sz as f32);
let dist_sqrd = Vec2::from(focus_pos).distance_squared(chunk_center);
if dist_sqrd < SPRITE_RENDER_DISTANCE.powf(2.0) {
if dist_sqrd < sprite_render_distance.powf(2.0) {
for (kind, instances) in &chunk.sprite_instances {
renderer.render_sprites(
if dist_sqrd < SPRITE_DETAIL_HIGH_DISTANCE.powf(2.0) {
if dist_sqrd < sprite_detail_high_distance.powf(2.0) {
&self.sprite_models[&kind][0]
} else if dist_sqrd < SPRITE_DETAIL_MID_DISTANCE.powf(2.0) {
} else if dist_sqrd < sprite_detail_mid_distance.powf(2.0) {
&self.sprite_models[&kind][1]
} else if dist_sqrd < SPRITE_DETAIL_LOW_DISTANCE.powf(2.0) {
} else if dist_sqrd < sprite_detail_low_distance.powf(2.0) {
&self.sprite_models[&kind][2]
} else {
&self.sprite_models[&kind][3]

View File

@ -4,7 +4,6 @@ use crate::{
i18n::{i18n_asset_key, VoxygenLocalization},
key_state::KeyState,
menu::char_selection::CharSelectionState,
render::Renderer,
scene::{camera, Scene, SceneData},
settings::AudioOutput,
window::{AnalogGameInput, Event, GameInput},
@ -111,26 +110,6 @@ impl SessionState {
/// Clean up the session (and the client attached to it) after a tick.
pub fn cleanup(&mut self) { self.client.borrow_mut().cleanup(); }
/// Render the session to the screen.
///
/// This method should be called once per frame.
pub fn render(&mut self, renderer: &mut Renderer) {
// Clear the screen
renderer.clear();
// Render the screen using the global renderer
{
let client = self.client.borrow();
self.scene
.render(renderer, client.state(), client.entity(), client.get_tick());
}
// Draw the UI to the screen
self.hud.render(renderer, self.scene.globals());
// Finish the frame
renderer.flush();
}
}
impl PlayState for SessionState {
@ -589,6 +568,10 @@ impl PlayState for SessionState {
global_state.settings.graphics.view_distance = view_distance;
global_state.settings.save_to_file_warn();
},
HudEvent::AdjustSpriteRenderDistance(sprite_render_distance) => {
global_state.settings.graphics.sprite_render_distance = sprite_render_distance;
global_state.settings.save_to_file_warn();
},
HudEvent::CrosshairTransp(crosshair_transp) => {
global_state.settings.gameplay.crosshair_transp = crosshair_transp;
global_state.settings.save_to_file_warn();
@ -720,9 +703,6 @@ impl PlayState for SessionState {
}
}
// Runs if either in a multiplayer server or the singleplayer server is unpaused
if global_state.singleplayer.is_none()
|| !global_state.singleplayer.as_ref().unwrap().is_paused()
{
let client = self.client.borrow();
let scene_data = SceneData {
@ -734,16 +714,30 @@ impl PlayState for SessionState {
thread_pool: client.thread_pool(),
gamma: global_state.settings.graphics.gamma,
mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable,
sprite_render_distance: global_state.settings.graphics.sprite_render_distance as f32,
};
self.scene.maintain(
global_state.window.renderer_mut(),
&mut global_state.audio,
&scene_data,
);
}
// Render the session.
self.render(global_state.window.renderer_mut());
// Runs if either in a multiplayer server or the singleplayer server is unpaused
if global_state.singleplayer.is_none()
|| !global_state.singleplayer.as_ref().unwrap().is_paused()
{
self.scene.maintain(
global_state.window.renderer_mut(),
&mut global_state.audio,
&scene_data,
);
}
let renderer = global_state.window.renderer_mut();
// Clear the screen
renderer.clear();
// Render the screen using the global renderer
self.scene.render(renderer, client.state(), client.entity(), client.get_tick(), &scene_data);
// Draw the UI to the screen
self.hud.render(renderer, self.scene.globals());
// Finish the frame
renderer.flush();
}
// Display the frame on the window.
global_state

View File

@ -548,6 +548,7 @@ impl Default for Log {
#[serde(default)]
pub struct GraphicsSettings {
pub view_distance: u32,
pub sprite_render_distance: u32,
pub max_fps: u32,
pub fov: u16,
pub gamma: f32,
@ -562,6 +563,7 @@ impl Default for GraphicsSettings {
fn default() -> Self {
Self {
view_distance: 10,
sprite_render_distance: 250,
max_fps: 60,
fov: 50,
gamma: 1.0,

View File

@ -142,16 +142,12 @@ impl Civs {
let mut rng = ctx.reseed().rng;
let world_site = match &site.kind {
SiteKind::Settlement => WorldSite::from(Settlement::generate(
wpos,
Some(ctx.sim),
&mut rng,
)),
SiteKind::Dungeon => WorldSite::from(Dungeon::generate(
wpos,
Some(ctx.sim),
&mut rng,
)),
SiteKind::Settlement => {
WorldSite::from(Settlement::generate(wpos, Some(ctx.sim), &mut rng))
},
SiteKind::Dungeon => {
WorldSite::from(Dungeon::generate(wpos, Some(ctx.sim), &mut rng))
},
};
let radius_chunks =