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 - Fleshed out range attack into charging and shooting anims for staff/bow
- Customized attack animation for hammers and axes - Customized attack animation for hammers and axes
- German translation - German translation
- Added a silhouette for players when they are occluded
- Added transparency to the player when zooming in
### Changed ### 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 - Asset cleanup to lower client-size
- Rewrote the humanoid skeleton to be more ideal for attack animations - Rewrote the humanoid skeleton to be more ideal for attack animations
### Removed ### Removed
## [0.5.0] - 2019-01-31 ## [0.5.0] - 2019-01-31

View File

@ -10,6 +10,9 @@ layout (std140)
uniform u_locals { uniform u_locals {
mat4 model_mat; mat4 model_mat;
vec4 model_col; vec4 model_col;
// bit 0 - is player
// bit 1-31 - unused
int flags;
}; };
struct BoneData { 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 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); 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 { uniform u_locals {
mat4 model_mat; mat4 model_mat;
vec4 model_col; vec4 model_col;
// bit 0 - is player
// bit 1-31 - unused
int flags;
}; };
struct BoneData { struct BoneData {

View File

@ -13,4 +13,5 @@ uniform u_globals {
uvec4 medium; uvec4 medium;
ivec4 select_pos; ivec4 select_pos;
vec4 gamma; 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, Globals, Light, Shadow,
}, },
renderer::{Renderer, TgtColorFmt, TgtDepthFmt, WinColorFmt, WinDepthFmt}, renderer::{Renderer, TgtColorFmt, TgtDepthStencilFmt, WinColorFmt, WinDepthFmt},
texture::Texture, texture::Texture,
}; };

View File

@ -1,10 +1,11 @@
use super::{ use super::{
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthFmt}, super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow, Globals, Light, Shadow,
}; };
use gfx::{ use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta, gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{ColorMask, Comparison, Stencil, StencilOp},
}; };
use vek::*; use vek::*;
@ -19,6 +20,7 @@ gfx_defines! {
constant Locals { constant Locals {
model_mat: [[f32; 4]; 4] = "model_mat", model_mat: [[f32; 4]; 4] = "model_mat",
model_col: [f32; 4] = "model_col", model_col: [f32; 4] = "model_col",
flags: u32 = "flags",
} }
constant BoneData { constant BoneData {
@ -36,8 +38,8 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color", 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::Replace))),
} }
} }
@ -58,16 +60,20 @@ impl Vertex {
} }
impl Locals { 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 { Self {
model_mat: arr_to_mat(model_mat.into_col_array()), model_mat: arr_to_mat(model_mat.into_col_array()),
model_col: col.into_array(), model_col: col.into_array(),
flags,
} }
} }
} }
impl Default for Locals { 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 { impl BoneData {

View File

@ -1,10 +1,11 @@
use super::{ use super::{
super::{Pipeline, TerrainLocals, TgtColorFmt, TgtDepthFmt}, super::{Pipeline, TerrainLocals, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow, Globals, Light, Shadow,
}; };
use gfx::{ use gfx::{
self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner, 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 std::ops::Mul;
use vek::*; use vek::*;
@ -27,7 +28,7 @@ gfx_defines! {
waves: gfx::TextureSampler<[f32; 4]> = "t_waves", waves: gfx::TextureSampler<[f32; 4]> = "t_waves",
tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), 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; pub mod ui;
use super::util::arr_to_mat; use super::util::arr_to_mat;
use crate::scene::camera::CameraMode;
use common::terrain::BlockKind; use common::terrain::BlockKind;
use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta}; use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta};
use vek::*; use vek::*;
@ -27,6 +28,7 @@ gfx_defines! {
medium: [u32; 4] = "medium", medium: [u32; 4] = "medium",
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",
} }
constant Light { constant Light {
@ -55,6 +57,7 @@ impl Globals {
medium: BlockKind, medium: BlockKind,
select_pos: Option<Vec3<i32>>, select_pos: Option<Vec3<i32>>,
gamma: f32, gamma: f32,
cam_mode: CameraMode,
) -> Self { ) -> Self {
Self { Self {
view_mat: arr_to_mat(view_mat.into_col_array()), view_mat: arr_to_mat(view_mat.into_col_array()),
@ -73,6 +76,7 @@ impl Globals {
.unwrap_or(Vec4::zero()) .unwrap_or(Vec4::zero())
.into_array(), .into_array(),
gamma: [gamma; 4], gamma: [gamma; 4],
cam_mode: cam_mode as u32,
} }
} }
} }
@ -93,6 +97,7 @@ impl Default for Globals {
BlockKind::Air, BlockKind::Air,
None, None,
1.0, 1.0,
CameraMode::ThirdPerson,
) )
} }
} }

View File

