Fix all clippy issues, clean up Rust code.

This commit is contained in:
Joshua Yanovski 2020-08-07 11:55:20 +02:00
parent 6f90e010b3
commit c79f512f84
30 changed files with 746 additions and 2741 deletions

View File

@ -233,10 +233,7 @@ impl Client {
map_size_lg,
core::ops::RangeInclusive::new(0.0, max_height),
);
// map_config.gain = max_height;
map_config.horizons = Some(&horizons);
// map_config.light_direction = Vec3::new(1.0, -1.0, 0.0);
// map_config.focus.z = 0.0;
let rescale_height = |h: f32| h / max_height;
let bounds_check = |pos: Vec2<i32>| {
pos.reduce_partial_min() >= 0
@ -308,8 +305,7 @@ impl Client {
},
);
let make_raw = |rgba| -> Result<_, Error> {
let mut raw =
vec![0u8; 4 * world_map.len()/*map_size.x * map_size.y*/];
let mut raw = vec![0u8; 4 * world_map.len()];
LittleEndian::write_u32_into(rgba, &mut raw);
Ok(Arc::new(
image::DynamicImage::ImageRgba8({
@ -323,15 +319,14 @@ impl Client {
.flipv(),
))
};
let lod_base = rgba; //make_raw(&rgba)?;
let lod_alt = alt; //make_raw(&alt)?;
let lod_base = rgba;
let lod_alt = alt;
let world_map = make_raw(&world_map)?;
let horizons = (west.0, west.1, east.0, east.1)
.into_par_iter()
.map(|(wa, wh, ea, eh)| u32::from_le_bytes([wa, wh, ea, eh]))
.collect::<Vec<_>>();
let lod_horizon = horizons; //make_raw(&horizons)?;
// TODO: Get sea_level from server.
let lod_horizon = horizons;
let map_bounds = Vec2::new(sea_level, max_height);
debug!("Done preparing image...");

View File

@ -157,7 +157,7 @@ impl MapSizeLg {
#[inline(always)]
pub const fn new(map_size_lg: Vec2<u32>) -> Result<Self, ()> {
// Assertion on dimensions: must be between
// 0 and MAX_WORLD_BLOCKS_LG] - [TERRAIN_CHUNK_BLOCKS_LG
// 0 and ([MAX_WORLD_BLOCKS_LG] - [TERRAIN_CHUNK_BLOCKS_LG])
let is_le_max = map_size_lg.x <= MAX_WORLD_BLOCKS_LG.x - TERRAIN_CHUNK_BLOCKS_LG
&& map_size_lg.y <= MAX_WORLD_BLOCKS_LG.y - TERRAIN_CHUNK_BLOCKS_LG;
// Assertion on dimensions: chunks must fit in a u16.
@ -667,14 +667,12 @@ impl<'a> MapConfig<'a> {
let i_a = Rgb::new(0.1, 0.1, 0.1);
// V = direction pointing towards the viewer (e.g. virtual camera).
let v = Vec3::new(0.0, 0.0, -1.0).normalized();
// let v = Vec3::new(0.0, -1.0, 0.0).normalized();
//
// for each light m,
// i_m,d = (RGB) intensity of diffuse component of light source m
let i_m_d = Rgb::new(1.0, 1.0, 1.0);
// i_m,s = (RGB) intensity of specular component of light source m
let i_m_s = Rgb::new(0.45, 0.45, 0.45);
// let i_m_s = Rgb::new(0.45, 0.45, 0.45);
// for each light m and point p,
// L_m = (normalized) direction vector from point on surface to light source m

View File

@ -6,13 +6,3 @@ pub use ::vek::{
bezier::repr_c::*, geom::repr_c::*, mat::repr_c::column_major::Mat4, ops::*,
quaternion::repr_c::*, transform::repr_c::*, transition::*, vec::repr_c::*,
}; */
/* pub use vek::{
bezier::repr_c::*,
geom::repr_c::*,
mat::repr_simd::column_major::Mat4,
ops::*,
quaternion::repr_simd::*,
transform::repr_c::*,
transition::*,
vec::repr_simd::*,
}; */

View File

@ -3,6 +3,13 @@ use vek::*;
type TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex;
type TodoRect = (
Vec3<i32>,
Vec2<Vec3<u16>>,
guillotiere::Rectangle,
Vec3<i32>,
);
/// `max_size`:
///
/// `draw_delta`:
@ -162,7 +169,7 @@ impl<'a> GreedyMesh<'a> {
FS: for<'r> FnMut(&'r mut D, Vec3<i32>, Vec3<i32>, Vec2<Vec3<i32>>) -> Option<(bool, M)>,
FP: FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
{
let (bounds, /* opaque, *//*shadow, */ cont) = greedy_mesh(
let (bounds, cont) = greedy_mesh(
&mut self.atlas,
&mut self.col_lights_size,
self.max_size,
@ -183,7 +190,10 @@ impl<'a> GreedyMesh<'a> {
/// Returns the ColLightsInfo corresponding to the consstructed atlas.
pub fn finalize(self) -> ColLightInfo {
let cur_size = self.col_lights_size;
let col_lights = vec![/*Default::default()*/TerrainVertex::make_col_light(254, Rgb::broadcast(254)); usize::from(cur_size.x) * usize::from(cur_size.y)];
let col_lights = vec![
TerrainVertex::make_col_light(254, Rgb::broadcast(254));
usize::from(cur_size.x) * usize::from(cur_size.y)
];
let mut col_lights_info = (col_lights, cur_size);
self.suspended.into_iter().for_each(|cont| {
cont(&mut col_lights_info);
@ -209,12 +219,7 @@ fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FC, FO, FS, FP>(
mut should_draw,
mut push_quad,
}: GreedyConfig<D, FL, FC, FO, FS, FP>,
) -> (
Aabb<u16>,
// Mesh<O>,
// Mesh<S>,
Box<SuspendedMesh<'a>>,
)
) -> (Aabb<u16>, Box<SuspendedMesh<'a>>)
where
FL: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
FC: for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a,
@ -222,24 +227,9 @@ where
FS: for<'r> FnMut(&'r mut D, Vec3<i32>, Vec3<i32>, Vec2<Vec3<i32>>) -> Option<(bool, M)>,
FP: FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
{
// let mut opaque_mesh = Mesh::new();
// let mut shadow_mesh = Mesh::new();
// TODO: Collect information to see if we can choose a good value here.
let mut todo_rects = Vec::with_capacity(1024);
/* let mut bounds = Aabb {
min: Vec3::zero(),
max: Vec3::zero(),
}; */
/* let compute_bounds = |pos: Vec3<usize>, dim: Vec2<usize>, uv: Vec2<Vec3<u16>>/*, norm: Vec3<u16>, faces_forward: bool*/| {
Aabb {
min: pos,
max: pos + uv.x.map(usize::from) * dim.x + uv.y.map(usize::from) * dim.y,
}
}; */
// x (u = y, v = z)
greedy_mesh_cross_section(
Vec3::new(greedy_size.y, greedy_size.z, greedy_size_cross.x),
@ -247,7 +237,7 @@ where
should_draw(
&mut data,
draw_delta + Vec3::new(pos.z, pos.x, pos.y),
Vec3::unit_x(), /* , pos.z, 0, x_size */
Vec3::unit_x(),
Vec2::new(Vec3::unit_y(), Vec3::unit_z()),
)
},
@ -255,7 +245,6 @@ where
let pos = Vec3::new(pos.z, pos.x, pos.y);
let uv = Vec2::new(Vec3::unit_y(), Vec3::unit_z());
let norm = Vec3::unit_x();
// bounds.expand_to_contain(compute_bounds(pos, dim, uv));
let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
atlas,
&mut todo_rects,
@ -267,29 +256,18 @@ where
max_size,
col_lights_size,
) {
// assert!(atlas_pos.max.x - atlas_pos.min.x == dim.x as i32);
// assert!(atlas_pos.max.y - atlas_pos.min.y == dim.y as i32);
atlas_pos
} else {
return;
};
create_quad_greedy(
// &mut shadow_mesh,
// &mut opaque_mesh,
/* Vec3::new(pos.z, pos.x, pos.y) */
pos,
dim,
uv,
norm,
faces_forward,
// Rgba::from_opaque(flat_get(pos).color),
// lightm
// ao,
meta,
atlas_pos,
// |pos| flat_get(pos),
// |pos, norm, meta| create_shadow(pos, norm, meta),
// |atlas_pos, pos, norm, meta| create_opaque(atlas_pos, pos, norm, meta),
|atlas_pos, dim, pos, draw_dim, norm, meta| {
push_quad(atlas_pos, dim, pos, draw_dim, norm, meta)
},
@ -312,7 +290,6 @@ where
let pos = Vec3::new(pos.y, pos.z, pos.x);
let uv = Vec2::new(Vec3::unit_z(), Vec3::unit_x());
let norm = Vec3::unit_y();
// bounds.expand_to_contain(compute_bounds(pos, dim, uv));
let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
atlas,
&mut todo_rects,
@ -329,18 +306,13 @@ where
return;
};
create_quad_greedy(
// &mut shadow_mesh,
// &mut opaque_mesh,
pos,
dim,
uv,
norm,
faces_forward,
// Rgba::from_opaque(flat_get(pos).color),
meta,
atlas_pos,
// |pos, norm, meta| create_shadow(pos, norm, meta),
// |atlas_pos, pos, norm, meta| create_opaque(atlas_pos, pos, norm, meta),
|atlas_pos, dim, pos, draw_dim, norm, meta| {
push_quad(atlas_pos, dim, pos, draw_dim, norm, meta)
},
@ -352,25 +324,17 @@ where
greedy_mesh_cross_section(
Vec3::new(greedy_size.x, greedy_size.y, greedy_size_cross.z),
|pos| {
/* if pos.z == 0 {
let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let to = flat_get(pos).is_opaque(); //map(|v| v.is_opaque()).unwrap_or(false);
if to { Some(false) } else { None }
} else */
{
should_draw(
&mut data,
draw_delta + Vec3::new(pos.x, pos.y, pos.z),
Vec3::unit_z(),
Vec2::new(Vec3::unit_x(), Vec3::unit_y()),
)
}
},
|pos, dim, &(faces_forward, ref meta)| {
let pos = Vec3::new(pos.x, pos.y, pos.z);
let uv = Vec2::new(Vec3::unit_x(), Vec3::unit_y());
let norm = Vec3::unit_z();
// bounds.expand_to_contain(compute_bounds(pos, dim, uv));
let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
atlas,
&mut todo_rects,
@ -387,18 +351,13 @@ where
return;
};
create_quad_greedy(
// &mut shadow_mesh,
// &mut opaque_mesh,
pos,
dim,
uv,
norm,
faces_forward,
// Rgba::from_opaque(flat_get(pos).color),
meta,
atlas_pos,
// |pos, norm, meta| create_shadow(pos, norm, meta),
// |atlas_pos, pos, norm, meta| create_opaque(atlas_pos, pos, norm, meta),
|atlas_pos, dim, pos, draw_dim, norm, meta| {
push_quad(atlas_pos, dim, pos, draw_dim, norm, meta)
},
@ -406,9 +365,6 @@ where
},
);
// NOTE: Safe because bound dimensions actually fit in a u16.
// let bounds = bounds.map(|e| e as u16);
// NOTE: Safe because draw_delta fits in i16.
let bounds = Aabb {
min: Vec3::zero(),
// NOTE: Safe because greedy_size fit in u16.
@ -416,7 +372,6 @@ where
};
(
bounds,
/* opaque_mesh, *//*shadow_mesh, */
Box::new(move |col_lights_info| {
let mut data = data;
draw_col_lights(
@ -435,7 +390,6 @@ where
// Greedy meshing a single cross-section.
fn greedy_mesh_cross_section<M: PartialEq>(
/* mask: &mut [bool], */
dims: Vec3<usize>,
// Should we draw a face here (below this vertex)? If so, provide its meta information.
mut draw_face: impl FnMut(Vec3<i32>) -> Option<M>,
@ -477,7 +431,7 @@ fn greedy_mesh_cross_section<M: PartialEq>(
.count();
let max_y = j + height;
// Add quad.
push_quads(Vec3::new(i, j, d /* + 1 */), Vec2::new(width, height), ori);
push_quads(Vec3::new(i, j, d), Vec2::new(width, height), ori);
// Unset mask bits in drawn region, so we don't try to re-draw them.
(j..max_y).for_each(|l| {
mask[l * dims.x + i..l * dims.x + max_x]
@ -498,12 +452,7 @@ fn greedy_mesh_cross_section<M: PartialEq>(
fn add_to_atlas(
atlas: &mut guillotiere::SimpleAtlasAllocator,
todo_rects: &mut Vec<(
Vec3<i32>,
Vec2<Vec3<u16>>,
guillotiere::Rectangle,
Vec3<i32>,
)>,
todo_rects: &mut Vec<TodoRect>,
pos: Vec3<usize>,
uv: Vec2<Vec3<u16>>,
dim: Vec2<usize>,
@ -542,7 +491,6 @@ fn add_to_atlas(
(max texture size={:?}, so we are discarding this rectangle.",
pos, dim, max_size
);
// return None;
}
// Otherwise, we haven't reached max size yet, so double the size (or reach the
// max texture size) and try again.
@ -551,7 +499,6 @@ fn add_to_atlas(
max_size.height.min(current_size.height.saturating_mul(2)),
);
atlas.grow(new_size);
// atlas.grow((current_size * 2).min(max_size));
}
// NOTE: Conversion is correct because our initial max size for the atlas was
// a u16 and we never grew the atlas, meaning all valid coordinates within the
@ -561,14 +508,6 @@ fn add_to_atlas(
cur_size.y.max(atlas_rect.max.y as u16),
);
/* let (dim, uv, norm) = if faces_forward {
// NOTE: Conversion to u16 safe by function precondition.
(dim.map(|e| e as u16), uv, norm)
} else {
// NOTE: Conversion to u16 safe by function precondition.
(Vec2::new(dim.y as u16, dim.x as u16), Vec2::new(uv.y, uv.x), -norm)
}; */
// NOTE: pos can be converted safely from usize to i32 because all legal block
// coordinates in this chunk must fit in an i32 (actually we have the much
// stronger property that this holds across the whole map).
@ -591,46 +530,28 @@ fn add_to_atlas(
fn draw_col_lights<D>(
(col_lights, cur_size): &mut ColLightInfo,
data: &mut D,
todo_rects: Vec<(
Vec3<i32>,
Vec2<Vec3<u16>>,
guillotiere::Rectangle,
Vec3<i32>,
)>,
todo_rects: Vec<TodoRect>,
draw_delta: Vec3<i32>,
mut get_light: impl FnMut(&mut D, Vec3<i32>) -> f32,
mut get_color: impl FnMut(&mut D, Vec3<i32>) -> Rgb<u8>,
mut get_opacity: impl FnMut(&mut D, Vec3<i32>) -> bool,
mut make_col_light: impl FnMut(u8, Rgb<u8>) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType,
) {
/* for i in 0..todo_rects.len() {
for j in 0..todo_rects.len() {
if i == j {
continue;
}
assert!(!todo_rects[i].2.intersects(&todo_rects[j].2));
}
} */
todo_rects
.into_iter()
// .rev()
.for_each(|(pos, uv, rect, delta)| {
todo_rects.into_iter().for_each(|(pos, uv, rect, delta)| {
// NOTE: Conversions are safe because width, height, and offset must be
// non-negative, and because every allocated coordinate in the atlas must be in
// bounds for the original size, max_texture_size, which fit into a u16.
let width = (rect.max.x - rect.min.x) as u16;//rect.width() as u16;
let height = (rect.max.y - rect.min.y) as u16;//rect.height() as u16;
/* if width > 32 || height > 32 {
println!("Rect: {:?}", rect);
} */
let width = (rect.max.x - rect.min.x) as u16;
let height = (rect.max.y - rect.min.y) as u16;
let left = rect.min.x as u16;
let top = rect.min.y as u16;
let uv = uv.map(|e| e.map(i32::from));
let pos = pos + draw_delta;//Vec3::new(0, 0, z_start - 1);// + mesh_delta;// + draw_delta;
let pos = pos + draw_delta;
(0..height).for_each(|v| {
let start = usize::from(cur_size.x) * usize::from(top + v) + usize::from(left);
(0..width).zip(&mut col_lights[start..start + usize::from(width)]).for_each(|(u, col_light)| {
(0..width)
.zip(&mut col_lights[start..start + usize::from(width)])
.for_each(|(u, col_light)| {
let pos = pos + uv.x * i32::from(u) + uv.y * i32::from(v);
// TODO: Consider optimizing to take advantage of the fact that this whole
// face should be facing nothing but air (this is not currently true, but
@ -642,33 +563,23 @@ fn draw_col_lights<D>(
// direct_opacity, and indirect_uv_opacity is multiplied by
// the maximum of both of u and v's indirect opacities (since there are
// two choices for how to get to the direct surface).
let pos = pos +
if u + 1 == width { -uv.x } else { Vec3::zero() } +
if v + 1 == height { -uv.y } else { Vec3::zero() };
let pos = pos
+ if u + 1 == width { -uv.x } else { Vec3::zero() }
+ if v + 1 == height { -uv.y } else { Vec3::zero() };
let uv = Vec2::new(
if u + 1 == width { -uv.x } else { uv.x },
if v + 1 == height { -uv.y } else { uv.y },
);
let light_pos = pos + /*range.min + */delta;
// let block = flat_get(pos);
let light_pos = pos + delta;
// Currently, we assume that direct_opacity is 1 (if it's 0, you can't see
// the face anyway, since it's blocked by the block directly in front of it).
// TODO: If we add non-0/1 opacities, fix this.
// top-left block
// let direct_opacity = !flat_get(pos + delta).is_opaque();
// bottom-left block
let direct_u_opacity = get_opacity(data, light_pos - uv.x);
// top-right block
let direct_v_opacity = get_opacity(data, light_pos - uv.y);
// top-left block
// NOTE: Currently, since we only have 0 / 1 opacities, we don't worry
// about whether the uv block itself is opaque, because if it is its light
// value will be 0 anyway. But if we add translucent objects, we'll need
// to care about uv's opacity as well.
// let direct_uv_opacity = !flat_get(pos + delta - uv.x - uv.y).is_opaque();
// let indirect_opacity = direct_uv_opacity && (direct_u_opacity || direct_v_opacity) && direct_opacity;
// NOTE: Since we only support 0/1 opacities currently, we asssume
// direct_opacity is 1, and the light value will be zero anyway for objects
@ -680,12 +591,16 @@ fn draw_col_lights<D>(
// Light from the bottom-right-front block to this vertex always
// appears on this face, since it's the block this face is facing (so
// it can't be blocked by anything).
if /*direct_u_opacity || direct_v_opacity*/true/* || !flat_get(pos - uv.x - uv.y).is_opaque()*//* || !block.is_opaque()*/ { get_light(data, light_pos) } else { 0.0 } +
if /*direct_opacity || direct_uv_opacity*/true/* || !flat_get(pos - uv.y).is_opaque()*/ { get_light(data, light_pos - uv.x) } else { 0.0 } +
if /*direct_opacity || direct_uv_opacity*/true/* || !flat_get(pos - uv.x).is_opaque()*/ { get_light(data, light_pos - uv.y) } else { 0.0 } +
if direct_u_opacity || direct_v_opacity/* || !block.is_opaque()*/ { get_light(data, light_pos - uv.x - uv.y) } else { 0.0 }
get_light(data, light_pos)
+ get_light(data, light_pos - uv.x)
+ get_light(data, light_pos - uv.y)
+ if direct_u_opacity || direct_v_opacity {
get_light(data, light_pos - uv.x - uv.y)
} else {
0.0
}
) / 4.0;
let col = get_color(data, pos);//.map(Rgba::from_opaque).unwrap_or(Rgba::zero());
let col = get_color(data, pos);
let light = (darkness * 255.0) as u8;
*col_light = make_col_light(light, col);
});
@ -695,9 +610,7 @@ fn draw_col_lights<D>(
/// Precondition: when this function is called, atlas_pos should reflect an
/// actual valid position in a texture atlas (meaning it should fit into a u16).
fn create_quad_greedy</* S: render::Pipeline, *//*O: render::Pipeline, */ M>(
// shadow_mesh: &mut Mesh<S>,
// opaque_mesh: &mut Mesh<O>,
fn create_quad_greedy<M>(
origin: Vec3<usize>,
dim: Vec2<usize>,
uv: Vec2<Vec3<u16>>,
@ -705,26 +618,16 @@ fn create_quad_greedy</* S: render::Pipeline, *//*O: render::Pipeline, */ M>(
faces_forward: bool,
meta: &M,
atlas_pos: guillotiere::Rectangle,
// origin, norm, meta
// create_shadow: impl Fn(Vec3<f32>, Vec3<f32>, &M) -> S::Vertex,
// create_opaque: impl Fn(Vec2<u16>, Vec3<f32>, Vec3<f32>, &M) -> O::Vertex,
mut push_quad: impl FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
) /* -> Quad<ShadowPipeline> */
{
) {
let origin = origin.map(|e| e as f32);
/* // NOTE: Conversion to u16 safe by function precondition.
let dim = uv.map2(dim.map(|e| e as u16), |e, f| e * f); */
// NOTE: Conversion to f32 safe by function precondition (u16 can losslessly
// cast to f32, and dim fits in a u16).
let draw_dim = uv.map2(dim.map(|e| e as f32), |e, f| e.map(f32::from) * f);
let dim = Vec2::new(Vec2::new(dim.x as u16, 0), Vec2::new(0, dim.y as u16));
let (draw_dim, dim, /* uv, */ norm) = if faces_forward {
/* // NOTE: Conversion to u16 safe by function precondition.
(dim.map(|e| e as u16), uv, norm) */
(draw_dim, dim, norm)
} else {
/* // NOTE: Conversion to u16 safe by function precondition.
(Vec2::new(dim.y as u16, dim.x as u16), Vec2::new(uv.y, uv.x), -norm) */
(
Vec2::new(draw_dim.y, draw_dim.x),
Vec2::new(dim.y, dim.x),
@ -732,21 +635,8 @@ fn create_quad_greedy</* S: render::Pipeline, *//*O: render::Pipeline, */ M>(
)
};
let norm = norm.map(f32::from);
// let draw_dim = draw_dim.map(|e| e.map(f32::from));
// NOTE: Conversion to u16 safe by function precondition.
let atlas_pos = Vec2::new(atlas_pos.min.x as u16, atlas_pos.min.y as u16);
/* shadow_mesh.push_quad(Quad::new(
create_shadow(origin, norm, &meta/*, atlas_pos*/),
create_shadow(origin + draw_dim.x, norm, &meta/*, atlas_pos + dim.x*/),
create_shadow(origin + draw_dim.x + draw_dim.y, norm, &meta/*, atlas_pos + dim.x + dim.y*/),
create_shadow(origin + draw_dim.y, norm, &meta/*, atlas_pos + dim.y*/),
)); */
/* opaque_mesh.push_quad(Quad::new(
create_opaque(atlas_pos, origin, norm, &meta),
create_opaque(atlas_pos + dim.x, origin + draw_dim.x, norm, &meta),
create_opaque(atlas_pos + dim.x + dim.y, origin + draw_dim.x + draw_dim.y, norm, &meta),
create_opaque(atlas_pos + dim.y, origin + draw_dim.y, norm, &meta),
)); */
push_quad(atlas_pos, dim, origin, draw_dim, norm, meta);
}
@ -769,9 +659,5 @@ pub fn create_quad<O: render::Pipeline, M>(
meta,
),
create_vertex(atlas_pos + dim.y, origin + draw_dim.y, norm, meta),
/* create_vertex(atlas_pos, origin, norm, meta),
create_vertex(atlas_pos + dim.y, origin + draw_dim.y, norm, meta),
create_vertex(atlas_pos + dim.x + dim.y, origin + draw_dim.x + draw_dim.y, norm, meta),
create_vertex(atlas_pos + dim.x, origin + draw_dim.x, norm, meta), */
)
}

View File

@ -4,6 +4,13 @@ pub mod terrain;
use crate::render::{self, Mesh};
pub type MeshGen<P, T, M> = (
Mesh<<M as Meshable<P, T>>::Pipeline>,
Mesh<<M as Meshable<P, T>>::TranslucentPipeline>,
Mesh<<M as Meshable<P, T>>::ShadowPipeline>,
<M as Meshable<P, T>>::Result,
);
pub trait Meshable<P: render::Pipeline, T> {
type Pipeline: render::Pipeline;
type TranslucentPipeline: render::Pipeline;
@ -12,13 +19,5 @@ pub trait Meshable<P: render::Pipeline, T> {
type Result;
// Generate meshes - one opaque, one translucent, one shadow
fn generate_mesh(
self,
supp: Self::Supplement,
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
Self::Result,
);
fn generate_mesh(self, supp: Self::Supplement) -> MeshGen<P, T, Self>;
}

View File

@ -1,7 +1,7 @@
use crate::{
mesh::{
greedy::{self, GreedyConfig, GreedyMesh},
Meshable,
MeshGen, Meshable,
},
render::{self, FigurePipeline, Mesh, ShadowPipeline, SpritePipeline, TerrainPipeline},
};
@ -32,12 +32,7 @@ where
fn generate_mesh(
self,
(greedy, offs, scale): Self::Supplement,
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
Self::Result,
) {
) -> MeshGen<FigurePipeline, &'b mut GreedyMesh<'a>, Self> {
let max_size = greedy.max_size();
// 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
@ -114,7 +109,7 @@ where
}
}
impl<'a: 'b, 'b, V: 'a> Meshable<SpritePipeline, /* SpritePipeline */ &'b mut GreedyMesh<'a>> for V
impl<'a: 'b, 'b, V: 'a> Meshable<SpritePipeline, &'b mut GreedyMesh<'a>> for V
where
V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
/* TODO: Use VolIterator instead of manually iterating
@ -132,12 +127,7 @@ where
fn generate_mesh(
self,
(greedy, vertical_stripes): Self::Supplement,
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
(),
) {
) -> MeshGen<SpritePipeline, &'b mut GreedyMesh<'a>, Self> {
let max_size = greedy.max_size();
// 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
@ -182,15 +172,8 @@ where
vol.get(vox).map(|vox| *vox).unwrap_or(Vox::empty())
})
};
// NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16.
// let create_shadow = |pos, norm, _meta| ShadowVertex::new_figure((pos + offs)
// * scale, norm, 0);
let create_opaque = |atlas_pos, pos: Vec3<f32>, norm, _meta| {
/* if pos.x >= 15.0 || pos.y >= 15.0 || pos.z >= 63.0 {
println!("{:?}", pos);
} */
SpriteVertex::new(atlas_pos, pos, norm /* , ao */)
};
let create_opaque =
|atlas_pos, pos: Vec3<f32>, norm, _meta| SpriteVertex::new(atlas_pos, pos, norm);
let mut opaque_mesh = Mesh::new();
let _bounds = greedy.push(GreedyConfig {
@ -224,10 +207,8 @@ fn should_draw_greedy(
_uv: Vec2<Vec3<i32>>,
flat_get: impl Fn(Vec3<i32>) -> Cell,
) -> Option<(bool, /* u8 */ ())> {
// TODO: Verify conversion.
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let from = flat_get(pos - delta); // map(|v| v.is_opaque()).unwrap_or(false);
let to = flat_get(pos); //map(|v| v.is_opaque()).unwrap_or(false);
let from = flat_get(pos - delta);
let to = flat_get(pos);
let from_opaque = !from.is_empty();
if from_opaque == !to.is_empty() {
None
@ -244,52 +225,17 @@ fn should_draw_greedy_ao(
delta: Vec3<i32>,
_uv: Vec2<Vec3<i32>>,
flat_get: impl Fn(Vec3<i32>) -> Cell,
) -> Option<(bool, /* u8 */ bool)> {
// TODO: Verify conversion.
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let from = flat_get(pos - delta); // map(|v| v.is_opaque()).unwrap_or(false);
let to = flat_get(pos); //map(|v| v.is_opaque()).unwrap_or(false);
) -> Option<(bool, bool)> {
let from = flat_get(pos - delta);
let to = flat_get(pos);
let from_opaque = !from.is_empty();
if from_opaque == !to.is_empty() {
None
} else {
let faces_forward = from_opaque;
let ao = /* if delta.z != 0 {
0u8
} else {
(pos.z & 1) as u8
// (((pos.x & 1) as u8) << 1) | (pos.y & 1) as u8
}*/!vertical_stripes || /*((pos.x & 1) ^ (pos.y & 1))*/(pos.z & 1) != 0/* as u8*/;
/* let (from, delta, uv) = if faces_forward {
(pos - delta - uv.x - uv.y, delta, uv)
} else {
(pos, -delta, Vec2::new(-uv.y, -uv.x))
};
let ao_vertex = |from: Vec3<i32>, delta: Vec3<i32>, uv: Vec2<Vec3<i32>>| {
let corner = !flat_get(from + delta - uv.x - uv.y).is_empty();
let s1 = !flat_get(from + delta - uv.x).is_empty();
let s2 = !flat_get(from + delta - uv.y).is_empty();
if s1 && s2 {
0
} else {
3 - (if corner { 1 } else { 0 } + if s1 { 1 } else { 0 } + if s2 { 1 } else { 0 })
}
};
// We only care about the vertices we are *not* merging, since the shared vertices
// by definition have the same AO values. But snce we go both down and right we end up
// needing all but the bottom right vertex.
let ao_corner = ao_vertex(from, delta, uv);
let ao1 = ao_vertex(from + uv.x, delta, uv);
let ao2 = ao_vertex(from + uv.y, delta, uv);
let ao3 = ao_vertex(from + uv.x + uv.y, delta, uv);
// NOTE: ao's 4 values correspond (from 0 to 3) to 0.25, 0.5, 0.75, 1.0.
//
// 0.0 is the None case.
let ao = (ao_corner << 6) | (ao1 << 4) | (ao2 << 2) | ao3; */
// let ao = ao_vertex(from, delta, uv);
let ao = !vertical_stripes || (pos.z & 1) != 0;
// If going from transparent to opaque, backward facing; otherwise, forward
// facing.
Some((faces_forward, ao))
// Some((faces_forward, ()))
}
}

View File

@ -1,7 +1,7 @@
use crate::{
mesh::{
greedy::{self, GreedyConfig, GreedyMesh},
Meshable,
MeshGen, Meshable,
},
render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline},
};
@ -230,12 +230,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
fn generate_mesh(
self,
(range, max_texture_size): Self::Supplement,
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
Self::Result,
) {
) -> MeshGen<TerrainPipeline, FluidPipeline, Self> {
let mut light = calc_light(range, self);
let mut lowest_opaque = range.size().d;
@ -315,180 +310,6 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
}
.min(range.size().d - 1);
// // We use multiple meshes and then combine them later such that we can group
// similar z // levels together (better rendering performance)
// let mut opaque_meshes = vec![Mesh::new(); ((z_end + 1 - z_start).clamped(1,
// 60) as usize / 10).max(1)];
// let mut opaque_mesh = Mesh::new();
// let mut fluid_mesh = Mesh::new();
/* for x in 1..range.size().w - 1 {
for y in 1..range.size().w - 1 {
let mut blocks = [[[None; 3]; 3]; 3];
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
blocks[k][j][i] = Some(flat_get(
Vec3::new(x, y, z_start) + Vec3::new(i as i32, j as i32, k as i32)
- 1,
));
}
}
}
let mut lights = [[[None; 3]; 3]; 3];
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
lights[k][j][i] = if blocks[k][j][i]
.map(|block| block.is_opaque())
.unwrap_or(false)
{
None
} else {
Some(light(
Vec3::new(
x + range.min.x,
y + range.min.y,
z_start + range.min.z,
) + Vec3::new(i as i32, j as i32, k as i32)
- 1,
))
};
}
}
}
let get_color = |maybe_block: Option<&Block>, neighbour: bool| {
maybe_block
.filter(|vox| vox.is_opaque() && (!neighbour || vox.is_blended()))
.and_then(|vox| vox.get_color())
.map(Rgba::from_opaque)
.unwrap_or(Rgba::zero())
};
for z in z_start..z_end + 1 {
let pos = Vec3::new(x, y, z);
let offs = (pos - Vec3::new(1, 1, -range.min.z)).map(|e| e as f32);
lights[0] = lights[1];
lights[1] = lights[2];
blocks[0] = blocks[1];
blocks[1] = blocks[2];
for i in 0..3 {
for j in 0..3 {
let block = Some(flat_get(pos + Vec3::new(i as i32, j as i32, 2) - 1));
blocks[2][j][i] = block;
}
}
for i in 0..3 {
for j in 0..3 {
lights[2][j][i] = if blocks[2][j][i]
.map(|block| block.is_opaque())
.unwrap_or(false)
{
None
} else {
Some(light(
pos + range.min + Vec3::new(i as i32, j as i32, 2) - 1,
))
};
}
}
let block = blocks[1][1][1];
let colors = if block.map_or(false, |vox| vox.is_blended()) {
let mut colors = [[[Rgba::zero(); 3]; 3]; 3];
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
colors[i][j][k] = get_color(
blocks[i][j][k].as_ref(),
i != 1 || j != 1 || k != 1,
)
}
}
}
colors
} else {
[[[get_color(blocks[1][1][1].as_ref(), false); 3]; 3]; 3]
};
// let opaque_mesh_index = ((z - z_start) * opaque_meshes.len() as i32 / (z_end
// + 1 - z_start).max(1)) as usize; let selected_opaque_mesh
// = &mut opaque_meshes[opaque_mesh_index]; Create mesh
// polygons
/* if block.map_or(false, |vox| vox.is_opaque()) {
vol::push_vox_verts(
&mut opaque_mesh, //selected_opaque_mesh,
faces_to_make(&blocks, None, |vox| {
if vox.is_opaque() {
None
} else {
Some(vox.is_fluid())
}
}),
offs,
&colors,
|pos, norm, col, light, ao, &meta| {
//let light = (light.min(ao) * 255.0) as u32;
let light = (light * 255.0) as u32;
let ao = (ao * 255.0) as u32;
let norm = 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 }
};
TerrainVertex::new(norm, light, ao, pos, col, meta)
},
&lights,
);
} else */if block.map_or(false, |vox| vox.is_fluid()) {
vol::push_vox_verts(
&mut fluid_mesh,
// NOTE: want to skip blocks that aren't either next to air, or next to
// opaque blocks like ground. Addnig the blocks next to ground lets us
// make sure we compute lighting effects both at the water surface, and
// just before hitting the ground.
faces_to_make(&blocks, Some(()), |vox| {
if vox.is_air() { Some(()) } else { None }
}),
offs,
&colors,
|pos, norm, col, light, _ao, _meta| {
/* let rel_pos = pos - offs;
let rel_vox_pos = if rel_pos == offs {
rel_pos + norm + 1.0
} else {
rel_pos + 1.0
}.map(|e| e as usize);
let vox_neighbor = blocks[rel_vox_pos.z][rel_vox_pos.y][rel_vox_pos.x];
if vox_neighbor.is_opaque() {
} else {
} */
FluidVertex::new(pos, norm, col, light, 0.3)
},
&lights,
);
}
}
}
}*/
// let opaque_mesh = opaque_meshes
// .into_iter()
// .rev()
// .fold(Mesh::new(), |mut opaque_mesh, m: Mesh<Self::Pipeline>| {
// m.verts().chunks_exact(3).rev().for_each(|vs| {
// opaque_mesh.push(vs[0]);
// opaque_mesh.push(vs[1]);
// opaque_mesh.push(vs[2]);
// });
// opaque_mesh
// });
let max_size =
guillotiere::Size::new(i32::from(max_texture_size.x), i32::from(max_texture_size.y));
let greedy_size = Vec3::new(
@ -508,8 +329,6 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
should_draw_greedy(pos, delta, flat_get)
};
// NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16.
// let create_shadow = |pos, norm, meta| ShadowVertex::new(pos + Vec3::new(0.0,
// 0.0, (z_start + range.min.z) as f32), norm, meta);
let mesh_delta = Vec3::new(0.0, 0.0, (z_start + range.min.z) as f32);
let create_opaque = |atlas_pos, pos, norm, meta| {
TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta)
@ -560,7 +379,6 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
max: bounds.max + mesh_delta,
};
let (col_lights, col_lights_size) = greedy.finalize();
// println!("z_bounds{:?}, bounds: {:?}", (mesh_delta.z, mesh_delta.z +
(
opaque_mesh,
@ -576,10 +394,8 @@ fn should_draw_greedy(
delta: Vec3<i32>,
flat_get: impl Fn(Vec3<i32>) -> Block,
) -> Option<(bool, FaceKind)> {
// TODO: Verify conversion.
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let from = flat_get(pos - delta); // map(|v| v.is_opaque()).unwrap_or(false);
let to = flat_get(pos); //map(|v| v.is_opaque()).unwrap_or(false);
let from = flat_get(pos - delta);
let to = flat_get(pos);
let from_opaque = from.is_opaque();
if from_opaque == to.is_opaque() {
// Check the interface of fluid and non-tangible non-fluids (e.g. air).

View File

@ -17,15 +17,6 @@ impl<T: Copy + gfx::traits::Pod> Consts<T> {
}
}
/* /// Create a new immutable `Const<T>`.
pub fn new_immutable(factory: &mut gfx_backend::Factory, data: &[T]) -> Result<gfx::handle::RawBuffer<T>, RenderError> {
Ok(Self {
ibuf: factory
.create_buffer_immutable_raw(gfx::memory::cast_slice(data), core::mem::size_of::<T>(), gfx::buffer::Role::Constant, gfx::memory::Bind::empty())
.map_err(|err| RenderError::BufferCreationError(err))?,
})
} */
/// Update the GPU-side value represented by this constant handle.
pub fn update(

View File

@ -4,7 +4,6 @@ use std::iter::FromIterator;
/// A `Vec`-based mesh structure used to store mesh data on the CPU.
pub struct Mesh<P: Pipeline> {
verts: Vec<P::Vertex>,
// textures: Vec<>
}
impl<P: Pipeline> Clone for Mesh<P>

View File

@ -21,7 +21,7 @@ pub use self::{
Locals as FigureLocals,
},
fluid::FluidPipeline,
lod_terrain::{Locals as LodTerrainLocals, LodTerrainPipeline},
lod_terrain::{Locals as LodTerrainLocals, LodData, LodTerrainPipeline},
postprocess::{
create_mesh as create_pp_mesh, Locals as PostProcessLocals, PostProcessPipeline,
},
@ -33,7 +33,7 @@ pub use self::{
create_quad as create_ui_quad, create_tri as create_ui_tri, Locals as UiLocals,
Mode as UiMode, UiPipeline,
},
Globals, Light, Shadow,
GlobalModel, Globals, Light, Shadow,
},
renderer::{
ColLightFmt, ColLightInfo, LodAltFmt, LodColorFmt, LodTextureFmt, Renderer,

View File

@ -119,7 +119,6 @@ impl Pipeline for FigurePipeline {
pub struct FigureModel {
pub bounds: Aabb<f32>,
pub opaque: Model<TerrainPipeline>,
// pub shadow: Model<ShadowPipeline>,
// TODO: Consider using mipmaps instead of storing multiple texture atlases for different LOD
// levels.
pub col_lights: Texture<ColLightFmt>,

View File

@ -11,7 +11,6 @@ use vek::*;
gfx_defines! {
vertex Vertex {
pos_norm: u32 = "v_pos_norm",
// col_light: u32 = "v_col_light",
}
pipeline pipe {
@ -41,31 +40,6 @@ gfx_defines! {
}
impl Vertex {
/* pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, light: f32, _opac: f32) -> Self {
let (norm_axis, norm_dir) = norm
.as_slice()
.into_iter()
.enumerate()
.find(|(_i, e)| **e != 0.0)
.unwrap_or((0, &1.0));
let norm_bits = ((norm_axis << 1) | if *norm_dir > 0.0 { 1 } else { 0 }) as u32;
const EXTRA_NEG_Z: f32 = 65536.0;
Self {
pos_norm: 0
| ((pos.x as u32) & 0x003F) << 0
| ((pos.y as u32) & 0x003F) << 6
| (((pos.z + EXTRA_NEG_Z).max(0.0).min((1 << 17) as f32) as u32) & 0x1FFFF) << 12
| (norm_bits & 0x7) << 29,
col_light: 0
| ((col.r.mul(200.0) as u32) & 0xFF) << 8
| ((col.g.mul(200.0) as u32) & 0xFF) << 16
| ((col.b.mul(200.0) as u32) & 0xFF) << 24
| ((light.mul(255.0) as u32) & 0xFF) << 0,
//| ((opac.mul(0.4) as u32) & 0xFF) << 0,
}
} */
#[allow(clippy::identity_op)] // TODO: Pending review in #587
#[allow(clippy::into_iter_on_ref)] // TODO: Pending review in #587
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
@ -85,12 +59,6 @@ impl Vertex {
| ((pos.y as u32) & 0x003F) << 6
| (((pos.z + EXTRA_NEG_Z).max(0.0).min((1 << 17) as f32) as u32) & 0x1FFFF) << 12
| (norm_bits & 0x7) << 29,
/* col_light: 0
| ((col.r.mul(200.0) as u32) & 0xFF) << 8
| ((col.g.mul(200.0) as u32) & 0xFF) << 16
| ((col.b.mul(200.0) as u32) & 0xFF) << 24
| ((light.mul(255.0) as u32) & 0xFF) << 0,
//| ((opac.mul(0.4) as u32) & 0xFF) << 0, */
}
}
}

View File

@ -1,10 +1,13 @@
use super::{
super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt},
super::{
LodAltFmt, LodColorFmt, LodTextureFmt, Pipeline, Renderer, Texture, 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,
gfx_pipeline_inner, gfx_vertex_struct_meta, texture::SamplerInfo,
};
use vek::*;
@ -51,3 +54,64 @@ pub struct LodTerrainPipeline;
impl Pipeline for LodTerrainPipeline {
type Vertex = Vertex;
}
pub struct LodData {
pub map: Texture<LodColorFmt>,
pub alt: Texture<LodAltFmt>,
pub horizon: Texture<LodTextureFmt>,
pub tgt_detail: u32,
}
impl LodData {
pub fn new(
renderer: &mut Renderer,
map_size: Vec2<u16>,
lod_base: &[u32],
lod_alt: &[u32],
lod_horizon: &[u32],
tgt_detail: u32,
border_color: gfx::texture::PackedColor,
) -> Self {
let kind = gfx::texture::Kind::D2(map_size.x, map_size.y, gfx::texture::AaMode::Single);
let info = gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Border,
);
Self {
map: renderer
.create_texture_immutable_raw(
kind,
gfx::texture::Mipmap::Provided,
&[gfx::memory::cast_slice(lod_base)],
SamplerInfo {
border: border_color,
..info
},
)
.expect("Failed to generate map texture"),
alt: renderer
.create_texture_immutable_raw(
kind,
gfx::texture::Mipmap::Provided,
&[gfx::memory::cast_slice(lod_alt)],
SamplerInfo {
border: [0.0, 0.0, 0.0, 0.0].into(),
..info
},
)
.expect("Failed to generate alt texture"),
horizon: renderer
.create_texture_immutable_raw(
kind,
gfx::texture::Mipmap::Provided,
&[gfx::memory::cast_slice(lod_horizon)],
SamplerInfo {
border: [1.0, 0.0, 1.0, 0.0].into(),
..info
},
)
.expect("Failed to generate horizon texture"),
tgt_detail,
}
}
}

View File

@ -8,6 +8,7 @@ pub mod sprite;
pub mod terrain;
pub mod ui;
use super::Consts;
use crate::scene::camera::CameraMode;
use common::terrain::BlockKind;
use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta};
@ -25,9 +26,6 @@ gfx_defines! {
cam_pos: [f32; 4] = "cam_pos",
focus_off: [f32; 4] = "focus_off",
focus_pos: [f32; 4] = "focus_pos",
/// NOTE: max_intensity is computed as the ratio between the brightest and least bright
/// intensities among all lights in the scene.
// hdr_ratio: [f32; 4] = "max_intensity",
/// NOTE: view_distance.x is the horizontal view distance, view_distance.y is the LOD
/// detail, view_distance.z is the
/// minimum height over any land chunk (i.e. the sea level), and view_distance.w is the
@ -54,7 +52,6 @@ gfx_defines! {
constant Light {
pos: [f32; 4] = "light_pos",
col: [f32; 4] = "light_col",
// proj: [[f32; 4]; 4] = "light_proj";
}
constant Shadow {
@ -201,3 +198,11 @@ impl Shadow {
impl Default for Shadow {
fn default() -> Self { Self::new(Vec3::zero(), 0.0) }
}
// Global scene data spread across several arrays.
pub struct GlobalModel {
pub globals: Consts<Globals>,
pub lights: Consts<Light>,
pub shadows: Consts<Shadow>,
pub shadow_mats: Consts<shadow::Locals>,
}

View File

@ -13,10 +13,7 @@ use vek::*;
gfx_defines! {
vertex Vertex {
// pos: [f32; 4] = "v_pos",
pos_norm: u32 = "v_pos_norm",
// col_light: u32 = "v_col_light",
// atlas_pos: u32 = "v_atlas_pos",
}
constant Locals {
@ -26,17 +23,10 @@ gfx_defines! {
pipeline pipe {
// Terrain vertex stuff
vbuf: gfx::VertexBuffer</*Vertex*/terrain::Vertex> = (),
vbuf: gfx::VertexBuffer<terrain::Vertex> = (),
locals: gfx::ConstantBuffer<TerrainLocals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
// lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
// alt: gfx::TextureSampler<[f32; 2]> = "t_map",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
// noise: gfx::TextureSampler<f32> = "t_noise",
// Shadow stuff
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
@ -45,23 +35,15 @@ gfx_defines! {
fun: gfx::state::Comparison::Less,
write: true,
},
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
pipeline figure_pipe {
// Terrain vertex stuff
vbuf: gfx::VertexBuffer</*Vertex*/terrain::Vertex> = (),
vbuf: gfx::VertexBuffer<terrain::Vertex> = (),
locals: gfx::ConstantBuffer<figure::Locals> = "u_locals",
bones: gfx::ConstantBuffer<figure::BoneData> = "u_bones",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
// lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
// alt: gfx::TextureSampler<[f32; 2]> = "t_map",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
// noise: gfx::TextureSampler<f32> = "t_noise",
// Shadow stuff
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
@ -70,16 +52,11 @@ gfx_defines! {
fun: gfx::state::Comparison::Less,
write: true,
},
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}
impl Vertex {
pub fn new(
pos: Vec3<f32>,
norm: Vec3<f32>,
meta: bool, /* , atlas_pos: Vec2<u16> */
) -> Self {
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, meta: bool) -> Self {
let norm_bits = if norm.x != 0.0 {
if norm.x < 0.0 { 0 } else { 1 }
} else if norm.y != 0.0 {
@ -89,10 +66,6 @@ impl Vertex {
} else {
5
};
// let ao = 0xFFu32;
// let light = 0xFFu32;
// let col = Rgb::new(1.0f32, 0.0, 0.0);
// let meta = true;
const EXTRA_NEG_Z: f32 = 32768.0;
@ -103,23 +76,10 @@ impl Vertex {
| (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
| if meta { 1 } else { 0 } << 28
| (norm_bits & 0x7) << 29,
/* atlas_pos: 0
| ((atlas_pos.x as u32) & 0xFFFF) << 0
| ((atlas_pos.y as u32) & 0xFFFF) << 16, */
/* col_light: 0
| (((col.r * 255.0) as u32) & 0xFF) << 8
| (((col.g * 255.0) as u32) & 0xFF) << 16
| (((col.b * 255.0) as u32) & 0xFF) << 24
| (ao >> 6) << 6
| ((light >> 2) & 0x3F) << 0, */
}
}
pub fn new_figure(
pos: Vec3<f32>,
norm: Vec3<f32>,
/* col: Rgb<f32>, ao: f32, */ bone_idx: u8,
) -> Self {
pub fn new_figure(pos: Vec3<f32>, norm: Vec3<f32>, bone_idx: u8) -> Self {
let norm_bits = if norm.x.min(norm.y).min(norm.z) < 0.0 {
0
} else {
@ -133,10 +93,6 @@ impl Vertex {
.reduce_bitor()
| (((bone_idx & 0xF) as u32) << 27)
| (norm_bits << 31),
// 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),
}
}
@ -172,7 +128,7 @@ impl ShadowPipeline {
gfx::texture::AaMode::Single,
),
gfx::texture::Mipmap::Provided,
&[&col_lights /* .raw_pixels() */],
&[&col_lights],
gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Clamp,

View File

@ -29,7 +29,6 @@ gfx_defines! {
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_TEST,
// tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = 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,7 +12,6 @@ use vek::*;
gfx_defines! {
vertex Vertex {
pos: [f32; 3] = "v_pos",
// pos_norm: u32 = "v_pos_norm",
// Because we try to restrict terrain sprite data to a 128×128 block
// we need an offset into the texture atlas.
atlas_pos: u32 = "v_atlas_pos",
@ -40,21 +39,17 @@ gfx_defines! {
inst_mat1: [f32; 4] = "inst_mat1",
inst_mat2: [f32; 4] = "inst_mat2",
inst_mat3: [f32; 4] = "inst_mat3",
// inst_mat: [[f32; 4]; 4] = "inst_mat",
// inst_col: [f32; 3] = "inst_col",
inst_wind_sway: f32 = "inst_wind_sway",
}
pipeline pipe {
vbuf: gfx::VertexBuffer<Vertex> = (),
ibuf: gfx::InstanceBuffer<Instance> = (),
// ibuf: gfx::/*handle::RawBuffer*/ConstantBuffer<Instance> = "u_ibuf",
col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
locals: gfx::ConstantBuffer<Locals> = "u_locals",
// A sprite instance is a cross between a sprite and a terrain chunk.
terrain_locals: gfx::ConstantBuffer<terrain::Locals> = "u_terrain_locals",
// locals: gfx::ConstantBuffer<terrain::Locals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
lights: gfx::ConstantBuffer<Light> = "u_lights",
shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
@ -113,24 +108,16 @@ impl Vertex {
// | if meta { 1 } else { 0 } << 28
// | (norm_bits & 0x7) << 29,
pos: pos.into_array(),
/* col: col
.map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift)
.reduce_bitor(), */
atlas_pos: 0
| ((atlas_pos.x as u32) & 0xFFFF) << 0
| ((atlas_pos.y as u32) & 0xFFFF) << 16, /* | axis_bits & 3 */
norm_ao: norm_bits, /* | (((ao * 3.9999) as u32) << 3) */
| ((atlas_pos.y as u32) & 0xFFFF) << 16,
norm_ao: norm_bits,
}
}
}
impl Instance {
pub fn new(
mat: Mat4<f32>,
/* col: Rgb<f32>, */ wind_sway: f32,
pos: Vec3<i32>,
ori_bits: u8,
) -> Self {
pub fn new(mat: Mat4<f32>, wind_sway: f32, pos: Vec3<i32>, ori_bits: u8) -> Self {
const EXTRA_NEG_Z: i32 = 32768;
let mat_arr = mat.into_col_arrays();
@ -138,29 +125,19 @@ impl Instance {
pos_ori: 0
| ((pos.x as u32) & 0x003F) << 0
| ((pos.y as u32) & 0x003F) << 6
| (((pos + EXTRA_NEG_Z).z.max(0).min(1 << 16/* as f32*/) as u32) & 0xFFFF) << 12
// | if meta { 1 } else { 0 } << 28
| (((pos + EXTRA_NEG_Z).z.max(0).min(1 << 16) as u32) & 0xFFFF) << 12
| (u32::from(ori_bits) & 0x7) << 29,
inst_mat0: mat_arr[0],
inst_mat1: mat_arr[1],
inst_mat2: mat_arr[2],
inst_mat3: mat_arr[3],
// inst_mat: mat_arr,
// inst_col: col.into_array(),
inst_wind_sway: wind_sway,
}
}
}
impl Default for Instance {
fn default() -> Self {
Self::new(
Mat4::identity(),
/* Rgb::broadcast(1.0), */ 0.0,
Vec3::zero(),
0,
)
}
fn default() -> Self { Self::new(Mat4::identity(), 0.0, Vec3::zero(), 0) }
}
impl Default for Locals {

View File

@ -10,8 +10,6 @@ use vek::*;
gfx_defines! {
vertex Vertex {
// pos_norm: u32 = "v_pos_norm",
// col_light: u32 = "v_col_light",
pos_norm: u32 = "v_pos_norm",
atlas_pos: u32 = "v_atlas_pos",
}
@ -23,8 +21,7 @@ gfx_defines! {
}
pipeline pipe {
vbuf: gfx::VertexBuffer</*shadow::Vertex*/Vertex> = (),
// abuf: gfx::VertexBuffer<Vertex> = (),
vbuf: gfx::VertexBuffer<Vertex> = (),
col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
locals: gfx::ConstantBuffer<Locals> = "u_locals",
@ -73,22 +70,10 @@ impl Vertex {
atlas_pos: 0
| ((atlas_pos.x as u32) & 0xFFFF) << 0
| ((atlas_pos.y as u32) & 0xFFFF) << 16,
/* col_light: 0
| (((col.r * 255.0) as u32) & 0xFF) << 8
| (((col.g * 255.0) as u32) & 0xFF) << 16
| (((col.b * 255.0) as u32) & 0xFF) << 24
| (ao >> 6) << 6
| ((light >> 2) & 0x3F) << 0, */
}
}
pub fn new_figure(
// norm: Vec3<f32>,
atlas_pos: Vec2<u16>,
pos: Vec3<f32>,
norm: Vec3<f32>,
bone_idx: u8,
) -> Self {
pub fn new_figure(atlas_pos: Vec2<u16>, pos: Vec3<f32>, norm: Vec3<f32>, bone_idx: u8) -> Self {
let norm_bits = if norm.x.min(norm.y).min(norm.z) < 0.0 {
0
} else {
@ -113,57 +98,15 @@ impl Vertex {
| ((atlas_pos.x as u32) & 0x7FFF) << 2
| ((atlas_pos.y as u32) & 0x7FFF) << 17
| axis_bits & 3,
/* col_light: 0
| (((col.r * 255.0) as u32) & 0xFF) << 8
| (((col.g * 255.0) as u32) & 0xFF) << 16
| (((col.b * 255.0) as u32) & 0xFF) << 24
| (ao >> 6) << 6
| ((light >> 2) & 0x3F) << 0, */
}
}
/* pub fn new(
norm_bits: u32,
light: u32,
ao: u32,
pos: Vec3<f32>,
col: Rgb<f32>,
meta: bool,
) -> Self {
const EXTRA_NEG_Z: f32 = 32768.0;
Self {
pos_norm: 0
| ((pos.x as u32) & 0x003F) << 0
| ((pos.y as u32) & 0x003F) << 6
| (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
| if meta { 1 } else { 0 } << 28
| (norm_bits & 0x7) << 29,
col_light: 0
| ((col.r.mul(255.0) as u32) & 0xFF) << 8
| ((col.g.mul(255.0) as u32) & 0xFF) << 16
| ((col.b.mul(255.0) as u32) & 0xFF) << 24
| (ao >> 6) << 6
| ((light >> 2) & 0x3F) << 0,
}
} */
pub fn make_col_light(
light: /* u32 */ u8,
// ao: u32,
// col: Rgb<f32>,
light: u8,
col: Rgb<u8>,
) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType
{
[
col.r, //.mul(255.0) as u8,
col.g, //.mul(255.0) as u8,
col.b, //.mul(255.0) as u8,
light,
/* | (ao as u8 >> 6) << 6
* | //((light as u8 >> 2) & 0x3F) << 0,
* | light */
]
[col.r, col.g, col.b, light]
}
pub fn with_bone_idx(self, bone_idx: u8) -> Self {
@ -187,5 +130,5 @@ impl Locals {
pub struct TerrainPipeline;
impl Pipeline for TerrainPipeline {
type Vertex = Vertex; //<<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType;
type Vertex = Vertex;
}

View File

@ -131,18 +131,6 @@ pub fn create_quad(
v([l, b], [uv_l, uv_b]),
v([r, b], [uv_r, uv_b]),
),
/* (true, true) | (false, false) => Quad::new(
v([l, t], [uv_l, uv_t]),
v([r, t], [uv_l, uv_b]),
v([r, b], [uv_r, uv_b]),
v([l, b], [uv_r, uv_t]),
),
_ => Quad::new(
v([l, t], [uv_l, uv_t]),
v([l, b], [uv_l, uv_b]),
v([r, b], [uv_r, uv_b]),
v([r, t], [uv_r, uv_t]),
) */
}
}

View File

@ -5,8 +5,8 @@ use super::{
mesh::Mesh,
model::{DynamicModel, Model},
pipelines::{
figure, fluid, lod_terrain, postprocess, shadow, skybox, sprite, terrain, ui, Globals,
Light, Shadow,
figure, fluid, lod_terrain, postprocess, shadow, skybox, sprite, terrain, ui, GlobalModel,
Globals,
},
texture::Texture,
AaMode, CloudMode, FilterMethod, FluidMode, LightingMode, Pipeline, RenderError, RenderMode,
@ -49,13 +49,13 @@ pub type WinColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, Wi
pub type WinDepthView = gfx::handle::DepthStencilView<gfx_backend::Resources, WinDepthFmt>;
/// Represents the format of LOD shadows.
pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); //[gfx::format::U8Norm; 4];
pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm);
/// Represents the format of LOD altitudes.
pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm); //[gfx::format::U8Norm; 4];
pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm);
/// Represents the format of LOD map colors.
pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); //[gfx::format::U8Norm; 4];
pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb);
/// Represents the format of greedy meshed color-light textures.
pub type ColLightFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb);
@ -420,6 +420,9 @@ impl Renderer {
}
/// Create textures and views for shadow maps.
// This is a one-use type and the two halves are not guaranteed to remain identical, so we
// disable the type complexity lint.
#[allow(clippy::type_complexity)]
fn create_shadow_views(
factory: &mut gfx_device_gl::Factory,
size: (u16, u16),
@ -457,7 +460,7 @@ impl Renderer {
}
}))?;
let levels = 1; //10;
let levels = 1;
let two_size = vec2_result(size.map(|e| {
u16::checked_next_power_of_two(e)
.filter(|&e| e <= max_texture_size)
@ -501,67 +504,26 @@ impl Renderer {
diag_size
))
})?;
/* let color_cty = <<TgtColorFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped
>::get_channel_type();
let tgt_color_tex = factory.create_texture(
kind,
levels,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::RENDER_TARGET,
gfx::memory::Usage::Data,
Some(color_cty),
)?;
let tgt_color_res = factory.view_texture_as_shader_resource::<TgtColorFmt>(
&tgt_color_tex,
(0, levels - 1),
gfx::format::Swizzle::new(),
)?;
let tgt_color_view = factory.view_texture_as_render_target(&tgt_color_tex, 0, None)?;
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_stencil_cty),
)?;
let tgt_depth_stencil_view =
factory.view_texture_as_depth_stencil_trivial(&tgt_depth_stencil_tex)?; */
let depth_stencil_cty = <<ShadowDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
let point_shadow_tex = factory
.create_texture(
gfx::texture::Kind::/*CubeArray*/Cube(
/* max_two_size */ diag_two_size / 4, /* size * 2*//*, 32 */
),
gfx::texture::Kind::Cube(diag_two_size / 4),
levels as gfx::texture::Level,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
gfx::memory::Usage::Data,
Some(depth_stencil_cty),
/* Some(<<F as gfx::format::Formatted>::Channel as
* gfx::format::ChannelTyped>::get_channel_type()), */
)
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
let point_tgt_shadow_view = factory
.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&point_shadow_tex,
0, // levels,
None, // Some(1),
0,
None,
gfx::texture::DepthStencilFlags::empty(),
)?;
// let tgt_shadow_view =
// factory.view_texture_as_depth_stencil_trivial(&shadow_tex)?;
/* let tgt_shadow_res = factory.view_texture_as_shader_resource::<TgtColorFmt>(
&tgt_color_tex,
(0, levels - 1),
gfx::format::Swizzle::new(),
)?; */
// let tgt_shadow_view =
// factory.view_texture_as_depth_stencil_trivial(&tgt_color_tex)?;
// let tgt_shadow_view = factory.view_texture_as_shader_resource(&tgt_color_tex,
// 0, None)?;
let point_tgt_shadow_res = factory
.view_texture_as_shader_resource::<ShadowDepthStencilFmt>(
&point_shadow_tex,
@ -569,21 +531,9 @@ impl Renderer {
gfx::format::Swizzle::new(),
)?;
/* println!(
"size: {:?}, two_size: {:?}, diag_size: {:?}, diag_two_size: {:?}",
size, two_size, diag_size, diag_two_size,
); */
let directed_shadow_tex = factory
.create_texture(
gfx::texture::Kind::D2(
/* size.x,// two_size.x,// 2 * size.x,
size.y,// two_size.y,// 2 * size.y, */
diag_two_size, /* max_two_size*//*two_size.x */
diag_two_size, /* max_two_size*//*two_size.y */
/* 6*//*1, */ gfx::texture::AaMode::Single,
),
// gfx::texture::Kind::D2Array(max_size/* * 2*/, max_size/* * 2*/, /*6*/1,
// gfx::texture::AaMode::Single),
gfx::texture::Kind::D2(diag_two_size, diag_two_size, gfx::texture::AaMode::Single),
levels as gfx::texture::Level,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
gfx::memory::Usage::Data,
@ -593,8 +543,8 @@ impl Renderer {
let directed_tgt_shadow_view = factory
.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&directed_shadow_tex,
0, // levels,
None, // Some(1),
0,
None,
gfx::texture::DepthStencilFlags::empty(),
)?;
let directed_tgt_shadow_res = factory
@ -606,31 +556,14 @@ impl Renderer {
let mut sampler_info = gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Border, //Clamp,
// Lights should always be assumed to flood areas we can't see.
gfx::texture::WrapMode::Border,
);
sampler_info.comparison = Some(Comparison::LessEqual);
// sampler_info.lod_bias = (-3.0).into();
// sampler_info.lod_range = (1.into(), (levels - 1).into());
// Point lights should clamp to whatever edge value there is.
sampler_info.border = [1.0; 4].into();
let point_shadow_tex_sampler = factory.create_sampler(sampler_info);
/* // Directed lights should always be assumed to flood areas we can't see.
sampler_info.wrap_mode = (gfx::texture::WrapMode::Border, gfx::texture::WrapMode::Border, gfx::texture::WrapMode::Border); */
let directed_shadow_tex_sampler = factory.create_sampler(sampler_info);
/* let tgt_sun_res = factory.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&shadow_tex,
0,
Some(0),
gfx::texture::DepthStencilFlags::RO_DEPTH,
)?;
let tgt_moon_res = factory.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&shadow_tex,
0,
Some(1),
gfx::texture::DepthStencilFlags::RO_DEPTH,
)?; */
Ok((
point_tgt_shadow_view,
point_tgt_shadow_res,
@ -676,7 +609,6 @@ impl Renderer {
// let directed_encoder = &mut shadow_map.directed_encoder;
let directed_encoder = &mut self.encoder;
directed_encoder.clear_depth(&shadow_map.directed_depth_stencil_view, 1.0);
// encoder.clear_stencil(&shadow_map.depth_stencil_view, 0);
}
}
@ -693,7 +625,6 @@ impl Renderer {
// NOTE: Currently just fail silently rather than complain if the computer is on
// a version lower than 3.2, where seamless cubemaps were introduced.
if !device.get_info().is_version_supported(3, 2) {
// println!("whoops");
return;
}
@ -719,7 +650,6 @@ impl Renderer {
// and having depth clamping disabled won't cause undefined
// behavior, just incorrect shadowing from objects behind the viewer.
if !device.get_info().is_version_supported(3, 3) {
// println!("whoops");
return;
}
@ -729,8 +659,6 @@ impl Renderer {
// essentially always be safe regardless of the state of the OpenGL
// context, so no further checks are needed.
device.with_gl(|gl| {
// println!("gl.Enable(gfx_gl::DEPTH_CLAMP) = {:?}",
// gl.IsEnabled(gfx_gl::DEPTH_CLAMP));
if depth_clamp {
gl.Enable(gfx_gl::DEPTH_CLAMP);
} else {
@ -759,7 +687,7 @@ impl Renderer {
}
}
/// Perform all queued draw calls for shadows.
/// Perform all queued draw calls for global.shadows.
pub fn flush_shadows(&mut self) {
if !self.mode.shadow.is_map() {
return;
@ -848,14 +776,6 @@ impl Renderer {
Ok(consts)
}
/* /// Create a raw set of constants with the provided values.
pub fn create_consts_immutable<T: Copy + gfx::traits::Pod>(
&mut self,
vals: &[T],
) -> Result<RawBuffer<T>, RenderError> {
Consts::new_immutable(&mut self.factory, vals)
} */
/// Update a set of constants with the provided values.
pub fn update_consts<T: Copy + gfx::traits::Pod>(
&mut self,
@ -865,25 +785,6 @@ impl Renderer {
consts.update(&mut self.encoder, vals, 0)
}
/* /// Update a set of shadow constants with the provided values.
pub fn update_shadow_consts<T: Copy + gfx::traits::Pod>(
&mut self,
consts: &mut Consts<T>,
vals: &[T],
directed_offset: usize,
point_offset: usize,
) -> Result<(), RenderError> {
if let Some(shadow_map) = self.shadow_map.as_mut() {
let directed_encoder = &mut shadow_map.directed_encoder;
consts.update(directed_encoder, &vals[directed_offset..point_offset], directed_offset)?;
let point_encoder = &mut shadow_map.point_encoder;
consts.update(point_encoder, &vals[point_offset..], point_offset)
} else {
// Fail silently if shadows aren't working in the first place.
Ok(())
}
} */
/// Create a new set of instances with the provided values.
pub fn create_instances<T: Copy + gfx::traits::Pod>(
&mut self,
@ -1004,22 +905,6 @@ impl Renderer {
Texture::new_dynamic(&mut self.factory, dims.x, dims.y)
}
/* /// Create a new greedy texture array (of color-lights).
pub fn create_greedy_texture<F: gfx::format::Formatted>(
&mut self,
kind: gfx::texture::Kind,
mipmap: gfx::texture::MipMap,
data: &[&[<F::Surface as gfx::format::SurfaceTyped>::DataType]],
sampler_info: gfx::texture::SamplerInfo,
) -> Result<Texture<F>, RenderError>
where
F::Surface: gfx::format::TextureSurface,
F::Channel: gfx::format::TextureChannel,
<F::Surface as gfx::format::SurfaceTyped>::DataType: Copy,
{
Texture::new_immutable_raw(&mut self.factory, kind, mipmap, data, sampler_info)
} */
/// Update a texture with the provided offset, size, and data.
pub fn update_texture(
&mut self,
@ -1082,10 +967,9 @@ impl Renderer {
pub fn render_skybox(
&mut self,
model: &Model<skybox::SkyboxPipeline>,
globals: &Consts<Globals>,
global: &GlobalModel,
locals: &Consts<skybox::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
lod: &lod_terrain::LodData,
) {
self.encoder.draw(
&gfx::Slice {
@ -1099,10 +983,10 @@ impl Renderer {
&skybox::pipe::Data {
vbuf: model.vbuf.clone(),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
globals: global.globals.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
},
@ -1114,16 +998,11 @@ impl Renderer {
&mut self,
model: &figure::FigureModel,
_col_lights: &Texture<ColLightFmt>,
globals: &Consts<Globals>,
global: &GlobalModel,
locals: &Consts<figure::Locals>,
bones: &Consts<figure::BoneData>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
lod: &lod_terrain::LodData,
) {
// return;
let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map {
(
@ -1144,8 +1023,6 @@ impl Renderer {
};
let col_lights = &model.col_lights;
let model = &model.opaque;
// let atlas_model = &model.opaque;
// let model = &model.shadow;
self.encoder.draw(
&gfx::Slice {
@ -1158,20 +1035,18 @@ impl Renderer {
&self.figure_pipeline.pso,
&figure::pipe::Data {
vbuf: model.vbuf.clone(),
// abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
globals: global.globals.buf.clone(),
bones: bones.buf.clone(),
lights: lights.buf.clone(),
shadows: shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(),
lights: global.lights.buf.clone(),
shadows: global.shadows.buf.clone(),
light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps,
directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
},
@ -1183,15 +1058,12 @@ impl Renderer {
&mut self,
_model: &figure::FigureModel,
_col_lights: &Texture<ColLightFmt>,
_globals: &Consts<Globals>,
_locals: &Consts<figure::Locals>,
_global: &GlobalModel,
_bones: &Consts<figure::BoneData>,
_lights: &Consts<Light>,
_shadows: &Consts<Shadow>,
_light_shadows: &Consts<shadow::Locals>,
_alt: &Texture<LodAltFmt>,
_horizon: &Texture<LodTextureFmt>,
_lod: &lod_terrain::LodData,
_locals: &Consts<shadow::Locals>,
) {
// FIXME: Consider reenabling at some point.
/* let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map {
(
@ -1228,18 +1100,18 @@ impl Renderer {
vbuf: model.vbuf.clone(),
// abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
// col_lights: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
globals: global.globals.buf.clone(),
bones: bones.buf.clone(),
lights: lights.buf.clone(),
shadows: shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(),
lights: global.lights.buf.clone(),
shadows: global.shadows.buf.clone(),
light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps,
directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (0, 0) */),
},
@ -1251,14 +1123,10 @@ impl Renderer {
&mut self,
model: &figure::FigureModel,
_col_lights: &Texture<ColLightFmt>,
globals: &Consts<Globals>,
global: &GlobalModel,
locals: &Consts<figure::Locals>,
bones: &Consts<figure::BoneData>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
lod: &lod_terrain::LodData,
) {
let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map {
@ -1280,8 +1148,6 @@ impl Renderer {
};
let col_lights = &model.col_lights;
let model = &model.opaque;
// let atlas_model = &model.opaque;
// let model = &model.shadow;
self.encoder.draw(
&gfx::Slice {
@ -1294,20 +1160,18 @@ impl Renderer {
&self.figure_pipeline.pso,
&figure::pipe::Data {
vbuf: model.vbuf.clone(),
// abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
globals: global.globals.buf.clone(),
bones: bones.buf.clone(),
lights: lights.buf.clone(),
shadows: shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(),
lights: global.lights.buf.clone(),
shadows: global.shadows.buf.clone(),
light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps,
directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
},
@ -1318,17 +1182,11 @@ impl Renderer {
/// frame.
pub fn render_terrain_chunk(
&mut self,
// atlas_model: &Model<terrain::TerrainPipeline>,
// model: &Model<shadow::ShadowPipeline>,
model: &Model<terrain::TerrainPipeline>,
col_lights: &Texture<ColLightFmt>,
globals: &Consts<Globals>,
global: &GlobalModel,
locals: &Consts<terrain::Locals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
lod: &lod_terrain::LodData,
) {
let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map {
@ -1361,20 +1219,18 @@ impl Renderer {
&terrain::pipe::Data {
vbuf: model.vbuf.clone(),
// TODO: Consider splitting out texture atlas data into a separate vertex buffer,
// since we don't need it for things like shadows.
// abuf: atlas_model.vbuf.clone(),
// since we don't need it for things like global.shadows.
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
lights: lights.buf.clone(),
shadows: shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(),
globals: global.globals.buf.clone(),
lights: global.lights.buf.clone(),
shadows: global.shadows.buf.clone(),
light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps,
directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
},
@ -1386,14 +1242,9 @@ impl Renderer {
pub fn render_shadow_point(
&mut self,
model: &Model<terrain::TerrainPipeline>,
// model: &Model<shadow::ShadowPipeline>,
globals: &Consts<Globals>,
global: &GlobalModel,
terrain_locals: &Consts<terrain::Locals>,
locals: &Consts<shadow::Locals>,
/* lights: &Consts<Light>,
* shadows: &Consts<Shadow>,
* alt: &Texture<LodAltFmt>,
* horizon: &Texture<LodTextureFmt>, */
) {
if !self.mode.shadow.is_map() {
return;
@ -1420,18 +1271,11 @@ impl Renderer {
// Terrain vertex stuff
vbuf: model.vbuf.clone(),
locals: terrain_locals.buf.clone(),
globals: globals.buf.clone(),
// lights: lights.buf.clone(),
// shadows: shadows.buf.clone(),
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
// alt: (alt.srv.clone(), alt.sampler.clone()),
// horizon: (horizon.srv.clone(), horizon.sampler.clone()),
globals: global.globals.buf.clone(),
// Shadow stuff
light_shadows: locals.buf.clone(),
tgt_depth_stencil: shadow_map.point_depth_stencil_view.clone(),
/* tgt_depth_stencil: (self.shadow_depth_stencil_view.clone(), (1, 1)),
* shadow_tex: (self.shadow_res.clone(), self.shadow_sampler.clone()), */
},
);
}
@ -1440,15 +1284,10 @@ impl Renderer {
/// the upcoming frame.
pub fn render_terrain_shadow_directed(
&mut self,
// model: &Model<shadow::ShadowPipeline>,
model: &Model<terrain::TerrainPipeline>,
globals: &Consts<Globals>,
global: &GlobalModel,
terrain_locals: &Consts<terrain::Locals>,
locals: &Consts<shadow::Locals>,
/* lights: &Consts<Light>,
* shadows: &Consts<Shadow>,
* alt: &Texture<LodAltFmt>,
* horizon: &Texture<LodTextureFmt>, */
) {
if !self.mode.shadow.is_map() {
return;
@ -1475,18 +1314,11 @@ impl Renderer {
// Terrain vertex stuff
vbuf: model.vbuf.clone(),
locals: terrain_locals.buf.clone(),
globals: globals.buf.clone(),
// lights: lights.buf.clone(),
// shadows: shadows.buf.clone(),
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
// alt: (alt.srv.clone(), alt.sampler.clone()),
// horizon: (horizon.srv.clone(), horizon.sampler.clone()),
globals: global.globals.buf.clone(),
// Shadow stuff
light_shadows: locals.buf.clone(),
tgt_depth_stencil: shadow_map.directed_depth_stencil_view.clone(),
/* tgt_depth_stencil: (self.shadow_depth_stencil_view.clone(), (1, 1)),
* shadow_tex: (self.shadow_res.clone(), self.shadow_sampler.clone()), */
},
);
}
@ -1495,16 +1327,11 @@ impl Renderer {
/// the upcoming frame.
pub fn render_figure_shadow_directed(
&mut self,
// model: &Model<shadow::ShadowPipeline>,
model: &figure::FigureModel,
globals: &Consts<Globals>,
global: &GlobalModel,
figure_locals: &Consts<figure::Locals>,
bones: &Consts<figure::BoneData>,
locals: &Consts<shadow::Locals>,
/* lights: &Consts<Light>,
* shadows: &Consts<Shadow>,
* alt: &Texture<LodAltFmt>,
* horizon: &Texture<LodTextureFmt>, */
) {
if !self.mode.shadow.is_map() {
return;
@ -1533,18 +1360,11 @@ impl Renderer {
vbuf: model.vbuf.clone(),
locals: figure_locals.buf.clone(),
bones: bones.buf.clone(),
globals: globals.buf.clone(),
// lights: lights.buf.clone(),
// shadows: shadows.buf.clone(),
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
// alt: (alt.srv.clone(), alt.sampler.clone()),
// horizon: (horizon.srv.clone(), horizon.sampler.clone()),
globals: global.globals.buf.clone(),
// Shadow stuff
light_shadows: locals.buf.clone(),
tgt_depth_stencil: shadow_map.directed_depth_stencil_view.clone(),
/* tgt_depth_stencil: (self.shadow_depth_stencil_view.clone(), (1, 1)),
* shadow_tex: (self.shadow_res.clone(), self.shadow_sampler.clone()), */
},
);
}
@ -1554,13 +1374,9 @@ impl Renderer {
pub fn render_fluid_chunk(
&mut self,
model: &Model<fluid::FluidPipeline>,
globals: &Consts<Globals>,
global: &GlobalModel,
locals: &Consts<terrain::Locals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
lod: &lod_terrain::LodData,
waves: &Texture,
) {
let (point_shadow_maps, directed_shadow_maps) =
@ -1594,14 +1410,14 @@ impl Renderer {
&fluid::pipe::Data {
vbuf: model.vbuf.clone(),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
lights: lights.buf.clone(),
shadows: shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(),
globals: global.globals.buf.clone(),
lights: global.lights.buf.clone(),
shadows: global.shadows.buf.clone(),
light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps,
directed_shadow_maps,
alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
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(),
@ -1616,17 +1432,11 @@ impl Renderer {
&mut self,
model: &Model<sprite::SpritePipeline>,
col_lights: &Texture<ColLightFmt>,
globals: &Consts<Globals>,
global: &GlobalModel,
terrain_locals: &Consts<terrain::Locals>,
locals: &Consts<sprite::Locals>,
// instance_count: usize,
// instances: &Consts<sprite::Instance>,
instances: &Instances<sprite::Instance>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
lod: &lod_terrain::LodData,
) {
let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map {
@ -1652,26 +1462,25 @@ impl Renderer {
start: model.vertex_range().start,
end: model.vertex_range().end,
base_vertex: 0,
instances: Some((instances.count()/*instance_count*/ as u32, 0)),
instances: Some((instances.count() as u32, 0)),
buffer: gfx::IndexBuffer::Auto,
},
&self.sprite_pipeline.pso,
&sprite::pipe::Data {
vbuf: model.vbuf.clone(),
ibuf: instances.ibuf.clone(),
// ibuf: instances.buf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
terrain_locals: terrain_locals.buf.clone(),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
lights: lights.buf.clone(),
shadows: shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(),
globals: global.globals.buf.clone(),
lights: global.lights.buf.clone(),
shadows: global.shadows.buf.clone(),
light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps,
directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
},
@ -1683,11 +1492,9 @@ impl Renderer {
pub fn render_lod_terrain(
&mut self,
model: &Model<lod_terrain::LodTerrainPipeline>,
globals: &Consts<Globals>,
global: &GlobalModel,
locals: &Consts<lod_terrain::Locals>,
map: &Texture<LodColorFmt>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
lod: &lod_terrain::LodData,
) {
self.encoder.draw(
&gfx::Slice {
@ -1701,11 +1508,11 @@ impl Renderer {
&lod_terrain::pipe::Data {
vbuf: model.vbuf.clone(),
locals: locals.buf.clone(),
globals: globals.buf.clone(),
globals: global.globals.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
map: (lod.map.srv.clone(), lod.map.sampler.clone()),
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
},
@ -1926,13 +1733,6 @@ fn create_pipelines(
)
.unwrap();
/* let directed_shadow_geom =
&assets::load_watched::<String>(
"voxygen.shaders.light-shadows-directed-geom",
shader_reload_indicator,
)
.unwrap(); */
let directed_shadow_frag = &assets::load_watched::<String>(
"voxygen.shaders.light-shadows-directed-frag",
shader_reload_indicator,
@ -2094,8 +1894,7 @@ fn create_pipelines(
.unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
None,
// Some(gfx::state::Offset(2, /* 10 */ 0)),
None, // Some(gfx::state::Offset(2, 0))
) {
Ok(pipe) => Some(pipe),
Err(err) => {
@ -2109,14 +1908,11 @@ fn create_pipelines(
factory,
shadow::pipe::new(),
&terrain_directed_shadow_vert,
None, // &directed_shadow_geom,
None,
&directed_shadow_frag,
&include_ctx,
gfx::state::CullFace::Back,
/* None, */
/* Some(gfx::state::Offset(4, 10)), */
None,
// Some(gfx::state::Offset(2, /*10*/1)),
None, // Some(gfx::state::Offset(2, 1))
) {
Ok(pipe) => Some(pipe),
Err(err) => {
@ -2133,14 +1929,11 @@ fn create_pipelines(
factory,
shadow::figure_pipe::new(),
&figure_directed_shadow_vert,
None, // &directed_shadow_geom,
None,
&directed_shadow_frag,
&include_ctx,
gfx::state::CullFace::Back,
/* None, */
/* Some(gfx::state::Offset(4, 10)), */
/*Some(gfx::state::Offset(2, 1))*/None,
/* Some(gfx::state::Offset(2, 10)), */
None, // Some(gfx::state::Offset(2, 1))
) {
Ok(pipe) => Some(pipe),
Err(err) => {
@ -2230,14 +2023,14 @@ fn create_shadow_pipeline<P: gfx::pso::PipelineInit>(
// Second-depth shadow mapping: should help reduce z-fighting provided all objects
// are "watertight" (every triangle edge is shared with at most one other
// triangle); this *should* be true for Veloren.
cull_face: /*gfx::state::CullFace::Nothing*/match cull_face {
cull_face: match cull_face {
gfx::state::CullFace::Front => gfx::state::CullFace::Back,
gfx::state::CullFace::Back => gfx::state::CullFace::Front,
gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing,
},
method: gfx::state::RasterMethod::Fill,
offset,
samples: None, // Some(gfx::state::MultiSample),
samples: None,
},
pipe,
)?,

View File

@ -139,8 +139,6 @@ where
)
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
// device.cleanup();
let srv = factory
.view_texture_as_shader_resource::<F>(&tex, levels, swizzle)
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?;

View File

@ -91,8 +91,6 @@ impl Camera {
(_, Err(_)) => self.dist,
}
.max(0.0)
// .max(NEAR_PLANE)
// self.dist.max(0.0)
};
self.dependents.view_mat = Mat4::<f32>::identity()

View File

@ -936,14 +936,14 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
.unwrap_or_else(<Skel::Attr as Default>::default);
let manifest_indicator = &mut self.manifest_indicator;
let mut make_model = |generate_mesh: for<'a> fn(&mut GreedyMesh<'a>, _, _) -> _| {
let mut make_model =
|generate_mesh: for<'a> fn(&mut GreedyMesh<'a>, _, _) -> _| {
let mut greedy = FigureModel::make_greedy();
let mut opaque = Mesh::new();
let mut figure_bounds = Aabb {
min: Vec3::zero(),
max: Vec3::zero(),
};
// let mut shadow = Mesh::new();
Self::bone_meshes(
body,
loadout,
@ -953,16 +953,19 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
|segment, offset| generate_mesh(&mut greedy, segment, offset),
)
.iter()
// .zip(&mut figure_bounds)
.enumerate()
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
.for_each(|(i, (opaque_mesh/*, shadow_mesh*/, bounds)/*, bone_bounds*/)| {
// opaque.push_mesh_map(opaque_mesh, |vert| vert.with_bone_idx(i as u8));
opaque.push_mesh_map(opaque_mesh, |vert| vert.with_bone_idx(i as u8));
figure_bounds.expand_to_contain(*bounds);
// shadow.push_mesh_map(shadow_mesh, |vert| vert.with_bone_idx(i as u8));
.for_each(
|(i, (opaque_mesh, bounds))| {
opaque.push_mesh_map(opaque_mesh, |vert| {
vert.with_bone_idx(i as u8)
});
col_lights.create_figure(renderer, greedy, (opaque/*, shadow*/, figure_bounds)).unwrap()
figure_bounds.expand_to_contain(*bounds);
},
);
col_lights
.create_figure(renderer, greedy, (opaque, figure_bounds))
.unwrap()
};
fn generate_mesh<'a>(
@ -970,11 +973,12 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
segment: Segment,
offset: Vec3<f32>,
) -> BoneMeshes {
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
let (opaque, _, _, bounds) =
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
segment,
(greedy, offset, Vec3::one()),
);
(opaque/*, shadow*/, bounds)
(opaque, bounds)
}
fn generate_mesh_lod_mid<'a>(
@ -983,11 +987,12 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
offset: Vec3<f32>,
) -> BoneMeshes {
let lod_scale = Vec3::broadcast(0.6);
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
let (opaque, _, _, bounds) =
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
segment.scaled_by(lod_scale),
(greedy, offset * lod_scale, Vec3::one() / lod_scale),
);
(opaque/*, shadow*/, bounds)
(opaque, bounds)
}
fn generate_mesh_lod_low<'a>(
@ -997,11 +1002,12 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
) -> BoneMeshes {
let lod_scale = Vec3::broadcast(0.3);
let segment = segment.scaled_by(lod_scale);
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
let (opaque, _, _, bounds) =
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
segment,
(greedy, offset * lod_scale, Vec3::one() / lod_scale),
);
(opaque/*, shadow*/, bounds)
(opaque, bounds)
}
(

View File

@ -793,7 +793,7 @@ impl HumMainWeaponSpec {
let tool_kind = if let Some(ItemKind::Tool(Tool { kind, .. })) = item_kind {
kind
} else {
return (Mesh::new() /* , Mesh::new() */, Aabb::default());
return (Mesh::new(), Aabb::default());
};
let spec = match self.0.get(tool_kind) {

View File

@ -8,8 +8,8 @@ use crate::{
ecs::comp::Interpolated,
mesh::greedy::GreedyMesh,
render::{
BoneMeshes, ColLightFmt, Consts, FigureBoneData, FigureLocals, FigureModel, Globals, Light,
RenderError, Renderer, Shadow, ShadowLocals, ShadowPipeline, Texture,
BoneMeshes, ColLightFmt, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel,
RenderError, Renderer, ShadowPipeline, Texture,
},
scene::{
camera::{Camera, CameraMode, Dependents},
@ -48,6 +48,9 @@ const DAMAGE_FADE_COEFFICIENT: f64 = 5.0;
const MOVING_THRESHOLD: f32 = 0.7;
const MOVING_THRESHOLD_SQR: f32 = MOVING_THRESHOLD * MOVING_THRESHOLD;
/// camera data, fiigure LOD render distance.
pub type CameraData<'a> = (&'a Camera, f32);
struct FigureMgrStates {
character_states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
quadruped_small_states: HashMap<EcsEntity, FigureState<QuadrupedSmallSkeleton>>,
@ -1996,12 +1999,9 @@ impl FigureMgr {
renderer: &mut Renderer,
state: &State,
tick: u64,
globals: &Consts<Globals>,
shadow_mats: &Consts<ShadowLocals>,
is_daylight: bool,
_light_data: &[Light],
camera: &Camera,
figure_lod_render_distance: f32,
global: &GlobalModel,
(is_daylight, _light_data): super::LightData,
(camera, figure_lod_render_distance): CameraData,
) {
let ecs = state.ecs();
@ -2034,10 +2034,10 @@ impl FigureMgr {
) {
renderer.render_figure_shadow_directed(
model,
globals,
global,
locals,
bone_consts,
shadow_mats,
&global.shadow_mats,
);
}
});
@ -2051,13 +2051,9 @@ impl FigureMgr {
state: &State,
player_entity: EcsEntity,
tick: u64,
globals: &Consts<Globals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
shadow_mats: &Consts<ShadowLocals>,
global: &GlobalModel,
lod: &LodData,
camera: &Camera,
figure_lod_render_distance: f32,
(camera, figure_lod_render_distance): CameraData,
) {
let ecs = state.ecs();
@ -2096,14 +2092,10 @@ impl FigureMgr {
renderer.render_figure(
model,
&col_lights.col_lights,
globals,
global,
locals,
bone_consts,
lights,
shadows,
shadow_mats,
&lod.alt,
&lod.horizon,
lod,
);
}
}
@ -2117,13 +2109,9 @@ impl FigureMgr {
state: &State,
player_entity: EcsEntity,
tick: u64,
globals: &Consts<Globals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
shadow_mats: &Consts<ShadowLocals>,
global: &GlobalModel,
lod: &LodData,
camera: &Camera,
figure_lod_render_distance: f32,
(camera, figure_lod_render_distance): CameraData,
) {
let ecs = state.ecs();
@ -2160,26 +2148,18 @@ impl FigureMgr {
renderer.render_player(
model,
&col_lights.col_lights,
globals,
global,
locals,
bone_consts,
lights,
shadows,
shadow_mats,
&lod.alt,
&lod.horizon,
lod,
);
renderer.render_player_shadow(
model,
&col_lights.col_lights,
globals,
locals,
global,
bone_consts,
lights,
shadows,
shadow_mats,
&lod.alt,
&lod.horizon,
lod,
&global.shadow_mats,
);
}
}

View File

@ -1,89 +1,24 @@
use crate::{
render::{
pipelines::lod_terrain::{Locals, Vertex},
Consts, Globals, LodAltFmt, LodColorFmt, LodTerrainPipeline, LodTextureFmt, Mesh, Model,
Quad, Renderer, Texture,
pipelines::lod_terrain::{Locals, LodData, Vertex},
Consts, GlobalModel, LodTerrainPipeline, Mesh, Model, Quad, Renderer,
},
settings::Settings,
};
use client::Client;
use common::{spiral::Spiral2d, util::srgba_to_linear};
use gfx::texture::SamplerInfo;
use vek::*;
pub struct LodData {
pub map: Texture<LodColorFmt>,
pub alt: Texture<LodAltFmt>,
pub horizon: Texture<LodTextureFmt>,
pub tgt_detail: u32,
}
pub struct Lod {
model: Option<(u32, Model<LodTerrainPipeline>)>,
locals: Consts<Locals>,
data: LodData,
}
impl LodData {
pub fn new(
renderer: &mut Renderer,
map_size: Vec2<u16>,
lod_base: &[u32],
lod_alt: &[u32],
lod_horizon: &[u32],
tgt_detail: u32,
border_color: gfx::texture::PackedColor,
) -> Self {
let kind = gfx::texture::Kind::D2(map_size.x, map_size.y, gfx::texture::AaMode::Single);
let info = gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Border,
);
Self {
map: renderer
.create_texture_immutable_raw(
kind,
gfx::texture::Mipmap::Provided,
&[gfx::memory::cast_slice(lod_base)],
SamplerInfo {
border: border_color,
..info
},
)
.expect("Failed to generate map texture"),
alt: renderer
.create_texture_immutable_raw(
kind,
gfx::texture::Mipmap::Provided,
&[gfx::memory::cast_slice(lod_alt)],
SamplerInfo {
border: [0.0, 0.0, 0.0, 0.0].into(),
..info
},
)
.expect("Failed to generate alt texture"),
horizon: renderer
.create_texture_immutable_raw(
kind,
gfx::texture::Mipmap::Provided,
&[gfx::memory::cast_slice(lod_horizon)],
SamplerInfo {
// filter: gfx::texture::FilterMethod::Nearest,
// filter: gfx::texture::FilterMethod::TriLinear,
border: [1.0, 0.0, 1.0, 0.0].into(),
..info
},
)
.expect("Failed to generate horizon texture"),
tgt_detail,
}
}
}
// TODO: Make constant when possible.
pub fn water_color() -> Rgba<f32> {
/* Rgba::new(0.2, 0.5, 1.0, 0.0) */
srgba_to_linear(Rgba::new(0.0, 0.25, 0.5, 0.0)/* * 0.5*/)
srgba_to_linear(Rgba::new(0.0, 0.25, 0.5, 0.0))
}
impl Lod {
@ -123,16 +58,9 @@ impl Lod {
}
}
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
pub fn render(&self, renderer: &mut Renderer, global: &GlobalModel) {
if let Some((_, model)) = self.model.as_ref() {
renderer.render_lod_terrain(
&model,
globals,
&self.locals,
&self.data.map,
&self.data.alt,
&self.data.horizon,
);
renderer.render_lod_terrain(&model, global, &self.locals, &self.data);
}
}
}

View File

@ -103,16 +103,6 @@ pub fn clip_points_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
plane: (Vec3<T>, T),
intersection_points: &mut Vec<Vec3<T>>,
) -> bool {
/* enum Intersection {
/// Previous point was inside the plane.
Inside,
/// Previous line segment was completely outside the plane.
Outside,
/// Previous line segment went from inside the plane to outside it.
InsideOut,
} */
// println!("points@clip_points_by_plane before clipping by {:?}: {:?}", plane,
// points);
if points.len() < 3 {
return false;
}
@ -135,36 +125,12 @@ pub fn clip_points_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
};
let last_is_outside = point_before_plane(current_point, plane);
let mut is_outside = last_is_outside;
/* // Might not actually be total, but if it is partial and the point is inside it will be
// written regardless, and if it is partial and the point is outside, it means the
// second-to-last point is inside; thus, the second-to-last point will be written regardless,
// current_point will hold the new intersection point, and is_total will be false, when the
// loop ends; thus all we need to do to take this case into account is to push current_point
// onto the points vector if (is_total || is_outside) is false at the end of the loop.
let mut is_total = true; */
let mut old_points = Vec::with_capacity((3 * points.len()) / 2);
mem::swap(&mut old_points, points);
old_points.into_iter().for_each(|point| {
/* let prev_point = current_point;
// Swap point i with the previous point in the polygon, so it is the one we normally save
// when we return false.
mem::swap(&mut current_point, point); */
let prev_point = mem::replace(&mut current_point, point);
/* if point_before_plane(current_point) {
// If we are an outside point, we should only calculate an intersection if the previous
// point was inside.
if
is_outside s
// point was outside.
} else {
// If we are an inside point, then we should only calculate an intersection if the previous
// point was outside.
} */
let before_plane = point_before_plane(current_point, plane);
let prev_is_outside = mem::replace(&mut is_outside, before_plane);
// println!("points@clip_points_by_plane clipping segment by {:?} (prev={:?} /
// outside={:?}, current={:?} / outside={:?})", plane, prev_point,
// prev_is_outside, current_point, is_outside);
if !prev_is_outside {
// Push previous point.
points.push(prev_point);
@ -176,115 +142,7 @@ pub fn clip_points_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
points.push(intersection_point);
}
}
/* let prev_is_total = mem::replace(
&mut is_total,
// Save the intersection point only if we go from outside to inside or inside to
// outside, and definitely intersect the plane edge.
prev_is_outside != is_outside &&
.map(|intersection_point| {
intersection_points.push(intersection_point);
if prev_is_outside {
// If the previous point is outside, we know
*point = intersection_point;
} else {
// i o i o
//
// i o (2)
// i i/o o/i (3)
//
// i o i (3)
// i i/o o/i i (4)
//
// i o i o (4)
// i i/o o/i i i/o o/i (6)
//
// i o i o i (5)
// i i/o o/i i i/o o/i i (7)
//
// i o i o i o (6)
// i i/o o/i i i/o o/i i i/o o/i (9)
current_point = intersection_point;
}
false
})
.is_none(),
);
// Save the previous point if it is either inside, or has been replaced by an intersection
// point.
!prev_is_outside || prev_is_total
/* match (prev_is_outside, is_outside) {
(true, true) => {
prev_is_total
},
(true, false) => {
// Outside to inside, so save the previous point only if it's been replaced by an
// intersection point.
do_intersection();
prev_is_total
},
(false, true) => {
// Inside to outside, so always save the previous point, and save the intersection
// point only if we definitively intersect the plane edge.
false
},
(false, false) => {
// Both points inside the plane, so always save the previous point.
false
}
} */ */
});
/* if !(is_total || is_outside) {
points.push(current_point);
}
/* match (before_plane, is_outside) {
(true, Previous::Outside) => {
}
}
let cur_is_outside = {
if let Intersection::Inside = is_outside {
} else {
}
let prev_is_outside = mem::replace(&mut is_outside, {
let if let Intersection::Inside = is_outside {
true
} else {
false
} point_before_plane(current_point) {
});
match (prev_is_outside, is_outside) {
(true, Some(is_outside)) => {
// Both points outside the plane, so save the previous point only if it's been
// replaced by an intersection point.
is_outside
},
(true, false) => {
// Outside to inside, so calculate the intersection, and save it.
intersect_points.push(*point);
false
},
(false, true) => {
// Inside to outside, so calculate the intersection, and save it and the current
// point.
intersect_points.push(*point);
false
},
(false, false) => {
// Both points inside the plane, so save previous point
*point = *
false
}
}
if is_outside {
if prev_is_outside {
} else {
}
} else {
if prev_is_outside {
}
}
});*/ }*/
last_is_outside
}
@ -338,11 +196,14 @@ fn append_intersection_points<T: Float + core::fmt::Debug>(
// We use floating points rounded to tolerance in order to make our HashMap
// lookups work. Otherwise we'd have to use a sorted structure, like a
// btree, which wouldn't be the end of the world but would have
// theoretically worse complexity. NOTE: Definitely non-ideal that we
// panic if the rounded value can't fit in an i64... TODO: If necessary,
// let the caller specify how to hash these keys, since in cases where
// we know the kind of floating point we're using we can just cast to bits or
// something.
// theoretically worse complexity.
//
// NOTE: Definitely non-ideal that we panic if the rounded value can't fit in an
// i64...
//
// TODO: If necessary, let the caller specify how to hash these keys, since in
// cases where we know the kind of floating point we're using we can
// just cast to bits or something.
point.map(|e| {
(e * tol)
.round()
@ -362,45 +223,17 @@ fn append_intersection_points<T: Float + core::fmt::Debug>(
// than lines).
(u_key != make_key(v)).then_some((u_key, v))
});
// .map(|uv| (make_key(uv[0]), uv[1]))
if let Some((last_key, first)) = lines_iter.next()
/* [last, first, rest @ ..] = &*intersection_points = &*intersection_points */
{
if let Some((last_key, first)) = lines_iter.next() {
let lines = lines_iter.collect::<HashMap<_, _>>();
/* if rest.len() < 4 {
// You need at least 3 sides for a polygon
return;
}
let lines = rest
.chunks_exact(2)
.filter_map(|uv| {
let u_key = make_key(uv[0]);
let v = uv[1];
(u_key != make_key(v)).then_some((u_key, v))
})
// .map(|uv| (make_key(uv[0]), uv[1]))
.collect::<HashMap<_, _>>(); */
if lines.len() < 2 {
// You need at least 3 sides for a polygon
return;
}
// println!("lines@append_intersection_points before merging points (last={:?},
// cur={:?}): {:?}", last, cur, lines);
// let mut poly = Vec::with_capacity(lines.len() + 1);
// poly.push(first);
// NOTE: Guaranteed to terminate, provided we have no cycles besides the one
// that touches every point (which should be the case given how these
// points were generated).
let /*mut */poly_iter = iter::successors(Some(first), |&cur| lines.get(&make_key(cur)).copied());
/* poly.extend(poly_iter.next());
// TODO: If we were smart and pre-tested whether (last, first) was a dup (guaranteeing we
// started on a non-dup), we would not need the take_while part.
poly.extend(poly_iter.take_while(|&cur| make_key(cur) != make_key(first)));
/* while let Some(&v) = lines.get(&make_key(cur)) {
cur = v;
poly.push(cur);
} */ */
let poly_iter = iter::successors(Some(first), |&cur| lines.get(&make_key(cur)).copied());
let poly: Vec<_> = poly_iter.collect();
// We have to check to make sure we really went through the whole cycle.
// TODO: Consider adaptively decreasing precision until we can make the cycle
@ -421,7 +254,6 @@ pub fn clip_object_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
polys.drain_filter(|points| {
let len = intersection_points.len();
let outside_first = clip_points_by_plane(points, plane, &mut intersection_points);
// println!("points@clip_object_by_plane after clipping by {:?} (outside_first={:?}, intersection_points={:?}): {:?}", plane, outside_first, intersection_points, points);
// Only remember intersections that are not coplanar with this side; i.e. those
// that have segment length 2.
if len + 2 != intersection_points.len() {
@ -444,8 +276,6 @@ pub fn clip_object_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
// Remove polygon if it was clipped away
points.is_empty()
});
// println!("polys@clip_object_by_plane after clipping by {:?} (before appending
// interection points {:?}): {:?}", plane, intersection_points, polys);
// Add a polygon of all intersection points with the plane to close out the
// object.
append_intersection_points(polys, intersection_points, tolerance);
@ -457,11 +287,8 @@ pub fn clip_object_by_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::Debu
tolerance: T,
) {
let planes = aabb_to_planes(bounds);
// println!("planes@clip_object_by_aabb: {:?}", planes);
planes.iter().for_each(|&plane| {
clip_object_by_plane(polys, plane, tolerance);
// println!("polys@clip_object_by_aabb (after clipping by {:?}):
// {:?}", plane, polys);
});
}
@ -469,7 +296,6 @@ pub fn clip_object_by_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::Debu
/// test plane. Otherwise 'None' is returned in which case the line
/// segment is entirely clipped.
pub fn clip_test<T: Float + core::fmt::Debug>(p: T, q: T, (u1, u2): (T, T)) -> Option<(T, T)> {
/* let res = */
if p == T::zero() {
if q >= T::zero() { Some((u1, u2)) } else { None }
} else {
@ -485,9 +311,7 @@ pub fn clip_test<T: Float + core::fmt::Debug>(p: T, q: T, (u1, u2): (T, T)) -> O
} else {
Some((u1, if r < u2 { r } else { u2 }))
}
} /*;
// println!("clip_test@(p={:?}, q={:?}, (u1, u2)=({:?}. {:?})):
// res={:?}", p, q, u1, u2, res); res*/
}
}
pub fn intersection_line_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::Debug>(
@ -495,9 +319,6 @@ pub fn intersection_line_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::D
dir: Vec3<T>,
bounds: Aabb<T>,
) -> Option<Vec3<T>> {
// println!("before@intersection_line_aabb: p={:?} dir={:?} bounds={:?}", p,
// dir, bounds);
/* let res = */
clip_test(-dir.z, p.z - bounds.min.z, (T::zero(), T::infinity()))
.and_then(|t| clip_test(dir.z, bounds.max.z - p.z, t))
.and_then(|t| clip_test(-dir.y, p.y - bounds.min.y, t))
@ -512,9 +333,7 @@ pub fn intersection_line_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::D
} else {
None
}
}) /*;
//println!("after@intersection_line_aabb (p={:?} dir={:?} bounds={:?}):
// {:?}", p, dir, bounds, res); res */
})
}
pub fn include_object_light_volume<
@ -525,12 +344,12 @@ pub fn include_object_light_volume<
light_dir: Vec3<T>,
bounds: Aabb<T>,
) -> impl Iterator<Item = Vec3<T>> {
/* obj.filter_map(move |pt| intersection_line_aabb(pt, -light_dir, bounds)) */
// obj.map(move |pt| intersection_line_aabb(pt, -light_dir,
// bounds).unwrap_or(pt))
obj.flat_map(move |pt| iter::once(pt).chain(intersection_line_aabb(pt, -light_dir, bounds)))
}
// NOTE: Currently specialized to skip extending to the end of the light ray,
// since our light ray is already infinite. Correct code is commented out
// below.
pub fn calc_focused_light_volume_points<T: Float + MulAdd<T, T, Output = T> + core::fmt::Debug>(
inv_proj_view: Mat4<T>,
_light_dir: Vec3<T>,
@ -538,13 +357,8 @@ pub fn calc_focused_light_volume_points<T: Float + MulAdd<T, T, Output = T> + co
tolerance: T,
) -> impl Iterator<Item = Vec3<T>> {
let world_pts = calc_view_frustum_world_coord(inv_proj_view);
// println!("world_pts: {:?}", world_pts);
let mut world_frust_object = calc_view_frust_object(&world_pts);
// println!("world_frust_object: {:?}", world_frust_object);
clip_object_by_aabb(&mut world_frust_object, scene_bounding_box, tolerance);
// println!("world_frust_object@clip_object_by_aabb: {:?}", world_frust_object);
/* let object_points = world_frust_object.into_iter().flat_map(|e| e.into_iter());
object_points.clone().chain(include_object_light_volume(object_points, light_dir, scene_bounding_box)) */
world_frust_object.into_iter().flat_map(|e| e.into_iter())
/* include_object_light_volume(
world_frust_object.into_iter().flat_map(|e| e.into_iter()),
@ -574,50 +388,4 @@ pub fn fit_psr<
min: min.xyz(),
max: max.xyz(),
}
/* let mut make_p = |x: f32, y: f32, z: f32| -> Vec3<f32> {
do_p(mat * Vec4::new(x, y, z, 1.0))
};
let p1 = make_p(bounds.min.x, bounds.min.y, bounds.min.z);
let p2 = make_p(bounds.max.x, bounds.min.y, bounds.min.z);
let p3 = make_p(bounds.min.x, bounds.max.y, bounds.min.z);
let p4 = make_p(bounds.max.x, bounds.max.y, bounds.min.z);
let p5 = make_p(bounds.min.x, bounds.min.y, bounds.max.z);
let p6 = make_p(bounds.max.x, bounds.min.y, bounds.max.z);
let p7 = make_p(bounds.min.x, bounds.max.y, bounds.max.z);
let p8 = make_p(bounds.max.x, bounds.max.y, bounds.max.z);
// let p1: Vec4<f32> = mat * Vec4::new(bounds.min.x, bounds.min.y, bounds.min.z, 1.0);
// let p2: Vec4<f32> = mat * Vec4::new(0.0, bounds.min.y, 0.0, 1.0);
// let p3: Vec4<f32> = mat * Vec4::new(0.0, 0.0, bounds.min.z, 1.0);
// let p4: Vec4<f32> = mat * Vec4::new(bounds.max.x, 0.0, 0.0, 1.0);
// let p5: Vec4<f32> = mat * Vec4::new(0.0, bounds.max.y, 0.0, 1.0);
// let p6: Vec4<f32> = mat * Vec4::new(bounds.max.x, bounds.max.y, bounds.max.z, 1.0);
// println!("p1 p6 {:?} {:?}", p1, p6);
// let xmin = p1.x.min(p6.x);
// let xmax = p1.x.max(p6.x);
// println!("p1 p2 p3 p4 p5 p6: {:?} {:?} {:?} {:?} {:?} {:?}", p1, p2, p3, p4, p5, p6);
let xmin = p1.x.min(p2.x.min(p3.x.min(p4.x.min(p5.x.min(p6.x.min(p7.x.min(p8.x)))))));
let xmax = p1.x.max(p2.x.max(p3.x.max(p4.x.max(p5.x.max(p6.x.max(p7.x.max(p8.x)))))));
// let xmin = p1.x.min(p2.x.min(p3.x.min(p4.x.min(p5.x.min(p6.x)))));
// let xmax = p1.x.max(p2.x.max(p3.x.max(p4.x.max(p5.x.max(p6.x)))));
// println!("xmin: {:?}, xmax: {:?}", xmin, xmax);
// let ymin = p1.y.min(p6.y);
// let ymax = p1.y.max(p6.y);
let ymin = p1.y.min(p2.y.min(p3.y.min(p4.y.min(p5.y.min(p6.y.min(p7.y.min(p8.y)))))));
let ymax = p1.y.max(p2.y.max(p3.y.max(p4.y.max(p5.y.max(p6.y.max(p7.y.max(p8.y)))))));
// println!("ymin: {:?}, ymax: {:?}", ymin, ymax);
// let p1: Vec4<f32> = view_mat * Vec4::new(scene_bounds.min.x, scene_bounds.min.y, scene_bounds.min.z, 1.0);
// let p2: Vec4<f32> = view_mat * Vec4::new(0.0, scene_bounds.min.y, 0.0, 1.0);
// let p3: Vec4<f32> = view_mat * Vec4::new(0.0, 0.0, scene_bounds.min.z, 1.0);
// let p4: Vec4<f32> = view_mat * Vec4::new(scene_bounds.max.x, scene_bounds.max.y, scene_bounds.max.z, 1.0);
// let p5: Vec4<f32> = view_mat * Vec4::new(0.0, scene_bounds.max.y, 0.0, 1.0);
// let p6: Vec4<f32> = view_mat * Vec4::new(0.0, 0.0, scene_bounds.max.z, 1.0);
// println!("p1 p2 p3 p4 p5 p6: {:?} {:?} {:?} {:?} {:?} {:?}", p1, p2, p3, p4, p5, p6);
// println!("p1 p4 {:?} {:?}", p1, p4);
let zmin = p1.z.min(p2.z.min(p3.z.min(p4.z.min(p5.z.min(p6.z.min(p7.z.min(p8.z)))))));
let zmax = p1.z.max(p2.z.max(p3.z.max(p4.z.max(p5.z.max(p6.z.max(p7.z.max(p8.z)))))));
Aabb {
min: Vec3::new(xmin, ymin, zmin),
max: Vec3::new(xmax, ymax, zmax),
} */
}

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,8 @@ use crate::{
mesh::{greedy::GreedyMesh, Meshable},
render::{
create_pp_mesh, create_skybox_mesh, BoneMeshes, Consts, FigureModel, FigurePipeline,
Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer, Shadow,
ShadowLocals, SkyboxLocals, SkyboxPipeline,
GlobalModel, Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer,
Shadow, ShadowLocals, SkyboxLocals, SkyboxPipeline,
},
scene::{
camera::{self, Camera, CameraMode},
@ -68,10 +68,7 @@ struct PostProcess {
}
pub struct Scene {
globals: Consts<Globals>,
lights: Consts<Light>,
shadows: Consts<Shadow>,
shadow_mats: Consts<ShadowLocals>,
data: GlobalModel,
camera: Camera,
skybox: Skybox,
@ -105,18 +102,8 @@ impl Scene {
let map_bounds = Vec2::new(-65536.0, 131071.0);
let map_border = [0.0, 0.0, 0.0, 0.0];
/* let map_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel(
1,
1,
image::Rgba([0, 0, 0, 0]),
)); */
let map_image = [0];
let alt_image = [0];
/* let horizon_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel(
1,
1,
image::Rgba([0, 1, 0, 1]),
)); */
let horizon_image = [0x_00_01_00_01];
let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson);
@ -127,10 +114,14 @@ impl Scene {
let mut col_lights = FigureColLights::new(renderer);
Self {
data: GlobalModel {
globals: renderer.create_consts(&[Globals::default()]).unwrap(),
lights: renderer.create_consts(&[Light::default(); 32]).unwrap(),
shadows: renderer.create_consts(&[Shadow::default(); 32]).unwrap(),
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]).unwrap(),
shadow_mats: renderer
.create_consts(&[ShadowLocals::default(); 6])
.unwrap(),
},
skybox: Skybox {
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
@ -142,8 +133,16 @@ impl Scene {
.create_consts(&[PostProcessLocals::default()])
.unwrap(),
},
lod: LodData::new(renderer, Vec2::new(1, 1), &map_image, &alt_image, &horizon_image, 1, map_border.into()),// Lod::new(renderer, client, settings),
map_bounds,//: client.world_map.2,
lod: LodData::new(
renderer,
Vec2::new(1, 1),
&map_image,
&alt_image,
&horizon_image,
1,
map_border.into(),
),
map_bounds,
figure_model_cache: FigureModelCache::new(),
figure_state: FigureState::new(renderer, CharacterSkeleton::default()),
@ -173,21 +172,18 @@ impl Scene {
&camera,
&mut buf,
);
(
model,
state,
)
(model, state)
}),
col_lights,
camera,
turning: false,
char_ori: /*0.0*/-start_angle,
char_ori: -start_angle,
}
}
pub fn globals(&self) -> &Consts<Globals> { &self.globals }
pub fn globals(&self) -> &Consts<Globals> { &self.data.globals }
pub fn camera_mut(&mut self) -> &mut Camera { &mut self.camera }
@ -234,19 +230,18 @@ impl Scene {
cam_pos,
} = self.camera.dependents();
const VD: f32 = 115.0; // View Distance
// const MAP_BOUNDS: Vec2<f32> = Vec2::new(140.0, 2048.0);
const TIME: f64 = 10.0 * 60.0 * 60.0; //43200.0; // 12 hours*3600 seconds
const TIME: f64 = 10.0 * 60.0 * 60.0;
const SHADOW_NEAR: f32 = 1.0;
const SHADOW_FAR: f32 = 25.0;
if let Err(e) = renderer.update_consts(&mut self.globals, &[Globals::new(
if let Err(e) = renderer.update_consts(&mut self.data.globals, &[Globals::new(
view_mat,
proj_mat,
cam_pos,
self.camera.get_focus_pos(),
VD,
self.lod.tgt_detail as f32,
self.map_bounds, //MAP_BOUNDS,
self.map_bounds,
TIME,
scene_data.time,
renderer.get_resolution(),
@ -338,10 +333,9 @@ impl Scene {
) {
renderer.render_skybox(
&self.skybox.model,
&self.globals,
&self.data,
&self.skybox.locals,
&self.lod.alt,
&self.lod.horizon,
&self.lod,
);
if let Some(body) = body {
@ -361,14 +355,10 @@ impl Scene {
renderer.render_figure(
&model[0],
&self.col_lights.texture(),
&self.globals,
&self.data,
self.figure_state.locals(),
self.figure_state.bone_consts(),
&self.lights,
&self.shadows,
&self.shadow_mats,
&self.lod.alt,
&self.lod.horizon,
&self.lod,
);
}
@ -376,20 +366,16 @@ impl Scene {
renderer.render_figure(
model,
&self.col_lights.texture(),
&self.globals,
&self.data,
state.locals(),
state.bone_consts(),
&self.lights,
&self.shadows,
&self.shadow_mats,
&self.lod.alt,
&self.lod.horizon,
&self.lod,
);
}
renderer.render_post_process(
&self.postprocess.model,
&self.globals,
&self.data.globals,
&self.postprocess.locals,
);
}

View File

@ -1,9 +1,9 @@
use crate::{
mesh::{greedy::GreedyMesh, Meshable},
render::{
ColLightFmt, ColLightInfo, Consts, FluidPipeline, Globals, Instances, Light, Mesh, Model,
RenderError, Renderer, Shadow, ShadowLocals, ShadowPipeline, SpriteInstance, SpriteLocals,
SpritePipeline, TerrainLocals, TerrainPipeline, Texture,
ColLightFmt, ColLightInfo, Consts, FluidPipeline, GlobalModel, Instances, Mesh, Model,
RenderError, Renderer, ShadowPipeline, SpriteInstance, SpriteLocals, SpritePipeline,
TerrainLocals, TerrainPipeline, Texture,
},
};
@ -40,13 +40,8 @@ struct TerrainChunkData {
load_time: f32,
opaque_model: Model<TerrainPipeline>,
fluid_model: Option<Model<FluidPipeline>>,
// shadow_model: Model<ShadowPipeline>,
// col_lights: Texture<ColLightFmt>,
col_lights: guillotiere::AllocId,
sprite_instances: HashMap<
(BlockKind, usize),
Instances<SpriteInstance>, /* RawBuffer*//*(Consts<SpriteInstance>, usize) */
>,
sprite_instances: HashMap<(BlockKind, usize), Instances<SpriteInstance>>,
locals: Consts<TerrainLocals>,
visible: Visibility,
@ -386,12 +381,10 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug>(
volume: <VolGrid2d<V> as SampleVol<Aabr<i32>>>::Sample,
max_texture_size: u16,
range: Aabb<i32>,
sprite_models: &HashMap<(BlockKind, usize), Vec</* Range<u32> */ SpriteData>>,
sprite_models: &HashMap<(BlockKind, usize), Vec<SpriteData>>,
) -> MeshWorkerResponse {
let (opaque_mesh /* col_lights */, fluid_mesh, _shadow_mesh, (bounds, col_lights_info)) =
let (opaque_mesh, fluid_mesh, _shadow_mesh, (bounds, col_lights_info)) =
volume.generate_mesh((range, Vec2::new(max_texture_size, max_texture_size)));
// println!("z_bounds{:?}, bounds: {:?}", z_bounds, (bounds.min.z,
// bounds.max.z));
MeshWorkerResponse {
pos,
z_bounds: (bounds.min.z, bounds.max.z),
@ -422,23 +415,12 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug>(
let sprite_data = &sprite_models[&key][0];
let instance = SpriteInstance::new(
Mat4::identity()
/*sprite_models[&key][0].mat
/* .scaled_3d(
lod_scale
) */
/* .translated_3d(
offset
) */
// * 1.0 / 11.0
.rotated_z(f32::consts::PI * 0.25 * ori as f32)
*/
.translated_3d(sprite_data.offset)
// .scaled_3d(SPRITE_SCALE)
.rotated_z(f32::consts::PI * 0.25 * ori as f32)
.translated_3d(
(rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)) / SPRITE_SCALE,
(rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0))
/ SPRITE_SCALE,
),
// Rgb::broadcast(1.0),
cfg.wind_sway,
rel_pos,
ori,
@ -490,8 +472,7 @@ pub struct Terrain<V: RectRasterableVol> {
mesh_todo: HashMap<Vec2<i32>, ChunkMeshState>,
// GPU data
// sprite_model_data: Model<SpritePipeline>,
sprite_models: Arc<HashMap<(BlockKind, usize), Vec</* Range<u32> */ SpriteData>>>,
sprite_models: Arc<HashMap<(BlockKind, usize), Vec<SpriteData>>>,
sprite_col_lights: Texture<ColLightFmt>,
col_lights: Texture<ColLightFmt>,
waves: Texture,
@ -518,9 +499,7 @@ impl<V: RectRasterableVol> Terrain<V> {
let max_texture_size = renderer.max_texture_size();
let max_size =
guillotiere::Size::new(i32::from(max_texture_size), i32::from(max_texture_size));
// let max_sprite_size = guillotiere::Size::new(128, 64);
let mut greedy = GreedyMesh::new(max_size);
// let mut mesh = Mesh::new();
let mut locals_buffer = [SpriteLocals::default(); 8];
let mut make_models = |(kind, variation), s, offset, lod_axes: Vec3<f32>| {
let scaled = [1.0, 0.8, 0.6, 0.4, 0.2];
@ -545,10 +524,6 @@ impl<V: RectRasterableVol> Terrain<V> {
scale
}
});
/* println!(
"model_size: {:?} (model_scale = {:?})",
model_size, model_scale
); */
let wind_sway = sprite_config_for(kind).map(|c| c.wind_sway).unwrap_or(0.0);
let sprite_mat: Mat4<f32> = Mat4::translation_3d(offset).scaled_3d(SPRITE_SCALE);
(
@ -556,45 +531,44 @@ impl<V: RectRasterableVol> Terrain<V> {
scaled
.iter()
.map(|&lod_scale_orig| {
let lod_scale = model_scale * if lod_scale_orig == 1.0 {
let lod_scale = model_scale
* if lod_scale_orig == 1.0 {
Vec3::broadcast(1.0)
} else {
lod_axes * lod_scale_orig + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 })
lod_axes * lod_scale_orig
+ lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 })
};
let opaque_model =
Meshable::<SpritePipeline, &mut GreedyMesh>::generate_mesh(
Segment::from(model.as_ref()).scaled_by(lod_scale),
(&mut greedy, wind_sway >= 0.4 && lod_scale_orig == 1.0/*>= 0.8*//*lod_axes.x == 0.0 && lod_axes.y == 0.0*//* && lod_scale.z >= 0.8*//*, offset * lod_scale, Vec3::one() / lod_scale*/),
(&mut greedy, wind_sway >= 0.4 && lod_scale_orig == 1.0),
)
.0;
let sprite_scale = Vec3::one() / lod_scale;
let sprite_mat: Mat4<f32> = sprite_mat * Mat4::scaling_3d(sprite_scale);
locals_buffer.iter_mut().enumerate().for_each(|(ori, locals)| {
let sprite_mat = sprite_mat.rotated_z(f32::consts::PI * 0.25 * ori as f32);
*locals = SpriteLocals::new(sprite_mat, sprite_scale, offset, wind_sway);
locals_buffer
.iter_mut()
.enumerate()
.for_each(|(ori, locals)| {
let sprite_mat =
sprite_mat.rotated_z(f32::consts::PI * 0.25 * ori as f32);
*locals =
SpriteLocals::new(sprite_mat, sprite_scale, offset, wind_sway);
});
SpriteData {
/* scale: sprite_scale, */
offset,
/* mat: sprite_mat, */
model: renderer.create_model(&opaque_model)
.unwrap(),
locals: renderer.create_consts(&locals_buffer)
model: renderer.create_model(&opaque_model).unwrap(),
locals: renderer
.create_consts(&locals_buffer)
.expect("Failed to upload sprite locals to the GPU!"),
}
/* // NOTE: Safe because atlas size is an upper bound on vertex count, and atlas
// width and height are at most u16::MAX.
let start = mesh.vertices().len() as u32;
let vbuf = (start..start + opaque_model.vertices().len() as u32);
mesh.push_mesh(&opaque_model);
vbuf */
})
.collect::<Vec<_>>(),
)
};
let sprite_models: HashMap<(BlockKind, usize), /* Vec<Range<u32>> */ _> = vec![
let sprite_models: HashMap<(BlockKind, usize), _> = vec![
// Windows
make_models(
(BlockKind::Window1, 0),
@ -2308,11 +2282,6 @@ impl<V: RectRasterableVol> Terrain<V> {
]
.into_iter()
.collect();
/* let sprite_model_data = renderer
.create_model(&mesh)
.expect("Failed to upload sprite vertex to the GPU!"); */
// println!("{:?}, {:?}", sprite_model_data.vbuf,
// sprite_model_data.vertex_range); println!("{:?}", sprite_models);
let sprite_col_lights = ShadowPipeline::create_col_lights(renderer, greedy.finalize())
.expect("Failed to upload sprite color and light data to the GPU!");
Self {
@ -2322,23 +2291,8 @@ impl<V: RectRasterableVol> Terrain<V> {
mesh_send_tmp: send,
mesh_recv: recv,
mesh_todo: HashMap::default(),
// sprite_model_data,
sprite_models: Arc::new(sprite_models),
sprite_col_lights, /*renderer
.create_texture_immutable_raw(
gfx::texture::Kind::D2(
tex_size.x,
tex_size.y,
gfx::texture::AaMode::Single,
),
gfx::texture::Mipmap::Provided,
&[&tex],
gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Clamp,
),
)
.expect("Failed to upload sprite color and light data to the GPU!"),*/
sprite_col_lights,
waves: renderer
.create_texture(
&assets::load_expect("voxygen.texture.waves"),
@ -2358,14 +2312,12 @@ impl<V: RectRasterableVol> Terrain<V> {
let max_texture_size = renderer.max_texture_size();
let atlas_size =
guillotiere::Size::new(i32::from(max_texture_size), i32::from(max_texture_size));
// let atlas_size = guillotiere::Size::new(1, 1);
let atlas = AtlasAllocator::with_options(atlas_size, &guillotiere::AllocatorOptions {
// TODO: Verify some good empirical constants.
small_size_threshold: 128,
large_size_threshold: 1024,
..guillotiere::AllocatorOptions::default()
});
// renderer.flush();
let texture = renderer.create_texture_raw(
gfx::texture::Kind::D2(
max_texture_size,
@ -2373,8 +2325,7 @@ impl<V: RectRasterableVol> Terrain<V> {
gfx::texture::AaMode::Single,
),
1 as gfx::texture::Level,
// gfx::memory::Upload,
gfx::memory::Bind::SHADER_RESOURCE, /* | gfx::memory::Bind::TRANSFER_DST */
gfx::memory::Bind::SHADER_RESOURCE,
gfx::memory::Usage::Dynamic,
(0, 0),
gfx::format::Swizzle::new(),
@ -2383,33 +2334,10 @@ impl<V: RectRasterableVol> Terrain<V> {
gfx::texture::WrapMode::Clamp,
),
)?;
/* renderer.flush();
let ten_millis = core::time::Duration::from_millis(10);
std::thread::sleep(ten_millis);
renderer.update_texture(
&texture,
[0, 0],
[max_texture_size, max_texture_size],
&vec![[0u8; 4]; (usize::from(max_texture_size) * usize::from(max_texture_size))],
//&[[255u8; 4]; 64 * 64],
// NOTE: Cast is safe since the origin was a u16.
)?;
renderer.flush(); */
// texture.cleanup();
// Not sure if this is necessary...
// renderer.flush();
// texture.update();
// // FIXME: Currently, there seems to be a bug where the very first texture
// update always // fails. Not sure why, but we currently work around
// it with a dummy allocation (which we // proceed to leak, in case the
// bug can return after it's freed). let _ = atlas.allocate(guillotiere:
// :Size::new(64, 64));
Ok((atlas, texture))
}
fn remove_chunk_meta(&mut self, _pos: Vec2<i32>, chunk: &TerrainChunkData) {
/* println!("Terrain chunk already existed: {:?}", pos); */
self.atlas.deallocate(chunk.col_lights);
/* let (zmin, zmax) = chunk.z_bounds;
self.z_index_up.remove(Vec3::from(zmin, pos.x, pos.y));
@ -2426,15 +2354,13 @@ impl<V: RectRasterableVol> Terrain<V> {
}
fn remove_chunk(&mut self, pos: Vec2<i32>) {
// println!("Terrain chunk removed: {:?}", pos);
if let Some(chunk) = self.chunks.remove(&pos) {
self.remove_chunk_meta(pos, &chunk);
// Temporarily remember dead chunks for shadowing purposes.
self.shadow_chunks.push((pos, chunk));
}
if let Some(_todo) = self.mesh_todo.remove(&pos) {
/* println!("Terrain chunk was being meshed: {:?}",
* (todo.pos, todo.started_tick)); */
//Do nothing on todo mesh removal.
}
}
@ -2452,11 +2378,7 @@ impl<V: RectRasterableVol> Terrain<V> {
loaded_distance: f32,
view_mat: Mat4<f32>,
proj_mat: Mat4<f32>,
) -> (
Aabb<f32>,
/* Aabb<f32>, Aabb<f32> */ Vec<math::Vec3<f32>>,
math::Aabr<f32>,
) {
) -> (Aabb<f32>, Vec<math::Vec3<f32>>, math::Aabr<f32>) {
let current_tick = scene_data.tick;
let current_time = scene_data.state.get_time();
let mut visible_bounding_box: Option<Aabb<f32>> = None;
@ -2478,7 +2400,6 @@ impl<V: RectRasterableVol> Terrain<V> {
.map(|c| (false, c)),
)
{
// println!("Terrain chunk change: {:?}", (modified, pos));
// TODO: ANOTHER PROBLEM HERE!
// What happens if the block on the edge of a chunk gets modified? We need to
// spawn a mesh worker to remesh its neighbour(s) too since their
@ -2500,7 +2421,6 @@ impl<V: RectRasterableVol> Terrain<V> {
}
if neighbours {
// println!("Insert mesh_todo:: {:?}", (pos, current_tick));
self.mesh_todo.insert(pos, ChunkMeshState {
pos,
started_tick: current_tick,
@ -2521,7 +2441,6 @@ impl<V: RectRasterableVol> Terrain<V> {
.iter()
.map(|(p, _)| *p)
{
// println!("Terrain block change: {:?}", pos);
let chunk_pos = scene_data.state.terrain().pos_key(pos);
// Only mesh if this chunk has all its neighbors
let mut neighbours = true;
@ -2535,7 +2454,6 @@ impl<V: RectRasterableVol> Terrain<V> {
}
}
if neighbours {
// println!("Insert mesh_todo: {:?}", (chunk_pos, current_tick));
self.mesh_todo.insert(chunk_pos, ChunkMeshState {
pos: chunk_pos,
started_tick: current_tick,
@ -2566,8 +2484,6 @@ impl<V: RectRasterableVol> Terrain<V> {
}
}
if neighbours {
// println!("Insert mesh_todo:: {:?}", (neighbour_chunk_pos,
// current_tick));
self.mesh_todo.insert(neighbour_chunk_pos, ChunkMeshState {
pos: neighbour_chunk_pos,
started_tick: current_tick,
@ -2673,8 +2589,6 @@ impl<V: RectRasterableVol> Terrain<V> {
// data structure (convert the mesh to a model first of course).
Some(todo) if response.started_tick <= todo.started_tick => {
let started_tick = todo.started_tick;
// println!("Finished meshing worker: (pos={:?}, response={:?}, todo={:?})",
// response.pos, response.started_tick, todo.started_tick);
let load_time = self
.chunks
.get(&response.pos)
@ -2682,30 +2596,6 @@ impl<V: RectRasterableVol> Terrain<V> {
.unwrap_or(current_time as f32);
// TODO: Allocate new atlas on allocation faillure.
let (tex, tex_size) = response.col_lights_info;
/* if self.chunks.len() == 0 {
println!("{:?}\n{:?}", tex, tex_size);
/*// HACK
let (atlas_, col_lights_) = Self::make_atlas(renderer)
.expect("Failed to create atlas texture");
// renderer.flush();
let ten_millis = core::time::Duration::from_millis(1000);
std::thread::sleep(ten_millis);
if let Err(err) = renderer.update_texture(
&self.col_lights,
// &col_lights,
// NOTE: Cast is safe since the origin was a u16.
[0, 0],
[1, 1],
&[[0u8; 4]],
) {
panic!("Ahhh {:?}", err);
warn!("Failed to update texture: {:?}", err);
}
renderer.flush();
std::thread::sleep(ten_millis);
self.atlas = atlas_;
self.col_lights = col_lights_; */
} */
let atlas = &mut self.atlas;
let allocation = atlas
.allocate(guillotiere::Size::new(
@ -2713,57 +2603,13 @@ impl<V: RectRasterableVol> Terrain<V> {
i32::from(tex_size.y),
))
.expect("Not yet implemented: allocate new atlas on allocation faillure.");
// println!("Allocation {:?} for {:?} (original size = {:?}... ugh)",
// allocation, response.pos, tex_size); NOTE: Cast is safe
// since the origin was a u16.
// NOTE: Cast is safe since the origin was a u16.
let atlas_offs = Vec2::new(
allocation.rectangle.min.x as u16,
allocation.rectangle.min.y as u16,
);
if atlas_offs == Vec2::zero() {
// println!("Model: {:?}",
// &response.opaque_mesh.vertices());
// println!("Texture: {:?}", tex);
}
// let atlas_offs : Vec2<u16> = Vec2::zero();
/* let col_lights = renderer
.create_texture_immutable_raw(
gfx::texture::Kind::D2(
tex_size.x,
tex_size.y,
gfx::texture::AaMode::Single,
),
gfx::texture::Mipmap::Provided,
&[&tex],
gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Clamp,
),
)
.expect("Failed to upload terrain color and light data to the GPU!"); */
/* let col_lights = renderer
.create_texture_raw(
gfx::texture::Kind::D2(
tex_size.x,
tex_size.y,
gfx::texture::AaMode::Single,
),
1 as gfx::texture::Level,
// gfx::memory::Upload,
gfx::memory::Bind::SHADER_RESOURCE,
gfx::memory::Usage::Dynamic,
(0, 0),
gfx::format::Swizzle::new(),
gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Clamp,
),
)
.expect("Failed to upload col lights data to the GPU!"); */
if let Err(err) = renderer.update_texture(
&self.col_lights,
// &col_lights,
// NOTE: Cast is safe since the origin was a u16.
atlas_offs.into_array(),
tex_size.into_array(),
&tex,
@ -2785,27 +2631,10 @@ impl<V: RectRasterableVol> Terrain<V> {
} else {
None
},
/* shadow_model: renderer
.create_model(&response.shadow_mesh)
.expect("Failed to upload chunk mesh to the GPU!"), */
col_lights: allocation.id,/*ShadowPipeline::create_col_lights(renderer, /*response.col_lights_info*/(tex, tex_size))
.expect("Failed to upload chunk light-color texture to the GPU!"),*/
/* sprite_instances: response
.sprite_instances
.into_iter()
.map(|(kind, instances)| {
(
kind,
(renderer./*create_consts_immutable*/create_consts(&instances).expect(
"Failed to upload chunk sprite instances to the GPU!",
), instances.len()),
)
})
.collect(), */
col_lights: allocation.id,
sprite_instances: response
.sprite_instances
.into_iter()
.map(|(kind, instances)| {
(
kind,
@ -2823,7 +2652,13 @@ impl<V: RectRasterableVol> Terrain<V> {
}),
)
.into_array(),
atlas_offs: Vec4::new(i32::from(atlas_offs.x), i32::from(atlas_offs.y), 0, 0).into_array(),
atlas_offs: Vec4::new(
i32::from(atlas_offs.x),
i32::from(atlas_offs.y),
0,
0,
)
.into_array(),
load_time,
}])
.expect("Failed to upload chunk locals to the GPU!"),
@ -2835,25 +2670,17 @@ impl<V: RectRasterableVol> Terrain<V> {
});
if response.started_tick == started_tick {
// println!("Terrain chunk removed from meshing: {:?}", (response.pos,
// response.started_tick));
self.mesh_todo.remove(&response.pos);
}
},
// Chunk must have been removed, or it was spawned on an old tick. Drop the mesh
// since it's either out of date or no longer needed.
Some(_todo) => {
/* println!("Finished meshing worker: (pos={:?}, response={:?}, todo={:?})", response.pos, response.started_tick, todo.started_tick);
println!("Terrain chunk removed from meshing due to being out of date: {:?}", (response.pos, response.started_tick));
self.mesh_todo.remove(&response.pos); */
},
Some(_todo) => {},
None => {},
}
}
// Construct view frustum
let _all_mat = proj_mat * view_mat;
//.scaled_3d(Vec3::new(proj_mat[(0, 0)], proj_mat[(1, 1)], 1.0));
let focus_off = focus_pos.map(|e| e.trunc());
let frustum = Frustum::from_modelview_projection(
(proj_mat * view_mat * Mat4::translation_3d(-focus_off)).into_col_arrays(),
@ -2861,13 +2688,6 @@ impl<V: RectRasterableVol> Terrain<V> {
// Update chunk visibility
let chunk_sz = V::RECT_SIZE.x as f32;
let _scene_bounding_box: Aabb<f32> = Aabb {
min: focus_pos - 2.0, /*
* - /0.5f32 */
max: focus_pos + 2.0, /* + 0.5f32 */
};
/* let mut shadow_queue =
* std::collections::VecDeque::with_capacity(self.chunks.len()); */
for (pos, chunk) in &mut self.chunks {
let chunk_pos = pos.map(|e| e as f32 * chunk_sz);
@ -2905,22 +2725,12 @@ impl<V: RectRasterableVol> Terrain<V> {
min: Vec3::from(chunk_min),
max: Vec3::from(chunk_max),
};
// scene_bounding_box.expand_to_contain(chunk_box);
if in_frustum {
/* let visible_box = Aabb {
min: chunk_box.min - focus_off,
max: chunk_box.max - focus_off,
};
let visible_box = super::fit_psr(all_mat, visible_box, |p| Vec3::from(p) / p.w/*.clamped(-p.w.abs(), p.w.abs())*/)
.map(|e| e.clamped(-1.0, 1.0))
; */
let visible_box = chunk_box;
visible_bounding_box = visible_bounding_box
.map(|e| e.union(visible_box))
.or(Some(visible_box));
/* shadow_queue.push_back(chunk_box);
// shadow_queue.push(chunk_min + chunk_sz * 0.5); */
}
// FIXME: Hack that only works when only the lantern casts point shadows
// (and hardcodes the shadow distance). Should ideally exist per-light, too.
@ -2929,17 +2739,11 @@ impl<V: RectRasterableVol> Terrain<V> {
// PSRs: potential shadow receivers
let visible_bounding_box = visible_bounding_box.unwrap_or(Aabb {
min: focus_pos - 2.0, /*
* - 0.5 */
max: focus_pos + 2.0, /* + 0.5 */
min: focus_pos - 2.0,
max: focus_pos + 2.0,
});
// PSCs: Potential shadow casters
let _psc_bounding_box: Aabb<f32> = visible_bounding_box;
/*Aabb {
min: focus_pos - 0.5f32,
max: focus_pos + 0.5f32,
}; */
let ray_direction = scene_data.get_sun_dir();
let collides_with_aabr = |a: math::Aabr<f32>, b: math::Aabr<f32>| {
a.min.partial_cmple(&b.max).reduce_and() && a.max.partial_cmpge(&b.min).reduce_and()
@ -2956,9 +2760,8 @@ impl<V: RectRasterableVol> Terrain<V> {
min: math::Vec3::from(visible_bounding_box.min.map(f64::from)),
max: math::Vec3::from(visible_bounding_box.max.map(f64::from)),
};
let inv_proj_view = math::Mat4::from_col_arrays(
(proj_mat * view_mat/* * Mat4::translation_3d(-focus_off)*/).into_col_arrays(),
)
let inv_proj_view =
math::Mat4::from_col_arrays((proj_mat * view_mat).into_col_arrays())
.map(f64::from)
.inverted();
let ray_direction = math::Vec3::<f32>::from(ray_direction);
@ -2971,44 +2774,16 @@ impl<V: RectRasterableVol> Terrain<V> {
.map(|v| v.map(|e| e as f32))
.collect::<Vec<_>>();
let cam_pos = math::Vec4::from(view_mat.inverted() * Vec4::unit_w()).xyz()/* + focus_off*/;
/* let view_dir = (focus_pos.map(f32::fract)) - cam_pos;
// let new_dir: Vec3<f32> = light_volume/*visible_light_volume*/.iter().map(|p|
// p - cam_pos).sum();
let new_dir = view_dir;
let new_dir = new_dir.normalized();
let dot_prod = f64::from(ray_direction.dot(new_dir));
let sin_gamma = (1.0 - dot_prod * dot_prod).sqrt();
// let sin_gamma = 0.0;
let _new_dir = if sin_gamma > super::EPSILON_GAMMA {
new_dir
} else {
Vec3::from(view_mat * Vec4::from_direction(Vec3::up())).normalized()
}; */
let up: math::Vec3<f32> = {
/* (ray_direction)
.cross(new_dir)
.cross(ray_direction)
.normalized() */
math::Vec3::up()
};
let cam_pos = math::Vec4::from(view_mat.inverted() * Vec4::unit_w()).xyz();
let up: math::Vec3<f32> = { math::Vec3::up() };
let ray_mat = math::Mat4::look_at_rh(
cam_pos,
cam_pos + ray_direction,
up,
// Vec3::up(),
);
// println!("old: {:?} new: {:?}", visible_bounding_box, visible_light_volume);
let ray_mat = math::Mat4::look_at_rh(cam_pos, cam_pos + ray_direction, up);
let visible_bounds = math::Aabr::from(math::fit_psr(
ray_mat,
/* super::aabb_to_points(visible_bounding_box).iter().copied() */
visible_light_volume.iter().copied(),
|p| p, //math::Vec3::from(p), /* / p.w */
|p| p,
));
let ray_mat = ray_mat * math::Mat4::translation_3d(-focus_off);
/* let visible_bounds_old = Aabr::from(super::fit_psr(ray_mat, super::aabb_to_points(visible_bounding_box).iter().copied(), |p| Vec3::from(p) / p.w));
println!("old: {:?} new: {:?}", visible_bounds_old, visible_bounds); */
let can_shadow_sun = |pos: Vec2<i32>, chunk: &TerrainChunkData| {
let chunk_pos = pos.map(|e| e as f32 * chunk_sz);
@ -3026,20 +2801,9 @@ impl<V: RectRasterableVol> Terrain<V> {
let chunk_from_light = math::Aabr::from(math::fit_psr(
ray_mat,
math::aabb_to_points(chunk_box).iter().copied(),
|p| p, /* math::Vec3::from(p)/* / p.w*/ */
|p| p,
));
/* let chunk_from_light = Aabr {
min: (ray_mat * Vec4::from_point(chunk_box.min)).xy(),
max: (ray_mat * Vec4::from_point(chunk_box.max)).xy(),
}.made_valid(); */
/* let can_shadow_sun = */
collides_with_aabr(chunk_from_light, visible_bounds)
/* let can_shadow_sun_old = collides_with_aabr(chunk_from_light, visible_bounds_old);
if can_shadow_sun != can_shadow_sun_old {
println!("Different results for chunk {:?} (from light = {:?}):\n\
old = {:?} new = {:?}",
chunk_box, chunk_from_light, can_shadow_sun_old, can_shadow_sun);
} */
};
// Handle potential shadow casters (chunks that aren't visible, but are still in
@ -3078,63 +2842,8 @@ impl<V: RectRasterableVol> Terrain<V> {
max: math::Vec2::zero(),
})
};
/* let cam_pos = Vec3::from(view_mat.inverted() * Vec4::unit_w()) + focus_off; let look_at = visible_box.center();
let view_dir = (focus_pos - cam_pos).normalized();
let up_vec = ray_direction.cross(view_dir).cross(light_dir).normalized();
let sun_light_mat = Mat4::look_at_rh(look_at - ray_direction, look_at, view_dir);
let sun_bounding_box = super::fit_psr(all_mat, visible_box, |p| Vec3::from(p) / p.w/*.clamped(-p.w.abs(), p.w.abs())*/)
Aabb {
min: -0.5,
max: 0.5,
}; */
/* if ray_direction.z < 0.0 && renderer.render_mode().shadow.is_map() {
let ray = if ray_direction.x.abs() * scene_bounding_box.size().d > ray_direction.z.abs() * chunk_sz {
-ray_direction / ray_direction.x * chunk_sz
} else {
/* -ray_direction / ray_direction.z * scene_bounding_box.size().d */
Vec3::new(0.0, 0.0, scene_bounding_box.size().d)
};
while let Some(shadow_chunk) = shadow_queue.pop_front() {
let collides_with_aabb = |a: Aabb<f32>, b: Aabb<f32>|
a.min.partial_cmple(&b.max).reduce_and() &&
a.max.partial_cmpge(&b.min).reduce_and();
if !collides_with_aabb(scene_bounding_box, shadow_chunk) {
continue;
}
let min_chunk_pos = Vec2::from(shadow_chunk.min.map(|e| (e / chunk_sz).floor()))
.map(|e: f32| e as i32);
let max_chunk_pos = Vec2::from(shadow_chunk.max.map(|e| (e / chunk_sz).ceil()))
.map(|e: f32| e as i32);
let mut check_chunk = |x, y| {
if let Some(mut chunk) = self.chunks.get_mut(&Vec2::new(x, y)) {
let (minz, maxz) = chunk.z_bounds;
if minz <= shadow_chunk.max.z && maxz >= shadow_chunk.min.z {
chunk.can_shadow_sun = true;
// NOTE: These casts are safe because the maximum chunk index we are
// currently considering is 16384.
let x = x as f32;
let y = y as f32;
psc_bounding_box.expand_to_contain(shadow_chunk.intersection(Aabb {
min: Vec3::new(x * chunk_sz, y * chunk_sz, minz),
max: Vec3::new((x + 1.0) * chunk_sz, (y + 1.0) * chunk_sz, maxz),
}));
}
}
};
(min_chunk_pos.y..max_chunk_pos.y).for_each(|y| {
(min_chunk_pos.x..max_chunk_pos.x).for_each(|x| {
check_chunk(x, y);
})
});
shadow_queue.push_back(Aabb {
min: shadow_chunk.min + ray,
max: shadow_chunk.max + ray,
});
}
} */
(
/* scene_bounding_box, visible_bounding_box, psc_bounding_box */
visible_bounding_box,
visible_light_volume,
visible_psr_bounds,
@ -3155,11 +2864,8 @@ impl<V: RectRasterableVol> Terrain<V> {
pub fn render_shadows(
&self,
renderer: &mut Renderer,
globals: &Consts<Globals>,
// lights: &Consts<Light>,
shadow_mats: &Consts<ShadowLocals>,
light_data: &[Light],
is_daylight: bool,
global: &GlobalModel,
(is_daylight, light_data): super::LightData,
focus_pos: Vec3<f32>,
) {
if !renderer.render_mode().shadow.is_map() {
@ -3177,8 +2883,6 @@ impl<V: RectRasterableVol> Terrain<V> {
})
.take(self.chunks.len());
// let is_daylight = sun_dir.z < 0.0/*0.6*/;
// Directed shadows
//
// NOTE: We also render shadows for dead chunks that were found to still be
@ -3192,15 +2896,10 @@ impl<V: RectRasterableVol> Terrain<V> {
.for_each(|chunk| {
// Directed light shadows.
renderer.render_terrain_shadow_directed(
// &chunk.shadow_model,
&chunk.opaque_model,
globals,
global,
&chunk.locals,
shadow_mats,
/* lights, */
/* shadows,
* &lod.alt,
* &lod.horizon, */
&global.shadow_mats,
);
});
}
@ -3212,17 +2911,11 @@ impl<V: RectRasterableVol> Terrain<V> {
light_data.iter().take(1).for_each(|_light| {
chunk_iter.clone().for_each(|chunk| {
if chunk.can_shadow_point {
// shadow_vertex_count += chunk.shadow_model.vertex_range.len();
renderer.render_shadow_point(
&chunk.opaque_model,
// &chunk.shadow_model,
globals,
global,
&chunk.locals,
shadow_mats,
/* lights, */
/* shadows,
* &lod.alt,
* &lod.horizon, */
&global.shadow_mats,
);
}
});
@ -3232,14 +2925,9 @@ impl<V: RectRasterableVol> Terrain<V> {
pub fn render(
&self,
renderer: &mut Renderer,
globals: &Consts<Globals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
shadow_mats: &Consts<ShadowLocals>,
global: &GlobalModel,
lod: &LodData,
focus_pos: Vec3<f32>,
/* sun_dir: Vec3<f32>,
* light_data: &[Light], */
) {
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
(e as i32).div_euclid(sz as i32)
@ -3252,105 +2940,23 @@ impl<V: RectRasterableVol> Terrain<V> {
})
.take(self.chunks.len());
// // Flush renderer to synchronize commands sent on the main encoder with the
// // start of the shadow encoder.
// renderer.flush();
// Shadows
/*scene_data.thread_pool.execute(move || {
let _ = send.send(mesh_worker(
pos,
(min_z as f32, max_z as f32),
started_tick,
volume,
max_texture_size,
aabb,
));
});*/
// let mut shadow_vertex_count = 0;
/* let is_daylight = sun_dir.z < 0.0/*0.6*/;
// Directed shadows
for (_, chunk) in chunk_iter.clone() {
if is_daylight {
// Directed light shadows.
renderer.render_shadow_directed(
// &chunk.shadow_model,
&chunk.opaque_model,
globals,
&chunk.locals,
shadow_mats,
// lights,
// shadows,
// &lod.alt,
// &lod.horizon,
);
}
}
// Point shadows
for _light in light_data.iter().take(1) {
for (_, chunk) in chunk_iter.clone() {
if chunk.can_shadow_point {
// shadow_vertex_count += chunk.shadow_model.vertex_range.len();
renderer.render_shadow_point(
&chunk.opaque_model,
// &chunk.shadow_model,
globals,
&chunk.locals,
shadow_mats,
// lights,
// shadows,
// &lod.alt,
// &lod.horizon,
);
}
}
}
// Flush shadows.
if is_daylight || light_data.len() > 0 {
renderer.flush_shadows();
} */
// Terrain
// let mut terrain_vertex_count = 0;
for (_, chunk) in chunk_iter {
// terrain_vertex_count += chunk.opaque_model.vertex_range.len();
if chunk.visible == Visibility::Visible
/* || chunk.can_shadow_sun() */
{
if chunk.visible == Visibility::Visible {
renderer.render_terrain_chunk(
&chunk.opaque_model,
// &chunk.shadow_model,
// &chunk.col_lights,
&self.col_lights,
globals,
global,
&chunk.locals,
lights,
shadows,
shadow_mats,
&lod.alt,
&lod.horizon,
lod,
);
}
}
/* println!(
"Vertex count (shadow / terrain / ratio): {:?} / {:?} / {:?}",
shadow_vertex_count,
terrain_vertex_count,
shadow_vertex_count as f64 / terrain_vertex_count as f64
); */
}
pub fn render_translucent(
&self,
renderer: &mut Renderer,
globals: &Consts<Globals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
shadow_mats: &Consts<ShadowLocals>,
global: &GlobalModel,
lod: &LodData,
focus_pos: Vec3<f32>,
cam_pos: Vec3<f32>,
@ -3394,10 +3000,13 @@ impl<V: RectRasterableVol> Terrain<V> {
chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5,
));
if focus_dist_sqrd < sprite_render_distance.powf(2.0) {
for (kind, /*(instances, instance_count)*/instances) in (&chunk.sprite_instances).into_iter()/*.take(1)*/ {
let SpriteData { model, locals, .. } =
if sprite_config_for(kind.0).map(|config| config.wind_sway >= 0.4).unwrap_or(false) && dist_sqrd <= chunk_mag
|| dist_sqrd < sprite_high_detail_distance.powf(2.0) {
for (kind, instances) in (&chunk.sprite_instances).into_iter() {
let SpriteData { model, locals, .. } = if sprite_config_for(kind.0)
.map(|config| config.wind_sway >= 0.4)
.unwrap_or(false)
&& dist_sqrd <= chunk_mag
|| dist_sqrd < sprite_high_detail_distance.powf(2.0)
{
&self.sprite_models[&kind][0]
} else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) {
&self.sprite_models[&kind][1]
@ -3409,34 +3018,13 @@ impl<V: RectRasterableVol> Terrain<V> {
&self.sprite_models[&kind][4]
};
renderer.render_sprites(
/*Model {
vbuf: self.sprite_model_data.vbuf.clone(),
vertex_range: /*self.sprite_model_data.vertex_range()*/*/
/* if sprite_config_for(kind.0).map(|config| config.wind_sway >= 0.4).unwrap_or(false) && dist_sqrd <= chunk_mag
|| dist_sqrd < sprite_high_detail_distance.powf(2.0) {
&self.sprite_models[&kind][0].model
} else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) {
&self.sprite_models[&kind][1].model
} else if dist_sqrd < sprite_mid_detail_distance.powf(2.0) {
&self.sprite_models[&kind][2].model
} else if dist_sqrd < sprite_low_detail_distance.powf(2.0) {
&self.sprite_models[&kind][3].model
} else {
&self.sprite_models[&kind][4].model
}/*.clone(),
}*/,*/
model,
&self.sprite_col_lights,
globals,
global,
&chunk.locals,
locals,
// *instance_count,
&instances,
lights,
shadows,
shadow_mats,
&lod.alt,
&lod.horizon,
lod,
);
}
}
@ -3459,13 +3047,9 @@ impl<V: RectRasterableVol> Terrain<V> {
.for_each(|(model, locals)| {
renderer.render_fluid_chunk(
model,
globals,
global,
locals,
lights,
shadows,
shadow_mats,
&lod.alt,
&lod.horizon,
lod,
&self.waves,
)
});