Added LoD slider

This commit is contained in:
Joshua Barretto 2020-02-24 15:14:06 +00:00
parent 779c36b538
commit aab059a450
7 changed files with 102 additions and 20 deletions

View File

@ -3,7 +3,7 @@
uniform sampler2D t_map;
vec2 pos_to_uv(vec2 pos) {
vec2 uv_pos = pos / 32768.0;
vec2 uv_pos = (pos + 16) / 32768.0;
return vec2(uv_pos.x, 1.0 - uv_pos.y);
}

View File

@ -196,6 +196,7 @@ pub enum Event {
ToggleZoomInvert(bool),
ToggleMouseYInvert(bool),
AdjustViewDistance(u32),
AdjustLodDetail(u32),
AdjustMusicVolume(f32),
AdjustSfxVolume(f32),
ChangeAudioDevice(String),
@ -1744,6 +1745,9 @@ impl Hud {
settings_window::Event::AdjustViewDistance(view_distance) => {
events.push(Event::AdjustViewDistance(view_distance));
},
settings_window::Event::AdjustLodDetail(lod_detail) => {
events.push(Event::AdjustLodDetail(lod_detail));
},
settings_window::Event::CrosshairTransp(crosshair_transp) => {
events.push(Event::CrosshairTransp(crosshair_transp));
},

View File

@ -83,6 +83,9 @@ widget_ids! {
vd_slider,
vd_text,
vd_value,
lod_detail_slider,
lod_detail_text,
lod_detail_value,
max_fps_slider,
max_fps_text,
max_fps_value,
@ -202,6 +205,7 @@ pub enum Event {
ToggleMouseYInvert(bool),
AdjustViewDistance(u32),
AdjustFOV(u16),
AdjustLodDetail(u32),
AdjustGamma(f32),
AdjustWindowSize([u16; 2]),
ToggleFullscreen,
@ -1558,9 +1562,44 @@ impl<'a> Widget for SettingsWindow<'a> {
.color(TEXT_COLOR)
.set(state.ids.fov_value, ui);
// LoD detail
Text::new(&self.localized_strings.get("hud.settings.lod_detail"))
.down_from(state.ids.fov_slider, 10.0)
.font_size(self.fonts.cyri.scale(14))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.lod_detail_text, ui);
if let Some(new_val) = ImageSlider::discrete(
self.global_state.settings.graphics.lod_detail,
100,
2000,
self.imgs.slider_indicator,
self.imgs.slider,
)
.w_h(104.0, 22.0)
.down_from(state.ids.lod_detail_text, 8.0)
.track_breadth(12.0)
.slider_length(10.0)
.pad_track((5.0, 5.0))
.set(state.ids.lod_detail_slider, ui)
{
events.push(Event::AdjustLodDetail(new_val as u32));
}
Text::new(&format!(
"{}",
self.global_state.settings.graphics.lod_detail
))
.right_from(state.ids.lod_detail_slider, 8.0)
.font_size(self.fonts.cyri.scale(14))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.lod_detail_value, ui);
// Gamma
Text::new(&self.localized_strings.get("hud.settings.gamma"))
.down_from(state.ids.fov_slider, 10.0)
.down_from(state.ids.lod_detail_slider, 10.0)
.font_size(self.fonts.cyri.scale(14))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)

View File

@ -1,38 +1,61 @@
use crate::render::{
pipelines::lod_terrain::{Locals, Vertex},
Consts, FilterMethod, Globals, LodTerrainPipeline, Mesh, Model, Quad, Renderer, Texture,
use crate::{
render::{
pipelines::lod_terrain::{Locals, Vertex},
Consts, FilterMethod, Globals, LodTerrainPipeline, Mesh, Model, Quad, Renderer, Texture,
},
settings::Settings,
};
use client::Client;
use common::spiral::Spiral2d;
use vek::*;
pub struct Lod {
model: Model<LodTerrainPipeline>,
model: Option<(u32, Model<LodTerrainPipeline>)>,
locals: Consts<Locals>,
map: Texture,
tgt_detail: u32,
}
impl Lod {
pub fn new(renderer: &mut Renderer, client: &Client) -> Self {
pub fn new(renderer: &mut Renderer, client: &Client, settings: &Settings) -> Self {
Self {
model: renderer
.create_model(&create_lod_terrain_mesh(500))
.unwrap(),
model: None,
locals: renderer.create_consts(&[Locals::default()]).unwrap(),
map: renderer
.create_texture(&client.world_map.0, Some(FilterMethod::Trilinear), None)
.expect("Failed to generate map texture"),
tgt_detail: settings.graphics.lod_detail,
}
}
pub fn set_detail(&mut self, detail: u32) { self.tgt_detail = detail.max(100).min(2000); }
pub fn maintain(&mut self, renderer: &mut Renderer) {
if self
.model
.as_ref()
.map(|(detail, _)| *detail != self.tgt_detail)
.unwrap_or(true)
{
self.model = Some((
self.tgt_detail,
renderer
.create_model(&create_lod_terrain_mesh(self.tgt_detail))
.unwrap(),
));
}
}
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
renderer.render_lod_terrain(&self.model, globals, &self.locals, &self.map);
if let Some((_, model)) = self.model.as_ref() {
renderer.render_lod_terrain(&model, globals, &self.locals, &self.map);
}
}
}
fn create_lod_terrain_mesh(detail: usize) -> Mesh<LodTerrainPipeline> {
fn create_lod_terrain_mesh(detail: u32) -> Mesh<LodTerrainPipeline> {
Spiral2d::new()
.take(detail * detail)
.take((detail * detail) as usize)
.map(|pos| {
let x = pos.x + detail as i32 / 2;
let y = pos.y + detail as i32 / 2;

View File

@ -17,6 +17,7 @@ use crate::{
create_pp_mesh, create_skybox_mesh, Consts, Globals, Light, Model, PostProcessLocals,
PostProcessPipeline, Renderer, Shadow, SkyboxLocals, SkyboxPipeline,
},
settings::Settings,
window::Event,
};
use client::Client;
@ -56,7 +57,7 @@ pub struct Scene {
skybox: Skybox,
postprocess: PostProcess,
terrain: Terrain<TerrainChunk>,
lod: Lod,
pub lod: Lod,
loaded_distance: f32,
select_pos: Option<Vec3<i32>>,
@ -67,7 +68,7 @@ pub struct Scene {
impl Scene {
/// Create a new `Scene` with default parameters.
pub fn new(renderer: &mut Renderer, client: &Client) -> Self {
pub fn new(renderer: &mut Renderer, client: &Client, settings: &Settings) -> Self {
let resolution = renderer.get_resolution().map(|e| e as f32);
Self {
@ -91,7 +92,7 @@ impl Scene {
.unwrap(),
},
terrain: Terrain::new(renderer),
lod: Lod::new(renderer, client),
lod: Lod::new(renderer, client, settings),
loaded_distance: 0.0,
select_pos: None,
@ -153,7 +154,7 @@ impl Scene {
renderer: &mut Renderer,
audio: &mut AudioFrontend,
client: &Client,
gamma: f32,
settings: &Settings,
) {
// Get player position.
let player_pos = client
@ -301,10 +302,13 @@ impl Scene {
.map(|b| b.kind())
.unwrap_or(BlockKind::Air),
self.select_pos,
gamma,
settings.graphics.gamma,
)])
.expect("Failed to update global constants");
// Maintain LoD.
self.lod.maintain(renderer);
// Maintain the terrain.
self.terrain.maintain(
renderer,

View File

@ -39,7 +39,11 @@ impl SessionState {
pub fn new(global_state: &mut GlobalState, client: Rc<RefCell<Client>>) -> Self {
// Create a scene for this session. The scene handles visible elements of the
// game world.
let mut scene = Scene::new(global_state.window.renderer_mut(), &*client.borrow());
let mut scene = Scene::new(
global_state.window.renderer_mut(),
&*client.borrow(),
&global_state.settings,
);
scene
.camera_mut()
.set_fov_deg(global_state.settings.graphics.fov);
@ -484,6 +488,12 @@ impl PlayState for SessionState {
global_state.settings.graphics.view_distance = view_distance;
global_state.settings.save_to_file_warn();
},
HudEvent::AdjustLodDetail(lod_detail) => {
self.scene.lod.set_detail(lod_detail);
global_state.settings.graphics.lod_detail = lod_detail;
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();
@ -614,7 +624,7 @@ impl PlayState for SessionState {
global_state.window.renderer_mut(),
&mut global_state.audio,
&self.client.borrow(),
global_state.settings.graphics.gamma,
&global_state.settings,
);
// Render the session.

View File

@ -197,6 +197,7 @@ pub struct GraphicsSettings {
pub fluid_mode: FluidMode,
pub window_size: [u16; 2],
pub fullscreen: bool,
pub lod_detail: u32,
}
impl Default for GraphicsSettings {
@ -211,6 +212,7 @@ impl Default for GraphicsSettings {
fluid_mode: FluidMode::Shiny,
window_size: [1920, 1080],
fullscreen: false,
lod_detail: 500,
}
}
}