@ -1,10 +1,11 @@
use super::{ use super::{
super::{Mesh, Pipeline, Quad, TgtColorFmt, TgtDepthFmt}, super::{Mesh, Pipeline, Quad, TgtColorFmt, TgtDepthStencilFmt},
Globals, Globals,
}; };
use gfx::{ use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta, gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{Comparison, Stencil, StencilOp},
}; };
gfx_defines! { gfx_defines! {
@ -25,7 +26,7 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color", 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::{ use super::{
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthFmt}, super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow, Globals, Light, Shadow,
}; };
use gfx::{ use gfx::{
self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner, 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::*; use vek::*;
@ -35,7 +36,7 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), 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::{ use super::{
super::{Pipeline, TgtColorFmt, TgtDepthFmt}, super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow, Globals, Light, Shadow,
}; };
use gfx::{ use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta, gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{Comparison, Stencil, StencilOp},
}; };
use std::ops::Mul; use std::ops::Mul;
use vek::*; use vek::*;
@ -31,7 +32,7 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color", 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::{ use gfx::{
self, self,
handle::Sampler, handle::Sampler,
state::{Comparison, Stencil, StencilOp},
traits::{Device, Factory, FactoryExt}, traits::{Device, Factory, FactoryExt},
}; };
use glsl_include::Context as IncludeContext; use glsl_include::Context as IncludeContext;
@ -20,8 +21,8 @@ use vek::*;
/// Represents the format of the pre-processed color target. /// Represents the format of the pre-processed color target.
pub type TgtColorFmt = gfx::format::Srgba8; pub type TgtColorFmt = gfx::format::Srgba8;
/// Represents the format of the pre-processed depth target. /// Represents the format of the pre-processed depth and stencil target.
pub type TgtDepthFmt = gfx::format::Depth; pub type TgtDepthStencilFmt = gfx::format::DepthStencil;
/// Represents the format of the window's color target. /// Represents the format of the window's color target.
pub type WinColorFmt = gfx::format::Srgba8; pub type WinColorFmt = gfx::format::Srgba8;
@ -31,7 +32,8 @@ pub type WinDepthFmt = gfx::format::Depth;
/// A handle to a pre-processed color target. /// A handle to a pre-processed color target.
pub type TgtColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, TgtColorFmt>; pub type TgtColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, TgtColorFmt>;
/// A handle to a pre-processed depth target. /// 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. /// A handle to a window color target.
pub type WinColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, WinColorFmt>; pub type WinColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, WinColorFmt>;
@ -57,7 +59,7 @@ pub struct Renderer {
win_depth_view: WinDepthView, win_depth_view: WinDepthView,
tgt_color_view: TgtColorView, tgt_color_view: TgtColorView,
tgt_depth_view: TgtDepthView, tgt_depth_stencil_view: TgtDepthStencilView,
tgt_color_res: TgtColorRes, tgt_color_res: TgtColorRes,
@ -70,6 +72,7 @@ pub struct Renderer {
sprite_pipeline: GfxPipeline<sprite::pipe::Init<'static>>, sprite_pipeline: GfxPipeline<sprite::pipe::Init<'static>>,
ui_pipeline: GfxPipeline<ui::pipe::Init<'static>>, ui_pipeline: GfxPipeline<ui::pipe::Init<'static>>,
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>, postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
player_shadow_pipeline: GfxPipeline<figure::pipe::Init<'static>>,
shader_reload_indicator: ReloadIndicator, shader_reload_indicator: ReloadIndicator,
@ -102,6 +105,7 @@ impl Renderer {
sprite_pipeline, sprite_pipeline,
ui_pipeline, ui_pipeline,
postprocess_pipeline, postprocess_pipeline,
player_shadow_pipeline,
) = create_pipelines( ) = create_pipelines(
&mut factory, &mut factory,
aa_mode, aa_mode,
@ -111,7 +115,7 @@ impl Renderer {
)?; )?;
let dims = win_color_view.get_dimensions(); 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)?; Self::create_rt_views(&mut factory, (dims.0, dims.1), aa_mode)?;
let sampler = factory.create_sampler_linear(); let sampler = factory.create_sampler_linear();
@ -132,7 +136,7 @@ impl Renderer {
win_depth_view, win_depth_view,
tgt_color_view, tgt_color_view,
tgt_depth_view, tgt_depth_stencil_view,
tgt_color_res, tgt_color_res,
sampler, sampler,
@ -144,6 +148,7 @@ impl Renderer {
sprite_pipeline, sprite_pipeline,
ui_pipeline, ui_pipeline,
postprocess_pipeline, postprocess_pipeline,
player_shadow_pipeline,
shader_reload_indicator, shader_reload_indicator,
@ -158,8 +163,8 @@ impl Renderer {
/// Get references to the internal render target views that get rendered to /// Get references to the internal render target views that get rendered to
/// before post-processing. /// before post-processing.
#[allow(dead_code)] #[allow(dead_code)]
pub fn tgt_views(&self) -> (&TgtColorView, &TgtDepthView) { pub fn tgt_views(&self) -> (&TgtColorView, &TgtDepthStencilView) {
(&self.tgt_color_view, &self.tgt_depth_view) (&self.tgt_color_view, &self.tgt_depth_stencil_view)
} }
/// Get references to the internal render target views that get displayed /// 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 /// Get mutable references to the internal render target views that get
/// rendered to before post-processing. /// rendered to before post-processing.
#[allow(dead_code)] #[allow(dead_code)]
pub fn tgt_views_mut(&mut self) -> (&mut TgtColorView, &mut TgtDepthView) { pub fn tgt_views_mut(&mut self) -> (&mut TgtColorView, &mut TgtDepthStencilView) {
(&mut self.tgt_color_view, &mut self.tgt_depth_view) (&mut self.tgt_color_view, &mut self.tgt_depth_stencil_view)
} }
/// Get mutable references to the internal render target views that get /// 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. // Avoid panics when creating texture with w,h of 0,0.
if dims.0 != 0 && dims.1 != 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::create_rt_views(&mut self.factory, (dims.0, dims.1), self.aa_mode)?;
self.tgt_color_res = tgt_color_res; self.tgt_color_res = tgt_color_res;
self.tgt_color_view = tgt_color_view; self.tgt_color_view = tgt_color_view;
self.tgt_depth_view = tgt_depth_view; self.tgt_depth_stencil_view = tgt_depth_stencil_view;
} }
Ok(()) Ok(())
@ -242,7 +247,7 @@ impl Renderer {
factory: &mut gfx_device_gl::Factory, factory: &mut gfx_device_gl::Factory,
size: (u16, u16), size: (u16, u16),
aa_mode: AaMode, aa_mode: AaMode,
) -> Result<(TgtColorView, TgtDepthView, TgtColorRes), RenderError> { ) -> Result<(TgtColorView, TgtDepthStencilView, TgtColorRes), RenderError> {
let kind = match aa_mode { let kind = match aa_mode {
AaMode::None | AaMode::Fxaa => { AaMode::None | AaMode::Fxaa => {
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Single) 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 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 depth_stencil_cty = <<TgtDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
let tgt_depth_tex = factory.create_texture( let tgt_depth_stencil_tex = factory.create_texture(
kind, kind,
levels, levels,
gfx::memory::Bind::DEPTH_STENCIL, gfx::memory::Bind::DEPTH_STENCIL,
gfx::memory::Usage::Data, 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. /// 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 /// Queue the clearing of the depth target ready for a new frame to be
/// rendered. /// rendered.
pub fn clear(&mut self) { 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); self.encoder.clear_depth(&self.win_depth_view, 1.0);
} }
@ -336,6 +343,7 @@ impl Renderer {
sprite_pipeline, sprite_pipeline,
ui_pipeline, ui_pipeline,
postprocess_pipeline, postprocess_pipeline,
player_shadow_pipeline,
)) => { )) => {
self.skybox_pipeline = skybox_pipeline; self.skybox_pipeline = skybox_pipeline;
self.figure_pipeline = figure_pipeline; self.figure_pipeline = figure_pipeline;
@ -344,6 +352,7 @@ impl Renderer {
self.sprite_pipeline = sprite_pipeline; self.sprite_pipeline = sprite_pipeline;
self.ui_pipeline = ui_pipeline; self.ui_pipeline = ui_pipeline;
self.postprocess_pipeline = postprocess_pipeline; self.postprocess_pipeline = postprocess_pipeline;
self.player_shadow_pipeline = player_shadow_pipeline;
}, },
Err(e) => error!( Err(e) => error!(
"Could not recreate shaders from assets due to an error: {:#?}", "Could not recreate shaders from assets due to an error: {:#?}",
@ -502,7 +511,7 @@ impl Renderer {
globals: globals.buf.clone(), globals: globals.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.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(), shadows: shadows.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.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(), shadows: shadows.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.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()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
waves: (waves.srv.clone(), waves.sampler.clone()), waves: (waves.srv.clone(), waves.sampler.clone()),
tgt_color: self.tgt_color_view.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(), shadows: shadows.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
tgt_color: self.tgt_color_view.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<sprite::pipe::Init<'static>>,
GfxPipeline<ui::pipe::Init<'static>>, GfxPipeline<ui::pipe::Init<'static>>,
GfxPipeline<postprocess::pipe::Init<'static>>, GfxPipeline<postprocess::pipe::Init<'static>>,
GfxPipeline<figure::pipe::Init<'static>>,
), ),
RenderError, RenderError,
> { > {
@ -869,6 +945,31 @@ fn create_pipelines(
gfx::state::CullFace::Back, 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(( Ok((
skybox_pipeline, skybox_pipeline,
figure_pipeline, figure_pipeline,
@ -877,6 +978,7 @@ fn create_pipelines(
sprite_pipeline, sprite_pipeline,
ui_pipeline, ui_pipeline,
postprocess_pipeline, postprocess_pipeline,
player_shadow_pipeline,
)) ))
} }

View File

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

View File

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

View File

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

View File

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