mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added LoD for figures and reduced update rates for far figures
This commit is contained in:
parent
3e62f7edc3
commit
39b88dbcb1
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -117,7 +117,7 @@ impl FigureMgr {
|
|||||||
.get(scene_data.player_entity)
|
.get(scene_data.player_entity)
|
||||||
.map_or(Vec3::zero(), |pos| pos.0);
|
.map_or(Vec3::zero(), |pos| pos.0);
|
||||||
|
|
||||||
for (
|
for (i, (
|
||||||
entity,
|
entity,
|
||||||
pos,
|
pos,
|
||||||
interpolated,
|
interpolated,
|
||||||
@ -129,7 +129,7 @@ impl FigureMgr {
|
|||||||
physics,
|
physics,
|
||||||
stats,
|
stats,
|
||||||
loadout,
|
loadout,
|
||||||
) in (
|
)) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
ecs.read_storage::<Interpolated>().maybe(),
|
ecs.read_storage::<Interpolated>().maybe(),
|
||||||
@ -143,7 +143,20 @@ impl FigureMgr {
|
|||||||
ecs.read_storage::<Loadout>().maybe(),
|
ecs.read_storage::<Loadout>().maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
|
.enumerate()
|
||||||
{
|
{
|
||||||
|
// Maintaining figure data and sending new figure data to the GPU turns out to be a
|
||||||
|
// very expensive operation. We want to avoid doing it as much as possible, so we
|
||||||
|
// make the assumption that players don't care so much about the update *rate* for far
|
||||||
|
// away things. As the entity goes further and further away, we start to 'skip' update
|
||||||
|
// ticks.
|
||||||
|
// TODO: Investigate passing the velocity into the shader so we can at least
|
||||||
|
// interpolate motion
|
||||||
|
const MIN_PERFECT_RATE_DIST: f32 = 96.0;
|
||||||
|
if (i as u64 + tick) % 1 + ((pos.0.distance(camera.get_focus_pos()).powf(0.5) - MIN_PERFECT_RATE_DIST.powf(0.5)).max(0.0) / 5.0) as u64 != 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let is_player = scene_data.player_entity == entity;
|
let is_player = scene_data.player_entity == entity;
|
||||||
|
|
||||||
let (pos, ori) = interpolated
|
let (pos, ori) = interpolated
|
||||||
@ -1385,7 +1398,7 @@ impl FigureMgr {
|
|||||||
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
|
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
|
||||||
let character_state = character_state_storage.get(player_entity);
|
let character_state = character_state_storage.get(player_entity);
|
||||||
|
|
||||||
for (entity, _, _, body, _, loadout, _) in (
|
for (entity, pos, _, body, _, loadout, _) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
ecs.read_storage::<Ori>().maybe(),
|
ecs.read_storage::<Ori>().maybe(),
|
||||||
@ -1413,6 +1426,7 @@ impl FigureMgr {
|
|||||||
body,
|
body,
|
||||||
loadout,
|
loadout,
|
||||||
false,
|
false,
|
||||||
|
pos.0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1434,7 +1448,10 @@ impl FigureMgr {
|
|||||||
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
|
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
|
||||||
let character_state = character_state_storage.get(player_entity);
|
let character_state = character_state_storage.get(player_entity);
|
||||||
|
|
||||||
if let Some(body) = ecs.read_storage::<Body>().get(player_entity) {
|
if let (Some(pos), Some(body)) = (
|
||||||
|
ecs.read_storage::<Pos>().get(player_entity),
|
||||||
|
ecs.read_storage::<Body>().get(player_entity),
|
||||||
|
) {
|
||||||
let stats_storage = state.read_storage::<Stats>();
|
let stats_storage = state.read_storage::<Stats>();
|
||||||
let stats = stats_storage.get(player_entity);
|
let stats = stats_storage.get(player_entity);
|
||||||
|
|
||||||
@ -1457,6 +1474,7 @@ impl FigureMgr {
|
|||||||
body,
|
body,
|
||||||
loadout,
|
loadout,
|
||||||
true,
|
true,
|
||||||
|
pos.0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1474,6 +1492,7 @@ impl FigureMgr {
|
|||||||
body: &Body,
|
body: &Body,
|
||||||
loadout: Option<&Loadout>,
|
loadout: Option<&Loadout>,
|
||||||
is_player: bool,
|
is_player: bool,
|
||||||
|
pos: Vec3<f32>,
|
||||||
) {
|
) {
|
||||||
let player_camera_mode = if is_player {
|
let player_camera_mode = if is_player {
|
||||||
camera.get_mode()
|
camera.get_mode()
|
||||||
@ -1686,6 +1705,17 @@ impl FigureMgr {
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
} {
|
} {
|
||||||
|
const FIGURE_LOD_LOW_DIST: f32 = 150.0;
|
||||||
|
const FIGURE_LOD_MID_DIST: f32 = 70.0;
|
||||||
|
|
||||||
|
let model = if pos.distance_squared(camera.get_focus_pos()) > FIGURE_LOD_LOW_DIST.powf(2.0) {
|
||||||
|
&model[2]
|
||||||
|
} else if pos.distance_squared(camera.get_focus_pos()) > FIGURE_LOD_MID_DIST.powf(2.0) {
|
||||||
|
&model[1]
|
||||||
|
} else {
|
||||||
|
&model[0]
|
||||||
|
};
|
||||||
|
|
||||||
if is_player {
|
if is_player {
|
||||||
renderer.render_player(model, globals, locals, bone_consts, lights, shadows);
|
renderer.render_player(model, globals, locals, bone_consts, lights, shadows);
|
||||||
renderer.render_player_shadow(model, globals, locals, bone_consts, lights, shadows);
|
renderer.render_player_shadow(model, globals, locals, bone_consts, lights, shadows);
|
||||||
|
@ -7,17 +7,20 @@ use crate::{
|
|||||||
render::{
|
render::{
|
||||||
create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Model,
|
create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Model,
|
||||||
PostProcessLocals, PostProcessPipeline, Renderer, Shadow, SkyboxLocals, SkyboxPipeline,
|
PostProcessLocals, PostProcessPipeline, Renderer, Shadow, SkyboxLocals, SkyboxPipeline,
|
||||||
|
Mesh,
|
||||||
},
|
},
|
||||||
scene::{
|
scene::{
|
||||||
camera::{self, Camera, CameraMode},
|
camera::{self, Camera, CameraMode},
|
||||||
figure::{load_mesh, FigureModelCache, FigureState},
|
figure::{load_mesh, FigureModelCache, FigureState},
|
||||||
},
|
},
|
||||||
window::{Event, PressState},
|
window::{Event, PressState},
|
||||||
|
mesh::Meshable,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{humanoid, Body, Loadout},
|
comp::{humanoid, Body, Loadout},
|
||||||
terrain::BlockKind,
|
terrain::BlockKind,
|
||||||
vol::{BaseVol, ReadVol, Vox},
|
vol::{BaseVol, ReadVol, Vox},
|
||||||
|
figure::Segment,
|
||||||
};
|
};
|
||||||
use log::error;
|
use log::error;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -40,6 +43,10 @@ impl ReadVol for VoidVol {
|
|||||||
fn get<'a>(&'a self, _pos: Vec3<i32>) -> Result<&'a Self::Vox, Self::Error> { Ok(&VoidVox) }
|
fn get<'a>(&'a self, _pos: Vec3<i32>) -> Result<&'a Self::Vox, Self::Error> { Ok(&VoidVox) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_mesh(segment: &Segment, offset: Vec3<f32>) -> Mesh<FigurePipeline> {
|
||||||
|
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(segment, (offset, Vec3::one())).0
|
||||||
|
}
|
||||||
|
|
||||||
struct Skybox {
|
struct Skybox {
|
||||||
model: Model<SkyboxPipeline>,
|
model: Model<SkyboxPipeline>,
|
||||||
locals: Consts<SkyboxLocals>,
|
locals: Consts<SkyboxLocals>,
|
||||||
@ -107,7 +114,7 @@ impl Scene {
|
|||||||
backdrop: backdrop.map(|specifier| {
|
backdrop: backdrop.map(|specifier| {
|
||||||
(
|
(
|
||||||
renderer
|
renderer
|
||||||
.create_model(&load_mesh(specifier, Vec3::new(-55.0, -49.5, -2.0)))
|
.create_model(&load_mesh(specifier, Vec3::new(-55.0, -49.5, -2.0), generate_mesh))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
FigureState::new(renderer, FixtureSkeleton::new()),
|
FigureState::new(renderer, FixtureSkeleton::new()),
|
||||||
)
|
)
|
||||||
@ -229,7 +236,7 @@ impl Scene {
|
|||||||
.0;
|
.0;
|
||||||
|
|
||||||
renderer.render_figure(
|
renderer.render_figure(
|
||||||
model,
|
&model[0],
|
||||||
&self.globals,
|
&self.globals,
|
||||||
self.figure_state.locals(),
|
self.figure_state.locals(),
|
||||||
self.figure_state.bone_consts(),
|
self.figure_state.bone_consts(),
|
||||||
|
Loading…
Reference in New Issue
Block a user