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

View File

@ -157,7 +157,7 @@ impl MapSizeLg {
#[inline(always)] #[inline(always)]
pub const fn new(map_size_lg: Vec2<u32>) -> Result<Self, ()> { pub const fn new(map_size_lg: Vec2<u32>) -> Result<Self, ()> {
// Assertion on dimensions: must be between // 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 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; && map_size_lg.y <= MAX_WORLD_BLOCKS_LG.y - TERRAIN_CHUNK_BLOCKS_LG;
// Assertion on dimensions: chunks must fit in a u16. // 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); let i_a = Rgb::new(0.1, 0.1, 0.1);
// V = direction pointing towards the viewer (e.g. virtual camera). // 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, 0.0, -1.0).normalized();
// let v = Vec3::new(0.0, -1.0, 0.0).normalized();
//
// for each light m, // for each light m,
// i_m,d = (RGB) intensity of diffuse component of light source 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); let i_m_d = Rgb::new(1.0, 1.0, 1.0);
// i_m,s = (RGB) intensity of specular component of light source m // 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);
// let i_m_s = Rgb::new(0.45, 0.45, 0.45);
// for each light m and point p, // for each light m and point p,
// L_m = (normalized) direction vector from point on surface to light source m // 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::*, bezier::repr_c::*, geom::repr_c::*, mat::repr_c::column_major::Mat4, ops::*,
quaternion::repr_c::*, transform::repr_c::*, transition::*, vec::repr_c::*, 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 TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex;
type TodoRect = (
Vec3<i32>,
Vec2<Vec3<u16>>,
guillotiere::Rectangle,
Vec3<i32>,
);
/// `max_size`: /// `max_size`:
/// ///
/// `draw_delta`: /// `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)>, 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), 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.atlas,
&mut self.col_lights_size, &mut self.col_lights_size,
self.max_size, self.max_size,
@ -183,7 +190,10 @@ impl<'a> GreedyMesh<'a> {
/// Returns the ColLightsInfo corresponding to the consstructed atlas. /// Returns the ColLightsInfo corresponding to the consstructed atlas.
pub fn finalize(self) -> ColLightInfo { pub fn finalize(self) -> ColLightInfo {
let cur_size = self.col_lights_size; 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); let mut col_lights_info = (col_lights, cur_size);
self.suspended.into_iter().for_each(|cont| { self.suspended.into_iter().for_each(|cont| {
cont(&mut col_lights_info); 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 should_draw,
mut push_quad, mut push_quad,
}: GreedyConfig<D, FL, FC, FO, FS, FP>, }: GreedyConfig<D, FL, FC, FO, FS, FP>,
) -> ( ) -> (Aabb<u16>, Box<SuspendedMesh<'a>>)
Aabb<u16>,
// Mesh<O>,
// Mesh<S>,
Box<SuspendedMesh<'a>>,
)
where where
FL: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a, FL: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
FC: for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + '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)>, 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), 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. // TODO: Collect information to see if we can choose a good value here.
let mut todo_rects = Vec::with_capacity(1024); 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) // x (u = y, v = z)
greedy_mesh_cross_section( greedy_mesh_cross_section(
Vec3::new(greedy_size.y, greedy_size.z, greedy_size_cross.x), Vec3::new(greedy_size.y, greedy_size.z, greedy_size_cross.x),
@ -247,7 +237,7 @@ where
should_draw( should_draw(
&mut data, &mut data,
draw_delta + Vec3::new(pos.z, pos.x, pos.y), 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()), Vec2::new(Vec3::unit_y(), Vec3::unit_z()),
) )
}, },
@ -255,7 +245,6 @@ where
let pos = Vec3::new(pos.z, pos.x, pos.y); let pos = Vec3::new(pos.z, pos.x, pos.y);
let uv = Vec2::new(Vec3::unit_y(), Vec3::unit_z()); let uv = Vec2::new(Vec3::unit_y(), Vec3::unit_z());
let norm = Vec3::unit_x(); 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( let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
atlas, atlas,
&mut todo_rects, &mut todo_rects,
@ -267,29 +256,18 @@ where
max_size, max_size,
col_lights_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 atlas_pos
} else { } else {
return; return;
}; };
create_quad_greedy( create_quad_greedy(
// &mut shadow_mesh,
// &mut opaque_mesh,
/* Vec3::new(pos.z, pos.x, pos.y) */
pos, pos,
dim, dim,
uv, uv,
norm, norm,
faces_forward, faces_forward,
// Rgba::from_opaque(flat_get(pos).color),
// lightm
// ao,
meta, meta,
atlas_pos, 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| { |atlas_pos, dim, pos, draw_dim, norm, meta| {
push_quad(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 pos = Vec3::new(pos.y, pos.z, pos.x);
let uv = Vec2::new(Vec3::unit_z(), Vec3::unit_x()); let uv = Vec2::new(Vec3::unit_z(), Vec3::unit_x());
let norm = Vec3::unit_y(); 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( let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
atlas, atlas,
&mut todo_rects, &mut todo_rects,
@ -329,18 +306,13 @@ where
return; return;
}; };
create_quad_greedy( create_quad_greedy(
// &mut shadow_mesh,
// &mut opaque_mesh,
pos, pos,
dim, dim,
uv, uv,
norm, norm,
faces_forward, faces_forward,
// Rgba::from_opaque(flat_get(pos).color),
meta, meta,
atlas_pos, 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| { |atlas_pos, dim, pos, draw_dim, norm, meta| {
push_quad(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( greedy_mesh_cross_section(
Vec3::new(greedy_size.x, greedy_size.y, greedy_size_cross.z), Vec3::new(greedy_size.x, greedy_size.y, greedy_size_cross.z),
|pos| { |pos| {
/* if pos.z == 0 { should_draw(
let pos = pos.map(|e| e as i32) + draw_delta; // - delta; &mut data,
let to = flat_get(pos).is_opaque(); //map(|v| v.is_opaque()).unwrap_or(false); draw_delta + Vec3::new(pos.x, pos.y, pos.z),
if to { Some(false) } else { None } Vec3::unit_z(),
} else */ Vec2::new(Vec3::unit_x(), Vec3::unit_y()),
{ )
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)| { |pos, dim, &(faces_forward, ref meta)| {
let pos = Vec3::new(pos.x, pos.y, pos.z); let pos = Vec3::new(pos.x, pos.y, pos.z);
let uv = Vec2::new(Vec3::unit_x(), Vec3::unit_y()); let uv = Vec2::new(Vec3::unit_x(), Vec3::unit_y());
let norm = Vec3::unit_z(); 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( let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
atlas, atlas,
&mut todo_rects, &mut todo_rects,
@ -387,18 +351,13 @@ where
return; return;
}; };
create_quad_greedy( create_quad_greedy(
// &mut shadow_mesh,
// &mut opaque_mesh,
pos, pos,
dim, dim,
uv, uv,
norm, norm,
faces_forward, faces_forward,
// Rgba::from_opaque(flat_get(pos).color),
meta, meta,
atlas_pos, 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| { |atlas_pos, dim, pos, draw_dim, norm, meta| {
push_quad(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 { let bounds = Aabb {
min: Vec3::zero(), min: Vec3::zero(),
// NOTE: Safe because greedy_size fit in u16. // NOTE: Safe because greedy_size fit in u16.
@ -416,7 +372,6 @@ where
}; };
( (
bounds, bounds,
/* opaque_mesh, *//*shadow_mesh, */
Box::new(move |col_lights_info| { Box::new(move |col_lights_info| {
let mut data = data; let mut data = data;
draw_col_lights( draw_col_lights(
@ -435,7 +390,6 @@ where
// Greedy meshing a single cross-section. // Greedy meshing a single cross-section.
fn greedy_mesh_cross_section<M: PartialEq>( fn greedy_mesh_cross_section<M: PartialEq>(
/* mask: &mut [bool], */
dims: Vec3<usize>, dims: Vec3<usize>,
// Should we draw a face here (below this vertex)? If so, provide its meta information. // Should we draw a face here (below this vertex)? If so, provide its meta information.
mut draw_face: impl FnMut(Vec3<i32>) -> Option<M>, mut draw_face: impl FnMut(Vec3<i32>) -> Option<M>,
@ -477,7 +431,7 @@ fn greedy_mesh_cross_section<M: PartialEq>(
.count(); .count();
let max_y = j + height; let max_y = j + height;
// Add quad. // 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. // Unset mask bits in drawn region, so we don't try to re-draw them.
(j..max_y).for_each(|l| { (j..max_y).for_each(|l| {
mask[l * dims.x + i..l * dims.x + max_x] 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( fn add_to_atlas(
atlas: &mut guillotiere::SimpleAtlasAllocator, atlas: &mut guillotiere::SimpleAtlasAllocator,
todo_rects: &mut Vec<( todo_rects: &mut Vec<TodoRect>,
Vec3<i32>,
Vec2<Vec3<u16>>,
guillotiere::Rectangle,
Vec3<i32>,
)>,
pos: Vec3<usize>, pos: Vec3<usize>,
uv: Vec2<Vec3<u16>>, uv: Vec2<Vec3<u16>>,
dim: Vec2<usize>, dim: Vec2<usize>,
@ -542,7 +491,6 @@ fn add_to_atlas(
(max texture size={:?}, so we are discarding this rectangle.", (max texture size={:?}, so we are discarding this rectangle.",
pos, dim, max_size pos, dim, max_size
); );
// return None;
} }
// Otherwise, we haven't reached max size yet, so double the size (or reach the // Otherwise, we haven't reached max size yet, so double the size (or reach the
// max texture size) and try again. // max texture size) and try again.
@ -551,7 +499,6 @@ fn add_to_atlas(
max_size.height.min(current_size.height.saturating_mul(2)), max_size.height.min(current_size.height.saturating_mul(2)),
); );
atlas.grow(new_size); 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 // 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 // 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), 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 // 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 // coordinates in this chunk must fit in an i32 (actually we have the much
// stronger property that this holds across the whole map). // stronger property that this holds across the whole map).
@ -591,46 +530,28 @@ fn add_to_atlas(
fn draw_col_lights<D>( fn draw_col_lights<D>(
(col_lights, cur_size): &mut ColLightInfo, (col_lights, cur_size): &mut ColLightInfo,
data: &mut D, data: &mut D,
todo_rects: Vec<( todo_rects: Vec<TodoRect>,
Vec3<i32>,
Vec2<Vec3<u16>>,
guillotiere::Rectangle,
Vec3<i32>,
)>,
draw_delta: Vec3<i32>, draw_delta: Vec3<i32>,
mut get_light: impl FnMut(&mut D, Vec3<i32>) -> f32, mut get_light: impl FnMut(&mut D, Vec3<i32>) -> f32,
mut get_color: impl FnMut(&mut D, Vec3<i32>) -> Rgb<u8>, mut get_color: impl FnMut(&mut D, Vec3<i32>) -> Rgb<u8>,
mut get_opacity: impl FnMut(&mut D, Vec3<i32>) -> bool, 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, 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() { todo_rects.into_iter().for_each(|(pos, uv, rect, delta)| {
for j in 0..todo_rects.len() { // NOTE: Conversions are safe because width, height, and offset must be
if i == j { // non-negative, and because every allocated coordinate in the atlas must be in
continue; // bounds for the original size, max_texture_size, which fit into a u16.
} let width = (rect.max.x - rect.min.x) as u16;
let height = (rect.max.y - rect.min.y) as u16;
assert!(!todo_rects[i].2.intersects(&todo_rects[j].2)); let left = rect.min.x as u16;
} let top = rect.min.y as u16;
} */ let uv = uv.map(|e| e.map(i32::from));
todo_rects let pos = pos + draw_delta;
.into_iter() (0..height).for_each(|v| {
// .rev() let start = usize::from(cur_size.x) * usize::from(top + v) + usize::from(left);
.for_each(|(pos, uv, rect, delta)| { (0..width)
// NOTE: Conversions are safe because width, height, and offset must be .zip(&mut col_lights[start..start + usize::from(width)])
// non-negative, and because every allocated coordinate in the atlas must be in .for_each(|(u, col_light)| {
// 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 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;
(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)| {
let pos = pos + uv.x * i32::from(u) + uv.y * i32::from(v); 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 // 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 // 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 // direct_opacity, and indirect_uv_opacity is multiplied by
// the maximum of both of u and v's indirect opacities (since there are // the maximum of both of u and v's indirect opacities (since there are
// two choices for how to get to the direct surface). // two choices for how to get to the direct surface).
let pos = pos + let pos = pos
if u + 1 == width { -uv.x } else { Vec3::zero() } + + if u + 1 == width { -uv.x } else { Vec3::zero() }
if v + 1 == height { -uv.y } else { Vec3::zero() }; + if v + 1 == height { -uv.y } else { Vec3::zero() };
let uv = Vec2::new( let uv = Vec2::new(
if u + 1 == width { -uv.x } else { uv.x }, if u + 1 == width { -uv.x } else { uv.x },
if v + 1 == height { -uv.y } else { uv.y }, if v + 1 == height { -uv.y } else { uv.y },
); );
let light_pos = pos + /*range.min + */delta; let light_pos = pos + delta;
// let block = flat_get(pos);
// Currently, we assume that direct_opacity is 1 (if it's 0, you can't see // 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). // 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. // 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 // bottom-left block
let direct_u_opacity = get_opacity(data, light_pos - uv.x); let direct_u_opacity = get_opacity(data, light_pos - uv.x);
// top-right block // top-right block
let direct_v_opacity = get_opacity(data, light_pos - uv.y); 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 // 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 // direct_opacity is 1, and the light value will be zero anyway for objects
@ -680,24 +591,26 @@ fn draw_col_lights<D>(
// Light from the bottom-right-front block to this vertex always // 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 // appears on this face, since it's the block this face is facing (so
// it can't be blocked by anything). // 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 } + get_light(data, light_pos)
if /*direct_opacity || direct_uv_opacity*/true/* || !flat_get(pos - uv.y).is_opaque()*/ { get_light(data, light_pos - uv.x) } else { 0.0 } + + get_light(data, light_pos - uv.x)
if /*direct_opacity || direct_uv_opacity*/true/* || !flat_get(pos - uv.x).is_opaque()*/ { get_light(data, light_pos - uv.y) } else { 0.0 } + + get_light(data, light_pos - uv.y)
if direct_u_opacity || direct_v_opacity/* || !block.is_opaque()*/ { get_light(data, light_pos - uv.x - uv.y) } else { 0.0 } + if direct_u_opacity || direct_v_opacity {
get_light(data, light_pos - uv.x - uv.y)
} else {
0.0
}
) / 4.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; let light = (darkness * 255.0) as u8;
*col_light = make_col_light(light, col); *col_light = make_col_light(light, col);
}); });
});
}); });
});
} }
/// Precondition: when this function is called, atlas_pos should reflect an /// 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). /// 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>( fn create_quad_greedy<M>(
// shadow_mesh: &mut Mesh<S>,
// opaque_mesh: &mut Mesh<O>,
origin: Vec3<usize>, origin: Vec3<usize>,
dim: Vec2<usize>, dim: Vec2<usize>,
uv: Vec2<Vec3<u16>>, uv: Vec2<Vec3<u16>>,
@ -705,26 +618,16 @@ fn create_quad_greedy</* S: render::Pipeline, *//*O: render::Pipeline, */ M>(
faces_forward: bool, faces_forward: bool,
meta: &M, meta: &M,
atlas_pos: guillotiere::Rectangle, 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), 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); 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 // NOTE: Conversion to f32 safe by function precondition (u16 can losslessly
// cast to f32, and dim fits in a u16). // 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 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 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 { 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) (draw_dim, dim, norm)
} else { } 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(draw_dim.y, draw_dim.x),
Vec2::new(dim.y, 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 norm = norm.map(f32::from);
// let draw_dim = draw_dim.map(|e| e.map(f32::from));
// NOTE: Conversion to u16 safe by function precondition. // 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); 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); push_quad(atlas_pos, dim, origin, draw_dim, norm, meta);
} }
@ -769,9 +659,5 @@ pub fn create_quad<O: render::Pipeline, M>(
meta, meta,
), ),
create_vertex(atlas_pos + dim.y, origin + draw_dim.y, norm, 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}; 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> { pub trait Meshable<P: render::Pipeline, T> {
type Pipeline: render::Pipeline; type Pipeline: render::Pipeline;
type TranslucentPipeline: render::Pipeline; type TranslucentPipeline: render::Pipeline;
@ -12,13 +19,5 @@ pub trait Meshable<P: render::Pipeline, T> {
type Result; type Result;
// Generate meshes - one opaque, one translucent, one shadow // Generate meshes - one opaque, one translucent, one shadow
fn generate_mesh( fn generate_mesh(self, supp: Self::Supplement) -> MeshGen<P, T, Self>;
self,
supp: Self::Supplement,
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
Self::Result,
);
} }

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
mesh::{ mesh::{
greedy::{self, GreedyConfig, GreedyMesh}, greedy::{self, GreedyConfig, GreedyMesh},
Meshable, MeshGen, Meshable,
}, },
render::{self, FigurePipeline, Mesh, ShadowPipeline, SpritePipeline, TerrainPipeline}, render::{self, FigurePipeline, Mesh, ShadowPipeline, SpritePipeline, TerrainPipeline},
}; };
@ -32,12 +32,7 @@ where
fn generate_mesh( fn generate_mesh(
self, self,
(greedy, offs, scale): Self::Supplement, (greedy, offs, scale): Self::Supplement,
) -> ( ) -> MeshGen<FigurePipeline, &'b mut GreedyMesh<'a>, Self> {
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
Self::Result,
) {
let max_size = greedy.max_size(); let max_size = greedy.max_size();
// NOTE: Required because we steal two bits from the normal in the shadow uint // 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 // 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 where
V: BaseVol<Vox = Cell> + ReadVol + SizedVol, V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
/* TODO: Use VolIterator instead of manually iterating /* TODO: Use VolIterator instead of manually iterating
@ -132,12 +127,7 @@ where
fn generate_mesh( fn generate_mesh(
self, self,
(greedy, vertical_stripes): Self::Supplement, (greedy, vertical_stripes): Self::Supplement,
) -> ( ) -> MeshGen<SpritePipeline, &'b mut GreedyMesh<'a>, Self> {
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
(),
) {
let max_size = greedy.max_size(); let max_size = greedy.max_size();
// NOTE: Required because we steal two bits from the normal in the shadow uint // 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 // 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()) 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_opaque =
// let create_shadow = |pos, norm, _meta| ShadowVertex::new_figure((pos + offs) |atlas_pos, pos: Vec3<f32>, norm, _meta| SpriteVertex::new(atlas_pos, pos, norm);
// * 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 mut opaque_mesh = Mesh::new(); let mut opaque_mesh = Mesh::new();
let _bounds = greedy.push(GreedyConfig { let _bounds = greedy.push(GreedyConfig {
@ -224,10 +207,8 @@ fn should_draw_greedy(
_uv: Vec2<Vec3<i32>>, _uv: Vec2<Vec3<i32>>,
flat_get: impl Fn(Vec3<i32>) -> Cell, flat_get: impl Fn(Vec3<i32>) -> Cell,
) -> Option<(bool, /* u8 */ ())> { ) -> Option<(bool, /* u8 */ ())> {
// TODO: Verify conversion. let from = flat_get(pos - delta);
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta; let to = flat_get(pos);
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_opaque = !from.is_empty(); let from_opaque = !from.is_empty();
if from_opaque == !to.is_empty() { if from_opaque == !to.is_empty() {
None None
@ -244,52 +225,17 @@ fn should_draw_greedy_ao(
delta: Vec3<i32>, delta: Vec3<i32>,
_uv: Vec2<Vec3<i32>>, _uv: Vec2<Vec3<i32>>,
flat_get: impl Fn(Vec3<i32>) -> Cell, flat_get: impl Fn(Vec3<i32>) -> Cell,
) -> Option<(bool, /* u8 */ bool)> { ) -> Option<(bool, bool)> {
// TODO: Verify conversion. let from = flat_get(pos - delta);
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta; let to = flat_get(pos);
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_opaque = !from.is_empty(); let from_opaque = !from.is_empty();
if from_opaque == !to.is_empty() { if from_opaque == !to.is_empty() {
None None
} else { } else {
let faces_forward = from_opaque; let faces_forward = from_opaque;
let ao = /* if delta.z != 0 { let ao = !vertical_stripes || (pos.z & 1) != 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);
// If going from transparent to opaque, backward facing; otherwise, forward // If going from transparent to opaque, backward facing; otherwise, forward
// facing. // facing.
Some((faces_forward, ao)) Some((faces_forward, ao))
// Some((faces_forward, ()))
} }
} }

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
mesh::{ mesh::{
greedy::{self, GreedyConfig, GreedyMesh}, greedy::{self, GreedyConfig, GreedyMesh},
Meshable, MeshGen, Meshable,
}, },
render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline}, render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline},
}; };
@ -230,12 +230,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
fn generate_mesh( fn generate_mesh(
self, self,
(range, max_texture_size): Self::Supplement, (range, max_texture_size): Self::Supplement,
) -> ( ) -> MeshGen<TerrainPipeline, FluidPipeline, Self> {
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
Self::Result,
) {
let mut light = calc_light(range, self); let mut light = calc_light(range, self);
let mut lowest_opaque = range.size().d; let mut lowest_opaque = range.size().d;
@ -315,180 +310,6 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
} }
.min(range.size().d - 1); .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 = let max_size =
guillotiere::Size::new(i32::from(max_texture_size.x), i32::from(max_texture_size.y)); guillotiere::Size::new(i32::from(max_texture_size.x), i32::from(max_texture_size.y));
let greedy_size = Vec3::new( let greedy_size = Vec3::new(
@ -508,8 +329,6 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
should_draw_greedy(pos, delta, flat_get) should_draw_greedy(pos, delta, flat_get)
}; };
// NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16. // 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 mesh_delta = Vec3::new(0.0, 0.0, (z_start + range.min.z) as f32);
let create_opaque = |atlas_pos, pos, norm, meta| { let create_opaque = |atlas_pos, pos, norm, meta| {
TerrainVertex::new(atlas_pos, pos + mesh_delta, 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, max: bounds.max + mesh_delta,
}; };
let (col_lights, col_lights_size) = greedy.finalize(); let (col_lights, col_lights_size) = greedy.finalize();
// println!("z_bounds{:?}, bounds: {:?}", (mesh_delta.z, mesh_delta.z +
( (
opaque_mesh, opaque_mesh,
@ -576,10 +394,8 @@ fn should_draw_greedy(
delta: Vec3<i32>, delta: Vec3<i32>,
flat_get: impl Fn(Vec3<i32>) -> Block, flat_get: impl Fn(Vec3<i32>) -> Block,
) -> Option<(bool, FaceKind)> { ) -> Option<(bool, FaceKind)> {
// TODO: Verify conversion. let from = flat_get(pos - delta);
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta; let to = flat_get(pos);
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_opaque = from.is_opaque(); let from_opaque = from.is_opaque();
if from_opaque == to.is_opaque() { if from_opaque == to.is_opaque() {
// Check the interface of fluid and non-tangible non-fluids (e.g. air). // 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. /// Update the GPU-side value represented by this constant handle.
pub fn update( 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. /// A `Vec`-based mesh structure used to store mesh data on the CPU.
pub struct Mesh<P: Pipeline> { pub struct Mesh<P: Pipeline> {
verts: Vec<P::Vertex>, verts: Vec<P::Vertex>,
// textures: Vec<>
} }
impl<P: Pipeline> Clone for Mesh<P> impl<P: Pipeline> Clone for Mesh<P>

View File

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

View File

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

View File

@ -11,7 +11,6 @@ use vek::*;
gfx_defines! { gfx_defines! {
vertex Vertex { vertex Vertex {
pos_norm: u32 = "v_pos_norm", pos_norm: u32 = "v_pos_norm",
// col_light: u32 = "v_col_light",
} }
pipeline pipe { pipeline pipe {
@ -41,31 +40,6 @@ gfx_defines! {
} }
impl Vertex { 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::identity_op)] // TODO: Pending review in #587
#[allow(clippy::into_iter_on_ref)] // 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 { pub fn new(pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
@ -85,12 +59,6 @@ impl Vertex {
| ((pos.y as u32) & 0x003F) << 6 | ((pos.y as u32) & 0x003F) << 6
| (((pos.z + EXTRA_NEG_Z).max(0.0).min((1 << 17) as f32) as u32) & 0x1FFFF) << 12 | (((pos.z + EXTRA_NEG_Z).max(0.0).min((1 << 17) as f32) as u32) & 0x1FFFF) << 12
| (norm_bits & 0x7) << 29, | (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::{ use super::{
super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt}, super::{
LodAltFmt, LodColorFmt, LodTextureFmt, Pipeline, Renderer, Texture, TgtColorFmt,
TgtDepthStencilFmt,
},
Globals, Globals,
}; };
use gfx::{ use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta, gfx_pipeline_inner, gfx_vertex_struct_meta, texture::SamplerInfo,
}; };
use vek::*; use vek::*;
@ -51,3 +54,64 @@ pub struct LodTerrainPipeline;
impl Pipeline for LodTerrainPipeline { impl Pipeline for LodTerrainPipeline {
type Vertex = Vertex; 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 terrain;
pub mod ui; pub mod ui;
use super::Consts;
use crate::scene::camera::CameraMode; use crate::scene::camera::CameraMode;
use common::terrain::BlockKind; use common::terrain::BlockKind;
use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta}; use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta};
@ -25,9 +26,6 @@ gfx_defines! {
cam_pos: [f32; 4] = "cam_pos", cam_pos: [f32; 4] = "cam_pos",
focus_off: [f32; 4] = "focus_off", focus_off: [f32; 4] = "focus_off",
focus_pos: [f32; 4] = "focus_pos", 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 /// NOTE: view_distance.x is the horizontal view distance, view_distance.y is the LOD
/// detail, view_distance.z is the /// detail, view_distance.z is the
/// minimum height over any land chunk (i.e. the sea level), and view_distance.w 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 { constant Light {
pos: [f32; 4] = "light_pos", pos: [f32; 4] = "light_pos",
col: [f32; 4] = "light_col", col: [f32; 4] = "light_col",
// proj: [[f32; 4]; 4] = "light_proj";
} }
constant Shadow { constant Shadow {
@ -201,3 +198,11 @@ impl Shadow {
impl Default for Shadow { impl Default for Shadow {
fn default() -> Self { Self::new(Vec3::zero(), 0.0) } 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! { gfx_defines! {
vertex Vertex { vertex Vertex {
// pos: [f32; 4] = "v_pos",
pos_norm: u32 = "v_pos_norm", pos_norm: u32 = "v_pos_norm",
// col_light: u32 = "v_col_light",
// atlas_pos: u32 = "v_atlas_pos",
} }
constant Locals { constant Locals {
@ -26,17 +23,10 @@ gfx_defines! {
pipeline pipe { pipeline pipe {
// Terrain vertex stuff // Terrain vertex stuff
vbuf: gfx::VertexBuffer</*Vertex*/terrain::Vertex> = (), vbuf: gfx::VertexBuffer<terrain::Vertex> = (),
locals: gfx::ConstantBuffer<TerrainLocals> = "u_locals", locals: gfx::ConstantBuffer<TerrainLocals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals", 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 // Shadow stuff
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows", light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
@ -45,23 +35,15 @@ gfx_defines! {
fun: gfx::state::Comparison::Less, fun: gfx::state::Comparison::Less,
write: true, 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 { pipeline figure_pipe {
// Terrain vertex stuff // Terrain vertex stuff
vbuf: gfx::VertexBuffer</*Vertex*/terrain::Vertex> = (), vbuf: gfx::VertexBuffer<terrain::Vertex> = (),
locals: gfx::ConstantBuffer<figure::Locals> = "u_locals", locals: gfx::ConstantBuffer<figure::Locals> = "u_locals",
bones: gfx::ConstantBuffer<figure::BoneData> = "u_bones", bones: gfx::ConstantBuffer<figure::BoneData> = "u_bones",
globals: gfx::ConstantBuffer<Globals> = "u_globals", 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 // Shadow stuff
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows", light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
@ -70,16 +52,11 @@ gfx_defines! {
fun: gfx::state::Comparison::Less, fun: gfx::state::Comparison::Less,
write: true, 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 { impl Vertex {
pub fn new( pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, meta: bool) -> Self {
pos: Vec3<f32>,
norm: Vec3<f32>,
meta: bool, /* , atlas_pos: Vec2<u16> */
) -> Self {
let norm_bits = if norm.x != 0.0 { let norm_bits = if norm.x != 0.0 {
if norm.x < 0.0 { 0 } else { 1 } if norm.x < 0.0 { 0 } else { 1 }
} else if norm.y != 0.0 { } else if norm.y != 0.0 {
@ -89,10 +66,6 @@ impl Vertex {
} else { } else {
5 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; 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 | (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
| if meta { 1 } else { 0 } << 28 | if meta { 1 } else { 0 } << 28
| (norm_bits & 0x7) << 29, | (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( pub fn new_figure(pos: Vec3<f32>, norm: Vec3<f32>, bone_idx: u8) -> Self {
pos: Vec3<f32>,
norm: Vec3<f32>,
/* col: Rgb<f32>, ao: f32, */ bone_idx: u8,
) -> Self {
let norm_bits = if norm.x.min(norm.y).min(norm.z) < 0.0 { let norm_bits = if norm.x.min(norm.y).min(norm.z) < 0.0 {
0 0
} else { } else {
@ -133,10 +93,6 @@ impl Vertex {
.reduce_bitor() .reduce_bitor()
| (((bone_idx & 0xF) as u32) << 27) | (((bone_idx & 0xF) as u32) << 27)
| (norm_bits << 31), | (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::AaMode::Single,
), ),
gfx::texture::Mipmap::Provided, gfx::texture::Mipmap::Provided,
&[&col_lights /* .raw_pixels() */], &[&col_lights],
gfx::texture::SamplerInfo::new( gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear, gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Clamp, gfx::texture::WrapMode::Clamp,

View File

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

View File

@ -10,8 +10,6 @@ use vek::*;
gfx_defines! { gfx_defines! {
vertex Vertex { vertex Vertex {
// pos_norm: u32 = "v_pos_norm",
// col_light: u32 = "v_col_light",
pos_norm: u32 = "v_pos_norm", pos_norm: u32 = "v_pos_norm",
atlas_pos: u32 = "v_atlas_pos", atlas_pos: u32 = "v_atlas_pos",
} }
@ -23,8 +21,7 @@ gfx_defines! {
} }
pipeline pipe { pipeline pipe {
vbuf: gfx::VertexBuffer</*shadow::Vertex*/Vertex> = (), vbuf: gfx::VertexBuffer<Vertex> = (),
// abuf: gfx::VertexBuffer<Vertex> = (),
col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light", col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
locals: gfx::ConstantBuffer<Locals> = "u_locals", locals: gfx::ConstantBuffer<Locals> = "u_locals",
@ -73,22 +70,10 @@ impl Vertex {
atlas_pos: 0 atlas_pos: 0
| ((atlas_pos.x as u32) & 0xFFFF) << 0 | ((atlas_pos.x as u32) & 0xFFFF) << 0
| ((atlas_pos.y as u32) & 0xFFFF) << 16, | ((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( pub fn new_figure(atlas_pos: Vec2<u16>, pos: Vec3<f32>, norm: Vec3<f32>, bone_idx: u8) -> Self {
// norm: Vec3<f32>,
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 { let norm_bits = if norm.x.min(norm.y).min(norm.z) < 0.0 {
0 0
} else { } else {
@ -113,57 +98,15 @@ impl Vertex {
| ((atlas_pos.x as u32) & 0x7FFF) << 2 | ((atlas_pos.x as u32) & 0x7FFF) << 2
| ((atlas_pos.y as u32) & 0x7FFF) << 17 | ((atlas_pos.y as u32) & 0x7FFF) << 17
| axis_bits & 3, | 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( pub fn make_col_light(
light: /* u32 */ u8, light: u8,
// ao: u32,
// col: Rgb<f32>,
col: Rgb<u8>, col: Rgb<u8>,
) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType ) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType
{ {
[ [col.r, col.g, col.b, light]
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 */
]
} }
pub fn with_bone_idx(self, bone_idx: u8) -> Self { pub fn with_bone_idx(self, bone_idx: u8) -> Self {
@ -187,5 +130,5 @@ impl Locals {
pub struct TerrainPipeline; pub struct TerrainPipeline;
impl Pipeline for 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([l, b], [uv_l, uv_b]),
v([r, b], [uv_r, 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, mesh::Mesh,
model::{DynamicModel, Model}, model::{DynamicModel, Model},
pipelines::{ pipelines::{
figure, fluid, lod_terrain, postprocess, shadow, skybox, sprite, terrain, ui, Globals, figure, fluid, lod_terrain, postprocess, shadow, skybox, sprite, terrain, ui, GlobalModel,
Light, Shadow, Globals,
}, },
texture::Texture, texture::Texture,
AaMode, CloudMode, FilterMethod, FluidMode, LightingMode, Pipeline, RenderError, RenderMode, 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>; pub type WinDepthView = gfx::handle::DepthStencilView<gfx_backend::Resources, WinDepthFmt>;
/// Represents the format of LOD shadows. /// 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. /// 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. /// 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. /// Represents the format of greedy meshed color-light textures.
pub type ColLightFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); 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. /// 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( fn create_shadow_views(
factory: &mut gfx_device_gl::Factory, factory: &mut gfx_device_gl::Factory,
size: (u16, u16), size: (u16, u16),
@ -457,7 +460,7 @@ impl Renderer {
} }
}))?; }))?;
let levels = 1; //10; let levels = 1;
let two_size = vec2_result(size.map(|e| { let two_size = vec2_result(size.map(|e| {
u16::checked_next_power_of_two(e) u16::checked_next_power_of_two(e)
.filter(|&e| e <= max_texture_size) .filter(|&e| e <= max_texture_size)
@ -501,67 +504,26 @@ impl Renderer {
diag_size 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 depth_stencil_cty = <<ShadowDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
let point_shadow_tex = factory let point_shadow_tex = factory
.create_texture( .create_texture(
gfx::texture::Kind::/*CubeArray*/Cube( gfx::texture::Kind::Cube(diag_two_size / 4),
/* max_two_size */ diag_two_size / 4, /* size * 2*//*, 32 */
),
levels as gfx::texture::Level, levels as gfx::texture::Level,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL, gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
gfx::memory::Usage::Data, gfx::memory::Usage::Data,
Some(depth_stencil_cty), 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)))?; .map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
let point_tgt_shadow_view = factory let point_tgt_shadow_view = factory
.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>( .view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&point_shadow_tex, &point_shadow_tex,
0, // levels, 0,
None, // Some(1), None,
gfx::texture::DepthStencilFlags::empty(), 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 let point_tgt_shadow_res = factory
.view_texture_as_shader_resource::<ShadowDepthStencilFmt>( .view_texture_as_shader_resource::<ShadowDepthStencilFmt>(
&point_shadow_tex, &point_shadow_tex,
@ -569,21 +531,9 @@ impl Renderer {
gfx::format::Swizzle::new(), 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 let directed_shadow_tex = factory
.create_texture( .create_texture(
gfx::texture::Kind::D2( gfx::texture::Kind::D2(diag_two_size, diag_two_size, gfx::texture::AaMode::Single),
/* 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),
levels as gfx::texture::Level, levels as gfx::texture::Level,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL, gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
gfx::memory::Usage::Data, gfx::memory::Usage::Data,
@ -593,8 +543,8 @@ impl Renderer {
let directed_tgt_shadow_view = factory let directed_tgt_shadow_view = factory
.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>( .view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&directed_shadow_tex, &directed_shadow_tex,
0, // levels, 0,
None, // Some(1), None,
gfx::texture::DepthStencilFlags::empty(), gfx::texture::DepthStencilFlags::empty(),
)?; )?;
let directed_tgt_shadow_res = factory let directed_tgt_shadow_res = factory
@ -606,31 +556,14 @@ impl Renderer {
let mut sampler_info = gfx::texture::SamplerInfo::new( let mut sampler_info = gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear, 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.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(); sampler_info.border = [1.0; 4].into();
let point_shadow_tex_sampler = factory.create_sampler(sampler_info); 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 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(( Ok((
point_tgt_shadow_view, point_tgt_shadow_view,
point_tgt_shadow_res, point_tgt_shadow_res,
@ -676,7 +609,6 @@ impl Renderer {
// let directed_encoder = &mut shadow_map.directed_encoder; // let directed_encoder = &mut shadow_map.directed_encoder;
let directed_encoder = &mut self.encoder; let directed_encoder = &mut self.encoder;
directed_encoder.clear_depth(&shadow_map.directed_depth_stencil_view, 1.0); 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 // NOTE: Currently just fail silently rather than complain if the computer is on
// a version lower than 3.2, where seamless cubemaps were introduced. // a version lower than 3.2, where seamless cubemaps were introduced.
if !device.get_info().is_version_supported(3, 2) { if !device.get_info().is_version_supported(3, 2) {
// println!("whoops");
return; return;
} }
@ -719,7 +650,6 @@ impl Renderer {
// and having depth clamping disabled won't cause undefined // and having depth clamping disabled won't cause undefined
// behavior, just incorrect shadowing from objects behind the viewer. // behavior, just incorrect shadowing from objects behind the viewer.
if !device.get_info().is_version_supported(3, 3) { if !device.get_info().is_version_supported(3, 3) {
// println!("whoops");
return; return;
} }
@ -729,8 +659,6 @@ impl Renderer {
// essentially always be safe regardless of the state of the OpenGL // essentially always be safe regardless of the state of the OpenGL
// context, so no further checks are needed. // context, so no further checks are needed.
device.with_gl(|gl| { device.with_gl(|gl| {
// println!("gl.Enable(gfx_gl::DEPTH_CLAMP) = {:?}",
// gl.IsEnabled(gfx_gl::DEPTH_CLAMP));
if depth_clamp { if depth_clamp {
gl.Enable(gfx_gl::DEPTH_CLAMP); gl.Enable(gfx_gl::DEPTH_CLAMP);
} else { } 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) { pub fn flush_shadows(&mut self) {
if !self.mode.shadow.is_map() { if !self.mode.shadow.is_map() {
return; return;
@ -848,14 +776,6 @@ impl Renderer {
Ok(consts) 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. /// Update a set of constants with the provided values.
pub fn update_consts<T: Copy + gfx::traits::Pod>( pub fn update_consts<T: Copy + gfx::traits::Pod>(
&mut self, &mut self,
@ -865,25 +785,6 @@ impl Renderer {
consts.update(&mut self.encoder, vals, 0) 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. /// Create a new set of instances with the provided values.
pub fn create_instances<T: Copy + gfx::traits::Pod>( pub fn create_instances<T: Copy + gfx::traits::Pod>(
&mut self, &mut self,
@ -1004,22 +905,6 @@ impl Renderer {
Texture::new_dynamic(&mut self.factory, dims.x, dims.y) 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. /// Update a texture with the provided offset, size, and data.
pub fn update_texture( pub fn update_texture(
&mut self, &mut self,
@ -1082,10 +967,9 @@ impl Renderer {
pub fn render_skybox( pub fn render_skybox(
&mut self, &mut self,
model: &Model<skybox::SkyboxPipeline>, model: &Model<skybox::SkyboxPipeline>,
globals: &Consts<Globals>, global: &GlobalModel,
locals: &Consts<skybox::Locals>, locals: &Consts<skybox::Locals>,
alt: &Texture<LodAltFmt>, lod: &lod_terrain::LodData,
horizon: &Texture<LodTextureFmt>,
) { ) {
self.encoder.draw( self.encoder.draw(
&gfx::Slice { &gfx::Slice {
@ -1099,10 +983,10 @@ impl Renderer {
&skybox::pipe::Data { &skybox::pipe::Data {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
locals: locals.buf.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()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()), alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
}, },
@ -1114,16 +998,11 @@ impl Renderer {
&mut self, &mut self,
model: &figure::FigureModel, model: &figure::FigureModel,
_col_lights: &Texture<ColLightFmt>, _col_lights: &Texture<ColLightFmt>,
globals: &Consts<Globals>, global: &GlobalModel,
locals: &Consts<figure::Locals>, locals: &Consts<figure::Locals>,
bones: &Consts<figure::BoneData>, bones: &Consts<figure::BoneData>,
lights: &Consts<Light>, lod: &lod_terrain::LodData,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
) { ) {
// return;
let (point_shadow_maps, directed_shadow_maps) = let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map { if let Some(shadow_map) = &mut self.shadow_map {
( (
@ -1144,8 +1023,6 @@ impl Renderer {
}; };
let col_lights = &model.col_lights; let col_lights = &model.col_lights;
let model = &model.opaque; let model = &model.opaque;
// let atlas_model = &model.opaque;
// let model = &model.shadow;
self.encoder.draw( self.encoder.draw(
&gfx::Slice { &gfx::Slice {
@ -1158,20 +1035,18 @@ impl Renderer {
&self.figure_pipeline.pso, &self.figure_pipeline.pso,
&figure::pipe::Data { &figure::pipe::Data {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
// abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: global.globals.buf.clone(),
bones: bones.buf.clone(), bones: bones.buf.clone(),
lights: lights.buf.clone(), lights: global.lights.buf.clone(),
shadows: shadows.buf.clone(), shadows: global.shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(), light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()), alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
}, },
@ -1183,15 +1058,12 @@ impl Renderer {
&mut self, &mut self,
_model: &figure::FigureModel, _model: &figure::FigureModel,
_col_lights: &Texture<ColLightFmt>, _col_lights: &Texture<ColLightFmt>,
_globals: &Consts<Globals>, _global: &GlobalModel,
_locals: &Consts<figure::Locals>,
_bones: &Consts<figure::BoneData>, _bones: &Consts<figure::BoneData>,
_lights: &Consts<Light>, _lod: &lod_terrain::LodData,
_shadows: &Consts<Shadow>, _locals: &Consts<shadow::Locals>,
_light_shadows: &Consts<shadow::Locals>,
_alt: &Texture<LodAltFmt>,
_horizon: &Texture<LodTextureFmt>,
) { ) {
// FIXME: Consider reenabling at some point.
/* let (point_shadow_maps, directed_shadow_maps) = /* let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map { if let Some(shadow_map) = &mut self.shadow_map {
( (
@ -1228,18 +1100,18 @@ impl Renderer {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
// abuf: atlas_model.vbuf.clone(), // abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.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(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: global.globals.buf.clone(),
bones: bones.buf.clone(), bones: bones.buf.clone(),
lights: lights.buf.clone(), lights: global.lights.buf.clone(),
shadows: shadows.buf.clone(), shadows: global.shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(), light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()), alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (0, 0) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (0, 0) */),
}, },
@ -1251,14 +1123,10 @@ impl Renderer {
&mut self, &mut self,
model: &figure::FigureModel, model: &figure::FigureModel,
_col_lights: &Texture<ColLightFmt>, _col_lights: &Texture<ColLightFmt>,
globals: &Consts<Globals>, global: &GlobalModel,
locals: &Consts<figure::Locals>, locals: &Consts<figure::Locals>,
bones: &Consts<figure::BoneData>, bones: &Consts<figure::BoneData>,
lights: &Consts<Light>, lod: &lod_terrain::LodData,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
) { ) {
let (point_shadow_maps, directed_shadow_maps) = let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map { if let Some(shadow_map) = &mut self.shadow_map {
@ -1280,8 +1148,6 @@ impl Renderer {
}; };
let col_lights = &model.col_lights; let col_lights = &model.col_lights;
let model = &model.opaque; let model = &model.opaque;
// let atlas_model = &model.opaque;
// let model = &model.shadow;
self.encoder.draw( self.encoder.draw(
&gfx::Slice { &gfx::Slice {
@ -1294,20 +1160,18 @@ impl Renderer {
&self.figure_pipeline.pso, &self.figure_pipeline.pso,
&figure::pipe::Data { &figure::pipe::Data {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
// abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: global.globals.buf.clone(),
bones: bones.buf.clone(), bones: bones.buf.clone(),
lights: lights.buf.clone(), lights: global.lights.buf.clone(),
shadows: shadows.buf.clone(), shadows: global.shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(), light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()), alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
}, },
@ -1318,17 +1182,11 @@ impl Renderer {
/// frame. /// frame.
pub fn render_terrain_chunk( pub fn render_terrain_chunk(
&mut self, &mut self,
// atlas_model: &Model<terrain::TerrainPipeline>,
// model: &Model<shadow::ShadowPipeline>,
model: &Model<terrain::TerrainPipeline>, model: &Model<terrain::TerrainPipeline>,
col_lights: &Texture<ColLightFmt>, col_lights: &Texture<ColLightFmt>,
globals: &Consts<Globals>, global: &GlobalModel,
locals: &Consts<terrain::Locals>, locals: &Consts<terrain::Locals>,
lights: &Consts<Light>, lod: &lod_terrain::LodData,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
) { ) {
let (point_shadow_maps, directed_shadow_maps) = let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map { if let Some(shadow_map) = &mut self.shadow_map {
@ -1361,20 +1219,18 @@ impl Renderer {
&terrain::pipe::Data { &terrain::pipe::Data {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
// TODO: Consider splitting out texture atlas data into a separate vertex buffer, // TODO: Consider splitting out texture atlas data into a separate vertex buffer,
// since we don't need it for things like shadows. // since we don't need it for things like global.shadows.
// abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: global.globals.buf.clone(),
lights: lights.buf.clone(), lights: global.lights.buf.clone(),
shadows: shadows.buf.clone(), shadows: global.shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(), light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()), alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
}, },
@ -1386,14 +1242,9 @@ impl Renderer {
pub fn render_shadow_point( pub fn render_shadow_point(
&mut self, &mut self,
model: &Model<terrain::TerrainPipeline>, model: &Model<terrain::TerrainPipeline>,
// model: &Model<shadow::ShadowPipeline>, global: &GlobalModel,
globals: &Consts<Globals>,
terrain_locals: &Consts<terrain::Locals>, terrain_locals: &Consts<terrain::Locals>,
locals: &Consts<shadow::Locals>, locals: &Consts<shadow::Locals>,
/* lights: &Consts<Light>,
* shadows: &Consts<Shadow>,
* alt: &Texture<LodAltFmt>,
* horizon: &Texture<LodTextureFmt>, */
) { ) {
if !self.mode.shadow.is_map() { if !self.mode.shadow.is_map() {
return; return;
@ -1420,18 +1271,11 @@ impl Renderer {
// Terrain vertex stuff // Terrain vertex stuff
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
locals: terrain_locals.buf.clone(), locals: terrain_locals.buf.clone(),
globals: globals.buf.clone(), globals: global.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()),
// Shadow stuff // Shadow stuff
light_shadows: locals.buf.clone(), light_shadows: locals.buf.clone(),
tgt_depth_stencil: shadow_map.point_depth_stencil_view.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. /// the upcoming frame.
pub fn render_terrain_shadow_directed( pub fn render_terrain_shadow_directed(
&mut self, &mut self,
// model: &Model<shadow::ShadowPipeline>,
model: &Model<terrain::TerrainPipeline>, model: &Model<terrain::TerrainPipeline>,
globals: &Consts<Globals>, global: &GlobalModel,
terrain_locals: &Consts<terrain::Locals>, terrain_locals: &Consts<terrain::Locals>,
locals: &Consts<shadow::Locals>, locals: &Consts<shadow::Locals>,
/* lights: &Consts<Light>,
* shadows: &Consts<Shadow>,
* alt: &Texture<LodAltFmt>,
* horizon: &Texture<LodTextureFmt>, */
) { ) {
if !self.mode.shadow.is_map() { if !self.mode.shadow.is_map() {
return; return;
@ -1475,18 +1314,11 @@ impl Renderer {
// Terrain vertex stuff // Terrain vertex stuff
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
locals: terrain_locals.buf.clone(), locals: terrain_locals.buf.clone(),
globals: globals.buf.clone(), globals: global.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()),
// Shadow stuff // Shadow stuff
light_shadows: locals.buf.clone(), light_shadows: locals.buf.clone(),
tgt_depth_stencil: shadow_map.directed_depth_stencil_view.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. /// the upcoming frame.
pub fn render_figure_shadow_directed( pub fn render_figure_shadow_directed(
&mut self, &mut self,
// model: &Model<shadow::ShadowPipeline>,
model: &figure::FigureModel, model: &figure::FigureModel,
globals: &Consts<Globals>, global: &GlobalModel,
figure_locals: &Consts<figure::Locals>, figure_locals: &Consts<figure::Locals>,
bones: &Consts<figure::BoneData>, bones: &Consts<figure::BoneData>,
locals: &Consts<shadow::Locals>, locals: &Consts<shadow::Locals>,
/* lights: &Consts<Light>,
* shadows: &Consts<Shadow>,
* alt: &Texture<LodAltFmt>,
* horizon: &Texture<LodTextureFmt>, */
) { ) {
if !self.mode.shadow.is_map() { if !self.mode.shadow.is_map() {
return; return;
@ -1533,18 +1360,11 @@ impl Renderer {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
locals: figure_locals.buf.clone(), locals: figure_locals.buf.clone(),
bones: bones.buf.clone(), bones: bones.buf.clone(),
globals: globals.buf.clone(), globals: global.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()),
// Shadow stuff // Shadow stuff
light_shadows: locals.buf.clone(), light_shadows: locals.buf.clone(),
tgt_depth_stencil: shadow_map.directed_depth_stencil_view.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( pub fn render_fluid_chunk(
&mut self, &mut self,
model: &Model<fluid::FluidPipeline>, model: &Model<fluid::FluidPipeline>,
globals: &Consts<Globals>, global: &GlobalModel,
locals: &Consts<terrain::Locals>, locals: &Consts<terrain::Locals>,
lights: &Consts<Light>, lod: &lod_terrain::LodData,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
waves: &Texture, waves: &Texture,
) { ) {
let (point_shadow_maps, directed_shadow_maps) = let (point_shadow_maps, directed_shadow_maps) =
@ -1594,14 +1410,14 @@ impl Renderer {
&fluid::pipe::Data { &fluid::pipe::Data {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: global.globals.buf.clone(),
lights: lights.buf.clone(), lights: global.lights.buf.clone(),
shadows: shadows.buf.clone(), shadows: global.shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(), light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
alt: (alt.srv.clone(), alt.sampler.clone()), alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
waves: (waves.srv.clone(), waves.sampler.clone()), waves: (waves.srv.clone(), waves.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
@ -1616,17 +1432,11 @@ impl Renderer {
&mut self, &mut self,
model: &Model<sprite::SpritePipeline>, model: &Model<sprite::SpritePipeline>,
col_lights: &Texture<ColLightFmt>, col_lights: &Texture<ColLightFmt>,
globals: &Consts<Globals>, global: &GlobalModel,
terrain_locals: &Consts<terrain::Locals>, terrain_locals: &Consts<terrain::Locals>,
locals: &Consts<sprite::Locals>, locals: &Consts<sprite::Locals>,
// instance_count: usize,
// instances: &Consts<sprite::Instance>,
instances: &Instances<sprite::Instance>, instances: &Instances<sprite::Instance>,
lights: &Consts<Light>, lod: &lod_terrain::LodData,
shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
) { ) {
let (point_shadow_maps, directed_shadow_maps) = let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map { if let Some(shadow_map) = &mut self.shadow_map {
@ -1652,26 +1462,25 @@ impl Renderer {
start: model.vertex_range().start, start: model.vertex_range().start,
end: model.vertex_range().end, end: model.vertex_range().end,
base_vertex: 0, base_vertex: 0,
instances: Some((instances.count()/*instance_count*/ as u32, 0)), instances: Some((instances.count() as u32, 0)),
buffer: gfx::IndexBuffer::Auto, buffer: gfx::IndexBuffer::Auto,
}, },
&self.sprite_pipeline.pso, &self.sprite_pipeline.pso,
&sprite::pipe::Data { &sprite::pipe::Data {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
ibuf: instances.ibuf.clone(), ibuf: instances.ibuf.clone(),
// ibuf: instances.buf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
terrain_locals: terrain_locals.buf.clone(), terrain_locals: terrain_locals.buf.clone(),
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: global.globals.buf.clone(),
lights: lights.buf.clone(), lights: global.lights.buf.clone(),
shadows: shadows.buf.clone(), shadows: global.shadows.buf.clone(),
light_shadows: light_shadows.buf.clone(), light_shadows: global.shadow_mats.buf.clone(),
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()), alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
}, },
@ -1683,11 +1492,9 @@ impl Renderer {
pub fn render_lod_terrain( pub fn render_lod_terrain(
&mut self, &mut self,
model: &Model<lod_terrain::LodTerrainPipeline>, model: &Model<lod_terrain::LodTerrainPipeline>,
globals: &Consts<Globals>, global: &GlobalModel,
locals: &Consts<lod_terrain::Locals>, locals: &Consts<lod_terrain::Locals>,
map: &Texture<LodColorFmt>, lod: &lod_terrain::LodData,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>,
) { ) {
self.encoder.draw( self.encoder.draw(
&gfx::Slice { &gfx::Slice {
@ -1701,11 +1508,11 @@ impl Renderer {
&lod_terrain::pipe::Data { &lod_terrain::pipe::Data {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
locals: locals.buf.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()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()), map: (lod.map.srv.clone(), lod.map.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()), alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
}, },
@ -1926,13 +1733,6 @@ fn create_pipelines(
) )
.unwrap(); .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>( let directed_shadow_frag = &assets::load_watched::<String>(
"voxygen.shaders.light-shadows-directed-frag", "voxygen.shaders.light-shadows-directed-frag",
shader_reload_indicator, shader_reload_indicator,
@ -2094,8 +1894,7 @@ fn create_pipelines(
.unwrap(), .unwrap(),
&include_ctx, &include_ctx,
gfx::state::CullFace::Back, gfx::state::CullFace::Back,
None, None, // Some(gfx::state::Offset(2, 0))
// Some(gfx::state::Offset(2, /* 10 */ 0)),
) { ) {
Ok(pipe) => Some(pipe), Ok(pipe) => Some(pipe),
Err(err) => { Err(err) => {
@ -2109,14 +1908,11 @@ fn create_pipelines(
factory, factory,
shadow::pipe::new(), shadow::pipe::new(),
&terrain_directed_shadow_vert, &terrain_directed_shadow_vert,
None, // &directed_shadow_geom, None,
&directed_shadow_frag, &directed_shadow_frag,
&include_ctx, &include_ctx,
gfx::state::CullFace::Back, gfx::state::CullFace::Back,
/* None, */ None, // Some(gfx::state::Offset(2, 1))
/* Some(gfx::state::Offset(4, 10)), */
None,
// Some(gfx::state::Offset(2, /*10*/1)),
) { ) {
Ok(pipe) => Some(pipe), Ok(pipe) => Some(pipe),
Err(err) => { Err(err) => {
@ -2133,14 +1929,11 @@ fn create_pipelines(
factory, factory,
shadow::figure_pipe::new(), shadow::figure_pipe::new(),
&figure_directed_shadow_vert, &figure_directed_shadow_vert,
None, // &directed_shadow_geom, None,
&directed_shadow_frag, &directed_shadow_frag,
&include_ctx, &include_ctx,
gfx::state::CullFace::Back, gfx::state::CullFace::Back,
/* None, */ None, // Some(gfx::state::Offset(2, 1))
/* Some(gfx::state::Offset(4, 10)), */
/*Some(gfx::state::Offset(2, 1))*/None,
/* Some(gfx::state::Offset(2, 10)), */
) { ) {
Ok(pipe) => Some(pipe), Ok(pipe) => Some(pipe),
Err(err) => { 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 // Second-depth shadow mapping: should help reduce z-fighting provided all objects
// are "watertight" (every triangle edge is shared with at most one other // are "watertight" (every triangle edge is shared with at most one other
// triangle); this *should* be true for Veloren. // 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::Front => gfx::state::CullFace::Back,
gfx::state::CullFace::Back => gfx::state::CullFace::Front, gfx::state::CullFace::Back => gfx::state::CullFace::Front,
gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing, gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing,
}, },
method: gfx::state::RasterMethod::Fill, method: gfx::state::RasterMethod::Fill,
offset, offset,
samples: None, // Some(gfx::state::MultiSample), samples: None,
}, },
pipe, pipe,
)?, )?,

View File

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

View File

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

View File

@ -936,45 +936,49 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
.unwrap_or_else(<Skel::Attr as Default>::default); .unwrap_or_else(<Skel::Attr as Default>::default);
let manifest_indicator = &mut self.manifest_indicator; let manifest_indicator = &mut self.manifest_indicator;
let mut make_model = |generate_mesh: for<'a> fn(&mut GreedyMesh<'a>, _, _) -> _| { let mut make_model =
let mut greedy = FigureModel::make_greedy(); |generate_mesh: for<'a> fn(&mut GreedyMesh<'a>, _, _) -> _| {
let mut opaque = Mesh::new(); let mut greedy = FigureModel::make_greedy();
let mut figure_bounds = Aabb { let mut opaque = Mesh::new();
min: Vec3::zero(), let mut figure_bounds = Aabb {
max: Vec3::zero(), min: Vec3::zero(),
max: Vec3::zero(),
};
Self::bone_meshes(
body,
loadout,
character_state,
camera_mode,
manifest_indicator,
|segment, offset| generate_mesh(&mut greedy, segment, offset),
)
.iter()
.enumerate()
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
.for_each(
|(i, (opaque_mesh, bounds))| {
opaque.push_mesh_map(opaque_mesh, |vert| {
vert.with_bone_idx(i as u8)
});
figure_bounds.expand_to_contain(*bounds);
},
);
col_lights
.create_figure(renderer, greedy, (opaque, figure_bounds))
.unwrap()
}; };
// let mut shadow = Mesh::new();
Self::bone_meshes(
body,
loadout,
character_state,
camera_mode,
manifest_indicator,
|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));
});
col_lights.create_figure(renderer, greedy, (opaque/*, shadow*/, figure_bounds)).unwrap()
};
fn generate_mesh<'a>( fn generate_mesh<'a>(
greedy: &mut GreedyMesh<'a>, greedy: &mut GreedyMesh<'a>,
segment: Segment, segment: Segment,
offset: Vec3<f32>, offset: Vec3<f32>,
) -> BoneMeshes { ) -> BoneMeshes {
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh( let (opaque, _, _, bounds) =
segment, Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
(greedy, offset, Vec3::one()), segment,
); (greedy, offset, Vec3::one()),
(opaque/*, shadow*/, bounds) );
(opaque, bounds)
} }
fn generate_mesh_lod_mid<'a>( fn generate_mesh_lod_mid<'a>(
@ -983,11 +987,12 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
offset: Vec3<f32>, offset: Vec3<f32>,
) -> BoneMeshes { ) -> BoneMeshes {
let lod_scale = Vec3::broadcast(0.6); let lod_scale = Vec3::broadcast(0.6);
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh( let (opaque, _, _, bounds) =
segment.scaled_by(lod_scale), Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
(greedy, offset * lod_scale, Vec3::one() / lod_scale), segment.scaled_by(lod_scale),
); (greedy, offset * lod_scale, Vec3::one() / lod_scale),
(opaque/*, shadow*/, bounds) );
(opaque, bounds)
} }
fn generate_mesh_lod_low<'a>( fn generate_mesh_lod_low<'a>(
@ -997,11 +1002,12 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
) -> BoneMeshes { ) -> BoneMeshes {
let lod_scale = Vec3::broadcast(0.3); let lod_scale = Vec3::broadcast(0.3);
let segment = segment.scaled_by(lod_scale); let segment = segment.scaled_by(lod_scale);
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh( let (opaque, _, _, bounds) =
segment, Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
(greedy, offset * lod_scale, Vec3::one() / lod_scale), 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 { let tool_kind = if let Some(ItemKind::Tool(Tool { kind, .. })) = item_kind {
kind kind
} else { } else {
return (Mesh::new() /* , Mesh::new() */, Aabb::default()); return (Mesh::new(), Aabb::default());
}; };
let spec = match self.0.get(tool_kind) { let spec = match self.0.get(tool_kind) {

View File

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

View File

@ -1,89 +1,24 @@
use crate::{ use crate::{
render::{ render::{
pipelines::lod_terrain::{Locals, Vertex}, pipelines::lod_terrain::{Locals, LodData, Vertex},
Consts, Globals, LodAltFmt, LodColorFmt, LodTerrainPipeline, LodTextureFmt, Mesh, Model, Consts, GlobalModel, LodTerrainPipeline, Mesh, Model, Quad, Renderer,
Quad, Renderer, Texture,
}, },
settings::Settings, settings::Settings,
}; };
use client::Client; use client::Client;
use common::{spiral::Spiral2d, util::srgba_to_linear}; use common::{spiral::Spiral2d, util::srgba_to_linear};
use gfx::texture::SamplerInfo;
use vek::*; use vek::*;
pub struct LodData {
pub map: Texture<LodColorFmt>,
pub alt: Texture<LodAltFmt>,
pub horizon: Texture<LodTextureFmt>,
pub tgt_detail: u32,
}
pub struct Lod { pub struct Lod {
model: Option<(u32, Model<LodTerrainPipeline>)>, model: Option<(u32, Model<LodTerrainPipeline>)>,
locals: Consts<Locals>, locals: Consts<Locals>,
data: LodData, 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. // TODO: Make constant when possible.
pub fn water_color() -> Rgba<f32> { pub fn water_color() -> Rgba<f32> {
/* Rgba::new(0.2, 0.5, 1.0, 0.0) */ /* 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 { 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() { if let Some((_, model)) = self.model.as_ref() {
renderer.render_lod_terrain( renderer.render_lod_terrain(&model, global, &self.locals, &self.data);
&model,
globals,
&self.locals,
&self.data.map,
&self.data.alt,
&self.data.horizon,
);
} }
} }
} }

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), plane: (Vec3<T>, T),
intersection_points: &mut Vec<Vec3<T>>, intersection_points: &mut Vec<Vec3<T>>,
) -> bool { ) -> 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 { if points.len() < 3 {
return false; 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 last_is_outside = point_before_plane(current_point, plane);
let mut is_outside = last_is_outside; 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); let mut old_points = Vec::with_capacity((3 * points.len()) / 2);
mem::swap(&mut old_points, points); mem::swap(&mut old_points, points);
old_points.into_iter().for_each(|point| { 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); 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 before_plane = point_before_plane(current_point, plane);
let prev_is_outside = mem::replace(&mut is_outside, before_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 { if !prev_is_outside {
// Push previous point. // Push previous point.
points.push(prev_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); 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 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 // 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 // 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 // btree, which wouldn't be the end of the world but would have
// theoretically worse complexity. NOTE: Definitely non-ideal that we // theoretically worse complexity.
// 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 // NOTE: Definitely non-ideal that we panic if the rounded value can't fit in an
// we know the kind of floating point we're using we can just cast to bits or // i64...
// something. //
// 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| { point.map(|e| {
(e * tol) (e * tol)
.round() .round()
@ -362,45 +223,17 @@ fn append_intersection_points<T: Float + core::fmt::Debug>(
// than lines). // than lines).
(u_key != make_key(v)).then_some((u_key, v)) (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() if let Some((last_key, first)) = lines_iter.next() {
/* [last, first, rest @ ..] = &*intersection_points = &*intersection_points */
{
let lines = lines_iter.collect::<HashMap<_, _>>(); 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 { if lines.len() < 2 {
// You need at least 3 sides for a polygon // You need at least 3 sides for a polygon
return; 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 // NOTE: Guaranteed to terminate, provided we have no cycles besides the one
// that touches every point (which should be the case given how these // that touches every point (which should be the case given how these
// points were generated). // points were generated).
let /*mut */poly_iter = iter::successors(Some(first), |&cur| lines.get(&make_key(cur)).copied()); let 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: Vec<_> = poly_iter.collect(); let poly: Vec<_> = poly_iter.collect();
// We have to check to make sure we really went through the whole cycle. // 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 // 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| { polys.drain_filter(|points| {
let len = intersection_points.len(); let len = intersection_points.len();
let outside_first = clip_points_by_plane(points, plane, &mut intersection_points); 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 // Only remember intersections that are not coplanar with this side; i.e. those
// that have segment length 2. // that have segment length 2.
if len + 2 != intersection_points.len() { 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 // Remove polygon if it was clipped away
points.is_empty() 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 // Add a polygon of all intersection points with the plane to close out the
// object. // object.
append_intersection_points(polys, intersection_points, tolerance); 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, tolerance: T,
) { ) {
let planes = aabb_to_planes(bounds); let planes = aabb_to_planes(bounds);
// println!("planes@clip_object_by_aabb: {:?}", planes);
planes.iter().for_each(|&plane| { planes.iter().for_each(|&plane| {
clip_object_by_plane(polys, plane, tolerance); 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 /// test plane. Otherwise 'None' is returned in which case the line
/// segment is entirely clipped. /// segment is entirely clipped.
pub fn clip_test<T: Float + core::fmt::Debug>(p: T, q: T, (u1, u2): (T, T)) -> Option<(T, T)> { 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 p == T::zero() {
if q >= T::zero() { Some((u1, u2)) } else { None } if q >= T::zero() { Some((u1, u2)) } else { None }
} else { } else {
@ -485,9 +311,7 @@ pub fn clip_test<T: Float + core::fmt::Debug>(p: T, q: T, (u1, u2): (T, T)) -> O
} else { } else {
Some((u1, if r < u2 { r } else { u2 })) 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>( 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>, dir: Vec3<T>,
bounds: Aabb<T>, bounds: Aabb<T>,
) -> Option<Vec3<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())) 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.z, bounds.max.z - p.z, t))
.and_then(|t| clip_test(-dir.y, p.y - bounds.min.y, 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 { } else {
None None
} }
}) /*; })
//println!("after@intersection_line_aabb (p={:?} dir={:?} bounds={:?}):
// {:?}", p, dir, bounds, res); res */
} }
pub fn include_object_light_volume< pub fn include_object_light_volume<
@ -525,12 +344,12 @@ pub fn include_object_light_volume<
light_dir: Vec3<T>, light_dir: Vec3<T>,
bounds: Aabb<T>, bounds: Aabb<T>,
) -> impl Iterator<Item = Vec3<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))) 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>( pub fn calc_focused_light_volume_points<T: Float + MulAdd<T, T, Output = T> + core::fmt::Debug>(
inv_proj_view: Mat4<T>, inv_proj_view: Mat4<T>,
_light_dir: Vec3<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, tolerance: T,
) -> impl Iterator<Item = Vec3<T>> { ) -> impl Iterator<Item = Vec3<T>> {
let world_pts = calc_view_frustum_world_coord(inv_proj_view); 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); 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); 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()) world_frust_object.into_iter().flat_map(|e| e.into_iter())
/* include_object_light_volume( /* include_object_light_volume(
world_frust_object.into_iter().flat_map(|e| e.into_iter()), world_frust_object.into_iter().flat_map(|e| e.into_iter()),
@ -574,50 +388,4 @@ pub fn fit_psr<
min: min.xyz(), min: min.xyz(),
max: max.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}, mesh::{greedy::GreedyMesh, Meshable},
render::{ render::{
create_pp_mesh, create_skybox_mesh, BoneMeshes, Consts, FigureModel, FigurePipeline, create_pp_mesh, create_skybox_mesh, BoneMeshes, Consts, FigureModel, FigurePipeline,
Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer, Shadow, GlobalModel, Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer,
ShadowLocals, SkyboxLocals, SkyboxPipeline, Shadow, ShadowLocals, SkyboxLocals, SkyboxPipeline,
}, },
scene::{ scene::{
camera::{self, Camera, CameraMode}, camera::{self, Camera, CameraMode},
@ -68,10 +68,7 @@ struct PostProcess {
} }
pub struct Scene { pub struct Scene {
globals: Consts<Globals>, data: GlobalModel,
lights: Consts<Light>,
shadows: Consts<Shadow>,
shadow_mats: Consts<ShadowLocals>,
camera: Camera, camera: Camera,
skybox: Skybox, skybox: Skybox,
@ -105,18 +102,8 @@ impl Scene {
let map_bounds = Vec2::new(-65536.0, 131071.0); let map_bounds = Vec2::new(-65536.0, 131071.0);
let map_border = [0.0, 0.0, 0.0, 0.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 map_image = [0];
let alt_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 horizon_image = [0x_00_01_00_01];
let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson); let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson);
@ -127,10 +114,14 @@ impl Scene {
let mut col_lights = FigureColLights::new(renderer); let mut col_lights = FigureColLights::new(renderer);
Self { Self {
globals: renderer.create_consts(&[Globals::default()]).unwrap(), data: GlobalModel {
lights: renderer.create_consts(&[Light::default(); 32]).unwrap(), globals: renderer.create_consts(&[Globals::default()]).unwrap(),
shadows: renderer.create_consts(&[Shadow::default(); 32]).unwrap(), lights: renderer.create_consts(&[Light::default(); 32]).unwrap(),
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]).unwrap(), shadows: renderer.create_consts(&[Shadow::default(); 32]).unwrap(),
shadow_mats: renderer
.create_consts(&[ShadowLocals::default(); 6])
.unwrap(),
},
skybox: Skybox { skybox: Skybox {
model: renderer.create_model(&create_skybox_mesh()).unwrap(), model: renderer.create_model(&create_skybox_mesh()).unwrap(),
@ -142,8 +133,16 @@ impl Scene {
.create_consts(&[PostProcessLocals::default()]) .create_consts(&[PostProcessLocals::default()])
.unwrap(), .unwrap(),
}, },
lod: LodData::new(renderer, Vec2::new(1, 1), &map_image, &alt_image, &horizon_image, 1, map_border.into()),// Lod::new(renderer, client, settings), lod: LodData::new(
map_bounds,//: client.world_map.2, renderer,
Vec2::new(1, 1),
&map_image,
&alt_image,
&horizon_image,
1,
map_border.into(),
),
map_bounds,
figure_model_cache: FigureModelCache::new(), figure_model_cache: FigureModelCache::new(),
figure_state: FigureState::new(renderer, CharacterSkeleton::default()), figure_state: FigureState::new(renderer, CharacterSkeleton::default()),
@ -173,21 +172,18 @@ impl Scene {
&camera, &camera,
&mut buf, &mut buf,
); );
( (model, state)
model,
state,
)
}), }),
col_lights, col_lights,
camera, camera,
turning: false, 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 } pub fn camera_mut(&mut self) -> &mut Camera { &mut self.camera }
@ -234,19 +230,18 @@ impl Scene {
cam_pos, cam_pos,
} = self.camera.dependents(); } = self.camera.dependents();
const VD: f32 = 115.0; // View Distance 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;
const TIME: f64 = 10.0 * 60.0 * 60.0; //43200.0; // 12 hours*3600 seconds
const SHADOW_NEAR: f32 = 1.0; const SHADOW_NEAR: f32 = 1.0;
const SHADOW_FAR: f32 = 25.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, view_mat,
proj_mat, proj_mat,
cam_pos, cam_pos,
self.camera.get_focus_pos(), self.camera.get_focus_pos(),
VD, VD,
self.lod.tgt_detail as f32, self.lod.tgt_detail as f32,
self.map_bounds, //MAP_BOUNDS, self.map_bounds,
TIME, TIME,
scene_data.time, scene_data.time,
renderer.get_resolution(), renderer.get_resolution(),
@ -338,10 +333,9 @@ impl Scene {
) { ) {
renderer.render_skybox( renderer.render_skybox(
&self.skybox.model, &self.skybox.model,
&self.globals, &self.data,
&self.skybox.locals, &self.skybox.locals,
&self.lod.alt, &self.lod,
&self.lod.horizon,
); );
if let Some(body) = body { if let Some(body) = body {
@ -361,14 +355,10 @@ impl Scene {
renderer.render_figure( renderer.render_figure(
&model[0], &model[0],
&self.col_lights.texture(), &self.col_lights.texture(),
&self.globals, &self.data,
self.figure_state.locals(), self.figure_state.locals(),
self.figure_state.bone_consts(), self.figure_state.bone_consts(),
&self.lights, &self.lod,
&self.shadows,
&self.shadow_mats,
&self.lod.alt,
&self.lod.horizon,
); );
} }
@ -376,20 +366,16 @@ impl Scene {
renderer.render_figure( renderer.render_figure(
model, model,
&self.col_lights.texture(), &self.col_lights.texture(),
&self.globals, &self.data,
state.locals(), state.locals(),
state.bone_consts(), state.bone_consts(),
&self.lights, &self.lod,
&self.shadows,
&self.shadow_mats,
&self.lod.alt,
&self.lod.horizon,
); );
} }
renderer.render_post_process( renderer.render_post_process(
&self.postprocess.model, &self.postprocess.model,
&self.globals, &self.data.globals,
&self.postprocess.locals, &self.postprocess.locals,
); );
} }

View File

@ -1,9 +1,9 @@
use crate::{ use crate::{
mesh::{greedy::GreedyMesh, Meshable}, mesh::{greedy::GreedyMesh, Meshable},
render::{ render::{
ColLightFmt, ColLightInfo, Consts, FluidPipeline, Globals, Instances, Light, Mesh, Model, ColLightFmt, ColLightInfo, Consts, FluidPipeline, GlobalModel, Instances, Mesh, Model,
RenderError, Renderer, Shadow, ShadowLocals, ShadowPipeline, SpriteInstance, SpriteLocals, RenderError, Renderer, ShadowPipeline, SpriteInstance, SpriteLocals, SpritePipeline,
SpritePipeline, TerrainLocals, TerrainPipeline, Texture, TerrainLocals, TerrainPipeline, Texture,
}, },
}; };
@ -40,13 +40,8 @@ struct TerrainChunkData {
load_time: f32, load_time: f32,
opaque_model: Model<TerrainPipeline>, opaque_model: Model<TerrainPipeline>,
fluid_model: Option<Model<FluidPipeline>>, fluid_model: Option<Model<FluidPipeline>>,
// shadow_model: Model<ShadowPipeline>,
// col_lights: Texture<ColLightFmt>,
col_lights: guillotiere::AllocId, col_lights: guillotiere::AllocId,
sprite_instances: HashMap< sprite_instances: HashMap<(BlockKind, usize), Instances<SpriteInstance>>,
(BlockKind, usize),
Instances<SpriteInstance>, /* RawBuffer*//*(Consts<SpriteInstance>, usize) */
>,
locals: Consts<TerrainLocals>, locals: Consts<TerrainLocals>,
visible: Visibility, visible: Visibility,
@ -386,12 +381,10 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug>(
volume: <VolGrid2d<V> as SampleVol<Aabr<i32>>>::Sample, volume: <VolGrid2d<V> as SampleVol<Aabr<i32>>>::Sample,
max_texture_size: u16, max_texture_size: u16,
range: Aabb<i32>, range: Aabb<i32>,
sprite_models: &HashMap<(BlockKind, usize), Vec</* Range<u32> */ SpriteData>>, sprite_models: &HashMap<(BlockKind, usize), Vec<SpriteData>>,
) -> MeshWorkerResponse { ) -> 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))); 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 { MeshWorkerResponse {
pos, pos,
z_bounds: (bounds.min.z, bounds.max.z), 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 sprite_data = &sprite_models[&key][0];
let instance = SpriteInstance::new( let instance = SpriteInstance::new(
Mat4::identity() 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) .translated_3d(sprite_data.offset)
// .scaled_3d(SPRITE_SCALE)
.rotated_z(f32::consts::PI * 0.25 * ori as f32) .rotated_z(f32::consts::PI * 0.25 * ori as f32)
.translated_3d( .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, cfg.wind_sway,
rel_pos, rel_pos,
ori, ori,
@ -490,8 +472,7 @@ pub struct Terrain<V: RectRasterableVol> {
mesh_todo: HashMap<Vec2<i32>, ChunkMeshState>, mesh_todo: HashMap<Vec2<i32>, ChunkMeshState>,
// GPU data // GPU data
// sprite_model_data: Model<SpritePipeline>, sprite_models: Arc<HashMap<(BlockKind, usize), Vec<SpriteData>>>,
sprite_models: Arc<HashMap<(BlockKind, usize), Vec</* Range<u32> */ SpriteData>>>,
sprite_col_lights: Texture<ColLightFmt>, sprite_col_lights: Texture<ColLightFmt>,
col_lights: Texture<ColLightFmt>, col_lights: Texture<ColLightFmt>,
waves: Texture, waves: Texture,
@ -518,9 +499,7 @@ impl<V: RectRasterableVol> Terrain<V> {
let max_texture_size = renderer.max_texture_size(); let max_texture_size = renderer.max_texture_size();
let max_size = let max_size =
guillotiere::Size::new(i32::from(max_texture_size), i32::from(max_texture_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 greedy = GreedyMesh::new(max_size);
// let mut mesh = Mesh::new();
let mut locals_buffer = [SpriteLocals::default(); 8]; let mut locals_buffer = [SpriteLocals::default(); 8];
let mut make_models = |(kind, variation), s, offset, lod_axes: Vec3<f32>| { let mut make_models = |(kind, variation), s, offset, lod_axes: Vec3<f32>| {
let scaled = [1.0, 0.8, 0.6, 0.4, 0.2]; let scaled = [1.0, 0.8, 0.6, 0.4, 0.2];
@ -545,10 +524,6 @@ impl<V: RectRasterableVol> Terrain<V> {
scale 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 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); let sprite_mat: Mat4<f32> = Mat4::translation_3d(offset).scaled_3d(SPRITE_SCALE);
( (
@ -556,45 +531,44 @@ impl<V: RectRasterableVol> Terrain<V> {
scaled scaled
.iter() .iter()
.map(|&lod_scale_orig| { .map(|&lod_scale_orig| {
let lod_scale = model_scale * if lod_scale_orig == 1.0 { let lod_scale = model_scale
Vec3::broadcast(1.0) * if lod_scale_orig == 1.0 {
} else { Vec3::broadcast(1.0)
lod_axes * lod_scale_orig + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 }) } else {
}; lod_axes * lod_scale_orig
+ lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 })
};
let opaque_model = let opaque_model =
Meshable::<SpritePipeline, &mut GreedyMesh>::generate_mesh( Meshable::<SpritePipeline, &mut GreedyMesh>::generate_mesh(
Segment::from(model.as_ref()).scaled_by(lod_scale), 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; .0;
let sprite_scale = Vec3::one() / lod_scale; let sprite_scale = Vec3::one() / lod_scale;
let sprite_mat: Mat4<f32> = sprite_mat * Mat4::scaling_3d(sprite_scale); let sprite_mat: Mat4<f32> = sprite_mat * Mat4::scaling_3d(sprite_scale);
locals_buffer.iter_mut().enumerate().for_each(|(ori, locals)| { locals_buffer
let sprite_mat = sprite_mat.rotated_z(f32::consts::PI * 0.25 * ori as f32); .iter_mut()
*locals = SpriteLocals::new(sprite_mat, sprite_scale, offset, wind_sway); .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 { SpriteData {
/* scale: sprite_scale, */
offset, offset,
/* mat: sprite_mat, */ model: renderer.create_model(&opaque_model).unwrap(),
model: renderer.create_model(&opaque_model) locals: renderer
.unwrap(), .create_consts(&locals_buffer)
locals: renderer.create_consts(&locals_buffer)
.expect("Failed to upload sprite locals to the GPU!"), .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<_>>(), .collect::<Vec<_>>(),
) )
}; };
let sprite_models: HashMap<(BlockKind, usize), /* Vec<Range<u32>> */ _> = vec![ let sprite_models: HashMap<(BlockKind, usize), _> = vec![
// Windows // Windows
make_models( make_models(
(BlockKind::Window1, 0), (BlockKind::Window1, 0),
@ -2308,11 +2282,6 @@ impl<V: RectRasterableVol> Terrain<V> {
] ]
.into_iter() .into_iter()
.collect(); .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()) let sprite_col_lights = ShadowPipeline::create_col_lights(renderer, greedy.finalize())
.expect("Failed to upload sprite color and light data to the GPU!"); .expect("Failed to upload sprite color and light data to the GPU!");
Self { Self {
@ -2322,23 +2291,8 @@ impl<V: RectRasterableVol> Terrain<V> {
mesh_send_tmp: send, mesh_send_tmp: send,
mesh_recv: recv, mesh_recv: recv,
mesh_todo: HashMap::default(), mesh_todo: HashMap::default(),
// sprite_model_data,
sprite_models: Arc::new(sprite_models), sprite_models: Arc::new(sprite_models),
sprite_col_lights, /*renderer sprite_col_lights,
.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!"),*/
waves: renderer waves: renderer
.create_texture( .create_texture(
&assets::load_expect("voxygen.texture.waves"), &assets::load_expect("voxygen.texture.waves"),
@ -2358,14 +2312,12 @@ impl<V: RectRasterableVol> Terrain<V> {
let max_texture_size = renderer.max_texture_size(); let max_texture_size = renderer.max_texture_size();
let atlas_size = let atlas_size =
guillotiere::Size::new(i32::from(max_texture_size), i32::from(max_texture_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 { let atlas = AtlasAllocator::with_options(atlas_size, &guillotiere::AllocatorOptions {
// TODO: Verify some good empirical constants. // TODO: Verify some good empirical constants.
small_size_threshold: 128, small_size_threshold: 128,
large_size_threshold: 1024, large_size_threshold: 1024,
..guillotiere::AllocatorOptions::default() ..guillotiere::AllocatorOptions::default()
}); });
// renderer.flush();
let texture = renderer.create_texture_raw( let texture = renderer.create_texture_raw(
gfx::texture::Kind::D2( gfx::texture::Kind::D2(
max_texture_size, max_texture_size,
@ -2373,8 +2325,7 @@ impl<V: RectRasterableVol> Terrain<V> {
gfx::texture::AaMode::Single, gfx::texture::AaMode::Single,
), ),
1 as gfx::texture::Level, 1 as gfx::texture::Level,
// gfx::memory::Upload, gfx::memory::Bind::SHADER_RESOURCE,
gfx::memory::Bind::SHADER_RESOURCE, /* | gfx::memory::Bind::TRANSFER_DST */
gfx::memory::Usage::Dynamic, gfx::memory::Usage::Dynamic,
(0, 0), (0, 0),
gfx::format::Swizzle::new(), gfx::format::Swizzle::new(),
@ -2383,33 +2334,10 @@ impl<V: RectRasterableVol> Terrain<V> {
gfx::texture::WrapMode::Clamp, 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)) Ok((atlas, texture))
} }
fn remove_chunk_meta(&mut self, _pos: Vec2<i32>, chunk: &TerrainChunkData) { fn remove_chunk_meta(&mut self, _pos: Vec2<i32>, chunk: &TerrainChunkData) {
/* println!("Terrain chunk already existed: {:?}", pos); */
self.atlas.deallocate(chunk.col_lights); self.atlas.deallocate(chunk.col_lights);
/* let (zmin, zmax) = chunk.z_bounds; /* let (zmin, zmax) = chunk.z_bounds;
self.z_index_up.remove(Vec3::from(zmin, pos.x, pos.y)); 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>) { fn remove_chunk(&mut self, pos: Vec2<i32>) {
// println!("Terrain chunk removed: {:?}", pos);
if let Some(chunk) = self.chunks.remove(&pos) { if let Some(chunk) = self.chunks.remove(&pos) {
self.remove_chunk_meta(pos, &chunk); self.remove_chunk_meta(pos, &chunk);
// Temporarily remember dead chunks for shadowing purposes. // Temporarily remember dead chunks for shadowing purposes.
self.shadow_chunks.push((pos, chunk)); self.shadow_chunks.push((pos, chunk));
} }
if let Some(_todo) = self.mesh_todo.remove(&pos) { if let Some(_todo) = self.mesh_todo.remove(&pos) {
/* println!("Terrain chunk was being meshed: {:?}", //Do nothing on todo mesh removal.
* (todo.pos, todo.started_tick)); */
} }
} }
@ -2452,11 +2378,7 @@ impl<V: RectRasterableVol> Terrain<V> {
loaded_distance: f32, loaded_distance: f32,
view_mat: Mat4<f32>, view_mat: Mat4<f32>,
proj_mat: Mat4<f32>, proj_mat: Mat4<f32>,
) -> ( ) -> (Aabb<f32>, Vec<math::Vec3<f32>>, math::Aabr<f32>) {
Aabb<f32>,
/* Aabb<f32>, Aabb<f32> */ Vec<math::Vec3<f32>>,
math::Aabr<f32>,
) {
let current_tick = scene_data.tick; let current_tick = scene_data.tick;
let current_time = scene_data.state.get_time(); let current_time = scene_data.state.get_time();
let mut visible_bounding_box: Option<Aabb<f32>> = None; let mut visible_bounding_box: Option<Aabb<f32>> = None;
@ -2478,7 +2400,6 @@ impl<V: RectRasterableVol> Terrain<V> {
.map(|c| (false, c)), .map(|c| (false, c)),
) )
{ {
// println!("Terrain chunk change: {:?}", (modified, pos));
// TODO: ANOTHER PROBLEM HERE! // TODO: ANOTHER PROBLEM HERE!
// What happens if the block on the edge of a chunk gets modified? We need to // 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 // spawn a mesh worker to remesh its neighbour(s) too since their
@ -2500,7 +2421,6 @@ impl<V: RectRasterableVol> Terrain<V> {
} }
if neighbours { if neighbours {
// println!("Insert mesh_todo:: {:?}", (pos, current_tick));
self.mesh_todo.insert(pos, ChunkMeshState { self.mesh_todo.insert(pos, ChunkMeshState {
pos, pos,
started_tick: current_tick, started_tick: current_tick,
@ -2521,7 +2441,6 @@ impl<V: RectRasterableVol> Terrain<V> {
.iter() .iter()
.map(|(p, _)| *p) .map(|(p, _)| *p)
{ {
// println!("Terrain block change: {:?}", pos);
let chunk_pos = scene_data.state.terrain().pos_key(pos); let chunk_pos = scene_data.state.terrain().pos_key(pos);
// Only mesh if this chunk has all its neighbors // Only mesh if this chunk has all its neighbors
let mut neighbours = true; let mut neighbours = true;
@ -2535,7 +2454,6 @@ impl<V: RectRasterableVol> Terrain<V> {
} }
} }
if neighbours { if neighbours {
// println!("Insert mesh_todo: {:?}", (chunk_pos, current_tick));
self.mesh_todo.insert(chunk_pos, ChunkMeshState { self.mesh_todo.insert(chunk_pos, ChunkMeshState {
pos: chunk_pos, pos: chunk_pos,
started_tick: current_tick, started_tick: current_tick,
@ -2566,8 +2484,6 @@ impl<V: RectRasterableVol> Terrain<V> {
} }
} }
if neighbours { if neighbours {
// println!("Insert mesh_todo:: {:?}", (neighbour_chunk_pos,
// current_tick));
self.mesh_todo.insert(neighbour_chunk_pos, ChunkMeshState { self.mesh_todo.insert(neighbour_chunk_pos, ChunkMeshState {
pos: neighbour_chunk_pos, pos: neighbour_chunk_pos,
started_tick: current_tick, started_tick: current_tick,
@ -2673,8 +2589,6 @@ impl<V: RectRasterableVol> Terrain<V> {
// data structure (convert the mesh to a model first of course). // data structure (convert the mesh to a model first of course).
Some(todo) if response.started_tick <= todo.started_tick => { Some(todo) if response.started_tick <= todo.started_tick => {
let 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 let load_time = self
.chunks .chunks
.get(&response.pos) .get(&response.pos)
@ -2682,30 +2596,6 @@ impl<V: RectRasterableVol> Terrain<V> {
.unwrap_or(current_time as f32); .unwrap_or(current_time as f32);
// TODO: Allocate new atlas on allocation faillure. // TODO: Allocate new atlas on allocation faillure.
let (tex, tex_size) = response.col_lights_info; 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 atlas = &mut self.atlas;
let allocation = atlas let allocation = atlas
.allocate(guillotiere::Size::new( .allocate(guillotiere::Size::new(
@ -2713,57 +2603,13 @@ impl<V: RectRasterableVol> Terrain<V> {
i32::from(tex_size.y), i32::from(tex_size.y),
)) ))
.expect("Not yet implemented: allocate new atlas on allocation faillure."); .expect("Not yet implemented: allocate new atlas on allocation faillure.");
// println!("Allocation {:?} for {:?} (original size = {:?}... ugh)", // NOTE: Cast is safe since the origin was a u16.
// allocation, response.pos, tex_size); NOTE: Cast is safe
// since the origin was a u16.
let atlas_offs = Vec2::new( let atlas_offs = Vec2::new(
allocation.rectangle.min.x as u16, allocation.rectangle.min.x as u16,
allocation.rectangle.min.y 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( if let Err(err) = renderer.update_texture(
&self.col_lights, &self.col_lights,
// &col_lights,
// NOTE: Cast is safe since the origin was a u16.
atlas_offs.into_array(), atlas_offs.into_array(),
tex_size.into_array(), tex_size.into_array(),
&tex, &tex,
@ -2785,27 +2631,10 @@ impl<V: RectRasterableVol> Terrain<V> {
} else { } else {
None None
}, },
/* shadow_model: renderer col_lights: allocation.id,
.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(), */
sprite_instances: response sprite_instances: response
.sprite_instances .sprite_instances
.into_iter() .into_iter()
.map(|(kind, instances)| { .map(|(kind, instances)| {
( (
kind, kind,
@ -2823,7 +2652,13 @@ impl<V: RectRasterableVol> Terrain<V> {
}), }),
) )
.into_array(), .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, load_time,
}]) }])
.expect("Failed to upload chunk locals to the GPU!"), .expect("Failed to upload chunk locals to the GPU!"),
@ -2835,25 +2670,17 @@ impl<V: RectRasterableVol> Terrain<V> {
}); });
if response.started_tick == started_tick { if response.started_tick == started_tick {
// println!("Terrain chunk removed from meshing: {:?}", (response.pos,
// response.started_tick));
self.mesh_todo.remove(&response.pos); self.mesh_todo.remove(&response.pos);
} }
}, },
// Chunk must have been removed, or it was spawned on an old tick. Drop the mesh // 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. // since it's either out of date or no longer needed.
Some(_todo) => { 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); */
},
None => {}, None => {},
} }
} }
// Construct view frustum // 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 focus_off = focus_pos.map(|e| e.trunc());
let frustum = Frustum::from_modelview_projection( let frustum = Frustum::from_modelview_projection(
(proj_mat * view_mat * Mat4::translation_3d(-focus_off)).into_col_arrays(), (proj_mat * view_mat * Mat4::translation_3d(-focus_off)).into_col_arrays(),
@ -2861,13 +2688,6 @@ impl<V: RectRasterableVol> Terrain<V> {
// Update chunk visibility // Update chunk visibility
let chunk_sz = V::RECT_SIZE.x as f32; 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 { for (pos, chunk) in &mut self.chunks {
let chunk_pos = pos.map(|e| e as f32 * chunk_sz); 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), min: Vec3::from(chunk_min),
max: Vec3::from(chunk_max), max: Vec3::from(chunk_max),
}; };
// scene_bounding_box.expand_to_contain(chunk_box);
if in_frustum { 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; let visible_box = chunk_box;
visible_bounding_box = visible_bounding_box visible_bounding_box = visible_bounding_box
.map(|e| e.union(visible_box)) .map(|e| e.union(visible_box))
.or(Some(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 // FIXME: Hack that only works when only the lantern casts point shadows
// (and hardcodes the shadow distance). Should ideally exist per-light, too. // (and hardcodes the shadow distance). Should ideally exist per-light, too.
@ -2929,17 +2739,11 @@ impl<V: RectRasterableVol> Terrain<V> {
// PSRs: potential shadow receivers // PSRs: potential shadow receivers
let visible_bounding_box = visible_bounding_box.unwrap_or(Aabb { let visible_bounding_box = visible_bounding_box.unwrap_or(Aabb {
min: focus_pos - 2.0, /* min: focus_pos - 2.0,
* - 0.5 */ max: focus_pos + 2.0,
max: focus_pos + 2.0, /* + 0.5 */
}); });
// PSCs: Potential shadow casters // 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 ray_direction = scene_data.get_sun_dir();
let collides_with_aabr = |a: math::Aabr<f32>, b: math::Aabr<f32>| { 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() a.min.partial_cmple(&b.max).reduce_and() && a.max.partial_cmpge(&b.min).reduce_and()
@ -2956,11 +2760,10 @@ impl<V: RectRasterableVol> Terrain<V> {
min: math::Vec3::from(visible_bounding_box.min.map(f64::from)), min: math::Vec3::from(visible_bounding_box.min.map(f64::from)),
max: math::Vec3::from(visible_bounding_box.max.map(f64::from)), max: math::Vec3::from(visible_bounding_box.max.map(f64::from)),
}; };
let inv_proj_view = math::Mat4::from_col_arrays( let inv_proj_view =
(proj_mat * view_mat/* * Mat4::translation_3d(-focus_off)*/).into_col_arrays(), math::Mat4::from_col_arrays((proj_mat * view_mat).into_col_arrays())
) .map(f64::from)
.map(f64::from) .inverted();
.inverted();
let ray_direction = math::Vec3::<f32>::from(ray_direction); let ray_direction = math::Vec3::<f32>::from(ray_direction);
let visible_light_volume = math::calc_focused_light_volume_points( let visible_light_volume = math::calc_focused_light_volume_points(
inv_proj_view, inv_proj_view,
@ -2971,44 +2774,16 @@ impl<V: RectRasterableVol> Terrain<V> {
.map(|v| v.map(|e| e as f32)) .map(|v| v.map(|e| e as f32))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let cam_pos = math::Vec4::from(view_mat.inverted() * Vec4::unit_w()).xyz()/* + focus_off*/; let cam_pos = math::Vec4::from(view_mat.inverted() * Vec4::unit_w()).xyz();
/* let view_dir = (focus_pos.map(f32::fract)) - cam_pos; let up: math::Vec3<f32> = { math::Vec3::up() };
// 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 ray_mat = math::Mat4::look_at_rh( let ray_mat = math::Mat4::look_at_rh(cam_pos, cam_pos + ray_direction, up);
cam_pos,
cam_pos + ray_direction,
up,
// Vec3::up(),
);
// println!("old: {:?} new: {:?}", visible_bounding_box, visible_light_volume);
let visible_bounds = math::Aabr::from(math::fit_psr( let visible_bounds = math::Aabr::from(math::fit_psr(
ray_mat, ray_mat,
/* super::aabb_to_points(visible_bounding_box).iter().copied() */
visible_light_volume.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 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 can_shadow_sun = |pos: Vec2<i32>, chunk: &TerrainChunkData| {
let chunk_pos = pos.map(|e| e as f32 * chunk_sz); 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( let chunk_from_light = math::Aabr::from(math::fit_psr(
ray_mat, ray_mat,
math::aabb_to_points(chunk_box).iter().copied(), 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) 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 // Handle potential shadow casters (chunks that aren't visible, but are still in
@ -3059,7 +2823,7 @@ impl<V: RectRasterableVol> Terrain<V> {
// If the sun can currently cast shadows, we retain only those shadow chunks // If the sun can currently cast shadows, we retain only those shadow chunks
// that both: 1. have not been replaced by a real chunk instance, // that both: 1. have not been replaced by a real chunk instance,
// and 2. are currently potential shadow casters (as witnessed by // and 2. are currently potential shadow casters (as witnessed by
// `can_shadow_sun` returning true). // `can_shadow_sun` returning true).
// //
// NOTE: Please make sure this runs *after* any code that could insert a chunk! // NOTE: Please make sure this runs *after* any code that could insert a chunk!
// Otherwise we may end up with multiple instances of the chunk trying to cast // Otherwise we may end up with multiple instances of the chunk trying to cast
@ -3078,63 +2842,8 @@ impl<V: RectRasterableVol> Terrain<V> {
max: math::Vec2::zero(), 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_bounding_box,
visible_light_volume, visible_light_volume,
visible_psr_bounds, visible_psr_bounds,
@ -3155,11 +2864,8 @@ impl<V: RectRasterableVol> Terrain<V> {
pub fn render_shadows( pub fn render_shadows(
&self, &self,
renderer: &mut Renderer, renderer: &mut Renderer,
globals: &Consts<Globals>, global: &GlobalModel,
// lights: &Consts<Light>, (is_daylight, light_data): super::LightData,
shadow_mats: &Consts<ShadowLocals>,
light_data: &[Light],
is_daylight: bool,
focus_pos: Vec3<f32>, focus_pos: Vec3<f32>,
) { ) {
if !renderer.render_mode().shadow.is_map() { if !renderer.render_mode().shadow.is_map() {
@ -3177,8 +2883,6 @@ impl<V: RectRasterableVol> Terrain<V> {
}) })
.take(self.chunks.len()); .take(self.chunks.len());
// let is_daylight = sun_dir.z < 0.0/*0.6*/;
// Directed shadows // Directed shadows
// //
// NOTE: We also render shadows for dead chunks that were found to still be // 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| { .for_each(|chunk| {
// Directed light shadows. // Directed light shadows.
renderer.render_terrain_shadow_directed( renderer.render_terrain_shadow_directed(
// &chunk.shadow_model,
&chunk.opaque_model, &chunk.opaque_model,
globals, global,
&chunk.locals, &chunk.locals,
shadow_mats, &global.shadow_mats,
/* lights, */
/* shadows,
* &lod.alt,
* &lod.horizon, */
); );
}); });
} }
@ -3212,17 +2911,11 @@ impl<V: RectRasterableVol> Terrain<V> {
light_data.iter().take(1).for_each(|_light| { light_data.iter().take(1).for_each(|_light| {
chunk_iter.clone().for_each(|chunk| { chunk_iter.clone().for_each(|chunk| {
if chunk.can_shadow_point { if chunk.can_shadow_point {
// shadow_vertex_count += chunk.shadow_model.vertex_range.len();
renderer.render_shadow_point( renderer.render_shadow_point(
&chunk.opaque_model, &chunk.opaque_model,
// &chunk.shadow_model, global,
globals,
&chunk.locals, &chunk.locals,
shadow_mats, &global.shadow_mats,
/* lights, */
/* shadows,
* &lod.alt,
* &lod.horizon, */
); );
} }
}); });
@ -3232,14 +2925,9 @@ impl<V: RectRasterableVol> Terrain<V> {
pub fn render( pub fn render(
&self, &self,
renderer: &mut Renderer, renderer: &mut Renderer,
globals: &Consts<Globals>, global: &GlobalModel,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
shadow_mats: &Consts<ShadowLocals>,
lod: &LodData, lod: &LodData,
focus_pos: Vec3<f32>, 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| { let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
(e as i32).div_euclid(sz as i32) (e as i32).div_euclid(sz as i32)
@ -3252,105 +2940,23 @@ impl<V: RectRasterableVol> Terrain<V> {
}) })
.take(self.chunks.len()); .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 { for (_, chunk) in chunk_iter {
// terrain_vertex_count += chunk.opaque_model.vertex_range.len(); if chunk.visible == Visibility::Visible {
if chunk.visible == Visibility::Visible
/* || chunk.can_shadow_sun() */
{
renderer.render_terrain_chunk( renderer.render_terrain_chunk(
&chunk.opaque_model, &chunk.opaque_model,
// &chunk.shadow_model,
// &chunk.col_lights,
&self.col_lights, &self.col_lights,
globals, global,
&chunk.locals, &chunk.locals,
lights, lod,
shadows,
shadow_mats,
&lod.alt,
&lod.horizon,
); );
} }
} }
/* 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( pub fn render_translucent(
&self, &self,
renderer: &mut Renderer, renderer: &mut Renderer,
globals: &Consts<Globals>, global: &GlobalModel,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
shadow_mats: &Consts<ShadowLocals>,
lod: &LodData, lod: &LodData,
focus_pos: Vec3<f32>, focus_pos: Vec3<f32>,
cam_pos: Vec3<f32>, cam_pos: Vec3<f32>,
@ -3394,49 +3000,31 @@ impl<V: RectRasterableVol> Terrain<V> {
chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5, chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5,
)); ));
if focus_dist_sqrd < sprite_render_distance.powf(2.0) { if focus_dist_sqrd < sprite_render_distance.powf(2.0) {
for (kind, /*(instances, instance_count)*/instances) in (&chunk.sprite_instances).into_iter()/*.take(1)*/ { for (kind, instances) in (&chunk.sprite_instances).into_iter() {
let SpriteData { model, locals, .. } = let SpriteData { model, locals, .. } = if sprite_config_for(kind.0)
if sprite_config_for(kind.0).map(|config| config.wind_sway >= 0.4).unwrap_or(false) && dist_sqrd <= chunk_mag .map(|config| config.wind_sway >= 0.4)
|| dist_sqrd < sprite_high_detail_distance.powf(2.0) { .unwrap_or(false)
&self.sprite_models[&kind][0] && dist_sqrd <= chunk_mag
} else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) { || dist_sqrd < sprite_high_detail_distance.powf(2.0)
&self.sprite_models[&kind][1] {
} else if dist_sqrd < sprite_mid_detail_distance.powf(2.0) { &self.sprite_models[&kind][0]
&self.sprite_models[&kind][2] } else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) {
} else if dist_sqrd < sprite_low_detail_distance.powf(2.0) { &self.sprite_models[&kind][1]
&self.sprite_models[&kind][3] } else if dist_sqrd < sprite_mid_detail_distance.powf(2.0) {
} else { &self.sprite_models[&kind][2]
&self.sprite_models[&kind][4] } else if dist_sqrd < sprite_low_detail_distance.powf(2.0) {
}; &self.sprite_models[&kind][3]
} else {
&self.sprite_models[&kind][4]
};
renderer.render_sprites( 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, model,
&self.sprite_col_lights, &self.sprite_col_lights,
globals, global,
&chunk.locals, &chunk.locals,
locals, locals,
// *instance_count,
&instances, &instances,
lights, lod,
shadows,
shadow_mats,
&lod.alt,
&lod.horizon,
); );
} }
} }
@ -3459,13 +3047,9 @@ impl<V: RectRasterableVol> Terrain<V> {
.for_each(|(model, locals)| { .for_each(|(model, locals)| {
renderer.render_fluid_chunk( renderer.render_fluid_chunk(
model, model,
globals, global,
locals, locals,
lights, lod,
shadows,
shadow_mats,
&lod.alt,
&lod.horizon,
&self.waves, &self.waves,
) )
}); });