mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'zesterer/perf' into 'master'
Performance improvements, LoD system for terrain sprites and figures See merge request veloren/veloren!944
This commit is contained in:
commit
e690efe717
@ -62,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Made players spawn in towns
|
- Made players spawn in towns
|
||||||
- Added non-uniform block heights
|
- Added non-uniform block heights
|
||||||
- Added `/sudo` command
|
- Added `/sudo` command
|
||||||
|
- Added a Level of Detail (LoD) system for terrain sprites and entities
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -252,7 +252,8 @@ Viel Spaß in der Welt von Veloren, Abenteurer!"#,
|
|||||||
"hud.settings.invert_mouse_y_axis": "Maus Y-Achse invertieren",
|
"hud.settings.invert_mouse_y_axis": "Maus Y-Achse invertieren",
|
||||||
"hud.settings.free_look_behavior": "Freies Umsehen",
|
"hud.settings.free_look_behavior": "Freies Umsehen",
|
||||||
|
|
||||||
"hud.settings.view_distance": "Sichtweite",
|
"hud.settings.view_distance": "Gelände Sichtweite",
|
||||||
|
"hud.settings.sprites_view_distance": "Objekt Sichtweite",
|
||||||
"hud.settings.maximum_fps": "Maximale FPS",
|
"hud.settings.maximum_fps": "Maximale FPS",
|
||||||
"hud.settings.fov": "Sichtfeld (Grad)",
|
"hud.settings.fov": "Sichtfeld (Grad)",
|
||||||
"hud.settings.gamma": "Gamma",
|
"hud.settings.gamma": "Gamma",
|
||||||
|
@ -250,6 +250,7 @@ Enjoy your stay in the World of Veloren."#,
|
|||||||
"hud.settings.free_look_behavior": "Free look behavior",
|
"hud.settings.free_look_behavior": "Free look behavior",
|
||||||
|
|
||||||
"hud.settings.view_distance": "View Distance",
|
"hud.settings.view_distance": "View Distance",
|
||||||
|
"hud.settings.sprites_view_distance": "Sprites View Distance",
|
||||||
"hud.settings.maximum_fps": "Maximum FPS",
|
"hud.settings.maximum_fps": "Maximum FPS",
|
||||||
"hud.settings.fov": "Field of View (deg)",
|
"hud.settings.fov": "Field of View (deg)",
|
||||||
"hud.settings.gamma": "Gamma",
|
"hud.settings.gamma": "Gamma",
|
||||||
|
@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
#include <globals.glsl>
|
#include <globals.glsl>
|
||||||
|
|
||||||
in vec3 v_pos;
|
in uint v_pos_norm;
|
||||||
in vec3 v_norm;
|
in vec3 v_norm;
|
||||||
in vec3 v_col;
|
in uint v_col;
|
||||||
in float v_ao;
|
in uint v_ao_bone;
|
||||||
in uint v_bone_idx;
|
|
||||||
|
|
||||||
layout (std140)
|
layout (std140)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
@ -23,6 +22,7 @@ struct BoneData {
|
|||||||
|
|
||||||
layout (std140)
|
layout (std140)
|
||||||
uniform u_bones {
|
uniform u_bones {
|
||||||
|
// Warning: might not actually be 16 elements long. Don't index out of bounds!
|
||||||
BoneData bones[16];
|
BoneData bones[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,20 +33,27 @@ flat out vec3 f_norm;
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Pre-calculate bone matrix
|
// Pre-calculate bone matrix
|
||||||
mat4 combined_mat = model_mat * bones[v_bone_idx].bone_mat;
|
uint bone_idx = (v_ao_bone >> 2) & 0x3Fu;
|
||||||
|
mat4 combined_mat = model_mat * bones[bone_idx].bone_mat;
|
||||||
|
|
||||||
|
vec3 pos = vec3((uvec3(v_pos_norm) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) - 128.0;
|
||||||
|
|
||||||
f_pos = (
|
f_pos = (
|
||||||
combined_mat *
|
combined_mat *
|
||||||
vec4(v_pos, 1)).xyz;
|
vec4(pos, 1)).xyz;
|
||||||
|
|
||||||
f_col = v_col;
|
f_col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0;
|
||||||
|
|
||||||
f_ao = v_ao;
|
f_ao = float(v_ao_bone & 0x3u) / 4.0;
|
||||||
|
|
||||||
|
// First 3 normals are negative, next 3 are positive
|
||||||
|
vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
|
||||||
|
vec3 norm = normals[(v_pos_norm >> 24) & 0x7u];
|
||||||
|
|
||||||
// Calculate normal here rather than for each pixel in the fragment shader
|
// Calculate normal here rather than for each pixel in the fragment shader
|
||||||
f_norm = normalize((
|
f_norm = normalize((
|
||||||
combined_mat *
|
combined_mat *
|
||||||
vec4(v_norm, 0.0)
|
vec4(norm, 0.0)
|
||||||
).xyz);
|
).xyz);
|
||||||
|
|
||||||
gl_Position = all_mat * vec4(f_pos, 1);
|
gl_Position = all_mat * vec4(f_pos, 1);
|
||||||
|
@ -16,6 +16,7 @@ uniform u_globals {
|
|||||||
// 0 - FirstPerson
|
// 0 - FirstPerson
|
||||||
// 1 - ThirdPerson
|
// 1 - ThirdPerson
|
||||||
uint cam_mode;
|
uint cam_mode;
|
||||||
|
float sprite_render_distance;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specifies the pattern used in the player dithering
|
// Specifies the pattern used in the player dithering
|
||||||
|
@ -13,7 +13,6 @@ out vec4 tgt_color;
|
|||||||
#include <sky.glsl>
|
#include <sky.glsl>
|
||||||
#include <light.glsl>
|
#include <light.glsl>
|
||||||
|
|
||||||
const float RENDER_DIST = 112.0;
|
|
||||||
const float FADE_DIST = 32.0;
|
const float FADE_DIST = 32.0;
|
||||||
|
|
||||||
void main() {
|
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 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);
|
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));
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
#include <srgb.glsl>
|
#include <srgb.glsl>
|
||||||
|
|
||||||
in vec3 v_pos;
|
in vec3 v_pos;
|
||||||
in vec3 v_norm;
|
in uint v_col;
|
||||||
in vec3 v_col;
|
in uint v_norm_ao;
|
||||||
in float v_ao;
|
|
||||||
in vec4 inst_mat0;
|
in vec4 inst_mat0;
|
||||||
in vec4 inst_mat1;
|
in vec4 inst_mat1;
|
||||||
in vec4 inst_mat2;
|
in vec4 inst_mat2;
|
||||||
@ -32,6 +31,7 @@ void main() {
|
|||||||
vec3 sprite_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz;
|
vec3 sprite_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz;
|
||||||
|
|
||||||
f_pos = (inst_mat * vec4(v_pos * SCALE, 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
|
// Wind waving
|
||||||
f_pos += inst_wind_sway * vec3(
|
f_pos += inst_wind_sway * vec3(
|
||||||
@ -40,10 +40,13 @@ void main() {
|
|||||||
0.0
|
0.0
|
||||||
) * pow(abs(v_pos.z) * SCALE, 1.3) * 0.2;
|
) * pow(abs(v_pos.z) * SCALE, 1.3) * 0.2;
|
||||||
|
|
||||||
f_norm = (inst_mat * vec4(v_norm, 0)).xyz;
|
// First 3 normals are negative, next 3 are positive
|
||||||
|
vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
|
||||||
|
f_norm = (inst_mat * vec4(normals[(v_norm_ao >> 0) & 0x7u], 0)).xyz;
|
||||||
|
|
||||||
f_col = srgb_to_linear(v_col) * srgb_to_linear(inst_col);
|
vec3 col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0;
|
||||||
f_ao = v_ao;
|
f_col = srgb_to_linear(col) * srgb_to_linear(inst_col);
|
||||||
|
f_ao = float((v_norm_ao >> 3) & 0x3u) / 4.0;
|
||||||
|
|
||||||
// Select glowing
|
// Select glowing
|
||||||
if (select_pos.w > 0 && select_pos.xyz == floor(sprite_pos)) {
|
if (select_pos.w > 0 && select_pos.xyz == floor(sprite_pos)) {
|
||||||
|
BIN
assets/voxygen/voxel/sprite/chests/chest.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/sprite/chests/chest.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/chests/chest_dark.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/sprite/chests/chest_dark.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/chests/chest_demon.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/sprite/chests/chest_demon.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/chests/chest_gold.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/sprite/chests/chest_gold.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/chests/chest_light.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/sprite/chests/chest_light.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/chests/chest_skull.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/sprite/chests/chest_skull.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/chests/chest_vines.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/sprite/chests/chest_vines.vox
(Stored with Git LFS)
Binary file not shown.
@ -2,7 +2,9 @@ pub mod cell;
|
|||||||
pub mod mat_cell;
|
pub mod mat_cell;
|
||||||
pub use mat_cell::Material;
|
pub use mat_cell::Material;
|
||||||
|
|
||||||
use self::{cell::Cell, mat_cell::MatCell};
|
// Reexport
|
||||||
|
pub use self::{cell::Cell, mat_cell::MatCell};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
vol::{IntoFullPosIterator, IntoFullVolIterator, ReadVol, SizedVol, Vox, WriteVol},
|
vol::{IntoFullPosIterator, IntoFullVolIterator, ReadVol, SizedVol, Vox, WriteVol},
|
||||||
volumes::dyna::Dyna,
|
volumes::dyna::Dyna,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::ray::Ray;
|
use crate::{ray::Ray, volumes::scaled::Scaled};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -24,6 +24,13 @@ pub trait Vox: Sized + Clone + PartialEq {
|
|||||||
pub trait BaseVol {
|
pub trait BaseVol {
|
||||||
type Vox: Vox;
|
type Vox: Vox;
|
||||||
type Error: Debug;
|
type Error: Debug;
|
||||||
|
|
||||||
|
fn scaled_by(&self, scale: Vec3<f32>) -> Scaled<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
Scaled { inner: self, scale }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementing `BaseVol` for any `&'a BaseVol` makes it possible to implement
|
/// Implementing `BaseVol` for any `&'a BaseVol` makes it possible to implement
|
||||||
@ -159,6 +166,7 @@ where
|
|||||||
/// Unfortunately we can't just implement `IntoIterator` in this generic way
|
/// Unfortunately we can't just implement `IntoIterator` in this generic way
|
||||||
/// because it's defined in another crate. That's actually the only reason why
|
/// because it's defined in another crate. That's actually the only reason why
|
||||||
/// the trait `IntoFullVolIterator` exists.
|
/// the trait `IntoFullVolIterator` exists.
|
||||||
|
// TODO: See whether relaxed orphan rules permit this to be replaced now
|
||||||
impl<'a, T: 'a + SizedVol> IntoFullVolIterator<'a> for &'a T
|
impl<'a, T: 'a + SizedVol> IntoFullVolIterator<'a> for &'a T
|
||||||
where
|
where
|
||||||
Self: IntoVolIterator<'a>,
|
Self: IntoVolIterator<'a>,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
pub mod chunk;
|
pub mod chunk;
|
||||||
pub mod dyna;
|
pub mod dyna;
|
||||||
|
pub mod scaled;
|
||||||
pub mod vol_grid_2d;
|
pub mod vol_grid_2d;
|
||||||
pub mod vol_grid_3d;
|
pub mod vol_grid_3d;
|
||||||
|
53
common/src/volumes/scaled.rs
Normal file
53
common/src/volumes/scaled.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use crate::vol::{BaseVol, ReadVol, SizedVol, Vox};
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
|
pub struct Scaled<'a, V> {
|
||||||
|
pub inner: &'a V,
|
||||||
|
pub scale: Vec3<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, V: BaseVol> BaseVol for Scaled<'a, V> {
|
||||||
|
type Error = V::Error;
|
||||||
|
type Vox = V::Vox;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Error> {
|
||||||
|
let ideal_pos = pos.map2(self.scale, |e, scale| e as f32 / scale);
|
||||||
|
let pos = ideal_pos.map(|e| e.trunc() as i32);
|
||||||
|
|
||||||
|
let ideal_search_size = Vec3::<f32>::one() / self.scale;
|
||||||
|
let range_iter = |i: usize| {
|
||||||
|
std::iter::successors(Some(0), |p| Some(if *p < 0 { -*p } else { -(*p + 1) }))
|
||||||
|
.take_while(move |p| {
|
||||||
|
((ideal_pos[i] - ideal_search_size[i] / 2.0).round() as i32
|
||||||
|
..(ideal_pos[i] + ideal_search_size[i] / 2.0).round() as i32)
|
||||||
|
.contains(&(pos[i] + *p))
|
||||||
|
})
|
||||||
|
};
|
||||||
|
range_iter(0)
|
||||||
|
.map(|i| range_iter(1).map(move |j| range_iter(2).map(move |k| Vec3::new(i, j, k))))
|
||||||
|
.flatten()
|
||||||
|
.flatten()
|
||||||
|
.map(|offs| self.inner.get(pos + offs))
|
||||||
|
.find(|vox| vox.as_ref().map(|v| !v.is_empty()).unwrap_or(false))
|
||||||
|
.unwrap_or_else(|| self.inner.get(pos))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, V: SizedVol> SizedVol for Scaled<'a, V> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn lower_bound(&self) -> Vec3<i32> {
|
||||||
|
self.inner
|
||||||
|
.lower_bound()
|
||||||
|
.map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn upper_bound(&self) -> Vec3<i32> {
|
||||||
|
self.inner
|
||||||
|
.upper_bound()
|
||||||
|
.map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32 + 1)
|
||||||
|
}
|
||||||
|
}
|
@ -47,6 +47,8 @@ impl BipedLargeSkeleton {
|
|||||||
impl Skeleton for BipedLargeSkeleton {
|
impl Skeleton for BipedLargeSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 11 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
let upper_torso_mat = self.upper_torso.compute_base_matrix();
|
let upper_torso_mat = self.upper_torso.compute_base_matrix();
|
||||||
let shoulder_l_mat = self.shoulder_l.compute_base_matrix();
|
let shoulder_l_mat = self.shoulder_l.compute_base_matrix();
|
||||||
|
@ -27,6 +27,8 @@ impl BirdMediumSkeleton {
|
|||||||
impl Skeleton for BirdMediumSkeleton {
|
impl Skeleton for BirdMediumSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 7 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
let torso_mat = self.torso.compute_base_matrix();
|
let torso_mat = self.torso.compute_base_matrix();
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ impl BirdSmallSkeleton {
|
|||||||
impl Skeleton for BirdSmallSkeleton {
|
impl Skeleton for BirdSmallSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 4 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
let torso_mat = self.torso.compute_base_matrix();
|
let torso_mat = self.torso.compute_base_matrix();
|
||||||
|
|
||||||
|
@ -62,6 +62,8 @@ impl CharacterSkeleton {
|
|||||||
impl Skeleton for CharacterSkeleton {
|
impl Skeleton for CharacterSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 15 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
let chest_mat = self.chest.compute_base_matrix();
|
let chest_mat = self.chest.compute_base_matrix();
|
||||||
let torso_mat = self.torso.compute_base_matrix();
|
let torso_mat = self.torso.compute_base_matrix();
|
||||||
|
@ -32,6 +32,8 @@ impl CritterSkeleton {
|
|||||||
impl Skeleton for CritterSkeleton {
|
impl Skeleton for CritterSkeleton {
|
||||||
type Attr = CritterAttr;
|
type Attr = CritterAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 5 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
[
|
[
|
||||||
FigureBoneData::new(self.head.compute_base_matrix()),
|
FigureBoneData::new(self.head.compute_base_matrix()),
|
||||||
|
@ -49,6 +49,8 @@ impl DragonSkeleton {
|
|||||||
impl Skeleton for DragonSkeleton {
|
impl Skeleton for DragonSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 13 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
let chest_front_mat = self.chest_front.compute_base_matrix();
|
let chest_front_mat = self.chest_front.compute_base_matrix();
|
||||||
let wing_in_l_mat = self.wing_in_l.compute_base_matrix();
|
let wing_in_l_mat = self.wing_in_l.compute_base_matrix();
|
||||||
|
@ -35,6 +35,8 @@ impl FishMediumSkeleton {
|
|||||||
impl Skeleton for FishMediumSkeleton {
|
impl Skeleton for FishMediumSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 6 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
let torso_mat = self.torso.compute_base_matrix();
|
let torso_mat = self.torso.compute_base_matrix();
|
||||||
let rear_mat = self.rear.compute_base_matrix();
|
let rear_mat = self.rear.compute_base_matrix();
|
||||||
|
@ -27,6 +27,8 @@ impl FishSmallSkeleton {
|
|||||||
impl Skeleton for FishSmallSkeleton {
|
impl Skeleton for FishSmallSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 2 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
let torso_mat = self.torso.compute_base_matrix();
|
let torso_mat = self.torso.compute_base_matrix();
|
||||||
|
|
||||||
|
@ -13,9 +13,11 @@ impl FixtureSkeleton {
|
|||||||
impl Skeleton for FixtureSkeleton {
|
impl Skeleton for FixtureSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 1 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
[
|
[
|
||||||
FigureBoneData::new(vek::Mat4::identity()),
|
FigureBoneData::new(vek::Mat4::identity()), // <-- This is actually a bone!
|
||||||
FigureBoneData::new(vek::Mat4::identity()),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(vek::Mat4::identity()),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(vek::Mat4::identity()),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
|
@ -52,6 +52,8 @@ impl Bone {
|
|||||||
pub trait Skeleton: Send + Sync + 'static {
|
pub trait Skeleton: Send + Sync + 'static {
|
||||||
type Attr;
|
type Attr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 16 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16];
|
fn compute_matrices(&self) -> [FigureBoneData; 16];
|
||||||
|
|
||||||
/// Change the current skeleton to be more like `target`.
|
/// Change the current skeleton to be more like `target`.
|
||||||
|
@ -15,24 +15,26 @@ const SCALE: f32 = 1.0 / 11.0;
|
|||||||
impl Skeleton for ObjectSkeleton {
|
impl Skeleton for ObjectSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 1 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
[
|
[
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
FigureBoneData::new(vek::Mat4::identity()),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ impl QuadrupedMediumSkeleton {
|
|||||||
impl Skeleton for QuadrupedMediumSkeleton {
|
impl Skeleton for QuadrupedMediumSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 11 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
let ears_mat = self.ears.compute_base_matrix();
|
let ears_mat = self.ears.compute_base_matrix();
|
||||||
let head_upper_mat = self.head_upper.compute_base_matrix();
|
let head_upper_mat = self.head_upper.compute_base_matrix();
|
||||||
|
@ -26,6 +26,8 @@ impl QuadrupedSmallSkeleton {
|
|||||||
impl Skeleton for QuadrupedSmallSkeleton {
|
impl Skeleton for QuadrupedSmallSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
|
|
||||||
|
fn bone_count(&self) -> usize { 6 }
|
||||||
|
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||||
[
|
[
|
||||||
FigureBoneData::new(self.head.compute_base_matrix()),
|
FigureBoneData::new(self.head.compute_base_matrix()),
|
||||||
|
@ -210,6 +210,7 @@ pub enum Event {
|
|||||||
ToggleMouseYInvert(bool),
|
ToggleMouseYInvert(bool),
|
||||||
ToggleSmoothPan(bool),
|
ToggleSmoothPan(bool),
|
||||||
AdjustViewDistance(u32),
|
AdjustViewDistance(u32),
|
||||||
|
AdjustSpriteRenderDistance(u32),
|
||||||
AdjustMusicVolume(f32),
|
AdjustMusicVolume(f32),
|
||||||
AdjustSfxVolume(f32),
|
AdjustSfxVolume(f32),
|
||||||
ChangeAudioDevice(String),
|
ChangeAudioDevice(String),
|
||||||
@ -1801,6 +1802,9 @@ impl Hud {
|
|||||||
settings_window::Event::AdjustViewDistance(view_distance) => {
|
settings_window::Event::AdjustViewDistance(view_distance) => {
|
||||||
events.push(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) => {
|
settings_window::Event::CrosshairTransp(crosshair_transp) => {
|
||||||
events.push(Event::CrosshairTransp(crosshair_transp));
|
events.push(Event::CrosshairTransp(crosshair_transp));
|
||||||
},
|
},
|
||||||
|
@ -89,6 +89,9 @@ widget_ids! {
|
|||||||
vd_slider,
|
vd_slider,
|
||||||
vd_text,
|
vd_text,
|
||||||
vd_value,
|
vd_value,
|
||||||
|
sprite_dist_slider,
|
||||||
|
sprite_dist_text,
|
||||||
|
sprite_dist_value,
|
||||||
max_fps_slider,
|
max_fps_slider,
|
||||||
max_fps_text,
|
max_fps_text,
|
||||||
max_fps_value,
|
max_fps_value,
|
||||||
@ -209,6 +212,7 @@ pub enum Event {
|
|||||||
ToggleMouseYInvert(bool),
|
ToggleMouseYInvert(bool),
|
||||||
ToggleSmoothPan(bool),
|
ToggleSmoothPan(bool),
|
||||||
AdjustViewDistance(u32),
|
AdjustViewDistance(u32),
|
||||||
|
AdjustSpriteRenderDistance(u32),
|
||||||
AdjustFOV(u16),
|
AdjustFOV(u16),
|
||||||
AdjustGamma(f32),
|
AdjustGamma(f32),
|
||||||
AdjustWindowSize([u16; 2]),
|
AdjustWindowSize([u16; 2]),
|
||||||
@ -1612,7 +1616,43 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
.font_id(self.fonts.cyri.conrod_id)
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(state.ids.gamma_value, ui);
|
.set(state.ids.gamma_value, ui);
|
||||||
|
// Sprites VD
|
||||||
|
if let Some(new_val) = ImageSlider::discrete(
|
||||||
|
self.global_state.settings.graphics.sprite_render_distance,
|
||||||
|
50,
|
||||||
|
500,
|
||||||
|
self.imgs.slider_indicator,
|
||||||
|
self.imgs.slider,
|
||||||
|
)
|
||||||
|
.w_h(104.0, 22.0)
|
||||||
|
.right_from(state.ids.vd_slider, 50.0)
|
||||||
|
.track_breadth(12.0)
|
||||||
|
.slider_length(10.0)
|
||||||
|
.pad_track((5.0, 5.0))
|
||||||
|
.set(state.ids.sprite_dist_slider, ui)
|
||||||
|
{
|
||||||
|
events.push(Event::AdjustSpriteRenderDistance(new_val));
|
||||||
|
}
|
||||||
|
Text::new(
|
||||||
|
&self
|
||||||
|
.localized_strings
|
||||||
|
.get("hud.settings.sprites_view_distance"),
|
||||||
|
)
|
||||||
|
.up_from(state.ids.sprite_dist_slider, 8.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.sprite_dist_text, ui);
|
||||||
|
|
||||||
|
Text::new(&format!(
|
||||||
|
"{}",
|
||||||
|
self.global_state.settings.graphics.sprite_render_distance
|
||||||
|
))
|
||||||
|
.right_from(state.ids.sprite_dist_slider, 8.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.sprite_dist_value, ui);
|
||||||
// AaMode
|
// AaMode
|
||||||
Text::new(&self.localized_strings.get("hud.settings.antialiasing_mode"))
|
Text::new(&self.localized_strings.get("hud.settings.antialiasing_mode"))
|
||||||
.down_from(state.ids.gamma_slider, 8.0)
|
.down_from(state.ids.gamma_slider, 8.0)
|
||||||
|
@ -4,14 +4,14 @@ mod vol;
|
|||||||
|
|
||||||
use crate::render::{self, Mesh};
|
use crate::render::{self, Mesh};
|
||||||
|
|
||||||
pub trait Meshable<P: render::Pipeline, T: render::Pipeline> {
|
pub trait Meshable<'a, P: render::Pipeline, T: render::Pipeline> {
|
||||||
type Pipeline: render::Pipeline;
|
type Pipeline: render::Pipeline;
|
||||||
type TranslucentPipeline: render::Pipeline;
|
type TranslucentPipeline: render::Pipeline;
|
||||||
type Supplement;
|
type Supplement;
|
||||||
|
|
||||||
// Generate meshes - one opaque, one translucent
|
// Generate meshes - one opaque, one translucent
|
||||||
fn generate_mesh(
|
fn generate_mesh(
|
||||||
&self,
|
&'a self,
|
||||||
supp: Self::Supplement,
|
supp: Self::Supplement,
|
||||||
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>);
|
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>);
|
||||||
}
|
}
|
||||||
|
@ -3,27 +3,43 @@ use crate::{
|
|||||||
render::{self, FigurePipeline, Mesh, SpritePipeline},
|
render::{self, FigurePipeline, Mesh, SpritePipeline},
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
figure::Segment,
|
figure::Cell,
|
||||||
util::{linear_to_srgb, srgb_to_linear},
|
util::{linear_to_srgb, srgb_to_linear},
|
||||||
vol::{IntoFullVolIterator, ReadVol, Vox},
|
vol::{BaseVol, ReadVol, SizedVol, Vox},
|
||||||
};
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
type FigureVertex = <FigurePipeline as render::Pipeline>::Vertex;
|
type FigureVertex = <FigurePipeline as render::Pipeline>::Vertex;
|
||||||
type SpriteVertex = <SpritePipeline as render::Pipeline>::Vertex;
|
type SpriteVertex = <SpritePipeline as render::Pipeline>::Vertex;
|
||||||
|
|
||||||
impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
impl<'a, V: 'a> Meshable<'a, FigurePipeline, FigurePipeline> for V
|
||||||
|
where
|
||||||
|
V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
|
||||||
|
/* TODO: Use VolIterator instead of manually iterating
|
||||||
|
* &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>,
|
||||||
|
* &'a V: BaseVol<Vox=Cell>, */
|
||||||
|
{
|
||||||
type Pipeline = FigurePipeline;
|
type Pipeline = FigurePipeline;
|
||||||
type Supplement = Vec3<f32>;
|
type Supplement = (Vec3<f32>, Vec3<f32>);
|
||||||
type TranslucentPipeline = FigurePipeline;
|
type TranslucentPipeline = FigurePipeline;
|
||||||
|
|
||||||
fn generate_mesh(
|
fn generate_mesh(
|
||||||
&self,
|
&'a self,
|
||||||
offs: Self::Supplement,
|
(offs, scale): Self::Supplement,
|
||||||
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
||||||
let mut mesh = Mesh::new();
|
let mut mesh = Mesh::new();
|
||||||
|
|
||||||
for (pos, vox) in self.full_vol_iter() {
|
let vol_iter = (self.lower_bound().x..self.upper_bound().x)
|
||||||
|
.map(|i| {
|
||||||
|
(self.lower_bound().y..self.upper_bound().y).map(move |j| {
|
||||||
|
(self.lower_bound().z..self.upper_bound().z).map(move |k| Vec3::new(i, j, k))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.flatten()
|
||||||
|
.map(|pos| (pos, self.get(pos).map(|x| *x).unwrap_or(Vox::empty())));
|
||||||
|
|
||||||
|
for (pos, vox) in vol_iter {
|
||||||
if let Some(col) = vox.get_color() {
|
if let Some(col) = vox.get_color() {
|
||||||
vol::push_vox_verts(
|
vol::push_vox_verts(
|
||||||
&mut mesh,
|
&mut mesh,
|
||||||
@ -32,7 +48,7 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
|||||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||||
|origin, norm, col, light, ao| {
|
|origin, norm, col, light, ao| {
|
||||||
FigureVertex::new(
|
FigureVertex::new(
|
||||||
origin,
|
origin * scale,
|
||||||
norm,
|
norm,
|
||||||
linear_to_srgb(srgb_to_linear(col) * light),
|
linear_to_srgb(srgb_to_linear(col) * light),
|
||||||
ao,
|
ao,
|
||||||
@ -62,18 +78,34 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Meshable<SpritePipeline, SpritePipeline> for Segment {
|
impl<'a, V: 'a> Meshable<'a, SpritePipeline, SpritePipeline> for V
|
||||||
|
where
|
||||||
|
V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
|
||||||
|
/* TODO: Use VolIterator instead of manually iterating
|
||||||
|
* &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>,
|
||||||
|
* &'a V: BaseVol<Vox=Cell>, */
|
||||||
|
{
|
||||||
type Pipeline = SpritePipeline;
|
type Pipeline = SpritePipeline;
|
||||||
type Supplement = Vec3<f32>;
|
type Supplement = (Vec3<f32>, Vec3<f32>);
|
||||||
type TranslucentPipeline = SpritePipeline;
|
type TranslucentPipeline = SpritePipeline;
|
||||||
|
|
||||||
fn generate_mesh(
|
fn generate_mesh(
|
||||||
&self,
|
&'a self,
|
||||||
offs: Self::Supplement,
|
(offs, scale): Self::Supplement,
|
||||||
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
||||||
let mut mesh = Mesh::new();
|
let mut mesh = Mesh::new();
|
||||||
|
|
||||||
for (pos, vox) in self.full_vol_iter() {
|
let vol_iter = (self.lower_bound().x..self.upper_bound().x)
|
||||||
|
.map(|i| {
|
||||||
|
(self.lower_bound().y..self.upper_bound().y).map(move |j| {
|
||||||
|
(self.lower_bound().z..self.upper_bound().z).map(move |k| Vec3::new(i, j, k))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.flatten()
|
||||||
|
.map(|pos| (pos, self.get(pos).map(|x| *x).unwrap_or(Vox::empty())));
|
||||||
|
|
||||||
|
for (pos, vox) in vol_iter {
|
||||||
if let Some(col) = vox.get_color() {
|
if let Some(col) = vox.get_color() {
|
||||||
vol::push_vox_verts(
|
vol::push_vox_verts(
|
||||||
&mut mesh,
|
&mut mesh,
|
||||||
@ -82,7 +114,7 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
|
|||||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||||
|origin, norm, col, light, ao| {
|
|origin, norm, col, light, ao| {
|
||||||
SpriteVertex::new(
|
SpriteVertex::new(
|
||||||
origin,
|
origin * scale,
|
||||||
norm,
|
norm,
|
||||||
linear_to_srgb(srgb_to_linear(col) * light),
|
linear_to_srgb(srgb_to_linear(col) * light),
|
||||||
ao,
|
ao,
|
||||||
|
@ -198,15 +198,15 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeline, FluidPipeline>
|
impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||||
for VolGrid2d<V>
|
Meshable<'a, TerrainPipeline, FluidPipeline> for VolGrid2d<V>
|
||||||
{
|
{
|
||||||
type Pipeline = TerrainPipeline;
|
type Pipeline = TerrainPipeline;
|
||||||
type Supplement = Aabb<i32>;
|
type Supplement = Aabb<i32>;
|
||||||
type TranslucentPipeline = FluidPipeline;
|
type TranslucentPipeline = FluidPipeline;
|
||||||
|
|
||||||
fn generate_mesh(
|
fn generate_mesh(
|
||||||
&self,
|
&'a self,
|
||||||
range: Self::Supplement,
|
range: Self::Supplement,
|
||||||
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
||||||
let mut light = calc_light(range, self);
|
let mut light = calc_light(range, self);
|
||||||
|
@ -11,11 +11,12 @@ use vek::*;
|
|||||||
|
|
||||||
gfx_defines! {
|
gfx_defines! {
|
||||||
vertex Vertex {
|
vertex Vertex {
|
||||||
pos: [f32; 3] = "v_pos",
|
pos_norm: u32 = "v_pos_norm",
|
||||||
norm: [f32; 3] = "v_norm",
|
col: u32 = "v_col",
|
||||||
col: [f32; 3] = "v_col",
|
// BBBBBBAA
|
||||||
ao: f32 = "v_ao",
|
// B = Bone
|
||||||
bone_idx: u8 = "v_bone_idx",
|
// A = AO
|
||||||
|
ao_bone: u8 = "v_ao_bone",
|
||||||
}
|
}
|
||||||
|
|
||||||
constant Locals {
|
constant Locals {
|
||||||
@ -46,17 +47,29 @@ gfx_defines! {
|
|||||||
|
|
||||||
impl Vertex {
|
impl Vertex {
|
||||||
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, ao: f32, bone_idx: u8) -> Self {
|
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, ao: f32, bone_idx: u8) -> Self {
|
||||||
|
let norm_bits = if norm.x != 0.0 {
|
||||||
|
if norm.x < 0.0 { 0 } else { 1 }
|
||||||
|
} else if norm.y != 0.0 {
|
||||||
|
if norm.y < 0.0 { 2 } else { 3 }
|
||||||
|
} else {
|
||||||
|
if norm.z < 0.0 { 4 } else { 5 }
|
||||||
|
};
|
||||||
Self {
|
Self {
|
||||||
pos: pos.into_array(),
|
pos_norm: pos
|
||||||
col: col.into_array(),
|
.map2(Vec3::new(0, 8, 16), |e, shift| {
|
||||||
norm: norm.into_array(),
|
((e + 128.0) as u32) << shift
|
||||||
ao,
|
})
|
||||||
bone_idx,
|
.reduce_bitor()
|
||||||
|
| (norm_bits << 24),
|
||||||
|
col: col
|
||||||
|
.map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift)
|
||||||
|
.reduce_bitor(),
|
||||||
|
ao_bone: (bone_idx << 2) | ((ao * 3.9999) as u8),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_bone_idx(mut self, bone_idx: u8) -> Self {
|
pub fn with_bone_idx(mut self, bone_idx: u8) -> Self {
|
||||||
self.bone_idx = bone_idx;
|
self.ao_bone = (self.ao_bone & 0b11) | (bone_idx << 2);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ gfx_defines! {
|
|||||||
select_pos: [i32; 4] = "select_pos",
|
select_pos: [i32; 4] = "select_pos",
|
||||||
gamma: [f32; 4] = "gamma",
|
gamma: [f32; 4] = "gamma",
|
||||||
cam_mode: u32 = "cam_mode",
|
cam_mode: u32 = "cam_mode",
|
||||||
|
sprite_render_distance: f32 = "sprite_render_distance",
|
||||||
}
|
}
|
||||||
|
|
||||||
constant Light {
|
constant Light {
|
||||||
@ -58,6 +59,7 @@ impl Globals {
|
|||||||
select_pos: Option<Vec3<i32>>,
|
select_pos: Option<Vec3<i32>>,
|
||||||
gamma: f32,
|
gamma: f32,
|
||||||
cam_mode: CameraMode,
|
cam_mode: CameraMode,
|
||||||
|
sprite_render_distance: f32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
view_mat: arr_to_mat(view_mat.into_col_array()),
|
view_mat: arr_to_mat(view_mat.into_col_array()),
|
||||||
@ -77,6 +79,7 @@ impl Globals {
|
|||||||
.into_array(),
|
.into_array(),
|
||||||
gamma: [gamma; 4],
|
gamma: [gamma; 4],
|
||||||
cam_mode: cam_mode as u32,
|
cam_mode: cam_mode as u32,
|
||||||
|
sprite_render_distance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,6 +101,7 @@ impl Default for Globals {
|
|||||||
None,
|
None,
|
||||||
1.0,
|
1.0,
|
||||||
CameraMode::ThirdPerson,
|
CameraMode::ThirdPerson,
|
||||||
|
250.0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,12 @@ use vek::*;
|
|||||||
gfx_defines! {
|
gfx_defines! {
|
||||||
vertex Vertex {
|
vertex Vertex {
|
||||||
pos: [f32; 3] = "v_pos",
|
pos: [f32; 3] = "v_pos",
|
||||||
norm: [f32; 3] = "v_norm",
|
// ____BBBBBBBBGGGGGGGGRRRRRRRR
|
||||||
col: [f32; 3] = "v_col",
|
col: u32 = "v_col",
|
||||||
ao: f32 = "v_ao",
|
// ...AANNN
|
||||||
|
// A = AO
|
||||||
|
// N = Normal
|
||||||
|
norm_ao: u32 = "v_norm_ao",
|
||||||
}
|
}
|
||||||
|
|
||||||
vertex Instance {
|
vertex Instance {
|
||||||
@ -43,11 +46,20 @@ gfx_defines! {
|
|||||||
|
|
||||||
impl Vertex {
|
impl Vertex {
|
||||||
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, ao: f32) -> Self {
|
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, ao: f32) -> Self {
|
||||||
|
let norm_bits = if norm.x != 0.0 {
|
||||||
|
if norm.x < 0.0 { 0 } else { 1 }
|
||||||
|
} else if norm.y != 0.0 {
|
||||||
|
if norm.y < 0.0 { 2 } else { 3 }
|
||||||
|
} else {
|
||||||
|
if norm.z < 0.0 { 4 } else { 5 }
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pos: pos.into_array(),
|
pos: pos.into_array(),
|
||||||
col: col.into_array(),
|
col: col
|
||||||
norm: norm.into_array(),
|
.map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift)
|
||||||
ao,
|
.reduce_bitor(),
|
||||||
|
norm_ao: norm_bits | (((ao * 3.9999) as u32) << 3),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -118,17 +118,20 @@ impl FigureMgr {
|
|||||||
.map_or(Vec3::zero(), |pos| pos.0);
|
.map_or(Vec3::zero(), |pos| pos.0);
|
||||||
|
|
||||||
for (
|
for (
|
||||||
entity,
|
i,
|
||||||
pos,
|
(
|
||||||
interpolated,
|
entity,
|
||||||
vel,
|
pos,
|
||||||
scale,
|
interpolated,
|
||||||
body,
|
vel,
|
||||||
character,
|
scale,
|
||||||
last_character,
|
body,
|
||||||
physics,
|
character,
|
||||||
stats,
|
last_character,
|
||||||
loadout,
|
physics,
|
||||||
|
stats,
|
||||||
|
loadout,
|
||||||
|
),
|
||||||
) in (
|
) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
@ -143,7 +146,26 @@ 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 = 50.0;
|
||||||
|
if (i as u64 + tick)
|
||||||
|
% (1 + ((pos.0.distance_squared(camera.get_focus_pos()).powf(0.25)
|
||||||
|
- MIN_PERFECT_RATE_DIST.powf(0.5))
|
||||||
|
.max(0.0)
|
||||||
|
/ 3.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 +1407,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 +1435,7 @@ impl FigureMgr {
|
|||||||
body,
|
body,
|
||||||
loadout,
|
loadout,
|
||||||
false,
|
false,
|
||||||
|
pos.0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1434,7 +1457,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 +1483,7 @@ impl FigureMgr {
|
|||||||
body,
|
body,
|
||||||
loadout,
|
loadout,
|
||||||
true,
|
true,
|
||||||
|
pos.0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1474,6 +1501,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 +1714,19 @@ impl FigureMgr {
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
} {
|
} {
|
||||||
|
const FIGURE_LOW_LOD_DIST: f32 = 150.0;
|
||||||
|
const FIGURE_MID_LOD_DIST: f32 = 85.0;
|
||||||
|
|
||||||
|
let model = if pos.distance_squared(camera.get_focus_pos())
|
||||||
|
> FIGURE_LOW_LOD_DIST.powf(2.0)
|
||||||
|
{
|
||||||
|
&model[2]
|
||||||
|
} else if pos.distance_squared(camera.get_focus_pos()) > FIGURE_MID_LOD_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);
|
||||||
@ -1818,7 +1859,10 @@ impl<S: Skeleton> FigureState<S> {
|
|||||||
renderer.update_consts(&mut self.locals, &[locals]).unwrap();
|
renderer.update_consts(&mut self.locals, &[locals]).unwrap();
|
||||||
|
|
||||||
renderer
|
renderer
|
||||||
.update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices())
|
.update_consts(
|
||||||
|
&mut self.bone_consts,
|
||||||
|
&self.skeleton.compute_matrices()[0..self.skeleton.bone_count()],
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ pub struct SceneData<'a> {
|
|||||||
pub thread_pool: &'a uvth::ThreadPool,
|
pub thread_pool: &'a uvth::ThreadPool,
|
||||||
pub gamma: f32,
|
pub gamma: f32,
|
||||||
pub mouse_smoothing: bool,
|
pub mouse_smoothing: bool,
|
||||||
|
pub sprite_render_distance: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scene {
|
impl Scene {
|
||||||
@ -353,6 +354,7 @@ impl Scene {
|
|||||||
self.select_pos,
|
self.select_pos,
|
||||||
scene_data.gamma,
|
scene_data.gamma,
|
||||||
self.camera.get_mode(),
|
self.camera.get_mode(),
|
||||||
|
scene_data.sprite_render_distance as f32 - 20.0,
|
||||||
)])
|
)])
|
||||||
.expect("Failed to update global constants");
|
.expect("Failed to update global constants");
|
||||||
|
|
||||||
@ -385,6 +387,7 @@ impl Scene {
|
|||||||
state: &State,
|
state: &State,
|
||||||
player_entity: EcsEntity,
|
player_entity: EcsEntity,
|
||||||
tick: u64,
|
tick: u64,
|
||||||
|
scene_data: &SceneData,
|
||||||
) {
|
) {
|
||||||
// Render terrain and figures.
|
// Render terrain and figures.
|
||||||
self.terrain.render(
|
self.terrain.render(
|
||||||
@ -425,6 +428,7 @@ impl Scene {
|
|||||||
&self.lights,
|
&self.lights,
|
||||||
&self.shadows,
|
&self.shadows,
|
||||||
self.camera.get_focus_pos(),
|
self.camera.get_focus_pos(),
|
||||||
|
scene_data.sprite_render_distance,
|
||||||
);
|
);
|
||||||
|
|
||||||
renderer.render_post_process(
|
renderer.render_post_process(
|
||||||
|
@ -4,8 +4,9 @@ use crate::{
|
|||||||
fixture::FixtureSkeleton,
|
fixture::FixtureSkeleton,
|
||||||
Animation, Skeleton,
|
Animation, Skeleton,
|
||||||
},
|
},
|
||||||
|
mesh::Meshable,
|
||||||
render::{
|
render::{
|
||||||
create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Model,
|
create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Mesh, Model,
|
||||||
PostProcessLocals, PostProcessPipeline, Renderer, Shadow, SkyboxLocals, SkyboxPipeline,
|
PostProcessLocals, PostProcessPipeline, Renderer, Shadow, SkyboxLocals, SkyboxPipeline,
|
||||||
},
|
},
|
||||||
scene::{
|
scene::{
|
||||||
@ -16,6 +17,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{humanoid, Body, Loadout},
|
comp::{humanoid, Body, Loadout},
|
||||||
|
figure::Segment,
|
||||||
terrain::BlockKind,
|
terrain::BlockKind,
|
||||||
vol::{BaseVol, ReadVol, Vox},
|
vol::{BaseVol, ReadVol, Vox},
|
||||||
};
|
};
|
||||||
@ -40,6 +42,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 +113,11 @@ 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()),
|
||||||
)
|
)
|
||||||
@ -173,6 +183,7 @@ impl Scene {
|
|||||||
None,
|
None,
|
||||||
scene_data.gamma,
|
scene_data.gamma,
|
||||||
self.camera.get_mode(),
|
self.camera.get_mode(),
|
||||||
|
250.0,
|
||||||
)]) {
|
)]) {
|
||||||
error!("Renderer failed to update: {:?}", err);
|
error!("Renderer failed to update: {:?}", err);
|
||||||
}
|
}
|
||||||
@ -229,7 +240,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(),
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,6 @@ use crate::{
|
|||||||
i18n::{i18n_asset_key, VoxygenLocalization},
|
i18n::{i18n_asset_key, VoxygenLocalization},
|
||||||
key_state::KeyState,
|
key_state::KeyState,
|
||||||
menu::char_selection::CharSelectionState,
|
menu::char_selection::CharSelectionState,
|
||||||
render::Renderer,
|
|
||||||
scene::{camera, Scene, SceneData},
|
scene::{camera, Scene, SceneData},
|
||||||
settings::AudioOutput,
|
settings::AudioOutput,
|
||||||
window::{AnalogGameInput, Event, GameInput},
|
window::{AnalogGameInput, Event, GameInput},
|
||||||
@ -111,26 +110,6 @@ impl SessionState {
|
|||||||
|
|
||||||
/// Clean up the session (and the client attached to it) after a tick.
|
/// Clean up the session (and the client attached to it) after a tick.
|
||||||
pub fn cleanup(&mut self) { self.client.borrow_mut().cleanup(); }
|
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 {
|
impl PlayState for SessionState {
|
||||||
@ -589,6 +568,11 @@ impl PlayState for SessionState {
|
|||||||
global_state.settings.graphics.view_distance = view_distance;
|
global_state.settings.graphics.view_distance = view_distance;
|
||||||
global_state.settings.save_to_file_warn();
|
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) => {
|
HudEvent::CrosshairTransp(crosshair_transp) => {
|
||||||
global_state.settings.gameplay.crosshair_transp = crosshair_transp;
|
global_state.settings.gameplay.crosshair_transp = crosshair_transp;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state.settings.save_to_file_warn();
|
||||||
@ -720,9 +704,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 client = self.client.borrow();
|
||||||
let scene_data = SceneData {
|
let scene_data = SceneData {
|
||||||
@ -734,17 +715,38 @@ impl PlayState for SessionState {
|
|||||||
thread_pool: client.thread_pool(),
|
thread_pool: client.thread_pool(),
|
||||||
gamma: global_state.settings.graphics.gamma,
|
gamma: global_state.settings.graphics.gamma,
|
||||||
mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable,
|
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(),
|
// Runs if either in a multiplayer server or the singleplayer server is unpaused
|
||||||
&mut global_state.audio,
|
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,
|
&scene_data,
|
||||||
);
|
);
|
||||||
|
// Draw the UI to the screen
|
||||||
|
self.hud.render(renderer, self.scene.globals());
|
||||||
|
// Finish the frame
|
||||||
|
renderer.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the session.
|
|
||||||
self.render(global_state.window.renderer_mut());
|
|
||||||
|
|
||||||
// Display the frame on the window.
|
// Display the frame on the window.
|
||||||
global_state
|
global_state
|
||||||
.window
|
.window
|
||||||
|
@ -548,6 +548,7 @@ impl Default for Log {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct GraphicsSettings {
|
pub struct GraphicsSettings {
|
||||||
pub view_distance: u32,
|
pub view_distance: u32,
|
||||||
|
pub sprite_render_distance: u32,
|
||||||
pub max_fps: u32,
|
pub max_fps: u32,
|
||||||
pub fov: u16,
|
pub fov: u16,
|
||||||
pub gamma: f32,
|
pub gamma: f32,
|
||||||
@ -562,6 +563,7 @@ impl Default for GraphicsSettings {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
view_distance: 10,
|
view_distance: 10,
|
||||||
|
sprite_render_distance: 250,
|
||||||
max_fps: 60,
|
max_fps: 60,
|
||||||
fov: 50,
|
fov: 50,
|
||||||
gamma: 1.0,
|
gamma: 1.0,
|
||||||
|
@ -140,12 +140,13 @@ impl Civs {
|
|||||||
e * sz as i32 + sz as i32 / 2
|
e * sz as i32 + sz as i32 / 2
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut rng = ctx.reseed().rng;
|
||||||
let world_site = match &site.kind {
|
let world_site = match &site.kind {
|
||||||
SiteKind::Settlement => {
|
SiteKind::Settlement => {
|
||||||
WorldSite::from(Settlement::generate(wpos, Some(ctx.sim), &mut ctx.rng))
|
WorldSite::from(Settlement::generate(wpos, Some(ctx.sim), &mut rng))
|
||||||
},
|
},
|
||||||
SiteKind::Dungeon => {
|
SiteKind::Dungeon => {
|
||||||
WorldSite::from(Dungeon::generate(wpos, Some(ctx.sim), &mut ctx.rng))
|
WorldSite::from(Dungeon::generate(wpos, Some(ctx.sim), &mut rng))
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ impl Archetype for House {
|
|||||||
storey_fill: StoreyFill::All,
|
storey_fill: StoreyFill::All,
|
||||||
mansard: 0,
|
mansard: 0,
|
||||||
pillar: match rng.gen_range(0, 3) {
|
pillar: match rng.gen_range(0, 3) {
|
||||||
0 => Pillar::Chimney(9 + locus + rng.gen_range(0, 4)),
|
0 => Pillar::Chimney(10 + locus + rng.gen_range(0, 4)),
|
||||||
1 => Pillar::Tower(15 + locus + rng.gen_range(0, 4)),
|
1 => Pillar::Tower(15 + locus + rng.gen_range(0, 4)),
|
||||||
_ => Pillar::None,
|
_ => Pillar::None,
|
||||||
},
|
},
|
||||||
@ -199,7 +199,8 @@ impl Archetype for House {
|
|||||||
|
|
||||||
let facade_layer = 3;
|
let facade_layer = 3;
|
||||||
let structural_layer = facade_layer + 1;
|
let structural_layer = facade_layer + 1;
|
||||||
let foundation_layer = structural_layer + 1;
|
let internal_layer = structural_layer + 1;
|
||||||
|
let foundation_layer = internal_layer + 1;
|
||||||
let floor_layer = foundation_layer + 1;
|
let floor_layer = foundation_layer + 1;
|
||||||
|
|
||||||
let foundation = make_block(100, 100, 100).with_priority(foundation_layer);
|
let foundation = make_block(100, 100, 100).with_priority(foundation_layer);
|
||||||
@ -207,9 +208,9 @@ impl Archetype for House {
|
|||||||
let floor = make_block(100, 75, 50);
|
let floor = make_block(100, 75, 50);
|
||||||
let wall = make_block(200, 180, 150).with_priority(facade_layer);
|
let wall = make_block(200, 180, 150).with_priority(facade_layer);
|
||||||
let roof = make_block(self.roof_color.r, self.roof_color.g, self.roof_color.b)
|
let roof = make_block(self.roof_color.r, self.roof_color.g, self.roof_color.b)
|
||||||
.with_priority(facade_layer);
|
.with_priority(facade_layer - 1);
|
||||||
let empty = BlockMask::nothing();
|
let empty = BlockMask::nothing();
|
||||||
let internal = BlockMask::new(Block::empty(), structural_layer);
|
let internal = BlockMask::new(Block::empty(), internal_layer);
|
||||||
let end_window = BlockMask::new(
|
let end_window = BlockMask::new(
|
||||||
Block::new(BlockKind::Window1, make_meta(ori.flip())),
|
Block::new(BlockKind::Window1, make_meta(ori.flip())),
|
||||||
structural_layer,
|
structural_layer,
|
||||||
|
Loading…
Reference in New Issue
Block a user