Add player transparency and silhouette

This commit is contained in:
Capucho 2020-04-04 19:36:55 +00:00 committed by Joshua Barretto
parent e0e86de21d
commit a21ae27a77
17 changed files with 517 additions and 250 deletions

View File

@ -41,6 +41,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fleshed out range attack into charging and shooting anims for staff/bow
- Customized attack animation for hammers and axes
- German translation
- Added a silhouette for players when they are occluded
- Added transparency to the player when zooming in
### Changed
@ -56,7 +58,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Asset cleanup to lower client-size
- Rewrote the humanoid skeleton to be more ideal for attack animations
### Removed
## [0.5.0] - 2019-01-31

View File

@ -10,6 +10,9 @@ layout (std140)
uniform u_locals {
mat4 model_mat;
vec4 model_col;
// bit 0 - is player
// bit 1-31 - unused
int flags;
};
struct BoneData {
@ -43,5 +46,13 @@ 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);
float opacity = 1.0;
if ((flags & 1) == 1 && int(cam_mode) == 1) {
float distance = distance(vec3(cam_pos), f_pos) - 1;
opacity = clamp(distance / 3, 0, 1);
}
tgt_color = vec4(color, opacity);
}

View File

@ -11,6 +11,9 @@ layout (std140)
uniform u_locals {
mat4 model_mat;
vec4 model_col;
// bit 0 - is player
// bit 1-31 - unused
int flags;
};
struct BoneData {

View File

@ -13,4 +13,5 @@ uniform u_globals {
uvec4 medium;
ivec4 select_pos;
vec4 gamma;
uint cam_mode;
};

View File

@ -0,0 +1,33 @@
#version 330 core
#include <globals.glsl>
in vec3 f_pos;
in vec3 f_col;
flat in vec3 f_norm;
layout (std140)
uniform u_locals {
mat4 model_mat;
vec4 model_col;
int flags;
};
struct BoneData {
mat4 bone_mat;
};
layout (std140)
uniform u_bones {
BoneData bones[16];
};
#include <sky.glsl>
#include <light.glsl>
#include <srgb.glsl>
out vec4 tgt_color;
void main() {
tgt_color = vec4(0.0,0.0,0.0, 1.0);
}

View File

@ -30,7 +30,7 @@ pub use self::{
},
Globals, Light, Shadow,
},
renderer::{Renderer, TgtColorFmt, TgtDepthFmt, WinColorFmt, WinDepthFmt},
renderer::{Renderer, TgtColorFmt, TgtDepthStencilFmt, WinColorFmt, WinDepthFmt},
texture::Texture,
};

View File

@ -1,10 +1,11 @@
use super::{
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthFmt},
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow,
};
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{ColorMask, Comparison, Stencil, StencilOp},
};
use vek::*;
@ -19,6 +20,7 @@ gfx_defines! {
constant Locals {
model_mat: [[f32; 4]; 4] = "model_mat",
model_col: [f32; 4] = "model_col",
flags: u32 = "flags",
}
constant BoneData {
@ -36,8 +38,8 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
tgt_depth: gfx::DepthTarget<TgtDepthFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA),
tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))),
}
}
@ -58,16 +60,20 @@ impl Vertex {
}
impl Locals {
pub fn new(model_mat: Mat4<f32>, col: Rgba<f32>) -> Self {
pub fn new(model_mat: Mat4<f32>, col: Rgba<f32>, is_player: bool) -> Self {
let mut flags = 0;
flags |= is_player as u32;
Self {
model_mat: arr_to_mat(model_mat.into_col_array()),
model_col: col.into_array(),
flags,
}
}
}
impl Default for Locals {
fn default() -> Self { Self::new(Mat4::identity(), Rgba::broadcast(1.0)) }
fn default() -> Self { Self::new(Mat4::identity(), Rgba::broadcast(1.0), false) }
}
impl BoneData {

View File

@ -1,10 +1,11 @@
use super::{
super::{Pipeline, TerrainLocals, TgtColorFmt, TgtDepthFmt},
super::{Pipeline, TerrainLocals, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow,
};
use gfx::{
self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner,
gfx_vertex_struct_meta, state::ColorMask,
gfx_vertex_struct_meta,
state::{ColorMask, Comparison, Stencil, StencilOp},
};
use std::ops::Mul;
use vek::*;
@ -27,7 +28,7 @@ gfx_defines! {
waves: gfx::TextureSampler<[f32; 4]> = "t_waves",
tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA),
tgt_depth: gfx::DepthTarget<TgtDepthFmt> = gfx::preset::depth::LESS_EQUAL_TEST,
tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_TEST,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}

View File

@ -7,6 +7,7 @@ pub mod terrain;
pub mod ui;
use super::util::arr_to_mat;
use crate::scene::camera::CameraMode;
use common::terrain::BlockKind;
use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta};
use vek::*;
@ -27,6 +28,7 @@ gfx_defines! {
medium: [u32; 4] = "medium",
select_pos: [i32; 4] = "select_pos",
gamma: [f32; 4] = "gamma",
cam_mode: u32 = "cam_mode",
}
constant Light {
@ -55,6 +57,7 @@ impl Globals {
medium: BlockKind,
select_pos: Option<Vec3<i32>>,
gamma: f32,
cam_mode: CameraMode,
) -> Self {
Self {
view_mat: arr_to_mat(view_mat.into_col_array()),
@ -73,6 +76,7 @@ impl Globals {
.unwrap_or(Vec4::zero())
.into_array(),
gamma: [gamma; 4],
cam_mode: cam_mode as u32,
}
}
}
@ -93,6 +97,7 @@ impl Default for Globals {
BlockKind::Air,
None,
1.0,
CameraMode::ThirdPerson,
)
}
}

