use super::{ super::{Mesh, Model, Pipeline, TerrainPipeline, TgtColorFmt, TgtDepthStencilFmt}, shadow, Globals, Light, Shadow, }; use crate::mesh::greedy::GreedyMesh; use core::ops::Range; use gfx::{ self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner, state::ColorMask, }; use vek::*; gfx_defines! { constant Locals { model_mat: [[f32; 4]; 4] = "model_mat", model_col: [f32; 4] = "model_col", atlas_offs: [i32; 4] = "atlas_offs", model_pos: [f32; 3] = "model_pos", flags: u32 = "flags", } constant BoneData { bone_mat: [[f32; 4]; 4] = "bone_mat", normals_mat: [[f32; 4]; 4] = "normals_mat", } pipeline pipe { vbuf: gfx::VertexBuffer<::Vertex> = (), // abuf: gfx::VertexBuffer<::Vertex> = (), col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", locals: gfx::ConstantBuffer = "u_locals", globals: gfx::ConstantBuffer = "u_globals", bones: gfx::ConstantBuffer = "u_bones", lights: gfx::ConstantBuffer = "u_lights", shadows: gfx::ConstantBuffer = "u_shadows", point_shadow_maps: gfx::TextureSampler = "t_point_shadow_maps", directed_shadow_maps: gfx::TextureSampler = "t_directed_shadow_maps", alt: gfx::TextureSampler<[f32; 2]> = "t_alt", horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", noise: gfx::TextureSampler = "t_noise", // Shadow stuff light_shadows: gfx::ConstantBuffer = "u_light_shadows", tgt_color: gfx::BlendTarget = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, // tgt_depth_stencil: gfx::DepthStencilTarget = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))), } } impl Locals { pub fn new( model_mat: anim::vek::Mat4, col: Rgba, pos: anim::vek::Vec3, atlas_offs: Vec2, is_player: bool, ) -> Self { let mut flags = 0; flags |= is_player as u32; Self { model_mat: model_mat.into_col_arrays(), model_col: col.into_array(), model_pos: pos.into_array(), atlas_offs: Vec4::from(atlas_offs).into_array(), flags, } } } impl Default for Locals { fn default() -> Self { Self::new( anim::vek::Mat4::identity(), Rgba::broadcast(1.0), anim::vek::Vec3::default(), Vec2::default(), false, ) } } impl BoneData { pub fn new(bone_mat: anim::vek::Mat4, normals_mat: anim::vek::Mat4) -> Self { Self { bone_mat: bone_mat.into_col_arrays(), normals_mat: normals_mat.into_col_arrays(), } } } impl Default for BoneData { fn default() -> Self { Self::new(anim::vek::Mat4::identity(), anim::vek::Mat4::identity()) } } pub struct FigurePipeline; impl Pipeline for FigurePipeline { type Vertex = ::Vertex; } pub struct FigureModel { pub opaque: Model, /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different * LOD levels. */ } impl FigureModel { /// Start a greedy mesh designed for figure bones. pub fn make_greedy<'a>() -> GreedyMesh<'a> { // NOTE: Required because we steal two bits from the normal in the shadow uint // in order to store the bone index. The two bits are instead taken out // of the atlas coordinates, which is why we "only" allow 1 << 15 per // coordinate instead of 1 << 16. let max_size = guillotiere::Size::new((1 << 15) - 1, (1 << 15) - 1); GreedyMesh::new(max_size) } } pub type BoneMeshes = (Mesh, (anim::vek::Aabb, Range));