View File

@ -1,10 +1,11 @@
use super::{
super::{Mesh, Pipeline, Quad, TgtColorFmt, TgtDepthFmt},
super::{Mesh, Pipeline, Quad, TgtColorFmt, TgtDepthStencilFmt},
Globals,
};
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{Comparison, Stencil, StencilOp},
};
gfx_defines! {
@ -25,7 +26,7 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
tgt_depth: gfx::DepthTarget<TgtDepthFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}

View File

@ -1,10 +1,11 @@
use super::{
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthFmt},
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow,
};
use gfx::{
self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner,
gfx_vertex_struct_meta, state::ColorMask,
gfx_vertex_struct_meta,
state::{ColorMask, Comparison, Stencil, StencilOp},
};
use vek::*;
@ -35,7 +36,7 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA),
tgt_depth: gfx::DepthTarget<TgtDepthFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}

View File

@ -1,10 +1,11 @@
use super::{
super::{Pipeline, TgtColorFmt, TgtDepthFmt},
super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow,
};
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{Comparison, Stencil, StencilOp},
};
use std::ops::Mul;
use vek::*;
@ -31,7 +32,7 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
tgt_depth: gfx::DepthTarget<TgtDepthFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}

View File

@ -12,6 +12,7 @@ use common::assets::{self, watch::ReloadIndicator};
use gfx::{
self,
handle::Sampler,
state::{Comparison, Stencil, StencilOp},
traits::{Device, Factory, FactoryExt},
};
use glsl_include::Context as IncludeContext;
@ -20,8 +21,8 @@ use vek::*;
/// Represents the format of the pre-processed color target.
pub type TgtColorFmt = gfx::format::Srgba8;
/// Represents the format of the pre-processed depth target.
pub type TgtDepthFmt = gfx::format::Depth;
/// Represents the format of the pre-processed depth and stencil target.
pub type TgtDepthStencilFmt = gfx::format::DepthStencil;
/// Represents the format of the window's color target.
pub type WinColorFmt = gfx::format::Srgba8;
@ -31,7 +32,8 @@ pub type WinDepthFmt = gfx::format::Depth;
/// A handle to a pre-processed color target.
pub type TgtColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, TgtColorFmt>;
/// A handle to a pre-processed depth target.
pub type TgtDepthView = gfx::handle::DepthStencilView<gfx_backend::Resources, TgtDepthFmt>;
pub type TgtDepthStencilView =
gfx::handle::DepthStencilView<gfx_backend::Resources, TgtDepthStencilFmt>;
/// A handle to a window color target.
pub type WinColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, WinColorFmt>;
@ -57,7 +59,7 @@ pub struct Renderer {
win_depth_view: WinDepthView,
tgt_color_view: TgtColorView,
tgt_depth_view: TgtDepthView,
tgt_depth_stencil_view: TgtDepthStencilView,
tgt_color_res: TgtColorRes,
@ -70,6 +72,7 @@ pub struct Renderer {
sprite_pipeline: GfxPipeline<sprite::pipe::Init<'static>>,
ui_pipeline: GfxPipeline<ui::pipe::Init<'static>>,
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
player_shadow_pipeline: GfxPipeline<figure::pipe::Init<'static>>,
shader_reload_indicator: ReloadIndicator,
@ -102,6 +105,7 @@ impl Renderer {
sprite_pipeline,
ui_pipeline,
postprocess_pipeline,
player_shadow_pipeline,
) = create_pipelines(
&mut factory,
aa_mode,
@ -111,7 +115,7 @@ impl Renderer {
)?;
let dims = win_color_view.get_dimensions();
let (tgt_color_view, tgt_depth_view, tgt_color_res) =
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_res) =
Self::create_rt_views(&mut factory, (dims.0, dims.1), aa_mode)?;
let sampler = factory.create_sampler_linear();
@ -132,7 +136,7 @@ impl Renderer {
win_depth_view,
tgt_color_view,
tgt_depth_view,
tgt_depth_stencil_view,
tgt_color_res,
sampler,
@ -144,6 +148,7 @@ impl Renderer {
sprite_pipeline,
ui_pipeline,
postprocess_pipeline,
player_shadow_pipeline,
shader_reload_indicator,
@ -158,8 +163,8 @@ impl Renderer {
/// Get references to the internal render target views that get rendered to
/// before post-processing.
#[allow(dead_code)]
pub fn tgt_views(&self) -> (&TgtColorView, &TgtDepthView) {
(&self.tgt_color_view, &self.tgt_depth_view)
pub fn tgt_views(&self) -> (&TgtColorView, &TgtDepthStencilView) {
(&self.tgt_color_view, &self.tgt_depth_stencil_view)
}
/// Get references to the internal render target views that get displayed
@ -172,8 +177,8 @@ impl Renderer {
/// Get mutable references to the internal render target views that get
/// rendered to before post-processing.
#[allow(dead_code)]
pub fn tgt_views_mut(&mut self) -> (&mut TgtColorView, &mut TgtDepthView) {
(&mut self.tgt_color_view, &mut self.tgt_depth_view)
pub fn tgt_views_mut(&mut self) -> (&mut TgtColorView, &mut TgtDepthStencilView) {
(&mut self.tgt_color_view, &mut self.tgt_depth_stencil_view)
}
/// Get mutable references to the internal render target views that get
@ -228,11 +233,11 @@ impl Renderer {
// Avoid panics when creating texture with w,h of 0,0.
if dims.0 != 0 && dims.1 != 0 {
let (tgt_color_view, tgt_depth_view, tgt_color_res) =
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_res) =
Self::create_rt_views(&mut self.factory, (dims.0, dims.1), self.aa_mode)?;
self.tgt_color_res = tgt_color_res;
self.tgt_color_view = tgt_color_view;
self.tgt_depth_view = tgt_depth_view;
self.tgt_depth_stencil_view = tgt_depth_stencil_view;
}
Ok(())
@ -242,7 +247,7 @@ impl Renderer {
factory: &mut gfx_device_gl::Factory,
size: (u16, u16),
aa_mode: AaMode,
) -> Result<(TgtColorView, TgtDepthView, TgtColorRes), RenderError> {
) -> Result<(TgtColorView, TgtDepthStencilView, TgtColorRes), RenderError> {
let kind = match aa_mode {
AaMode::None | AaMode::Fxaa => {
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Single)
@ -279,17 +284,18 @@ impl Renderer {
)?;
let tgt_color_view = factory.view_texture_as_render_target(&tgt_color_tex, 0, None)?;
let depth_cty = <<TgtDepthFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
let tgt_depth_tex = factory.create_texture(
let depth_stencil_cty = <<TgtDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
let tgt_depth_stencil_tex = factory.create_texture(
kind,
levels,
gfx::memory::Bind::DEPTH_STENCIL,
gfx::memory::Usage::Data,
Some(depth_cty),
Some(depth_stencil_cty),
)?;
let tgt_depth_view = factory.view_texture_as_depth_stencil_trivial(&tgt_depth_tex)?;
let tgt_depth_stencil_view =
factory.view_texture_as_depth_stencil_trivial(&tgt_depth_stencil_tex)?;
Ok((tgt_color_view, tgt_depth_view, tgt_color_res))
Ok((tgt_color_view, tgt_depth_stencil_view, tgt_color_res))
}
/// Get the resolution of the render target.
@ -303,7 +309,8 @@ impl Renderer {
/// Queue the clearing of the depth target ready for a new frame to be
/// rendered.
pub fn clear(&mut self) {
self.encoder.clear_depth(&self.tgt_depth_view, 1.0);
self.encoder.clear_depth(&self.tgt_depth_stencil_view, 1.0);
self.encoder.clear_stencil(&self.tgt_depth_stencil_view, 0);
self.encoder.clear_depth(&self.win_depth_view, 1.0);
}
@ -336,6 +343,7 @@ impl Renderer {
sprite_pipeline,
ui_pipeline,
postprocess_pipeline,
player_shadow_pipeline,
)) => {
self.skybox_pipeline = skybox_pipeline;
self.figure_pipeline = figure_pipeline;
@ -344,6 +352,7 @@ impl Renderer {
self.sprite_pipeline = sprite_pipeline;
self.ui_pipeline = ui_pipeline;
self.postprocess_pipeline = postprocess_pipeline;
self.player_shadow_pipeline = player_shadow_pipeline;
},
Err(e) => error!(
"Could not recreate shaders from assets due to an error: {:#?}",
@ -502,7 +511,7 @@ impl Renderer {
globals: globals.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth: self.tgt_depth_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone(), (1, 1)),
},
);
}
@ -535,7 +544,73 @@ impl Renderer {
shadows: shadows.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth: self.tgt_depth_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone(), (1, 1)),
},
);
}
/// Queue the rendering of the player silhouette in the upcoming frame.
pub fn render_player_shadow(
&mut self,
model: &Model<figure::FigurePipeline>,
globals: &Consts<Globals>,
locals: &Consts<figure::Locals>,
bones: &Consts<figure::BoneData>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
) {
self.encoder.draw(
&gfx::Slice {
start: model.vertex_range().start,
end: model.vertex_range().end,
base_vertex: 0,
instances: None,
buffer: gfx::IndexBuffer::Auto,
},
&self.player_shadow_pipeline.pso,
&figure::pipe::Data {
vbuf: model.vbuf.clone(),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
bones: bones.buf.clone(),
lights: lights.buf.clone(),
shadows: shadows.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone(), (0, 0)),
},
);
}
/// Queue the rendering of the player model in the upcoming frame.
pub fn render_player(
&mut self,
model: &Model<figure::FigurePipeline>,
globals: &Consts<Globals>,
locals: &Consts<figure::Locals>,
bones: &Consts<figure::BoneData>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
) {
self.encoder.draw(
&gfx::Slice {
start: model.vertex_range().start,
end: model.vertex_range().end,
base_vertex: 0,
instances: None,
buffer: gfx::IndexBuffer::Auto,
},
&self.figure_pipeline.pso,
&figure::pipe::Data {
vbuf: model.vbuf.clone(),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
bones: bones.buf.clone(),
lights: lights.buf.clone(),
shadows: shadows.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone(), (1, 1)),
},
);
}
@ -567,7 +642,7 @@ impl Renderer {
shadows: shadows.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth: self.tgt_depth_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone(), (1, 1)),
},
);
}
@ -601,7 +676,7 @@ impl Renderer {
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
waves: (waves.srv.clone(), waves.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth: self.tgt_depth_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone(), (1, 1)),
},
);
}
@ -633,7 +708,7 @@ impl Renderer {
shadows: shadows.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth: self.tgt_depth_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone(), (1, 1)),
},
);
}
@ -721,6 +796,7 @@ fn create_pipelines(
GfxPipeline<sprite::pipe::Init<'static>>,
GfxPipeline<ui::pipe::Init<'static>>,
GfxPipeline<postprocess::pipe::Init<'static>>,
GfxPipeline<figure::pipe::Init<'static>>,
),
RenderError,
> {
@ -869,6 +945,31 @@ fn create_pipelines(
gfx::state::CullFace::Back,
)?;
// Construct a pipeline for rendering the player silhouette
let player_shadow_pipeline = create_pipeline(
factory,
figure::pipe::Init {
tgt_depth_stencil: (
gfx::preset::depth::PASS_TEST,
Stencil::new(
Comparison::Equal,
0xff,
(StencilOp::Keep, StencilOp::Keep, StencilOp::Keep),
),
),
..figure::pipe::new()
},
&assets::load_watched::<String>("voxygen.shaders.figure-vert", shader_reload_indicator)
.unwrap(),
&assets::load_watched::<String>(
"voxygen.shaders.player-shadow-frag",
shader_reload_indicator,
)
.unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
Ok((
skybox_pipeline,
figure_pipeline,
@ -877,6 +978,7 @@ fn create_pipelines(
sprite_pipeline,
ui_pipeline,
postprocess_pipeline,
player_shadow_pipeline,
))
}

View File

@ -13,8 +13,8 @@ pub const MIN_ZOOM: f32 = 0.1;
// Possible TODO: Add more modes
#[derive(PartialEq, Clone, Copy, Eq, Hash)]
pub enum CameraMode {
FirstPerson,
ThirdPerson,
FirstPerson = 0,
ThirdPerson = 1,
}
impl Default for CameraMode {

View File

@ -144,6 +144,8 @@ impl FigureMgr {
)
.join()
{
let is_player = scene_data.player_entity == entity;
let (pos, ori) = interpolated
.map(|i| (Pos(i.pos), *i.ori))
.unwrap_or((*pos, Vec3::unit_y()));
@ -380,7 +382,7 @@ impl FigureMgr {
let col = stats
.map(|s| {
Rgba::broadcast(1.0)
+ Rgba::new(2.0, 2.0, 2.0, 0.0).map(|c| {
+ Rgba::new(2.0, 2.0, 2., 0.00).map(|c| {
(c / (1.0 + DAMAGE_FADE_COEFFICIENT * s.health.last_change.0)) as f32
})
})
@ -627,6 +629,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::QuadrupedSmall(_) => {
@ -707,6 +710,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::QuadrupedMedium(_) => {
@ -789,6 +793,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::BirdMedium(_) => {
@ -863,6 +868,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::FishMedium(_) => {
@ -937,6 +943,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::Dragon(_) => {
@ -1011,6 +1018,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::Critter(_) => {
@ -1085,6 +1093,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::BirdSmall(_) => {
@ -1159,6 +1168,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::FishSmall(_) => {
@ -1233,6 +1243,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::BipedLarge(_) => {
@ -1307,6 +1318,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
Body::Object(_) => {
@ -1326,6 +1338,7 @@ impl FigureMgr {
state_animation_rate,
lpindex,
true,
is_player,
);
},
}
@ -1386,201 +1399,110 @@ impl FigureMgr {
.filter(|(_, _, _, _, stats, _, _)| stats.map_or(true, |s| !s.is_dead))
{
let is_player = entity == player_entity;
let player_camera_mode = if is_player {
camera.get_mode()
} else {
CameraMode::default()
};
let character_state = if is_player { character_state } else { None };
let FigureMgr {
model_cache,
critter_model_cache,
quadruped_small_model_cache,
quadruped_medium_model_cache,
bird_medium_model_cache,
bird_small_model_cache,
dragon_model_cache,
fish_medium_model_cache,
fish_small_model_cache,
biped_large_model_cache,
character_states,
quadruped_small_states,
quadruped_medium_states,
bird_medium_states,
fish_medium_states,
critter_states,
dragon_states,
bird_small_states,
fish_small_states,
biped_large_states,
object_states,
} = self;
if let Some((locals, bone_consts, model)) = match body {
Body::Humanoid(_) => character_states
.get(&entity)
.filter(|state| state.visible)
.map(|state| {
(
state.locals(),
state.bone_consts(),
&model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::QuadrupedSmall(_) => quadruped_small_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&quadruped_small_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::QuadrupedMedium(_) => quadruped_medium_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&quadruped_medium_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::BirdMedium(_) => bird_medium_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&bird_medium_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::FishMedium(_) => fish_medium_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&fish_medium_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::Critter(_) => critter_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&critter_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::Dragon(_) => dragon_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&dragon_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::BirdSmall(_) => bird_small_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&bird_small_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::FishSmall(_) => fish_small_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&fish_small_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::BipedLarge(_) => biped_large_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&biped_large_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::Object(_) => object_states.get(&entity).map(|state| {
if !is_player {
self.render_figure(
renderer,
tick,
globals,
lights,
shadows,
camera,
character_state,
entity,
body,
loadout,
false,
);
}
}
}
pub fn render_player(
&mut self,
renderer: &mut Renderer,
state: &State,
player_entity: EcsEntity,
tick: u64,
globals: &Consts<Globals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
camera: &Camera,
) {
let ecs = state.ecs();
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
let character_state = character_state_storage.get(player_entity);
if let Some(body) = ecs.read_storage::<Body>().get(player_entity) {
let loadout_storage = ecs.read_storage::<Loadout>();
let loadout = loadout_storage.get(player_entity);
self.render_figure(
renderer,
tick,
globals,
lights,
shadows,
camera,
character_state,
player_entity,
body,
loadout,
true,
);
}
}
fn render_figure(
&mut self,
renderer: &mut Renderer,
tick: u64,
globals: &Consts<Globals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
camera: &Camera,
character_state: Option<&CharacterState>,
entity: EcsEntity,
body: &Body,
loadout: Option<&Loadout>,
is_player: bool,
) {
let player_camera_mode = if is_player {
camera.get_mode()
} else {
CameraMode::default()
};
let character_state = if is_player { character_state } else { None };
let FigureMgr {
model_cache,
critter_model_cache,
quadruped_small_model_cache,
quadruped_medium_model_cache,
bird_medium_model_cache,
bird_small_model_cache,
dragon_model_cache,
fish_medium_model_cache,
fish_small_model_cache,
biped_large_model_cache,
character_states,
quadruped_small_states,
quadruped_medium_states,
bird_medium_states,
fish_medium_states,
critter_states,
dragon_states,
bird_small_states,
fish_small_states,
biped_large_states,
object_states,
} = self;
if let Some((locals, bone_consts, model)) = match body {
Body::Humanoid(_) => character_states
.get(&entity)
.filter(|state| state.visible)
.map(|state| {
(
state.locals(),
state.bone_consts(),
@ -1596,11 +1518,175 @@ impl FigureMgr {
.0,
)
}),
} {
renderer.render_figure(model, globals, locals, bone_consts, lights, shadows);
Body::QuadrupedSmall(_) => quadruped_small_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&quadruped_small_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::QuadrupedMedium(_) => quadruped_medium_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&quadruped_medium_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::BirdMedium(_) => bird_medium_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&bird_medium_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::FishMedium(_) => fish_medium_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&fish_medium_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::Critter(_) => critter_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&critter_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::Dragon(_) => dragon_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&dragon_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::BirdSmall(_) => bird_small_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&bird_small_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::FishSmall(_) => fish_small_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&fish_small_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::BipedLarge(_) => biped_large_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&biped_large_model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
Body::Object(_) => object_states.get(&entity).map(|state| {
(
state.locals(),
state.bone_consts(),
&model_cache
.get_or_create_model(
renderer,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
)
}),
} {
if is_player {
renderer.render_player(model, globals, locals, bone_consts, lights, shadows);
renderer.render_player_shadow(model, globals, locals, bone_consts, lights, shadows);
} else {
trace!("Body has no saved figure");
renderer.render_figure(model, globals, locals, bone_consts, lights, shadows);
}
} else {
trace!("Body has no saved figure");
}
}
@ -1705,6 +1791,7 @@ impl<S: Skeleton> FigureState<S> {
state_animation_rate: f32,
lpindex: u8,
visible: bool,
is_player: bool,
) {
self.visible = visible;
self.lpindex = lpindex;
@ -1720,7 +1807,7 @@ impl<S: Skeleton> FigureState<S> {
* Mat4::rotation_x(ori.z.atan2(Vec2::from(ori).magnitude()))
* Mat4::scaling_3d(Vec3::from(0.8 * scale));
let locals = FigureLocals::new(mat, col);
let locals = FigureLocals::new(mat, col, is_player);
renderer.update_consts(&mut self.locals, &[locals]).unwrap();
renderer

View File

@ -347,6 +347,7 @@ impl Scene {
.unwrap_or(BlockKind::Air),
self.select_pos,
gamma,
self.camera.get_mode(),
)])
.expect("Failed to update global constants");
@ -381,6 +382,13 @@ impl Scene {
tick: u64,
) {
// Render terrain and figures.
self.terrain.render(
renderer,
&self.globals,
&self.lights,
&self.shadows,
self.camera.get_focus_pos(),
);
self.figure_mgr.render(
renderer,
state,
@ -391,13 +399,6 @@ impl Scene {
&self.shadows,
&self.camera,
);
self.terrain.render(
renderer,
&self.globals,
&self.lights,
&self.shadows,
self.camera.get_focus_pos(),
);
// Render the skybox.
renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals);
@ -410,6 +411,17 @@ impl Scene {
self.camera.get_focus_pos(),
);
self.figure_mgr.render_player(
renderer,
state,
player_entity,
tick,
&self.globals,
&self.lights,
&self.shadows,
&self.camera,
);
renderer.render_post_process(
&self.postprocess.model,
&self.globals,

View File

@ -170,6 +170,7 @@ impl Scene {
BlockKind::Air,
None,
scene_data.gamma,
self.camera.get_mode(),
)]) {
error!("Renderer failed to update: {:?}", err);
}
@ -199,6 +200,7 @@ impl Scene {
1.0,
0,
true,
false,
);
}