mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fix all clippy issues, clean up Rust code.
This commit is contained in:
parent
6f90e010b3
commit
c79f512f84
@ -233,10 +233,7 @@ impl Client {
|
||||
map_size_lg,
|
||||
core::ops::RangeInclusive::new(0.0, max_height),
|
||||
);
|
||||
// map_config.gain = max_height;
|
||||
map_config.horizons = Some(&horizons);
|
||||
// map_config.light_direction = Vec3::new(1.0, -1.0, 0.0);
|
||||
// map_config.focus.z = 0.0;
|
||||
let rescale_height = |h: f32| h / max_height;
|
||||
let bounds_check = |pos: Vec2<i32>| {
|
||||
pos.reduce_partial_min() >= 0
|
||||
@ -308,8 +305,7 @@ impl Client {
|
||||
},
|
||||
);
|
||||
let make_raw = |rgba| -> Result<_, Error> {
|
||||
let mut raw =
|
||||
vec![0u8; 4 * world_map.len()/*map_size.x * map_size.y*/];
|
||||
let mut raw = vec![0u8; 4 * world_map.len()];
|
||||
LittleEndian::write_u32_into(rgba, &mut raw);
|
||||
Ok(Arc::new(
|
||||
image::DynamicImage::ImageRgba8({
|
||||
@ -323,15 +319,14 @@ impl Client {
|
||||
.flipv(),
|
||||
))
|
||||
};
|
||||
let lod_base = rgba; //make_raw(&rgba)?;
|
||||
let lod_alt = alt; //make_raw(&alt)?;
|
||||
let lod_base = rgba;
|
||||
let lod_alt = alt;
|
||||
let world_map = make_raw(&world_map)?;
|
||||
let horizons = (west.0, west.1, east.0, east.1)
|
||||
.into_par_iter()
|
||||
.map(|(wa, wh, ea, eh)| u32::from_le_bytes([wa, wh, ea, eh]))
|
||||
.collect::<Vec<_>>();
|
||||
let lod_horizon = horizons; //make_raw(&horizons)?;
|
||||
// TODO: Get sea_level from server.
|
||||
let lod_horizon = horizons;
|
||||
let map_bounds = Vec2::new(sea_level, max_height);
|
||||
debug!("Done preparing image...");
|
||||
|
||||
|
@ -157,7 +157,7 @@ impl MapSizeLg {
|
||||
#[inline(always)]
|
||||
pub const fn new(map_size_lg: Vec2<u32>) -> Result<Self, ()> {
|
||||
// Assertion on dimensions: must be between
|
||||
// 0 and MAX_WORLD_BLOCKS_LG] - [TERRAIN_CHUNK_BLOCKS_LG
|
||||
// 0 and ([MAX_WORLD_BLOCKS_LG] - [TERRAIN_CHUNK_BLOCKS_LG])
|
||||
let is_le_max = map_size_lg.x <= MAX_WORLD_BLOCKS_LG.x - TERRAIN_CHUNK_BLOCKS_LG
|
||||
&& map_size_lg.y <= MAX_WORLD_BLOCKS_LG.y - TERRAIN_CHUNK_BLOCKS_LG;
|
||||
// Assertion on dimensions: chunks must fit in a u16.
|
||||
@ -667,14 +667,12 @@ impl<'a> MapConfig<'a> {
|
||||
let i_a = Rgb::new(0.1, 0.1, 0.1);
|
||||
// V = direction pointing towards the viewer (e.g. virtual camera).
|
||||
let v = Vec3::new(0.0, 0.0, -1.0).normalized();
|
||||
// let v = Vec3::new(0.0, -1.0, 0.0).normalized();
|
||||
//
|
||||
|
||||
// for each light m,
|
||||
// i_m,d = (RGB) intensity of diffuse component of light source m
|
||||
let i_m_d = Rgb::new(1.0, 1.0, 1.0);
|
||||
// i_m,s = (RGB) intensity of specular component of light source m
|
||||
let i_m_s = Rgb::new(0.45, 0.45, 0.45);
|
||||
// let i_m_s = Rgb::new(0.45, 0.45, 0.45);
|
||||
|
||||
// for each light m and point p,
|
||||
// L_m = (normalized) direction vector from point on surface to light source m
|
||||
|
@ -6,13 +6,3 @@ pub use ::vek::{
|
||||
bezier::repr_c::*, geom::repr_c::*, mat::repr_c::column_major::Mat4, ops::*,
|
||||
quaternion::repr_c::*, transform::repr_c::*, transition::*, vec::repr_c::*,
|
||||
}; */
|
||||
/* pub use vek::{
|
||||
bezier::repr_c::*,
|
||||
geom::repr_c::*,
|
||||
mat::repr_simd::column_major::Mat4,
|
||||
ops::*,
|
||||
quaternion::repr_simd::*,
|
||||
transform::repr_c::*,
|
||||
transition::*,
|
||||
vec::repr_simd::*,
|
||||
}; */
|
||||
|
@ -3,6 +3,13 @@ use vek::*;
|
||||
|
||||
type TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex;
|
||||
|
||||
type TodoRect = (
|
||||
Vec3<i32>,
|
||||
Vec2<Vec3<u16>>,
|
||||
guillotiere::Rectangle,
|
||||
Vec3<i32>,
|
||||
);
|
||||
|
||||
/// `max_size`:
|
||||
///
|
||||
/// `draw_delta`:
|
||||
@ -162,7 +169,7 @@ impl<'a> GreedyMesh<'a> {
|
||||
FS: for<'r> FnMut(&'r mut D, Vec3<i32>, Vec3<i32>, Vec2<Vec3<i32>>) -> Option<(bool, M)>,
|
||||
FP: FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
|
||||
{
|
||||
let (bounds, /* opaque, *//*shadow, */ cont) = greedy_mesh(
|
||||
let (bounds, cont) = greedy_mesh(
|
||||
&mut self.atlas,
|
||||
&mut self.col_lights_size,
|
||||
self.max_size,
|
||||
@ -183,7 +190,10 @@ impl<'a> GreedyMesh<'a> {
|
||||
/// Returns the ColLightsInfo corresponding to the consstructed atlas.
|
||||
pub fn finalize(self) -> ColLightInfo {
|
||||
let cur_size = self.col_lights_size;
|
||||
let col_lights = vec![/*Default::default()*/TerrainVertex::make_col_light(254, Rgb::broadcast(254)); usize::from(cur_size.x) * usize::from(cur_size.y)];
|
||||
let col_lights = vec![
|
||||
TerrainVertex::make_col_light(254, Rgb::broadcast(254));
|
||||
usize::from(cur_size.x) * usize::from(cur_size.y)
|
||||
];
|
||||
let mut col_lights_info = (col_lights, cur_size);
|
||||
self.suspended.into_iter().for_each(|cont| {
|
||||
cont(&mut col_lights_info);
|
||||
@ -209,12 +219,7 @@ fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FC, FO, FS, FP>(
|
||||
mut should_draw,
|
||||
mut push_quad,
|
||||
}: GreedyConfig<D, FL, FC, FO, FS, FP>,
|
||||
) -> (
|
||||
Aabb<u16>,
|
||||
// Mesh<O>,
|
||||
// Mesh<S>,
|
||||
Box<SuspendedMesh<'a>>,
|
||||
)
|
||||
) -> (Aabb<u16>, Box<SuspendedMesh<'a>>)
|
||||
where
|
||||
FL: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
|
||||
FC: for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a,
|
||||
@ -222,24 +227,9 @@ where
|
||||
FS: for<'r> FnMut(&'r mut D, Vec3<i32>, Vec3<i32>, Vec2<Vec3<i32>>) -> Option<(bool, M)>,
|
||||
FP: FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
|
||||
{
|
||||
// let mut opaque_mesh = Mesh::new();
|
||||
// let mut shadow_mesh = Mesh::new();
|
||||
|
||||
// TODO: Collect information to see if we can choose a good value here.
|
||||
let mut todo_rects = Vec::with_capacity(1024);
|
||||
|
||||
/* let mut bounds = Aabb {
|
||||
min: Vec3::zero(),
|
||||
max: Vec3::zero(),
|
||||
}; */
|
||||
|
||||
/* let compute_bounds = |pos: Vec3<usize>, dim: Vec2<usize>, uv: Vec2<Vec3<u16>>/*, norm: Vec3<u16>, faces_forward: bool*/| {
|
||||
Aabb {
|
||||
min: pos,
|
||||
max: pos + uv.x.map(usize::from) * dim.x + uv.y.map(usize::from) * dim.y,
|
||||
}
|
||||
}; */
|
||||
|
||||
// x (u = y, v = z)
|
||||
greedy_mesh_cross_section(
|
||||
Vec3::new(greedy_size.y, greedy_size.z, greedy_size_cross.x),
|
||||
@ -247,7 +237,7 @@ where
|
||||
should_draw(
|
||||
&mut data,
|
||||
draw_delta + Vec3::new(pos.z, pos.x, pos.y),
|
||||
Vec3::unit_x(), /* , pos.z, 0, x_size */
|
||||
Vec3::unit_x(),
|
||||
Vec2::new(Vec3::unit_y(), Vec3::unit_z()),
|
||||
)
|
||||
},
|
||||
@ -255,7 +245,6 @@ where
|
||||
let pos = Vec3::new(pos.z, pos.x, pos.y);
|
||||
let uv = Vec2::new(Vec3::unit_y(), Vec3::unit_z());
|
||||
let norm = Vec3::unit_x();
|
||||
// bounds.expand_to_contain(compute_bounds(pos, dim, uv));
|
||||
let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
|
||||
atlas,
|
||||
&mut todo_rects,
|
||||
@ -267,29 +256,18 @@ where
|
||||
max_size,
|
||||
col_lights_size,
|
||||
) {
|
||||
// assert!(atlas_pos.max.x - atlas_pos.min.x == dim.x as i32);
|
||||
// assert!(atlas_pos.max.y - atlas_pos.min.y == dim.y as i32);
|
||||
atlas_pos
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
create_quad_greedy(
|
||||
// &mut shadow_mesh,
|
||||
// &mut opaque_mesh,
|
||||
/* Vec3::new(pos.z, pos.x, pos.y) */
|
||||
pos,
|
||||
dim,
|
||||
uv,
|
||||
norm,
|
||||
faces_forward,
|
||||
// Rgba::from_opaque(flat_get(pos).color),
|
||||
// lightm
|
||||
// ao,
|
||||
meta,
|
||||
atlas_pos,
|
||||
// |pos| flat_get(pos),
|
||||
// |pos, norm, meta| create_shadow(pos, norm, meta),
|
||||
// |atlas_pos, pos, norm, meta| create_opaque(atlas_pos, pos, norm, meta),
|
||||
|atlas_pos, dim, pos, draw_dim, norm, meta| {
|
||||
push_quad(atlas_pos, dim, pos, draw_dim, norm, meta)
|
||||
},
|
||||
@ -312,7 +290,6 @@ where
|
||||
let pos = Vec3::new(pos.y, pos.z, pos.x);
|
||||
let uv = Vec2::new(Vec3::unit_z(), Vec3::unit_x());
|
||||
let norm = Vec3::unit_y();
|
||||
// bounds.expand_to_contain(compute_bounds(pos, dim, uv));
|
||||
let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
|
||||
atlas,
|
||||
&mut todo_rects,
|
||||
@ -329,18 +306,13 @@ where
|
||||
return;
|
||||
};
|
||||
create_quad_greedy(
|
||||
// &mut shadow_mesh,
|
||||
// &mut opaque_mesh,
|
||||
pos,
|
||||
dim,
|
||||
uv,
|
||||
norm,
|
||||
faces_forward,
|
||||
// Rgba::from_opaque(flat_get(pos).color),
|
||||
meta,
|
||||
atlas_pos,
|
||||
// |pos, norm, meta| create_shadow(pos, norm, meta),
|
||||
// |atlas_pos, pos, norm, meta| create_opaque(atlas_pos, pos, norm, meta),
|
||||
|atlas_pos, dim, pos, draw_dim, norm, meta| {
|
||||
push_quad(atlas_pos, dim, pos, draw_dim, norm, meta)
|
||||
},
|
||||
@ -352,25 +324,17 @@ where
|
||||
greedy_mesh_cross_section(
|
||||
Vec3::new(greedy_size.x, greedy_size.y, greedy_size_cross.z),
|
||||
|pos| {
|
||||
/* if pos.z == 0 {
|
||||
let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
|
||||
let to = flat_get(pos).is_opaque(); //map(|v| v.is_opaque()).unwrap_or(false);
|
||||
if to { Some(false) } else { None }
|
||||
} else */
|
||||
{
|
||||
should_draw(
|
||||
&mut data,
|
||||
draw_delta + Vec3::new(pos.x, pos.y, pos.z),
|
||||
Vec3::unit_z(),
|
||||
Vec2::new(Vec3::unit_x(), Vec3::unit_y()),
|
||||
)
|
||||
}
|
||||
},
|
||||
|pos, dim, &(faces_forward, ref meta)| {
|
||||
let pos = Vec3::new(pos.x, pos.y, pos.z);
|
||||
let uv = Vec2::new(Vec3::unit_x(), Vec3::unit_y());
|
||||
let norm = Vec3::unit_z();
|
||||
// bounds.expand_to_contain(compute_bounds(pos, dim, uv));
|
||||
let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
|
||||
atlas,
|
||||
&mut todo_rects,
|
||||
@ -387,18 +351,13 @@ where
|
||||
return;
|
||||
};
|
||||
create_quad_greedy(
|
||||
// &mut shadow_mesh,
|
||||
// &mut opaque_mesh,
|
||||
pos,
|
||||
dim,
|
||||
uv,
|
||||
norm,
|
||||
faces_forward,
|
||||
// Rgba::from_opaque(flat_get(pos).color),
|
||||
meta,
|
||||
atlas_pos,
|
||||
// |pos, norm, meta| create_shadow(pos, norm, meta),
|
||||
// |atlas_pos, pos, norm, meta| create_opaque(atlas_pos, pos, norm, meta),
|
||||
|atlas_pos, dim, pos, draw_dim, norm, meta| {
|
||||
push_quad(atlas_pos, dim, pos, draw_dim, norm, meta)
|
||||
},
|
||||
@ -406,9 +365,6 @@ where
|
||||
},
|
||||
);
|
||||
|
||||
// NOTE: Safe because bound dimensions actually fit in a u16.
|
||||
// let bounds = bounds.map(|e| e as u16);
|
||||
// NOTE: Safe because draw_delta fits in i16.
|
||||
let bounds = Aabb {
|
||||
min: Vec3::zero(),
|
||||
// NOTE: Safe because greedy_size fit in u16.
|
||||
@ -416,7 +372,6 @@ where
|
||||
};
|
||||
(
|
||||
bounds,
|
||||
/* opaque_mesh, *//*shadow_mesh, */
|
||||
Box::new(move |col_lights_info| {
|
||||
let mut data = data;
|
||||
draw_col_lights(
|
||||
@ -435,7 +390,6 @@ where
|
||||
|
||||
// Greedy meshing a single cross-section.
|
||||
fn greedy_mesh_cross_section<M: PartialEq>(
|
||||
/* mask: &mut [bool], */
|
||||
dims: Vec3<usize>,
|
||||
// Should we draw a face here (below this vertex)? If so, provide its meta information.
|
||||
mut draw_face: impl FnMut(Vec3<i32>) -> Option<M>,
|
||||
@ -477,7 +431,7 @@ fn greedy_mesh_cross_section<M: PartialEq>(
|
||||
.count();
|
||||
let max_y = j + height;
|
||||
// Add quad.
|
||||
push_quads(Vec3::new(i, j, d /* + 1 */), Vec2::new(width, height), ori);
|
||||
push_quads(Vec3::new(i, j, d), Vec2::new(width, height), ori);
|
||||
// Unset mask bits in drawn region, so we don't try to re-draw them.
|
||||
(j..max_y).for_each(|l| {
|
||||
mask[l * dims.x + i..l * dims.x + max_x]
|
||||
@ -498,12 +452,7 @@ fn greedy_mesh_cross_section<M: PartialEq>(
|
||||
|
||||
fn add_to_atlas(
|
||||
atlas: &mut guillotiere::SimpleAtlasAllocator,
|
||||
todo_rects: &mut Vec<(
|
||||
Vec3<i32>,
|
||||
Vec2<Vec3<u16>>,
|
||||
guillotiere::Rectangle,
|
||||
Vec3<i32>,
|
||||
)>,
|
||||
todo_rects: &mut Vec<TodoRect>,
|
||||
pos: Vec3<usize>,
|
||||
uv: Vec2<Vec3<u16>>,
|
||||
dim: Vec2<usize>,
|
||||
@ -542,7 +491,6 @@ fn add_to_atlas(
|
||||
(max texture size={:?}, so we are discarding this rectangle.",
|
||||
pos, dim, max_size
|
||||
);
|
||||
// return None;
|
||||
}
|
||||
// Otherwise, we haven't reached max size yet, so double the size (or reach the
|
||||
// max texture size) and try again.
|
||||
@ -551,7 +499,6 @@ fn add_to_atlas(
|
||||
max_size.height.min(current_size.height.saturating_mul(2)),
|
||||
);
|
||||
atlas.grow(new_size);
|
||||
// atlas.grow((current_size * 2).min(max_size));
|
||||
}
|
||||
// NOTE: Conversion is correct because our initial max size for the atlas was
|
||||
// a u16 and we never grew the atlas, meaning all valid coordinates within the
|
||||
@ -561,14 +508,6 @@ fn add_to_atlas(
|
||||
cur_size.y.max(atlas_rect.max.y as u16),
|
||||
);
|
||||
|
||||
/* let (dim, uv, norm) = if faces_forward {
|
||||
// NOTE: Conversion to u16 safe by function precondition.
|
||||
(dim.map(|e| e as u16), uv, norm)
|
||||
} else {
|
||||
// NOTE: Conversion to u16 safe by function precondition.
|
||||
(Vec2::new(dim.y as u16, dim.x as u16), Vec2::new(uv.y, uv.x), -norm)
|
||||
}; */
|
||||
|
||||
// NOTE: pos can be converted safely from usize to i32 because all legal block
|
||||
// coordinates in this chunk must fit in an i32 (actually we have the much
|
||||
// stronger property that this holds across the whole map).
|
||||
@ -591,46 +530,28 @@ fn add_to_atlas(
|
||||
fn draw_col_lights<D>(
|
||||
(col_lights, cur_size): &mut ColLightInfo,
|
||||
data: &mut D,
|
||||
todo_rects: Vec<(
|
||||
Vec3<i32>,
|
||||
Vec2<Vec3<u16>>,
|
||||
guillotiere::Rectangle,
|
||||
Vec3<i32>,
|
||||
)>,
|
||||
todo_rects: Vec<TodoRect>,
|
||||
draw_delta: Vec3<i32>,
|
||||
mut get_light: impl FnMut(&mut D, Vec3<i32>) -> f32,
|
||||
mut get_color: impl FnMut(&mut D, Vec3<i32>) -> Rgb<u8>,
|
||||
mut get_opacity: impl FnMut(&mut D, Vec3<i32>) -> bool,
|
||||
mut make_col_light: impl FnMut(u8, Rgb<u8>) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType,
|
||||
) {
|
||||
/* for i in 0..todo_rects.len() {
|
||||
for j in 0..todo_rects.len() {
|
||||
if i == j {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert!(!todo_rects[i].2.intersects(&todo_rects[j].2));
|
||||
}
|
||||
} */
|
||||
todo_rects
|
||||
.into_iter()
|
||||
// .rev()
|
||||
.for_each(|(pos, uv, rect, delta)| {
|
||||
todo_rects.into_iter().for_each(|(pos, uv, rect, delta)| {
|
||||
// NOTE: Conversions are safe because width, height, and offset must be
|
||||
// non-negative, and because every allocated coordinate in the atlas must be in
|
||||
// bounds for the original size, max_texture_size, which fit into a u16.
|
||||
let width = (rect.max.x - rect.min.x) as u16;//rect.width() as u16;
|
||||
let height = (rect.max.y - rect.min.y) as u16;//rect.height() as u16;
|
||||
/* if width > 32 || height > 32 {
|
||||
println!("Rect: {:?}", rect);
|
||||
} */
|
||||
let width = (rect.max.x - rect.min.x) as u16;
|
||||
let height = (rect.max.y - rect.min.y) as u16;
|
||||
let left = rect.min.x as u16;
|
||||
let top = rect.min.y as u16;
|
||||
let uv = uv.map(|e| e.map(i32::from));
|
||||
let pos = pos + draw_delta;//Vec3::new(0, 0, z_start - 1);// + mesh_delta;// + draw_delta;
|
||||
let pos = pos + draw_delta;
|
||||
(0..height).for_each(|v| {
|
||||
let start = usize::from(cur_size.x) * usize::from(top + v) + usize::from(left);
|
||||
(0..width).zip(&mut col_lights[start..start + usize::from(width)]).for_each(|(u, col_light)| {
|
||||
(0..width)
|
||||
.zip(&mut col_lights[start..start + usize::from(width)])
|
||||
.for_each(|(u, col_light)| {
|
||||
let pos = pos + uv.x * i32::from(u) + uv.y * i32::from(v);
|
||||
// TODO: Consider optimizing to take advantage of the fact that this whole
|
||||
// face should be facing nothing but air (this is not currently true, but
|
||||
@ -642,33 +563,23 @@ fn draw_col_lights<D>(
|
||||
// direct_opacity, and indirect_uv_opacity is multiplied by
|
||||
// the maximum of both of u and v's indirect opacities (since there are
|
||||
// two choices for how to get to the direct surface).
|
||||
let pos = pos +
|
||||
if u + 1 == width { -uv.x } else { Vec3::zero() } +
|
||||
if v + 1 == height { -uv.y } else { Vec3::zero() };
|
||||
let pos = pos
|
||||
+ if u + 1 == width { -uv.x } else { Vec3::zero() }
|
||||
+ if v + 1 == height { -uv.y } else { Vec3::zero() };
|
||||
let uv = Vec2::new(
|
||||
if u + 1 == width { -uv.x } else { uv.x },
|
||||
if v + 1 == height { -uv.y } else { uv.y },
|
||||
);
|
||||
|
||||
let light_pos = pos + /*range.min + */delta;
|
||||
// let block = flat_get(pos);
|
||||
let light_pos = pos + delta;
|
||||
|
||||
// Currently, we assume that direct_opacity is 1 (if it's 0, you can't see
|
||||
// the face anyway, since it's blocked by the block directly in front of it).
|
||||
// TODO: If we add non-0/1 opacities, fix this.
|
||||
// top-left block
|
||||
// let direct_opacity = !flat_get(pos + delta).is_opaque();
|
||||
// bottom-left block
|
||||
let direct_u_opacity = get_opacity(data, light_pos - uv.x);
|
||||
// top-right block
|
||||
let direct_v_opacity = get_opacity(data, light_pos - uv.y);
|
||||
// top-left block
|
||||
// NOTE: Currently, since we only have 0 / 1 opacities, we don't worry
|
||||
// about whether the uv block itself is opaque, because if it is its light
|
||||
// value will be 0 anyway. But if we add translucent objects, we'll need
|
||||
// to care about uv's opacity as well.
|
||||
// let direct_uv_opacity = !flat_get(pos + delta - uv.x - uv.y).is_opaque();
|
||||
// let indirect_opacity = direct_uv_opacity && (direct_u_opacity || direct_v_opacity) && direct_opacity;
|
||||
|
||||
// NOTE: Since we only support 0/1 opacities currently, we asssume
|
||||
// direct_opacity is 1, and the light value will be zero anyway for objects
|
||||
@ -680,12 +591,16 @@ fn draw_col_lights<D>(
|
||||
// Light from the bottom-right-front block to this vertex always
|
||||
// appears on this face, since it's the block this face is facing (so
|
||||
// it can't be blocked by anything).
|
||||
if /*direct_u_opacity || direct_v_opacity*/true/* || !flat_get(pos - uv.x - uv.y).is_opaque()*//* || !block.is_opaque()*/ { get_light(data, light_pos) } else { 0.0 } +
|
||||
if /*direct_opacity || direct_uv_opacity*/true/* || !flat_get(pos - uv.y).is_opaque()*/ { get_light(data, light_pos - uv.x) } else { 0.0 } +
|
||||
if /*direct_opacity || direct_uv_opacity*/true/* || !flat_get(pos - uv.x).is_opaque()*/ { get_light(data, light_pos - uv.y) } else { 0.0 } +
|
||||
if direct_u_opacity || direct_v_opacity/* || !block.is_opaque()*/ { get_light(data, light_pos - uv.x - uv.y) } else { 0.0 }
|
||||
get_light(data, light_pos)
|
||||
+ get_light(data, light_pos - uv.x)
|
||||
+ get_light(data, light_pos - uv.y)
|
||||
+ if direct_u_opacity || direct_v_opacity {
|
||||
get_light(data, light_pos - uv.x - uv.y)
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
) / 4.0;
|
||||
let col = get_color(data, pos);//.map(Rgba::from_opaque).unwrap_or(Rgba::zero());
|
||||
let col = get_color(data, pos);
|
||||
let light = (darkness * 255.0) as u8;
|
||||
*col_light = make_col_light(light, col);
|
||||
});
|
||||
@ -695,9 +610,7 @@ fn draw_col_lights<D>(
|
||||
|
||||
/// Precondition: when this function is called, atlas_pos should reflect an
|
||||
/// actual valid position in a texture atlas (meaning it should fit into a u16).
|
||||
fn create_quad_greedy</* S: render::Pipeline, *//*O: render::Pipeline, */ M>(
|
||||
// shadow_mesh: &mut Mesh<S>,
|
||||
// opaque_mesh: &mut Mesh<O>,
|
||||
fn create_quad_greedy<M>(
|
||||
origin: Vec3<usize>,
|
||||
dim: Vec2<usize>,
|
||||
uv: Vec2<Vec3<u16>>,
|
||||
@ -705,26 +618,16 @@ fn create_quad_greedy</* S: render::Pipeline, *//*O: render::Pipeline, */ M>(
|
||||
faces_forward: bool,
|
||||
meta: &M,
|
||||
atlas_pos: guillotiere::Rectangle,
|
||||
// origin, norm, meta
|
||||
// create_shadow: impl Fn(Vec3<f32>, Vec3<f32>, &M) -> S::Vertex,
|
||||
// create_opaque: impl Fn(Vec2<u16>, Vec3<f32>, Vec3<f32>, &M) -> O::Vertex,
|
||||
mut push_quad: impl FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
|
||||
) /* -> Quad<ShadowPipeline> */
|
||||
{
|
||||
) {
|
||||
let origin = origin.map(|e| e as f32);
|
||||
/* // NOTE: Conversion to u16 safe by function precondition.
|
||||
let dim = uv.map2(dim.map(|e| e as u16), |e, f| e * f); */
|
||||
// NOTE: Conversion to f32 safe by function precondition (u16 can losslessly
|
||||
// cast to f32, and dim fits in a u16).
|
||||
let draw_dim = uv.map2(dim.map(|e| e as f32), |e, f| e.map(f32::from) * f);
|
||||
let dim = Vec2::new(Vec2::new(dim.x as u16, 0), Vec2::new(0, dim.y as u16));
|
||||
let (draw_dim, dim, /* uv, */ norm) = if faces_forward {
|
||||
/* // NOTE: Conversion to u16 safe by function precondition.
|
||||
(dim.map(|e| e as u16), uv, norm) */
|
||||
(draw_dim, dim, norm)
|
||||
} else {
|
||||
/* // NOTE: Conversion to u16 safe by function precondition.
|
||||
(Vec2::new(dim.y as u16, dim.x as u16), Vec2::new(uv.y, uv.x), -norm) */
|
||||
(
|
||||
Vec2::new(draw_dim.y, draw_dim.x),
|
||||
Vec2::new(dim.y, dim.x),
|
||||
@ -732,21 +635,8 @@ fn create_quad_greedy</* S: render::Pipeline, *//*O: render::Pipeline, */ M>(
|
||||
)
|
||||
};
|
||||
let norm = norm.map(f32::from);
|
||||
// let draw_dim = draw_dim.map(|e| e.map(f32::from));
|
||||
// NOTE: Conversion to u16 safe by function precondition.
|
||||
let atlas_pos = Vec2::new(atlas_pos.min.x as u16, atlas_pos.min.y as u16);
|
||||
/* shadow_mesh.push_quad(Quad::new(
|
||||
create_shadow(origin, norm, &meta/*, atlas_pos*/),
|
||||
create_shadow(origin + draw_dim.x, norm, &meta/*, atlas_pos + dim.x*/),
|
||||
create_shadow(origin + draw_dim.x + draw_dim.y, norm, &meta/*, atlas_pos + dim.x + dim.y*/),
|
||||
create_shadow(origin + draw_dim.y, norm, &meta/*, atlas_pos + dim.y*/),
|
||||
)); */
|
||||
/* opaque_mesh.push_quad(Quad::new(
|
||||
create_opaque(atlas_pos, origin, norm, &meta),
|
||||
create_opaque(atlas_pos + dim.x, origin + draw_dim.x, norm, &meta),
|
||||
create_opaque(atlas_pos + dim.x + dim.y, origin + draw_dim.x + draw_dim.y, norm, &meta),
|
||||
create_opaque(atlas_pos + dim.y, origin + draw_dim.y, norm, &meta),
|
||||
)); */
|
||||
push_quad(atlas_pos, dim, origin, draw_dim, norm, meta);
|
||||
}
|
||||
|
||||
@ -769,9 +659,5 @@ pub fn create_quad<O: render::Pipeline, M>(
|
||||
meta,
|
||||
),
|
||||
create_vertex(atlas_pos + dim.y, origin + draw_dim.y, norm, meta),
|
||||
/* create_vertex(atlas_pos, origin, norm, meta),
|
||||
create_vertex(atlas_pos + dim.y, origin + draw_dim.y, norm, meta),
|
||||
create_vertex(atlas_pos + dim.x + dim.y, origin + draw_dim.x + draw_dim.y, norm, meta),
|
||||
create_vertex(atlas_pos + dim.x, origin + draw_dim.x, norm, meta), */
|
||||
)
|
||||
}
|
||||
|
@ -4,6 +4,13 @@ pub mod terrain;
|
||||
|
||||
use crate::render::{self, Mesh};
|
||||
|
||||
pub type MeshGen<P, T, M> = (
|
||||
Mesh<<M as Meshable<P, T>>::Pipeline>,
|
||||
Mesh<<M as Meshable<P, T>>::TranslucentPipeline>,
|
||||
Mesh<<M as Meshable<P, T>>::ShadowPipeline>,
|
||||
<M as Meshable<P, T>>::Result,
|
||||
);
|
||||
|
||||
pub trait Meshable<P: render::Pipeline, T> {
|
||||
type Pipeline: render::Pipeline;
|
||||
type TranslucentPipeline: render::Pipeline;
|
||||
@ -12,13 +19,5 @@ pub trait Meshable<P: render::Pipeline, T> {
|
||||
type Result;
|
||||
|
||||
// Generate meshes - one opaque, one translucent, one shadow
|
||||
fn generate_mesh(
|
||||
self,
|
||||
supp: Self::Supplement,
|
||||
) -> (
|
||||
Mesh<Self::Pipeline>,
|
||||
Mesh<Self::TranslucentPipeline>,
|
||||
Mesh<Self::ShadowPipeline>,
|
||||
Self::Result,
|
||||
);
|
||||
fn generate_mesh(self, supp: Self::Supplement) -> MeshGen<P, T, Self>;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
mesh::{
|
||||
greedy::{self, GreedyConfig, GreedyMesh},
|
||||
Meshable,
|
||||
MeshGen, Meshable,
|
||||
},
|
||||
render::{self, FigurePipeline, Mesh, ShadowPipeline, SpritePipeline, TerrainPipeline},
|
||||
};
|
||||
@ -32,12 +32,7 @@ where
|
||||
fn generate_mesh(
|
||||
self,
|
||||
(greedy, offs, scale): Self::Supplement,
|
||||
) -> (
|
||||
Mesh<Self::Pipeline>,
|
||||
Mesh<Self::TranslucentPipeline>,
|
||||
Mesh<Self::ShadowPipeline>,
|
||||
Self::Result,
|
||||
) {
|
||||
) -> MeshGen<FigurePipeline, &'b mut GreedyMesh<'a>, Self> {
|
||||
let max_size = greedy.max_size();
|
||||
// NOTE: Required because we steal two bits from the normal in the shadow uint
|
||||
// in order to store the bone index. The two bits are instead taken out
|
||||
@ -114,7 +109,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a: 'b, 'b, V: 'a> Meshable<SpritePipeline, /* SpritePipeline */ &'b mut GreedyMesh<'a>> for V
|
||||
impl<'a: 'b, 'b, V: 'a> Meshable<SpritePipeline, &'b mut GreedyMesh<'a>> for V
|
||||
where
|
||||
V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
|
||||
/* TODO: Use VolIterator instead of manually iterating
|
||||
@ -132,12 +127,7 @@ where
|
||||
fn generate_mesh(
|
||||
self,
|
||||
(greedy, vertical_stripes): Self::Supplement,
|
||||
) -> (
|
||||
Mesh<Self::Pipeline>,
|
||||
Mesh<Self::TranslucentPipeline>,
|
||||
Mesh<Self::ShadowPipeline>,
|
||||
(),
|
||||
) {
|
||||
) -> MeshGen<SpritePipeline, &'b mut GreedyMesh<'a>, Self> {
|
||||
let max_size = greedy.max_size();
|
||||
// NOTE: Required because we steal two bits from the normal in the shadow uint
|
||||
// in order to store the bone index. The two bits are instead taken out
|
||||
@ -182,15 +172,8 @@ where
|
||||
vol.get(vox).map(|vox| *vox).unwrap_or(Vox::empty())
|
||||
})
|
||||
};
|
||||
// NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16.
|
||||
// let create_shadow = |pos, norm, _meta| ShadowVertex::new_figure((pos + offs)
|
||||
// * scale, norm, 0);
|
||||
let create_opaque = |atlas_pos, pos: Vec3<f32>, norm, _meta| {
|
||||
/* if pos.x >= 15.0 || pos.y >= 15.0 || pos.z >= 63.0 {
|
||||
println!("{:?}", pos);
|
||||
} */
|
||||
SpriteVertex::new(atlas_pos, pos, norm /* , ao */)
|
||||
};
|
||||
let create_opaque =
|
||||
|atlas_pos, pos: Vec3<f32>, norm, _meta| SpriteVertex::new(atlas_pos, pos, norm);
|
||||
|
||||
let mut opaque_mesh = Mesh::new();
|
||||
let _bounds = greedy.push(GreedyConfig {
|
||||
@ -224,10 +207,8 @@ fn should_draw_greedy(
|
||||
_uv: Vec2<Vec3<i32>>,
|
||||
flat_get: impl Fn(Vec3<i32>) -> Cell,
|
||||
) -> Option<(bool, /* u8 */ ())> {
|
||||
// TODO: Verify conversion.
|
||||
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
|
||||
let from = flat_get(pos - delta); // map(|v| v.is_opaque()).unwrap_or(false);
|
||||
let to = flat_get(pos); //map(|v| v.is_opaque()).unwrap_or(false);
|
||||
let from = flat_get(pos - delta);
|
||||
let to = flat_get(pos);
|
||||
let from_opaque = !from.is_empty();
|
||||
if from_opaque == !to.is_empty() {
|
||||
None
|
||||
@ -244,52 +225,17 @@ fn should_draw_greedy_ao(
|
||||
delta: Vec3<i32>,
|
||||
_uv: Vec2<Vec3<i32>>,
|
||||
flat_get: impl Fn(Vec3<i32>) -> Cell,
|
||||
) -> Option<(bool, /* u8 */ bool)> {
|
||||
// TODO: Verify conversion.
|
||||
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
|
||||
let from = flat_get(pos - delta); // map(|v| v.is_opaque()).unwrap_or(false);
|
||||
let to = flat_get(pos); //map(|v| v.is_opaque()).unwrap_or(false);
|
||||
) -> Option<(bool, bool)> {
|
||||
let from = flat_get(pos - delta);
|
||||
let to = flat_get(pos);
|
||||
let from_opaque = !from.is_empty();
|
||||
if from_opaque == !to.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let faces_forward = from_opaque;
|
||||
let ao = /* if delta.z != 0 {
|
||||
0u8
|
||||
} else {
|
||||
(pos.z & 1) as u8
|
||||
// (((pos.x & 1) as u8) << 1) | (pos.y & 1) as u8
|
||||
}*/!vertical_stripes || /*((pos.x & 1) ^ (pos.y & 1))*/(pos.z & 1) != 0/* as u8*/;
|
||||
/* let (from, delta, uv) = if faces_forward {
|
||||
(pos - delta - uv.x - uv.y, delta, uv)
|
||||
} else {
|
||||
(pos, -delta, Vec2::new(-uv.y, -uv.x))
|
||||
};
|
||||
let ao_vertex = |from: Vec3<i32>, delta: Vec3<i32>, uv: Vec2<Vec3<i32>>| {
|
||||
let corner = !flat_get(from + delta - uv.x - uv.y).is_empty();
|
||||
let s1 = !flat_get(from + delta - uv.x).is_empty();
|
||||
let s2 = !flat_get(from + delta - uv.y).is_empty();
|
||||
if s1 && s2 {
|
||||
0
|
||||
} else {
|
||||
3 - (if corner { 1 } else { 0 } + if s1 { 1 } else { 0 } + if s2 { 1 } else { 0 })
|
||||
}
|
||||
};
|
||||
// We only care about the vertices we are *not* merging, since the shared vertices
|
||||
// by definition have the same AO values. But snce we go both down and right we end up
|
||||
// needing all but the bottom right vertex.
|
||||
let ao_corner = ao_vertex(from, delta, uv);
|
||||
let ao1 = ao_vertex(from + uv.x, delta, uv);
|
||||
let ao2 = ao_vertex(from + uv.y, delta, uv);
|
||||
let ao3 = ao_vertex(from + uv.x + uv.y, delta, uv);
|
||||
// NOTE: ao's 4 values correspond (from 0 to 3) to 0.25, 0.5, 0.75, 1.0.
|
||||
//
|
||||
// 0.0 is the None case.
|
||||
let ao = (ao_corner << 6) | (ao1 << 4) | (ao2 << 2) | ao3; */
|
||||
// let ao = ao_vertex(from, delta, uv);
|
||||
let ao = !vertical_stripes || (pos.z & 1) != 0;
|
||||
// If going from transparent to opaque, backward facing; otherwise, forward
|
||||
// facing.
|
||||
Some((faces_forward, ao))
|
||||
// Some((faces_forward, ()))
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
mesh::{
|
||||
greedy::{self, GreedyConfig, GreedyMesh},
|
||||
Meshable,
|
||||
MeshGen, Meshable,
|
||||
},
|
||||
render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline},
|
||||
};
|
||||
@ -230,12 +230,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
fn generate_mesh(
|
||||
self,
|
||||
(range, max_texture_size): Self::Supplement,
|
||||
) -> (
|
||||
Mesh<Self::Pipeline>,
|
||||
Mesh<Self::TranslucentPipeline>,
|
||||
Mesh<Self::ShadowPipeline>,
|
||||
Self::Result,
|
||||
) {
|
||||
) -> MeshGen<TerrainPipeline, FluidPipeline, Self> {
|
||||
let mut light = calc_light(range, self);
|
||||
|
||||
let mut lowest_opaque = range.size().d;
|
||||
@ -315,180 +310,6 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
}
|
||||
.min(range.size().d - 1);
|
||||
|
||||
// // We use multiple meshes and then combine them later such that we can group
|
||||
// similar z // levels together (better rendering performance)
|
||||
// let mut opaque_meshes = vec![Mesh::new(); ((z_end + 1 - z_start).clamped(1,
|
||||
// 60) as usize / 10).max(1)];
|
||||
// let mut opaque_mesh = Mesh::new();
|
||||
// let mut fluid_mesh = Mesh::new();
|
||||
|
||||
/* for x in 1..range.size().w - 1 {
|
||||
for y in 1..range.size().w - 1 {
|
||||
let mut blocks = [[[None; 3]; 3]; 3];
|
||||
for i in 0..3 {
|
||||
for j in 0..3 {
|
||||
for k in 0..3 {
|
||||
blocks[k][j][i] = Some(flat_get(
|
||||
Vec3::new(x, y, z_start) + Vec3::new(i as i32, j as i32, k as i32)
|
||||
- 1,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut lights = [[[None; 3]; 3]; 3];
|
||||
for i in 0..3 {
|
||||
for j in 0..3 {
|
||||
for k in 0..3 {
|
||||
lights[k][j][i] = if blocks[k][j][i]
|
||||
.map(|block| block.is_opaque())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(light(
|
||||
Vec3::new(
|
||||
x + range.min.x,
|
||||
y + range.min.y,
|
||||
z_start + range.min.z,
|
||||
) + Vec3::new(i as i32, j as i32, k as i32)
|
||||
- 1,
|
||||
))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let get_color = |maybe_block: Option<&Block>, neighbour: bool| {
|
||||
maybe_block
|
||||
.filter(|vox| vox.is_opaque() && (!neighbour || vox.is_blended()))
|
||||
.and_then(|vox| vox.get_color())
|
||||
.map(Rgba::from_opaque)
|
||||
.unwrap_or(Rgba::zero())
|
||||
};
|
||||
|
||||
for z in z_start..z_end + 1 {
|
||||
let pos = Vec3::new(x, y, z);
|
||||
let offs = (pos - Vec3::new(1, 1, -range.min.z)).map(|e| e as f32);
|
||||
|
||||
lights[0] = lights[1];
|
||||
lights[1] = lights[2];
|
||||
blocks[0] = blocks[1];
|
||||
blocks[1] = blocks[2];
|
||||
|
||||
for i in 0..3 {
|
||||
for j in 0..3 {
|
||||
let block = Some(flat_get(pos + Vec3::new(i as i32, j as i32, 2) - 1));
|
||||
blocks[2][j][i] = block;
|
||||
}
|
||||
}
|
||||
for i in 0..3 {
|
||||
for j in 0..3 {
|
||||
lights[2][j][i] = if blocks[2][j][i]
|
||||
.map(|block| block.is_opaque())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(light(
|
||||
pos + range.min + Vec3::new(i as i32, j as i32, 2) - 1,
|
||||
))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let block = blocks[1][1][1];
|
||||
let colors = if block.map_or(false, |vox| vox.is_blended()) {
|
||||
let mut colors = [[[Rgba::zero(); 3]; 3]; 3];
|
||||
for i in 0..3 {
|
||||
for j in 0..3 {
|
||||
for k in 0..3 {
|
||||
colors[i][j][k] = get_color(
|
||||
blocks[i][j][k].as_ref(),
|
||||
i != 1 || j != 1 || k != 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
colors
|
||||
} else {
|
||||
[[[get_color(blocks[1][1][1].as_ref(), false); 3]; 3]; 3]
|
||||
};
|
||||
|
||||
// let opaque_mesh_index = ((z - z_start) * opaque_meshes.len() as i32 / (z_end
|
||||
// + 1 - z_start).max(1)) as usize; let selected_opaque_mesh
|
||||
// = &mut opaque_meshes[opaque_mesh_index]; Create mesh
|
||||
// polygons
|
||||
/* if block.map_or(false, |vox| vox.is_opaque()) {
|
||||
vol::push_vox_verts(
|
||||
&mut opaque_mesh, //selected_opaque_mesh,
|
||||
faces_to_make(&blocks, None, |vox| {
|
||||
if vox.is_opaque() {
|
||||
None
|
||||
} else {
|
||||
Some(vox.is_fluid())
|
||||
}
|
||||
}),
|
||||
offs,
|
||||
&colors,
|
||||
|pos, norm, col, light, ao, &meta| {
|
||||
//let light = (light.min(ao) * 255.0) as u32;
|
||||
let light = (light * 255.0) as u32;
|
||||
let ao = (ao * 255.0) as u32;
|
||||
let norm = if norm.x != 0.0 {
|
||||
if norm.x < 0.0 { 0 } else { 1 }
|
||||
} else if norm.y != 0.0 {
|
||||
if norm.y < 0.0 { 2 } else { 3 }
|
||||
} else {
|
||||
if norm.z < 0.0 { 4 } else { 5 }
|
||||
};
|
||||
TerrainVertex::new(norm, light, ao, pos, col, meta)
|
||||
},
|
||||
&lights,
|
||||
);
|
||||
} else */if block.map_or(false, |vox| vox.is_fluid()) {
|
||||
vol::push_vox_verts(
|
||||
&mut fluid_mesh,
|
||||
// NOTE: want to skip blocks that aren't either next to air, or next to
|
||||
// opaque blocks like ground. Addnig the blocks next to ground lets us
|
||||
// make sure we compute lighting effects both at the water surface, and
|
||||
// just before hitting the ground.
|
||||
faces_to_make(&blocks, Some(()), |vox| {
|
||||
if vox.is_air() { Some(()) } else { None }
|
||||
}),
|
||||
offs,
|
||||
&colors,
|
||||
|pos, norm, col, light, _ao, _meta| {
|
||||
/* let rel_pos = pos - offs;
|
||||
let rel_vox_pos = if rel_pos == offs {
|
||||
rel_pos + norm + 1.0
|
||||
} else {
|
||||
rel_pos + 1.0
|
||||
}.map(|e| e as usize);
|
||||
let vox_neighbor = blocks[rel_vox_pos.z][rel_vox_pos.y][rel_vox_pos.x];
|
||||
if vox_neighbor.is_opaque() {
|
||||
} else {
|
||||
} */
|
||||
FluidVertex::new(pos, norm, col, light, 0.3)
|
||||
},
|
||||
&lights,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// let opaque_mesh = opaque_meshes
|
||||
// .into_iter()
|
||||
// .rev()
|
||||
// .fold(Mesh::new(), |mut opaque_mesh, m: Mesh<Self::Pipeline>| {
|
||||
// m.verts().chunks_exact(3).rev().for_each(|vs| {
|
||||
// opaque_mesh.push(vs[0]);
|
||||
// opaque_mesh.push(vs[1]);
|
||||
// opaque_mesh.push(vs[2]);
|
||||
// });
|
||||
// opaque_mesh
|
||||
// });
|
||||
let max_size =
|
||||
guillotiere::Size::new(i32::from(max_texture_size.x), i32::from(max_texture_size.y));
|
||||
let greedy_size = Vec3::new(
|
||||
@ -508,8 +329,6 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
should_draw_greedy(pos, delta, flat_get)
|
||||
};
|
||||
// NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16.
|
||||
// let create_shadow = |pos, norm, meta| ShadowVertex::new(pos + Vec3::new(0.0,
|
||||
// 0.0, (z_start + range.min.z) as f32), norm, meta);
|
||||
let mesh_delta = Vec3::new(0.0, 0.0, (z_start + range.min.z) as f32);
|
||||
let create_opaque = |atlas_pos, pos, norm, meta| {
|
||||
TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta)
|
||||
@ -560,7 +379,6 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
max: bounds.max + mesh_delta,
|
||||
};
|
||||
let (col_lights, col_lights_size) = greedy.finalize();
|
||||
// println!("z_bounds{:?}, bounds: {:?}", (mesh_delta.z, mesh_delta.z +
|
||||
|
||||
(
|
||||
opaque_mesh,
|
||||
@ -576,10 +394,8 @@ fn should_draw_greedy(
|
||||
delta: Vec3<i32>,
|
||||
flat_get: impl Fn(Vec3<i32>) -> Block,
|
||||
) -> Option<(bool, FaceKind)> {
|
||||
// TODO: Verify conversion.
|
||||
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
|
||||
let from = flat_get(pos - delta); // map(|v| v.is_opaque()).unwrap_or(false);
|
||||
let to = flat_get(pos); //map(|v| v.is_opaque()).unwrap_or(false);
|
||||
let from = flat_get(pos - delta);
|
||||
let to = flat_get(pos);
|
||||
let from_opaque = from.is_opaque();
|
||||
if from_opaque == to.is_opaque() {
|
||||
// Check the interface of fluid and non-tangible non-fluids (e.g. air).
|
||||
|
@ -17,15 +17,6 @@ impl<T: Copy + gfx::traits::Pod> Consts<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/* /// Create a new immutable `Const<T>`.
|
||||
pub fn new_immutable(factory: &mut gfx_backend::Factory, data: &[T]) -> Result<gfx::handle::RawBuffer<T>, RenderError> {
|
||||
Ok(Self {
|
||||
ibuf: factory
|
||||
.create_buffer_immutable_raw(gfx::memory::cast_slice(data), core::mem::size_of::<T>(), gfx::buffer::Role::Constant, gfx::memory::Bind::empty())
|
||||
.map_err(|err| RenderError::BufferCreationError(err))?,
|
||||
})
|
||||
} */
|
||||
|
||||
/// Update the GPU-side value represented by this constant handle.
|
||||
|
||||
pub fn update(
|
||||
|
@ -4,7 +4,6 @@ use std::iter::FromIterator;
|
||||
/// A `Vec`-based mesh structure used to store mesh data on the CPU.
|
||||
pub struct Mesh<P: Pipeline> {
|
||||
verts: Vec<P::Vertex>,
|
||||
// textures: Vec<>
|
||||
}
|
||||
|
||||
impl<P: Pipeline> Clone for Mesh<P>
|
||||
|
@ -21,7 +21,7 @@ pub use self::{
|
||||
Locals as FigureLocals,
|
||||
},
|
||||
fluid::FluidPipeline,
|
||||
lod_terrain::{Locals as LodTerrainLocals, LodTerrainPipeline},
|
||||
lod_terrain::{Locals as LodTerrainLocals, LodData, LodTerrainPipeline},
|
||||
postprocess::{
|
||||
create_mesh as create_pp_mesh, Locals as PostProcessLocals, PostProcessPipeline,
|
||||
},
|
||||
@ -33,7 +33,7 @@ pub use self::{
|
||||
create_quad as create_ui_quad, create_tri as create_ui_tri, Locals as UiLocals,
|
||||
Mode as UiMode, UiPipeline,
|
||||
},
|
||||
Globals, Light, Shadow,
|
||||
GlobalModel, Globals, Light, Shadow,
|
||||
},
|
||||
renderer::{
|
||||
ColLightFmt, ColLightInfo, LodAltFmt, LodColorFmt, LodTextureFmt, Renderer,
|
||||
|
@ -119,7 +119,6 @@ impl Pipeline for FigurePipeline {
|
||||
pub struct FigureModel {
|
||||
pub bounds: Aabb<f32>,
|
||||
pub opaque: Model<TerrainPipeline>,
|
||||
// pub shadow: Model<ShadowPipeline>,
|
||||
// TODO: Consider using mipmaps instead of storing multiple texture atlases for different LOD
|
||||
// levels.
|
||||
pub col_lights: Texture<ColLightFmt>,
|
||||
|
@ -11,7 +11,6 @@ use vek::*;
|
||||
gfx_defines! {
|
||||
vertex Vertex {
|
||||
pos_norm: u32 = "v_pos_norm",
|
||||
// col_light: u32 = "v_col_light",
|
||||
}
|
||||
|
||||
pipeline pipe {
|
||||
@ -41,31 +40,6 @@ gfx_defines! {
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
/* pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, light: f32, _opac: f32) -> Self {
|
||||
let (norm_axis, norm_dir) = norm
|
||||
.as_slice()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.find(|(_i, e)| **e != 0.0)
|
||||
.unwrap_or((0, &1.0));
|
||||
let norm_bits = ((norm_axis << 1) | if *norm_dir > 0.0 { 1 } else { 0 }) as u32;
|
||||
|
||||
const EXTRA_NEG_Z: f32 = 65536.0;
|
||||
|
||||
Self {
|
||||
pos_norm: 0
|
||||
| ((pos.x as u32) & 0x003F) << 0
|
||||
| ((pos.y as u32) & 0x003F) << 6
|
||||
| (((pos.z + EXTRA_NEG_Z).max(0.0).min((1 << 17) as f32) as u32) & 0x1FFFF) << 12
|
||||
| (norm_bits & 0x7) << 29,
|
||||
col_light: 0
|
||||
| ((col.r.mul(200.0) as u32) & 0xFF) << 8
|
||||
| ((col.g.mul(200.0) as u32) & 0xFF) << 16
|
||||
| ((col.b.mul(200.0) as u32) & 0xFF) << 24
|
||||
| ((light.mul(255.0) as u32) & 0xFF) << 0,
|
||||
//| ((opac.mul(0.4) as u32) & 0xFF) << 0,
|
||||
}
|
||||
} */
|
||||
#[allow(clippy::identity_op)] // TODO: Pending review in #587
|
||||
#[allow(clippy::into_iter_on_ref)] // TODO: Pending review in #587
|
||||
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
|
||||
@ -85,12 +59,6 @@ impl Vertex {
|
||||
| ((pos.y as u32) & 0x003F) << 6
|
||||
| (((pos.z + EXTRA_NEG_Z).max(0.0).min((1 << 17) as f32) as u32) & 0x1FFFF) << 12
|
||||
| (norm_bits & 0x7) << 29,
|
||||
/* col_light: 0
|
||||
| ((col.r.mul(200.0) as u32) & 0xFF) << 8
|
||||
| ((col.g.mul(200.0) as u32) & 0xFF) << 16
|
||||
| ((col.b.mul(200.0) as u32) & 0xFF) << 24
|
||||
| ((light.mul(255.0) as u32) & 0xFF) << 0,
|
||||
//| ((opac.mul(0.4) as u32) & 0xFF) << 0, */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
use super::{
|
||||
super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt},
|
||||
super::{
|
||||
LodAltFmt, LodColorFmt, LodTextureFmt, Pipeline, Renderer, Texture, TgtColorFmt,
|
||||
TgtDepthStencilFmt,
|
||||
},
|
||||
Globals,
|
||||
};
|
||||
use gfx::{
|
||||
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
|
||||
gfx_pipeline_inner, gfx_vertex_struct_meta,
|
||||
gfx_pipeline_inner, gfx_vertex_struct_meta, texture::SamplerInfo,
|
||||
};
|
||||
use vek::*;
|
||||
|
||||
@ -51,3 +54,64 @@ pub struct LodTerrainPipeline;
|
||||
impl Pipeline for LodTerrainPipeline {
|
||||
type Vertex = Vertex;
|
||||
}
|
||||
|
||||
pub struct LodData {
|
||||
pub map: Texture<LodColorFmt>,
|
||||
pub alt: Texture<LodAltFmt>,
|
||||
pub horizon: Texture<LodTextureFmt>,
|
||||
pub tgt_detail: u32,
|
||||
}
|
||||
|
||||
impl LodData {
|
||||
pub fn new(
|
||||
renderer: &mut Renderer,
|
||||
map_size: Vec2<u16>,
|
||||
lod_base: &[u32],
|
||||
lod_alt: &[u32],
|
||||
lod_horizon: &[u32],
|
||||
tgt_detail: u32,
|
||||
border_color: gfx::texture::PackedColor,
|
||||
) -> Self {
|
||||
let kind = gfx::texture::Kind::D2(map_size.x, map_size.y, gfx::texture::AaMode::Single);
|
||||
let info = gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Bilinear,
|
||||
gfx::texture::WrapMode::Border,
|
||||
);
|
||||
Self {
|
||||
map: renderer
|
||||
.create_texture_immutable_raw(
|
||||
kind,
|
||||
gfx::texture::Mipmap::Provided,
|
||||
&[gfx::memory::cast_slice(lod_base)],
|
||||
SamplerInfo {
|
||||
border: border_color,
|
||||
..info
|
||||
},
|
||||
)
|
||||
.expect("Failed to generate map texture"),
|
||||
alt: renderer
|
||||
.create_texture_immutable_raw(
|
||||
kind,
|
||||
gfx::texture::Mipmap::Provided,
|
||||
&[gfx::memory::cast_slice(lod_alt)],
|
||||
SamplerInfo {
|
||||
border: [0.0, 0.0, 0.0, 0.0].into(),
|
||||
..info
|
||||
},
|
||||
)
|
||||
.expect("Failed to generate alt texture"),
|
||||
horizon: renderer
|
||||
.create_texture_immutable_raw(
|
||||
kind,
|
||||
gfx::texture::Mipmap::Provided,
|
||||
&[gfx::memory::cast_slice(lod_horizon)],
|
||||
SamplerInfo {
|
||||
border: [1.0, 0.0, 1.0, 0.0].into(),
|
||||
..info
|
||||
},
|
||||
)
|
||||
.expect("Failed to generate horizon texture"),
|
||||
tgt_detail,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ pub mod sprite;
|
||||
pub mod terrain;
|
||||
pub mod ui;
|
||||
|
||||
use super::Consts;
|
||||
use crate::scene::camera::CameraMode;
|
||||
use common::terrain::BlockKind;
|
||||
use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta};
|
||||
@ -25,9 +26,6 @@ gfx_defines! {
|
||||
cam_pos: [f32; 4] = "cam_pos",
|
||||
focus_off: [f32; 4] = "focus_off",
|
||||
focus_pos: [f32; 4] = "focus_pos",
|
||||
/// NOTE: max_intensity is computed as the ratio between the brightest and least bright
|
||||
/// intensities among all lights in the scene.
|
||||
// hdr_ratio: [f32; 4] = "max_intensity",
|
||||
/// NOTE: view_distance.x is the horizontal view distance, view_distance.y is the LOD
|
||||
/// detail, view_distance.z is the
|
||||
/// minimum height over any land chunk (i.e. the sea level), and view_distance.w is the
|
||||
@ -54,7 +52,6 @@ gfx_defines! {
|
||||
constant Light {
|
||||
pos: [f32; 4] = "light_pos",
|
||||
col: [f32; 4] = "light_col",
|
||||
// proj: [[f32; 4]; 4] = "light_proj";
|
||||
}
|
||||
|
||||
constant Shadow {
|
||||
@ -201,3 +198,11 @@ impl Shadow {
|
||||
impl Default for Shadow {
|
||||
fn default() -> Self { Self::new(Vec3::zero(), 0.0) }
|
||||
}
|
||||
|
||||
// Global scene data spread across several arrays.
|
||||
pub struct GlobalModel {
|
||||
pub globals: Consts<Globals>,
|
||||
pub lights: Consts<Light>,
|
||||
pub shadows: Consts<Shadow>,
|
||||
pub shadow_mats: Consts<shadow::Locals>,
|
||||
}
|
||||
|
@ -13,10 +13,7 @@ use vek::*;
|
||||
|
||||
gfx_defines! {
|
||||
vertex Vertex {
|
||||
// pos: [f32; 4] = "v_pos",
|
||||
pos_norm: u32 = "v_pos_norm",
|
||||
// col_light: u32 = "v_col_light",
|
||||
// atlas_pos: u32 = "v_atlas_pos",
|
||||
}
|
||||
|
||||
constant Locals {
|
||||
@ -26,17 +23,10 @@ gfx_defines! {
|
||||
|
||||
pipeline pipe {
|
||||
// Terrain vertex stuff
|
||||
vbuf: gfx::VertexBuffer</*Vertex*/terrain::Vertex> = (),
|
||||
vbuf: gfx::VertexBuffer<terrain::Vertex> = (),
|
||||
|
||||
locals: gfx::ConstantBuffer<TerrainLocals> = "u_locals",
|
||||
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||
// lights: gfx::ConstantBuffer<Light> = "u_lights",
|
||||
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
|
||||
|
||||
// alt: gfx::TextureSampler<[f32; 2]> = "t_map",
|
||||
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
|
||||
|
||||
// noise: gfx::TextureSampler<f32> = "t_noise",
|
||||
|
||||
// Shadow stuff
|
||||
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
|
||||
@ -45,23 +35,15 @@ gfx_defines! {
|
||||
fun: gfx::state::Comparison::Less,
|
||||
write: true,
|
||||
},
|
||||
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
|
||||
}
|
||||
|
||||
pipeline figure_pipe {
|
||||
// Terrain vertex stuff
|
||||
vbuf: gfx::VertexBuffer</*Vertex*/terrain::Vertex> = (),
|
||||
vbuf: gfx::VertexBuffer<terrain::Vertex> = (),
|
||||
|
||||
locals: gfx::ConstantBuffer<figure::Locals> = "u_locals",
|
||||
bones: gfx::ConstantBuffer<figure::BoneData> = "u_bones",
|
||||
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||
// lights: gfx::ConstantBuffer<Light> = "u_lights",
|
||||
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
|
||||
|
||||
// alt: gfx::TextureSampler<[f32; 2]> = "t_map",
|
||||
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
|
||||
|
||||
// noise: gfx::TextureSampler<f32> = "t_noise",
|
||||
|
||||
// Shadow stuff
|
||||
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
|
||||
@ -70,16 +52,11 @@ gfx_defines! {
|
||||
fun: gfx::state::Comparison::Less,
|
||||
write: true,
|
||||
},
|
||||
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
|
||||
}
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
pub fn new(
|
||||
pos: Vec3<f32>,
|
||||
norm: Vec3<f32>,
|
||||
meta: bool, /* , atlas_pos: Vec2<u16> */
|
||||
) -> Self {
|
||||
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, meta: bool) -> Self {
|
||||
let norm_bits = if norm.x != 0.0 {
|
||||
if norm.x < 0.0 { 0 } else { 1 }
|
||||
} else if norm.y != 0.0 {
|
||||
@ -89,10 +66,6 @@ impl Vertex {
|
||||
} else {
|
||||
5
|
||||
};
|
||||
// let ao = 0xFFu32;
|
||||
// let light = 0xFFu32;
|
||||
// let col = Rgb::new(1.0f32, 0.0, 0.0);
|
||||
// let meta = true;
|
||||
|
||||
const EXTRA_NEG_Z: f32 = 32768.0;
|
||||
|
||||
@ -103,23 +76,10 @@ impl Vertex {
|
||||
| (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
|
||||
| if meta { 1 } else { 0 } << 28
|
||||
| (norm_bits & 0x7) << 29,
|
||||
/* atlas_pos: 0
|
||||
| ((atlas_pos.x as u32) & 0xFFFF) << 0
|
||||
| ((atlas_pos.y as u32) & 0xFFFF) << 16, */
|
||||
/* col_light: 0
|
||||
| (((col.r * 255.0) as u32) & 0xFF) << 8
|
||||
| (((col.g * 255.0) as u32) & 0xFF) << 16
|
||||
| (((col.b * 255.0) as u32) & 0xFF) << 24
|
||||
| (ao >> 6) << 6
|
||||
| ((light >> 2) & 0x3F) << 0, */
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_figure(
|
||||
pos: Vec3<f32>,
|
||||
norm: Vec3<f32>,
|
||||
/* col: Rgb<f32>, ao: f32, */ bone_idx: u8,
|
||||
) -> Self {
|
||||
pub fn new_figure(pos: Vec3<f32>, norm: Vec3<f32>, bone_idx: u8) -> Self {
|
||||
let norm_bits = if norm.x.min(norm.y).min(norm.z) < 0.0 {
|
||||
0
|
||||
} else {
|
||||
@ -133,10 +93,6 @@ impl Vertex {
|
||||
.reduce_bitor()
|
||||
| (((bone_idx & 0xF) as u32) << 27)
|
||||
| (norm_bits << 31),
|
||||
// col: col
|
||||
// .map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift)
|
||||
// .reduce_bitor(),
|
||||
// ao_bone: (bone_idx << 2) | ((ao * 3.9999) as u8),
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +128,7 @@ impl ShadowPipeline {
|
||||
gfx::texture::AaMode::Single,
|
||||
),
|
||||
gfx::texture::Mipmap::Provided,
|
||||
&[&col_lights /* .raw_pixels() */],
|
||||
&[&col_lights],
|
||||
gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Bilinear,
|
||||
gfx::texture::WrapMode::Clamp,
|
||||
|
@ -29,7 +29,6 @@ gfx_defines! {
|
||||
|
||||
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
|
||||
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_TEST,
|
||||
// tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
|
||||
// tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ use vek::*;
|
||||
gfx_defines! {
|
||||
vertex Vertex {
|
||||
pos: [f32; 3] = "v_pos",
|
||||
// pos_norm: u32 = "v_pos_norm",
|
||||
// Because we try to restrict terrain sprite data to a 128×128 block
|
||||
// we need an offset into the texture atlas.
|
||||
atlas_pos: u32 = "v_atlas_pos",
|
||||
@ -40,21 +39,17 @@ gfx_defines! {
|
||||
inst_mat1: [f32; 4] = "inst_mat1",
|
||||
inst_mat2: [f32; 4] = "inst_mat2",
|
||||
inst_mat3: [f32; 4] = "inst_mat3",
|
||||
// inst_mat: [[f32; 4]; 4] = "inst_mat",
|
||||
// inst_col: [f32; 3] = "inst_col",
|
||||
inst_wind_sway: f32 = "inst_wind_sway",
|
||||
}
|
||||
|
||||
pipeline pipe {
|
||||
vbuf: gfx::VertexBuffer<Vertex> = (),
|
||||
ibuf: gfx::InstanceBuffer<Instance> = (),
|
||||
// ibuf: gfx::/*handle::RawBuffer*/ConstantBuffer<Instance> = "u_ibuf",
|
||||
col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
|
||||
|
||||
locals: gfx::ConstantBuffer<Locals> = "u_locals",
|
||||
// A sprite instance is a cross between a sprite and a terrain chunk.
|
||||
terrain_locals: gfx::ConstantBuffer<terrain::Locals> = "u_terrain_locals",
|
||||
// locals: gfx::ConstantBuffer<terrain::Locals> = "u_locals",
|
||||
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||
lights: gfx::ConstantBuffer<Light> = "u_lights",
|
||||
shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
|
||||
@ -113,24 +108,16 @@ impl Vertex {
|
||||
// | if meta { 1 } else { 0 } << 28
|
||||
// | (norm_bits & 0x7) << 29,
|
||||
pos: pos.into_array(),
|
||||
/* col: col
|
||||
.map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift)
|
||||
.reduce_bitor(), */
|
||||
atlas_pos: 0
|
||||
| ((atlas_pos.x as u32) & 0xFFFF) << 0
|
||||
| ((atlas_pos.y as u32) & 0xFFFF) << 16, /* | axis_bits & 3 */
|
||||
norm_ao: norm_bits, /* | (((ao * 3.9999) as u32) << 3) */
|
||||
| ((atlas_pos.y as u32) & 0xFFFF) << 16,
|
||||
norm_ao: norm_bits,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Instance {
|
||||
pub fn new(
|
||||
mat: Mat4<f32>,
|
||||
/* col: Rgb<f32>, */ wind_sway: f32,
|
||||
pos: Vec3<i32>,
|
||||
ori_bits: u8,
|
||||
) -> Self {
|
||||
pub fn new(mat: Mat4<f32>, wind_sway: f32, pos: Vec3<i32>, ori_bits: u8) -> Self {
|
||||
const EXTRA_NEG_Z: i32 = 32768;
|
||||
|
||||
let mat_arr = mat.into_col_arrays();
|
||||
@ -138,29 +125,19 @@ impl Instance {
|
||||
pos_ori: 0
|
||||
| ((pos.x as u32) & 0x003F) << 0
|
||||
| ((pos.y as u32) & 0x003F) << 6
|
||||
| (((pos + EXTRA_NEG_Z).z.max(0).min(1 << 16/* as f32*/) as u32) & 0xFFFF) << 12
|
||||
// | if meta { 1 } else { 0 } << 28
|
||||
| (((pos + EXTRA_NEG_Z).z.max(0).min(1 << 16) as u32) & 0xFFFF) << 12
|
||||
| (u32::from(ori_bits) & 0x7) << 29,
|
||||
inst_mat0: mat_arr[0],
|
||||
inst_mat1: mat_arr[1],
|
||||
inst_mat2: mat_arr[2],
|
||||
inst_mat3: mat_arr[3],
|
||||
// inst_mat: mat_arr,
|
||||
// inst_col: col.into_array(),
|
||||
inst_wind_sway: wind_sway,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Instance {
|
||||
fn default() -> Self {
|
||||
Self::new(
|
||||
Mat4::identity(),
|
||||
/* Rgb::broadcast(1.0), */ 0.0,
|
||||
Vec3::zero(),
|
||||
0,
|
||||
)
|
||||
}
|
||||
fn default() -> Self { Self::new(Mat4::identity(), 0.0, Vec3::zero(), 0) }
|
||||
}
|
||||
|
||||
impl Default for Locals {
|
||||
|
@ -10,8 +10,6 @@ use vek::*;
|
||||
|
||||
gfx_defines! {
|
||||
vertex Vertex {
|
||||
// pos_norm: u32 = "v_pos_norm",
|
||||
// col_light: u32 = "v_col_light",
|
||||
pos_norm: u32 = "v_pos_norm",
|
||||
atlas_pos: u32 = "v_atlas_pos",
|
||||
}
|
||||
@ -23,8 +21,7 @@ gfx_defines! {
|
||||
}
|
||||
|
||||
pipeline pipe {
|
||||
vbuf: gfx::VertexBuffer</*shadow::Vertex*/Vertex> = (),
|
||||
// abuf: gfx::VertexBuffer<Vertex> = (),
|
||||
vbuf: gfx::VertexBuffer<Vertex> = (),
|
||||
col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
|
||||
|
||||
locals: gfx::ConstantBuffer<Locals> = "u_locals",
|
||||
@ -73,22 +70,10 @@ impl Vertex {
|
||||
atlas_pos: 0
|
||||
| ((atlas_pos.x as u32) & 0xFFFF) << 0
|
||||
| ((atlas_pos.y as u32) & 0xFFFF) << 16,
|
||||
/* col_light: 0
|
||||
| (((col.r * 255.0) as u32) & 0xFF) << 8
|
||||
| (((col.g * 255.0) as u32) & 0xFF) << 16
|
||||
| (((col.b * 255.0) as u32) & 0xFF) << 24
|
||||
| (ao >> 6) << 6
|
||||
| ((light >> 2) & 0x3F) << 0, */
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_figure(
|
||||
// norm: Vec3<f32>,
|
||||
atlas_pos: Vec2<u16>,
|
||||
pos: Vec3<f32>,
|
||||
norm: Vec3<f32>,
|
||||
bone_idx: u8,
|
||||
) -> Self {
|
||||
pub fn new_figure(atlas_pos: Vec2<u16>, pos: Vec3<f32>, norm: Vec3<f32>, bone_idx: u8) -> Self {
|
||||
let norm_bits = if norm.x.min(norm.y).min(norm.z) < 0.0 {
|
||||
0
|
||||
} else {
|
||||
@ -113,57 +98,15 @@ impl Vertex {
|
||||
| ((atlas_pos.x as u32) & 0x7FFF) << 2
|
||||
| ((atlas_pos.y as u32) & 0x7FFF) << 17
|
||||
| axis_bits & 3,
|
||||
/* col_light: 0
|
||||
| (((col.r * 255.0) as u32) & 0xFF) << 8
|
||||
| (((col.g * 255.0) as u32) & 0xFF) << 16
|
||||
| (((col.b * 255.0) as u32) & 0xFF) << 24
|
||||
| (ao >> 6) << 6
|
||||
| ((light >> 2) & 0x3F) << 0, */
|
||||
}
|
||||
}
|
||||
|
||||
/* pub fn new(
|
||||
norm_bits: u32,
|
||||
light: u32,
|
||||
ao: u32,
|
||||
pos: Vec3<f32>,
|
||||
col: Rgb<f32>,
|
||||
meta: bool,
|
||||
) -> Self {
|
||||
const EXTRA_NEG_Z: f32 = 32768.0;
|
||||
|
||||
Self {
|
||||
pos_norm: 0
|
||||
| ((pos.x as u32) & 0x003F) << 0
|
||||
| ((pos.y as u32) & 0x003F) << 6
|
||||
| (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
|
||||
| if meta { 1 } else { 0 } << 28
|
||||
| (norm_bits & 0x7) << 29,
|
||||
col_light: 0
|
||||
| ((col.r.mul(255.0) as u32) & 0xFF) << 8
|
||||
| ((col.g.mul(255.0) as u32) & 0xFF) << 16
|
||||
| ((col.b.mul(255.0) as u32) & 0xFF) << 24
|
||||
| (ao >> 6) << 6
|
||||
| ((light >> 2) & 0x3F) << 0,
|
||||
}
|
||||
} */
|
||||
|
||||
pub fn make_col_light(
|
||||
light: /* u32 */ u8,
|
||||
// ao: u32,
|
||||
// col: Rgb<f32>,
|
||||
light: u8,
|
||||
col: Rgb<u8>,
|
||||
) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType
|
||||
{
|
||||
[
|
||||
col.r, //.mul(255.0) as u8,
|
||||
col.g, //.mul(255.0) as u8,
|
||||
col.b, //.mul(255.0) as u8,
|
||||
light,
|
||||
/* | (ao as u8 >> 6) << 6
|
||||
* | //((light as u8 >> 2) & 0x3F) << 0,
|
||||
* | light */
|
||||
]
|
||||
[col.r, col.g, col.b, light]
|
||||
}
|
||||
|
||||
pub fn with_bone_idx(self, bone_idx: u8) -> Self {
|
||||
@ -187,5 +130,5 @@ impl Locals {
|
||||
pub struct TerrainPipeline;
|
||||
|
||||
impl Pipeline for TerrainPipeline {
|
||||
type Vertex = Vertex; //<<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType;
|
||||
type Vertex = Vertex;
|
||||
}
|
||||
|
@ -131,18 +131,6 @@ pub fn create_quad(
|
||||
v([l, b], [uv_l, uv_b]),
|
||||
v([r, b], [uv_r, uv_b]),
|
||||
),
|
||||
/* (true, true) | (false, false) => Quad::new(
|
||||
v([l, t], [uv_l, uv_t]),
|
||||
v([r, t], [uv_l, uv_b]),
|
||||
v([r, b], [uv_r, uv_b]),
|
||||
v([l, b], [uv_r, uv_t]),
|
||||
),
|
||||
_ => Quad::new(
|
||||
v([l, t], [uv_l, uv_t]),
|
||||
v([l, b], [uv_l, uv_b]),
|
||||
v([r, b], [uv_r, uv_b]),
|
||||
v([r, t], [uv_r, uv_t]),
|
||||
) */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ use super::{
|
||||
mesh::Mesh,
|
||||
model::{DynamicModel, Model},
|
||||
pipelines::{
|
||||
figure, fluid, lod_terrain, postprocess, shadow, skybox, sprite, terrain, ui, Globals,
|
||||
Light, Shadow,
|
||||
figure, fluid, lod_terrain, postprocess, shadow, skybox, sprite, terrain, ui, GlobalModel,
|
||||
Globals,
|
||||
},
|
||||
texture::Texture,
|
||||
AaMode, CloudMode, FilterMethod, FluidMode, LightingMode, Pipeline, RenderError, RenderMode,
|
||||
@ -49,13 +49,13 @@ pub type WinColorView = gfx::handle::RenderTargetView<gfx_backend::Resources, Wi
|
||||
pub type WinDepthView = gfx::handle::DepthStencilView<gfx_backend::Resources, WinDepthFmt>;
|
||||
|
||||
/// Represents the format of LOD shadows.
|
||||
pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); //[gfx::format::U8Norm; 4];
|
||||
pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm);
|
||||
|
||||
/// Represents the format of LOD altitudes.
|
||||
pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm); //[gfx::format::U8Norm; 4];
|
||||
pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm);
|
||||
|
||||
/// Represents the format of LOD map colors.
|
||||
pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); //[gfx::format::U8Norm; 4];
|
||||
pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb);
|
||||
|
||||
/// Represents the format of greedy meshed color-light textures.
|
||||
pub type ColLightFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb);
|
||||
@ -420,6 +420,9 @@ impl Renderer {
|
||||
}
|
||||
|
||||
/// Create textures and views for shadow maps.
|
||||
// This is a one-use type and the two halves are not guaranteed to remain identical, so we
|
||||
// disable the type complexity lint.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn create_shadow_views(
|
||||
factory: &mut gfx_device_gl::Factory,
|
||||
size: (u16, u16),
|
||||
@ -457,7 +460,7 @@ impl Renderer {
|
||||
}
|
||||
}))?;
|
||||
|
||||
let levels = 1; //10;
|
||||
let levels = 1;
|
||||
let two_size = vec2_result(size.map(|e| {
|
||||
u16::checked_next_power_of_two(e)
|
||||
.filter(|&e| e <= max_texture_size)
|
||||
@ -501,67 +504,26 @@ impl Renderer {
|
||||
diag_size
|
||||
))
|
||||
})?;
|
||||
/* let color_cty = <<TgtColorFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped
|
||||
>::get_channel_type();
|
||||
let tgt_color_tex = factory.create_texture(
|
||||
kind,
|
||||
levels,
|
||||
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::RENDER_TARGET,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(color_cty),
|
||||
)?;
|
||||
let tgt_color_res = factory.view_texture_as_shader_resource::<TgtColorFmt>(
|
||||
&tgt_color_tex,
|
||||
(0, levels - 1),
|
||||
gfx::format::Swizzle::new(),
|
||||
)?;
|
||||
let tgt_color_view = factory.view_texture_as_render_target(&tgt_color_tex, 0, None)?;
|
||||
|
||||
let depth_stencil_cty = <<TgtDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
|
||||
let tgt_depth_stencil_tex = factory.create_texture(
|
||||
kind,
|
||||
levels,
|
||||
gfx::memory::Bind::DEPTH_STENCIL,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(depth_stencil_cty),
|
||||
)?;
|
||||
let tgt_depth_stencil_view =
|
||||
factory.view_texture_as_depth_stencil_trivial(&tgt_depth_stencil_tex)?; */
|
||||
let depth_stencil_cty = <<ShadowDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
|
||||
|
||||
let point_shadow_tex = factory
|
||||
.create_texture(
|
||||
gfx::texture::Kind::/*CubeArray*/Cube(
|
||||
/* max_two_size */ diag_two_size / 4, /* size * 2*//*, 32 */
|
||||
),
|
||||
gfx::texture::Kind::Cube(diag_two_size / 4),
|
||||
levels as gfx::texture::Level,
|
||||
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(depth_stencil_cty),
|
||||
/* Some(<<F as gfx::format::Formatted>::Channel as
|
||||
* gfx::format::ChannelTyped>::get_channel_type()), */
|
||||
)
|
||||
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
|
||||
|
||||
let point_tgt_shadow_view = factory
|
||||
.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
|
||||
&point_shadow_tex,
|
||||
0, // levels,
|
||||
None, // Some(1),
|
||||
0,
|
||||
None,
|
||||
gfx::texture::DepthStencilFlags::empty(),
|
||||
)?;
|
||||
// let tgt_shadow_view =
|
||||
// factory.view_texture_as_depth_stencil_trivial(&shadow_tex)?;
|
||||
/* let tgt_shadow_res = factory.view_texture_as_shader_resource::<TgtColorFmt>(
|
||||
&tgt_color_tex,
|
||||
(0, levels - 1),
|
||||
gfx::format::Swizzle::new(),
|
||||
)?; */
|
||||
|
||||
// let tgt_shadow_view =
|
||||
// factory.view_texture_as_depth_stencil_trivial(&tgt_color_tex)?;
|
||||
// let tgt_shadow_view = factory.view_texture_as_shader_resource(&tgt_color_tex,
|
||||
// 0, None)?;
|
||||
let point_tgt_shadow_res = factory
|
||||
.view_texture_as_shader_resource::<ShadowDepthStencilFmt>(
|
||||
&point_shadow_tex,
|
||||
@ -569,21 +531,9 @@ impl Renderer {
|
||||
gfx::format::Swizzle::new(),
|
||||
)?;
|
||||
|
||||
/* println!(
|
||||
"size: {:?}, two_size: {:?}, diag_size: {:?}, diag_two_size: {:?}",
|
||||
size, two_size, diag_size, diag_two_size,
|
||||
); */
|
||||
let directed_shadow_tex = factory
|
||||
.create_texture(
|
||||
gfx::texture::Kind::D2(
|
||||
/* size.x,// two_size.x,// 2 * size.x,
|
||||
size.y,// two_size.y,// 2 * size.y, */
|
||||
diag_two_size, /* max_two_size*//*two_size.x */
|
||||
diag_two_size, /* max_two_size*//*two_size.y */
|
||||
/* 6*//*1, */ gfx::texture::AaMode::Single,
|
||||
),
|
||||
// gfx::texture::Kind::D2Array(max_size/* * 2*/, max_size/* * 2*/, /*6*/1,
|
||||
// gfx::texture::AaMode::Single),
|
||||
gfx::texture::Kind::D2(diag_two_size, diag_two_size, gfx::texture::AaMode::Single),
|
||||
levels as gfx::texture::Level,
|
||||
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
|
||||
gfx::memory::Usage::Data,
|
||||
@ -593,8 +543,8 @@ impl Renderer {
|
||||
let directed_tgt_shadow_view = factory
|
||||
.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
|
||||
&directed_shadow_tex,
|
||||
0, // levels,
|
||||
None, // Some(1),
|
||||
0,
|
||||
None,
|
||||
gfx::texture::DepthStencilFlags::empty(),
|
||||
)?;
|
||||
let directed_tgt_shadow_res = factory
|
||||
@ -606,31 +556,14 @@ impl Renderer {
|
||||
|
||||
let mut sampler_info = gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Bilinear,
|
||||
gfx::texture::WrapMode::Border, //Clamp,
|
||||
// Lights should always be assumed to flood areas we can't see.
|
||||
gfx::texture::WrapMode::Border,
|
||||
);
|
||||
sampler_info.comparison = Some(Comparison::LessEqual);
|
||||
// sampler_info.lod_bias = (-3.0).into();
|
||||
// sampler_info.lod_range = (1.into(), (levels - 1).into());
|
||||
// Point lights should clamp to whatever edge value there is.
|
||||
sampler_info.border = [1.0; 4].into();
|
||||
let point_shadow_tex_sampler = factory.create_sampler(sampler_info);
|
||||
/* // Directed lights should always be assumed to flood areas we can't see.
|
||||
sampler_info.wrap_mode = (gfx::texture::WrapMode::Border, gfx::texture::WrapMode::Border, gfx::texture::WrapMode::Border); */
|
||||
let directed_shadow_tex_sampler = factory.create_sampler(sampler_info);
|
||||
|
||||
/* let tgt_sun_res = factory.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
|
||||
&shadow_tex,
|
||||
0,
|
||||
Some(0),
|
||||
gfx::texture::DepthStencilFlags::RO_DEPTH,
|
||||
)?;
|
||||
let tgt_moon_res = factory.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
|
||||
&shadow_tex,
|
||||
0,
|
||||
Some(1),
|
||||
gfx::texture::DepthStencilFlags::RO_DEPTH,
|
||||
)?; */
|
||||
|
||||
Ok((
|
||||
point_tgt_shadow_view,
|
||||
point_tgt_shadow_res,
|
||||
@ -676,7 +609,6 @@ impl Renderer {
|
||||
// let directed_encoder = &mut shadow_map.directed_encoder;
|
||||
let directed_encoder = &mut self.encoder;
|
||||
directed_encoder.clear_depth(&shadow_map.directed_depth_stencil_view, 1.0);
|
||||
// encoder.clear_stencil(&shadow_map.depth_stencil_view, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -693,7 +625,6 @@ impl Renderer {
|
||||
// NOTE: Currently just fail silently rather than complain if the computer is on
|
||||
// a version lower than 3.2, where seamless cubemaps were introduced.
|
||||
if !device.get_info().is_version_supported(3, 2) {
|
||||
// println!("whoops");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -719,7 +650,6 @@ impl Renderer {
|
||||
// and having depth clamping disabled won't cause undefined
|
||||
// behavior, just incorrect shadowing from objects behind the viewer.
|
||||
if !device.get_info().is_version_supported(3, 3) {
|
||||
// println!("whoops");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -729,8 +659,6 @@ impl Renderer {
|
||||
// essentially always be safe regardless of the state of the OpenGL
|
||||
// context, so no further checks are needed.
|
||||
device.with_gl(|gl| {
|
||||
// println!("gl.Enable(gfx_gl::DEPTH_CLAMP) = {:?}",
|
||||
// gl.IsEnabled(gfx_gl::DEPTH_CLAMP));
|
||||
if depth_clamp {
|
||||
gl.Enable(gfx_gl::DEPTH_CLAMP);
|
||||
} else {
|
||||
@ -759,7 +687,7 @@ impl Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform all queued draw calls for shadows.
|
||||
/// Perform all queued draw calls for global.shadows.
|
||||
pub fn flush_shadows(&mut self) {
|
||||
if !self.mode.shadow.is_map() {
|
||||
return;
|
||||
@ -848,14 +776,6 @@ impl Renderer {
|
||||
Ok(consts)
|
||||
}
|
||||
|
||||
/* /// Create a raw set of constants with the provided values.
|
||||
pub fn create_consts_immutable<T: Copy + gfx::traits::Pod>(
|
||||
&mut self,
|
||||
vals: &[T],
|
||||
) -> Result<RawBuffer<T>, RenderError> {
|
||||
Consts::new_immutable(&mut self.factory, vals)
|
||||
} */
|
||||
|
||||
/// Update a set of constants with the provided values.
|
||||
pub fn update_consts<T: Copy + gfx::traits::Pod>(
|
||||
&mut self,
|
||||
@ -865,25 +785,6 @@ impl Renderer {
|
||||
consts.update(&mut self.encoder, vals, 0)
|
||||
}
|
||||
|
||||
/* /// Update a set of shadow constants with the provided values.
|
||||
pub fn update_shadow_consts<T: Copy + gfx::traits::Pod>(
|
||||
&mut self,
|
||||
consts: &mut Consts<T>,
|
||||
vals: &[T],
|
||||
directed_offset: usize,
|
||||
point_offset: usize,
|
||||
) -> Result<(), RenderError> {
|
||||
if let Some(shadow_map) = self.shadow_map.as_mut() {
|
||||
let directed_encoder = &mut shadow_map.directed_encoder;
|
||||
consts.update(directed_encoder, &vals[directed_offset..point_offset], directed_offset)?;
|
||||
let point_encoder = &mut shadow_map.point_encoder;
|
||||
consts.update(point_encoder, &vals[point_offset..], point_offset)
|
||||
} else {
|
||||
// Fail silently if shadows aren't working in the first place.
|
||||
Ok(())
|
||||
}
|
||||
} */
|
||||
|
||||
/// Create a new set of instances with the provided values.
|
||||
pub fn create_instances<T: Copy + gfx::traits::Pod>(
|
||||
&mut self,
|
||||
@ -1004,22 +905,6 @@ impl Renderer {
|
||||
Texture::new_dynamic(&mut self.factory, dims.x, dims.y)
|
||||
}
|
||||
|
||||
/* /// Create a new greedy texture array (of color-lights).
|
||||
pub fn create_greedy_texture<F: gfx::format::Formatted>(
|
||||
&mut self,
|
||||
kind: gfx::texture::Kind,
|
||||
mipmap: gfx::texture::MipMap,
|
||||
data: &[&[<F::Surface as gfx::format::SurfaceTyped>::DataType]],
|
||||
sampler_info: gfx::texture::SamplerInfo,
|
||||
) -> Result<Texture<F>, RenderError>
|
||||
where
|
||||
F::Surface: gfx::format::TextureSurface,
|
||||
F::Channel: gfx::format::TextureChannel,
|
||||
<F::Surface as gfx::format::SurfaceTyped>::DataType: Copy,
|
||||
{
|
||||
Texture::new_immutable_raw(&mut self.factory, kind, mipmap, data, sampler_info)
|
||||
} */
|
||||
|
||||
/// Update a texture with the provided offset, size, and data.
|
||||
pub fn update_texture(
|
||||
&mut self,
|
||||
@ -1082,10 +967,9 @@ impl Renderer {
|
||||
pub fn render_skybox(
|
||||
&mut self,
|
||||
model: &Model<skybox::SkyboxPipeline>,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
locals: &Consts<skybox::Locals>,
|
||||
alt: &Texture<LodAltFmt>,
|
||||
horizon: &Texture<LodTextureFmt>,
|
||||
lod: &lod_terrain::LodData,
|
||||
) {
|
||||
self.encoder.draw(
|
||||
&gfx::Slice {
|
||||
@ -1099,10 +983,10 @@ impl Renderer {
|
||||
&skybox::pipe::Data {
|
||||
vbuf: model.vbuf.clone(),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
globals: global.globals.buf.clone(),
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
|
||||
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
|
||||
},
|
||||
@ -1114,16 +998,11 @@ impl Renderer {
|
||||
&mut self,
|
||||
model: &figure::FigureModel,
|
||||
_col_lights: &Texture<ColLightFmt>,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
locals: &Consts<figure::Locals>,
|
||||
bones: &Consts<figure::BoneData>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
light_shadows: &Consts<shadow::Locals>,
|
||||
alt: &Texture<LodAltFmt>,
|
||||
horizon: &Texture<LodTextureFmt>,
|
||||
lod: &lod_terrain::LodData,
|
||||
) {
|
||||
// return;
|
||||
let (point_shadow_maps, directed_shadow_maps) =
|
||||
if let Some(shadow_map) = &mut self.shadow_map {
|
||||
(
|
||||
@ -1144,8 +1023,6 @@ impl Renderer {
|
||||
};
|
||||
let col_lights = &model.col_lights;
|
||||
let model = &model.opaque;
|
||||
// let atlas_model = &model.opaque;
|
||||
// let model = &model.shadow;
|
||||
|
||||
self.encoder.draw(
|
||||
&gfx::Slice {
|
||||
@ -1158,20 +1035,18 @@ impl Renderer {
|
||||
&self.figure_pipeline.pso,
|
||||
&figure::pipe::Data {
|
||||
vbuf: model.vbuf.clone(),
|
||||
// abuf: atlas_model.vbuf.clone(),
|
||||
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
|
||||
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
globals: global.globals.buf.clone(),
|
||||
bones: bones.buf.clone(),
|
||||
lights: lights.buf.clone(),
|
||||
shadows: shadows.buf.clone(),
|
||||
light_shadows: light_shadows.buf.clone(),
|
||||
lights: global.lights.buf.clone(),
|
||||
shadows: global.shadows.buf.clone(),
|
||||
light_shadows: global.shadow_mats.buf.clone(),
|
||||
point_shadow_maps,
|
||||
directed_shadow_maps,
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
|
||||
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
|
||||
},
|
||||
@ -1183,15 +1058,12 @@ impl Renderer {
|
||||
&mut self,
|
||||
_model: &figure::FigureModel,
|
||||
_col_lights: &Texture<ColLightFmt>,
|
||||
_globals: &Consts<Globals>,
|
||||
_locals: &Consts<figure::Locals>,
|
||||
_global: &GlobalModel,
|
||||
_bones: &Consts<figure::BoneData>,
|
||||
_lights: &Consts<Light>,
|
||||
_shadows: &Consts<Shadow>,
|
||||
_light_shadows: &Consts<shadow::Locals>,
|
||||
_alt: &Texture<LodAltFmt>,
|
||||
_horizon: &Texture<LodTextureFmt>,
|
||||
_lod: &lod_terrain::LodData,
|
||||
_locals: &Consts<shadow::Locals>,
|
||||
) {
|
||||
// FIXME: Consider reenabling at some point.
|
||||
/* let (point_shadow_maps, directed_shadow_maps) =
|
||||
if let Some(shadow_map) = &mut self.shadow_map {
|
||||
(
|
||||
@ -1228,18 +1100,18 @@ impl Renderer {
|
||||
vbuf: model.vbuf.clone(),
|
||||
// abuf: atlas_model.vbuf.clone(),
|
||||
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
|
||||
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
|
||||
// col_lights: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
globals: global.globals.buf.clone(),
|
||||
bones: bones.buf.clone(),
|
||||
lights: lights.buf.clone(),
|
||||
shadows: shadows.buf.clone(),
|
||||
light_shadows: light_shadows.buf.clone(),
|
||||
lights: global.lights.buf.clone(),
|
||||
shadows: global.shadows.buf.clone(),
|
||||
light_shadows: global.shadow_mats.buf.clone(),
|
||||
point_shadow_maps,
|
||||
directed_shadow_maps,
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
|
||||
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (0, 0) */),
|
||||
},
|
||||
@ -1251,14 +1123,10 @@ impl Renderer {
|
||||
&mut self,
|
||||
model: &figure::FigureModel,
|
||||
_col_lights: &Texture<ColLightFmt>,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
locals: &Consts<figure::Locals>,
|
||||
bones: &Consts<figure::BoneData>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
light_shadows: &Consts<shadow::Locals>,
|
||||
alt: &Texture<LodAltFmt>,
|
||||
horizon: &Texture<LodTextureFmt>,
|
||||
lod: &lod_terrain::LodData,
|
||||
) {
|
||||
let (point_shadow_maps, directed_shadow_maps) =
|
||||
if let Some(shadow_map) = &mut self.shadow_map {
|
||||
@ -1280,8 +1148,6 @@ impl Renderer {
|
||||
};
|
||||
let col_lights = &model.col_lights;
|
||||
let model = &model.opaque;
|
||||
// let atlas_model = &model.opaque;
|
||||
// let model = &model.shadow;
|
||||
|
||||
self.encoder.draw(
|
||||
&gfx::Slice {
|
||||
@ -1294,20 +1160,18 @@ impl Renderer {
|
||||
&self.figure_pipeline.pso,
|
||||
&figure::pipe::Data {
|
||||
vbuf: model.vbuf.clone(),
|
||||
// abuf: atlas_model.vbuf.clone(),
|
||||
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
|
||||
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
globals: global.globals.buf.clone(),
|
||||
bones: bones.buf.clone(),
|
||||
lights: lights.buf.clone(),
|
||||
shadows: shadows.buf.clone(),
|
||||
light_shadows: light_shadows.buf.clone(),
|
||||
lights: global.lights.buf.clone(),
|
||||
shadows: global.shadows.buf.clone(),
|
||||
light_shadows: global.shadow_mats.buf.clone(),
|
||||
point_shadow_maps,
|
||||
directed_shadow_maps,
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
|
||||
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
|
||||
},
|
||||
@ -1318,17 +1182,11 @@ impl Renderer {
|
||||
/// frame.
|
||||
pub fn render_terrain_chunk(
|
||||
&mut self,
|
||||
// atlas_model: &Model<terrain::TerrainPipeline>,
|
||||
// model: &Model<shadow::ShadowPipeline>,
|
||||
model: &Model<terrain::TerrainPipeline>,
|
||||
col_lights: &Texture<ColLightFmt>,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
locals: &Consts<terrain::Locals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
light_shadows: &Consts<shadow::Locals>,
|
||||
alt: &Texture<LodAltFmt>,
|
||||
horizon: &Texture<LodTextureFmt>,
|
||||
lod: &lod_terrain::LodData,
|
||||
) {
|
||||
let (point_shadow_maps, directed_shadow_maps) =
|
||||
if let Some(shadow_map) = &mut self.shadow_map {
|
||||
@ -1361,20 +1219,18 @@ impl Renderer {
|
||||
&terrain::pipe::Data {
|
||||
vbuf: model.vbuf.clone(),
|
||||
// TODO: Consider splitting out texture atlas data into a separate vertex buffer,
|
||||
// since we don't need it for things like shadows.
|
||||
// abuf: atlas_model.vbuf.clone(),
|
||||
// since we don't need it for things like global.shadows.
|
||||
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
|
||||
// col_lights: (alt.srv.clone(), alt.sampler.clone()),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
lights: lights.buf.clone(),
|
||||
shadows: shadows.buf.clone(),
|
||||
light_shadows: light_shadows.buf.clone(),
|
||||
globals: global.globals.buf.clone(),
|
||||
lights: global.lights.buf.clone(),
|
||||
shadows: global.shadows.buf.clone(),
|
||||
light_shadows: global.shadow_mats.buf.clone(),
|
||||
point_shadow_maps,
|
||||
directed_shadow_maps,
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
|
||||
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
|
||||
},
|
||||
@ -1386,14 +1242,9 @@ impl Renderer {
|
||||
pub fn render_shadow_point(
|
||||
&mut self,
|
||||
model: &Model<terrain::TerrainPipeline>,
|
||||
// model: &Model<shadow::ShadowPipeline>,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
terrain_locals: &Consts<terrain::Locals>,
|
||||
locals: &Consts<shadow::Locals>,
|
||||
/* lights: &Consts<Light>,
|
||||
* shadows: &Consts<Shadow>,
|
||||
* alt: &Texture<LodAltFmt>,
|
||||
* horizon: &Texture<LodTextureFmt>, */
|
||||
) {
|
||||
if !self.mode.shadow.is_map() {
|
||||
return;
|
||||
@ -1420,18 +1271,11 @@ impl Renderer {
|
||||
// Terrain vertex stuff
|
||||
vbuf: model.vbuf.clone(),
|
||||
locals: terrain_locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
// lights: lights.buf.clone(),
|
||||
// shadows: shadows.buf.clone(),
|
||||
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
// alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
// horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
globals: global.globals.buf.clone(),
|
||||
|
||||
// Shadow stuff
|
||||
light_shadows: locals.buf.clone(),
|
||||
tgt_depth_stencil: shadow_map.point_depth_stencil_view.clone(),
|
||||
/* tgt_depth_stencil: (self.shadow_depth_stencil_view.clone(), (1, 1)),
|
||||
* shadow_tex: (self.shadow_res.clone(), self.shadow_sampler.clone()), */
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -1440,15 +1284,10 @@ impl Renderer {
|
||||
/// the upcoming frame.
|
||||
pub fn render_terrain_shadow_directed(
|
||||
&mut self,
|
||||
// model: &Model<shadow::ShadowPipeline>,
|
||||
model: &Model<terrain::TerrainPipeline>,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
terrain_locals: &Consts<terrain::Locals>,
|
||||
locals: &Consts<shadow::Locals>,
|
||||
/* lights: &Consts<Light>,
|
||||
* shadows: &Consts<Shadow>,
|
||||
* alt: &Texture<LodAltFmt>,
|
||||
* horizon: &Texture<LodTextureFmt>, */
|
||||
) {
|
||||
if !self.mode.shadow.is_map() {
|
||||
return;
|
||||
@ -1475,18 +1314,11 @@ impl Renderer {
|
||||
// Terrain vertex stuff
|
||||
vbuf: model.vbuf.clone(),
|
||||
locals: terrain_locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
// lights: lights.buf.clone(),
|
||||
// shadows: shadows.buf.clone(),
|
||||
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
// alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
// horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
globals: global.globals.buf.clone(),
|
||||
|
||||
// Shadow stuff
|
||||
light_shadows: locals.buf.clone(),
|
||||
tgt_depth_stencil: shadow_map.directed_depth_stencil_view.clone(),
|
||||
/* tgt_depth_stencil: (self.shadow_depth_stencil_view.clone(), (1, 1)),
|
||||
* shadow_tex: (self.shadow_res.clone(), self.shadow_sampler.clone()), */
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -1495,16 +1327,11 @@ impl Renderer {
|
||||
/// the upcoming frame.
|
||||
pub fn render_figure_shadow_directed(
|
||||
&mut self,
|
||||
// model: &Model<shadow::ShadowPipeline>,
|
||||
model: &figure::FigureModel,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
figure_locals: &Consts<figure::Locals>,
|
||||
bones: &Consts<figure::BoneData>,
|
||||
locals: &Consts<shadow::Locals>,
|
||||
/* lights: &Consts<Light>,
|
||||
* shadows: &Consts<Shadow>,
|
||||
* alt: &Texture<LodAltFmt>,
|
||||
* horizon: &Texture<LodTextureFmt>, */
|
||||
) {
|
||||
if !self.mode.shadow.is_map() {
|
||||
return;
|
||||
@ -1533,18 +1360,11 @@ impl Renderer {
|
||||
vbuf: model.vbuf.clone(),
|
||||
locals: figure_locals.buf.clone(),
|
||||
bones: bones.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
// lights: lights.buf.clone(),
|
||||
// shadows: shadows.buf.clone(),
|
||||
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
// alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
// horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
globals: global.globals.buf.clone(),
|
||||
|
||||
// Shadow stuff
|
||||
light_shadows: locals.buf.clone(),
|
||||
tgt_depth_stencil: shadow_map.directed_depth_stencil_view.clone(),
|
||||
/* tgt_depth_stencil: (self.shadow_depth_stencil_view.clone(), (1, 1)),
|
||||
* shadow_tex: (self.shadow_res.clone(), self.shadow_sampler.clone()), */
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -1554,13 +1374,9 @@ impl Renderer {
|
||||
pub fn render_fluid_chunk(
|
||||
&mut self,
|
||||
model: &Model<fluid::FluidPipeline>,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
locals: &Consts<terrain::Locals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
light_shadows: &Consts<shadow::Locals>,
|
||||
alt: &Texture<LodAltFmt>,
|
||||
horizon: &Texture<LodTextureFmt>,
|
||||
lod: &lod_terrain::LodData,
|
||||
waves: &Texture,
|
||||
) {
|
||||
let (point_shadow_maps, directed_shadow_maps) =
|
||||
@ -1594,14 +1410,14 @@ impl Renderer {
|
||||
&fluid::pipe::Data {
|
||||
vbuf: model.vbuf.clone(),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
lights: lights.buf.clone(),
|
||||
shadows: shadows.buf.clone(),
|
||||
light_shadows: light_shadows.buf.clone(),
|
||||
globals: global.globals.buf.clone(),
|
||||
lights: global.lights.buf.clone(),
|
||||
shadows: global.shadows.buf.clone(),
|
||||
light_shadows: global.shadow_mats.buf.clone(),
|
||||
point_shadow_maps,
|
||||
directed_shadow_maps,
|
||||
alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
|
||||
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
waves: (waves.srv.clone(), waves.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
@ -1616,17 +1432,11 @@ impl Renderer {
|
||||
&mut self,
|
||||
model: &Model<sprite::SpritePipeline>,
|
||||
col_lights: &Texture<ColLightFmt>,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
terrain_locals: &Consts<terrain::Locals>,
|
||||
locals: &Consts<sprite::Locals>,
|
||||
// instance_count: usize,
|
||||
// instances: &Consts<sprite::Instance>,
|
||||
instances: &Instances<sprite::Instance>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
light_shadows: &Consts<shadow::Locals>,
|
||||
alt: &Texture<LodAltFmt>,
|
||||
horizon: &Texture<LodTextureFmt>,
|
||||
lod: &lod_terrain::LodData,
|
||||
) {
|
||||
let (point_shadow_maps, directed_shadow_maps) =
|
||||
if let Some(shadow_map) = &mut self.shadow_map {
|
||||
@ -1652,26 +1462,25 @@ impl Renderer {
|
||||
start: model.vertex_range().start,
|
||||
end: model.vertex_range().end,
|
||||
base_vertex: 0,
|
||||
instances: Some((instances.count()/*instance_count*/ as u32, 0)),
|
||||
instances: Some((instances.count() as u32, 0)),
|
||||
buffer: gfx::IndexBuffer::Auto,
|
||||
},
|
||||
&self.sprite_pipeline.pso,
|
||||
&sprite::pipe::Data {
|
||||
vbuf: model.vbuf.clone(),
|
||||
ibuf: instances.ibuf.clone(),
|
||||
// ibuf: instances.buf.clone(),
|
||||
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
|
||||
terrain_locals: terrain_locals.buf.clone(),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
lights: lights.buf.clone(),
|
||||
shadows: shadows.buf.clone(),
|
||||
light_shadows: light_shadows.buf.clone(),
|
||||
globals: global.globals.buf.clone(),
|
||||
lights: global.lights.buf.clone(),
|
||||
shadows: global.shadows.buf.clone(),
|
||||
light_shadows: global.shadow_mats.buf.clone(),
|
||||
point_shadow_maps,
|
||||
directed_shadow_maps,
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
|
||||
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
|
||||
},
|
||||
@ -1683,11 +1492,9 @@ impl Renderer {
|
||||
pub fn render_lod_terrain(
|
||||
&mut self,
|
||||
model: &Model<lod_terrain::LodTerrainPipeline>,
|
||||
globals: &Consts<Globals>,
|
||||
global: &GlobalModel,
|
||||
locals: &Consts<lod_terrain::Locals>,
|
||||
map: &Texture<LodColorFmt>,
|
||||
alt: &Texture<LodAltFmt>,
|
||||
horizon: &Texture<LodTextureFmt>,
|
||||
lod: &lod_terrain::LodData,
|
||||
) {
|
||||
self.encoder.draw(
|
||||
&gfx::Slice {
|
||||
@ -1701,11 +1508,11 @@ impl Renderer {
|
||||
&lod_terrain::pipe::Data {
|
||||
vbuf: model.vbuf.clone(),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
globals: global.globals.buf.clone(),
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
map: (map.srv.clone(), map.sampler.clone()),
|
||||
alt: (alt.srv.clone(), alt.sampler.clone()),
|
||||
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
|
||||
map: (lod.map.srv.clone(), lod.map.sampler.clone()),
|
||||
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
|
||||
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view.clone(),
|
||||
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
|
||||
},
|
||||
@ -1926,13 +1733,6 @@ fn create_pipelines(
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
/* let directed_shadow_geom =
|
||||
&assets::load_watched::<String>(
|
||||
"voxygen.shaders.light-shadows-directed-geom",
|
||||
shader_reload_indicator,
|
||||
)
|
||||
.unwrap(); */
|
||||
|
||||
let directed_shadow_frag = &assets::load_watched::<String>(
|
||||
"voxygen.shaders.light-shadows-directed-frag",
|
||||
shader_reload_indicator,
|
||||
@ -2094,8 +1894,7 @@ fn create_pipelines(
|
||||
.unwrap(),
|
||||
&include_ctx,
|
||||
gfx::state::CullFace::Back,
|
||||
None,
|
||||
// Some(gfx::state::Offset(2, /* 10 */ 0)),
|
||||
None, // Some(gfx::state::Offset(2, 0))
|
||||
) {
|
||||
Ok(pipe) => Some(pipe),
|
||||
Err(err) => {
|
||||
@ -2109,14 +1908,11 @@ fn create_pipelines(
|
||||
factory,
|
||||
shadow::pipe::new(),
|
||||
&terrain_directed_shadow_vert,
|
||||
None, // &directed_shadow_geom,
|
||||
None,
|
||||
&directed_shadow_frag,
|
||||
&include_ctx,
|
||||
gfx::state::CullFace::Back,
|
||||
/* None, */
|
||||
/* Some(gfx::state::Offset(4, 10)), */
|
||||
None,
|
||||
// Some(gfx::state::Offset(2, /*10*/1)),
|
||||
None, // Some(gfx::state::Offset(2, 1))
|
||||
) {
|
||||
Ok(pipe) => Some(pipe),
|
||||
Err(err) => {
|
||||
@ -2133,14 +1929,11 @@ fn create_pipelines(
|
||||
factory,
|
||||
shadow::figure_pipe::new(),
|
||||
&figure_directed_shadow_vert,
|
||||
None, // &directed_shadow_geom,
|
||||
None,
|
||||
&directed_shadow_frag,
|
||||
&include_ctx,
|
||||
gfx::state::CullFace::Back,
|
||||
/* None, */
|
||||
/* Some(gfx::state::Offset(4, 10)), */
|
||||
/*Some(gfx::state::Offset(2, 1))*/None,
|
||||
/* Some(gfx::state::Offset(2, 10)), */
|
||||
None, // Some(gfx::state::Offset(2, 1))
|
||||
) {
|
||||
Ok(pipe) => Some(pipe),
|
||||
Err(err) => {
|
||||
@ -2230,14 +2023,14 @@ fn create_shadow_pipeline<P: gfx::pso::PipelineInit>(
|
||||
// Second-depth shadow mapping: should help reduce z-fighting provided all objects
|
||||
// are "watertight" (every triangle edge is shared with at most one other
|
||||
// triangle); this *should* be true for Veloren.
|
||||
cull_face: /*gfx::state::CullFace::Nothing*/match cull_face {
|
||||
cull_face: match cull_face {
|
||||
gfx::state::CullFace::Front => gfx::state::CullFace::Back,
|
||||
gfx::state::CullFace::Back => gfx::state::CullFace::Front,
|
||||
gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing,
|
||||
},
|
||||
method: gfx::state::RasterMethod::Fill,
|
||||
offset,
|
||||
samples: None, // Some(gfx::state::MultiSample),
|
||||
samples: None,
|
||||
},
|
||||
pipe,
|
||||
)?,
|
||||
|
@ -139,8 +139,6 @@ where
|
||||
)
|
||||
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
|
||||
|
||||
// device.cleanup();
|
||||
|
||||
let srv = factory
|
||||
.view_texture_as_shader_resource::<F>(&tex, levels, swizzle)
|
||||
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?;
|
||||
|
@ -91,8 +91,6 @@ impl Camera {
|
||||
(_, Err(_)) => self.dist,
|
||||
}
|
||||
.max(0.0)
|
||||
// .max(NEAR_PLANE)
|
||||
// self.dist.max(0.0)
|
||||
};
|
||||
|
||||
self.dependents.view_mat = Mat4::<f32>::identity()
|
||||
|
@ -936,14 +936,14 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
|
||||
.unwrap_or_else(<Skel::Attr as Default>::default);
|
||||
|
||||
let manifest_indicator = &mut self.manifest_indicator;
|
||||
let mut make_model = |generate_mesh: for<'a> fn(&mut GreedyMesh<'a>, _, _) -> _| {
|
||||
let mut make_model =
|
||||
|generate_mesh: for<'a> fn(&mut GreedyMesh<'a>, _, _) -> _| {
|
||||
let mut greedy = FigureModel::make_greedy();
|
||||
let mut opaque = Mesh::new();
|
||||
let mut figure_bounds = Aabb {
|
||||
min: Vec3::zero(),
|
||||
max: Vec3::zero(),
|
||||
};
|
||||
// let mut shadow = Mesh::new();
|
||||
Self::bone_meshes(
|
||||
body,
|
||||
loadout,
|
||||
@ -953,16 +953,19 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
|
||||
|segment, offset| generate_mesh(&mut greedy, segment, offset),
|
||||
)
|
||||
.iter()
|
||||
// .zip(&mut figure_bounds)
|
||||
.enumerate()
|
||||
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
|
||||
.for_each(|(i, (opaque_mesh/*, shadow_mesh*/, bounds)/*, bone_bounds*/)| {
|
||||
// opaque.push_mesh_map(opaque_mesh, |vert| vert.with_bone_idx(i as u8));
|
||||
opaque.push_mesh_map(opaque_mesh, |vert| vert.with_bone_idx(i as u8));
|
||||
figure_bounds.expand_to_contain(*bounds);
|
||||
// shadow.push_mesh_map(shadow_mesh, |vert| vert.with_bone_idx(i as u8));
|
||||
.for_each(
|
||||
|(i, (opaque_mesh, bounds))| {
|
||||
opaque.push_mesh_map(opaque_mesh, |vert| {
|
||||
vert.with_bone_idx(i as u8)
|
||||
});
|
||||
col_lights.create_figure(renderer, greedy, (opaque/*, shadow*/, figure_bounds)).unwrap()
|
||||
figure_bounds.expand_to_contain(*bounds);
|
||||
},
|
||||
);
|
||||
col_lights
|
||||
.create_figure(renderer, greedy, (opaque, figure_bounds))
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
fn generate_mesh<'a>(
|
||||
@ -970,11 +973,12 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
|
||||
segment: Segment,
|
||||
offset: Vec3<f32>,
|
||||
) -> BoneMeshes {
|
||||
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
||||
let (opaque, _, _, bounds) =
|
||||
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
||||
segment,
|
||||
(greedy, offset, Vec3::one()),
|
||||
);
|
||||
(opaque/*, shadow*/, bounds)
|
||||
(opaque, bounds)
|
||||
}
|
||||
|
||||
fn generate_mesh_lod_mid<'a>(
|
||||
@ -983,11 +987,12 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
|
||||
offset: Vec3<f32>,
|
||||
) -> BoneMeshes {
|
||||
let lod_scale = Vec3::broadcast(0.6);
|
||||
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
||||
let (opaque, _, _, bounds) =
|
||||
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
||||
segment.scaled_by(lod_scale),
|
||||
(greedy, offset * lod_scale, Vec3::one() / lod_scale),
|
||||
);
|
||||
(opaque/*, shadow*/, bounds)
|
||||
(opaque, bounds)
|
||||
}
|
||||
|
||||
fn generate_mesh_lod_low<'a>(
|
||||
@ -997,11 +1002,12 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
|
||||
) -> BoneMeshes {
|
||||
let lod_scale = Vec3::broadcast(0.3);
|
||||
let segment = segment.scaled_by(lod_scale);
|
||||
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
||||
let (opaque, _, _, bounds) =
|
||||
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
||||
segment,
|
||||
(greedy, offset * lod_scale, Vec3::one() / lod_scale),
|
||||
);
|
||||
(opaque/*, shadow*/, bounds)
|
||||
(opaque, bounds)
|
||||
}
|
||||
|
||||
(
|
||||
|
@ -793,7 +793,7 @@ impl HumMainWeaponSpec {
|
||||
let tool_kind = if let Some(ItemKind::Tool(Tool { kind, .. })) = item_kind {
|
||||
kind
|
||||
} else {
|
||||
return (Mesh::new() /* , Mesh::new() */, Aabb::default());
|
||||
return (Mesh::new(), Aabb::default());
|
||||
};
|
||||
|
||||
let spec = match self.0.get(tool_kind) {
|
||||
|
@ -8,8 +8,8 @@ use crate::{
|
||||
ecs::comp::Interpolated,
|
||||
mesh::greedy::GreedyMesh,
|
||||
render::{
|
||||
BoneMeshes, ColLightFmt, Consts, FigureBoneData, FigureLocals, FigureModel, Globals, Light,
|
||||
RenderError, Renderer, Shadow, ShadowLocals, ShadowPipeline, Texture,
|
||||
BoneMeshes, ColLightFmt, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel,
|
||||
RenderError, Renderer, ShadowPipeline, Texture,
|
||||
},
|
||||
scene::{
|
||||
camera::{Camera, CameraMode, Dependents},
|
||||
@ -48,6 +48,9 @@ const DAMAGE_FADE_COEFFICIENT: f64 = 5.0;
|
||||
const MOVING_THRESHOLD: f32 = 0.7;
|
||||
const MOVING_THRESHOLD_SQR: f32 = MOVING_THRESHOLD * MOVING_THRESHOLD;
|
||||
|
||||
/// camera data, fiigure LOD render distance.
|
||||
pub type CameraData<'a> = (&'a Camera, f32);
|
||||
|
||||
struct FigureMgrStates {
|
||||
character_states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
|
||||
quadruped_small_states: HashMap<EcsEntity, FigureState<QuadrupedSmallSkeleton>>,
|
||||
@ -1996,12 +1999,9 @@ impl FigureMgr {
|
||||
renderer: &mut Renderer,
|
||||
state: &State,
|
||||
tick: u64,
|
||||
globals: &Consts<Globals>,
|
||||
shadow_mats: &Consts<ShadowLocals>,
|
||||
is_daylight: bool,
|
||||
_light_data: &[Light],
|
||||
camera: &Camera,
|
||||
figure_lod_render_distance: f32,
|
||||
global: &GlobalModel,
|
||||
(is_daylight, _light_data): super::LightData,
|
||||
(camera, figure_lod_render_distance): CameraData,
|
||||
) {
|
||||
let ecs = state.ecs();
|
||||
|
||||
@ -2034,10 +2034,10 @@ impl FigureMgr {
|
||||
) {
|
||||
renderer.render_figure_shadow_directed(
|
||||
model,
|
||||
globals,
|
||||
global,
|
||||
locals,
|
||||
bone_consts,
|
||||
shadow_mats,
|
||||
&global.shadow_mats,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -2051,13 +2051,9 @@ impl FigureMgr {
|
||||
state: &State,
|
||||
player_entity: EcsEntity,
|
||||
tick: u64,
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
shadow_mats: &Consts<ShadowLocals>,
|
||||
global: &GlobalModel,
|
||||
lod: &LodData,
|
||||
camera: &Camera,
|
||||
figure_lod_render_distance: f32,
|
||||
(camera, figure_lod_render_distance): CameraData,
|
||||
) {
|
||||
let ecs = state.ecs();
|
||||
|
||||
@ -2096,14 +2092,10 @@ impl FigureMgr {
|
||||
renderer.render_figure(
|
||||
model,
|
||||
&col_lights.col_lights,
|
||||
globals,
|
||||
global,
|
||||
locals,
|
||||
bone_consts,
|
||||
lights,
|
||||
shadows,
|
||||
shadow_mats,
|
||||
&lod.alt,
|
||||
&lod.horizon,
|
||||
lod,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -2117,13 +2109,9 @@ impl FigureMgr {
|
||||
state: &State,
|
||||
player_entity: EcsEntity,
|
||||
tick: u64,
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
shadow_mats: &Consts<ShadowLocals>,
|
||||
global: &GlobalModel,
|
||||
lod: &LodData,
|
||||
camera: &Camera,
|
||||
figure_lod_render_distance: f32,
|
||||
(camera, figure_lod_render_distance): CameraData,
|
||||
) {
|
||||
let ecs = state.ecs();
|
||||
|
||||
@ -2160,26 +2148,18 @@ impl FigureMgr {
|
||||
renderer.render_player(
|
||||
model,
|
||||
&col_lights.col_lights,
|
||||
globals,
|
||||
global,
|
||||
locals,
|
||||
bone_consts,
|
||||
lights,
|
||||
shadows,
|
||||
shadow_mats,
|
||||
&lod.alt,
|
||||
&lod.horizon,
|
||||
lod,
|
||||
);
|
||||
renderer.render_player_shadow(
|
||||
model,
|
||||
&col_lights.col_lights,
|
||||
globals,
|
||||
locals,
|
||||
global,
|
||||
bone_consts,
|
||||
lights,
|
||||
shadows,
|
||||
shadow_mats,
|
||||
&lod.alt,
|
||||
&lod.horizon,
|
||||
lod,
|
||||
&global.shadow_mats,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,89 +1,24 @@
|
||||
use crate::{
|
||||
render::{
|
||||
pipelines::lod_terrain::{Locals, Vertex},
|
||||
Consts, Globals, LodAltFmt, LodColorFmt, LodTerrainPipeline, LodTextureFmt, Mesh, Model,
|
||||
Quad, Renderer, Texture,
|
||||
pipelines::lod_terrain::{Locals, LodData, Vertex},
|
||||
Consts, GlobalModel, LodTerrainPipeline, Mesh, Model, Quad, Renderer,
|
||||
},
|
||||
settings::Settings,
|
||||
};
|
||||
use client::Client;
|
||||
use common::{spiral::Spiral2d, util::srgba_to_linear};
|
||||
use gfx::texture::SamplerInfo;
|
||||
use vek::*;
|
||||
|
||||
pub struct LodData {
|
||||
pub map: Texture<LodColorFmt>,
|
||||
pub alt: Texture<LodAltFmt>,
|
||||
pub horizon: Texture<LodTextureFmt>,
|
||||
pub tgt_detail: u32,
|
||||
}
|
||||
|
||||
pub struct Lod {
|
||||
model: Option<(u32, Model<LodTerrainPipeline>)>,
|
||||
locals: Consts<Locals>,
|
||||
data: LodData,
|
||||
}
|
||||
|
||||
impl LodData {
|
||||
pub fn new(
|
||||
renderer: &mut Renderer,
|
||||
map_size: Vec2<u16>,
|
||||
lod_base: &[u32],
|
||||
lod_alt: &[u32],
|
||||
lod_horizon: &[u32],
|
||||
tgt_detail: u32,
|
||||
border_color: gfx::texture::PackedColor,
|
||||
) -> Self {
|
||||
let kind = gfx::texture::Kind::D2(map_size.x, map_size.y, gfx::texture::AaMode::Single);
|
||||
let info = gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Bilinear,
|
||||
gfx::texture::WrapMode::Border,
|
||||
);
|
||||
Self {
|
||||
map: renderer
|
||||
.create_texture_immutable_raw(
|
||||
kind,
|
||||
gfx::texture::Mipmap::Provided,
|
||||
&[gfx::memory::cast_slice(lod_base)],
|
||||
SamplerInfo {
|
||||
border: border_color,
|
||||
..info
|
||||
},
|
||||
)
|
||||
.expect("Failed to generate map texture"),
|
||||
alt: renderer
|
||||
.create_texture_immutable_raw(
|
||||
kind,
|
||||
gfx::texture::Mipmap::Provided,
|
||||
&[gfx::memory::cast_slice(lod_alt)],
|
||||
SamplerInfo {
|
||||
border: [0.0, 0.0, 0.0, 0.0].into(),
|
||||
..info
|
||||
},
|
||||
)
|
||||
.expect("Failed to generate alt texture"),
|
||||
horizon: renderer
|
||||
.create_texture_immutable_raw(
|
||||
kind,
|
||||
gfx::texture::Mipmap::Provided,
|
||||
&[gfx::memory::cast_slice(lod_horizon)],
|
||||
SamplerInfo {
|
||||
// filter: gfx::texture::FilterMethod::Nearest,
|
||||
// filter: gfx::texture::FilterMethod::TriLinear,
|
||||
border: [1.0, 0.0, 1.0, 0.0].into(),
|
||||
..info
|
||||
},
|
||||
)
|
||||
.expect("Failed to generate horizon texture"),
|
||||
tgt_detail,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make constant when possible.
|
||||
pub fn water_color() -> Rgba<f32> {
|
||||
/* Rgba::new(0.2, 0.5, 1.0, 0.0) */
|
||||
srgba_to_linear(Rgba::new(0.0, 0.25, 0.5, 0.0)/* * 0.5*/)
|
||||
srgba_to_linear(Rgba::new(0.0, 0.25, 0.5, 0.0))
|
||||
}
|
||||
|
||||
impl Lod {
|
||||
@ -123,16 +58,9 @@ impl Lod {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
|
||||
pub fn render(&self, renderer: &mut Renderer, global: &GlobalModel) {
|
||||
if let Some((_, model)) = self.model.as_ref() {
|
||||
renderer.render_lod_terrain(
|
||||
&model,
|
||||
globals,
|
||||
&self.locals,
|
||||
&self.data.map,
|
||||
&self.data.alt,
|
||||
&self.data.horizon,
|
||||
);
|
||||
renderer.render_lod_terrain(&model, global, &self.locals, &self.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,16 +103,6 @@ pub fn clip_points_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
|
||||
plane: (Vec3<T>, T),
|
||||
intersection_points: &mut Vec<Vec3<T>>,
|
||||
) -> bool {
|
||||
/* enum Intersection {
|
||||
/// Previous point was inside the plane.
|
||||
Inside,
|
||||
/// Previous line segment was completely outside the plane.
|
||||
Outside,
|
||||
/// Previous line segment went from inside the plane to outside it.
|
||||
InsideOut,
|
||||
} */
|
||||
// println!("points@clip_points_by_plane before clipping by {:?}: {:?}", plane,
|
||||
// points);
|
||||
if points.len() < 3 {
|
||||
return false;
|
||||
}
|
||||
@ -135,36 +125,12 @@ pub fn clip_points_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
|
||||
};
|
||||
let last_is_outside = point_before_plane(current_point, plane);
|
||||
let mut is_outside = last_is_outside;
|
||||
/* // Might not actually be total, but if it is partial and the point is inside it will be
|
||||
// written regardless, and if it is partial and the point is outside, it means the
|
||||
// second-to-last point is inside; thus, the second-to-last point will be written regardless,
|
||||
// current_point will hold the new intersection point, and is_total will be false, when the
|
||||
// loop ends; thus all we need to do to take this case into account is to push current_point
|
||||
// onto the points vector if (is_total || is_outside) is false at the end of the loop.
|
||||
let mut is_total = true; */
|
||||
let mut old_points = Vec::with_capacity((3 * points.len()) / 2);
|
||||
mem::swap(&mut old_points, points);
|
||||
old_points.into_iter().for_each(|point| {
|
||||
/* let prev_point = current_point;
|
||||
// Swap point i with the previous point in the polygon, so it is the one we normally save
|
||||
// when we return false.
|
||||
mem::swap(&mut current_point, point); */
|
||||
let prev_point = mem::replace(&mut current_point, point);
|
||||
/* if point_before_plane(current_point) {
|
||||
// If we are an outside point, we should only calculate an intersection if the previous
|
||||
// point was inside.
|
||||
if
|
||||
is_outside s
|
||||
// point was outside.
|
||||
} else {
|
||||
// If we are an inside point, then we should only calculate an intersection if the previous
|
||||
// point was outside.
|
||||
} */
|
||||
let before_plane = point_before_plane(current_point, plane);
|
||||
let prev_is_outside = mem::replace(&mut is_outside, before_plane);
|
||||
// println!("points@clip_points_by_plane clipping segment by {:?} (prev={:?} /
|
||||
// outside={:?}, current={:?} / outside={:?})", plane, prev_point,
|
||||
// prev_is_outside, current_point, is_outside);
|
||||
if !prev_is_outside {
|
||||
// Push previous point.
|
||||
points.push(prev_point);
|
||||
@ -176,115 +142,7 @@ pub fn clip_points_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
|
||||
points.push(intersection_point);
|
||||
}
|
||||
}
|
||||
/* let prev_is_total = mem::replace(
|
||||
&mut is_total,
|
||||
// Save the intersection point only if we go from outside to inside or inside to
|
||||
// outside, and definitely intersect the plane edge.
|
||||
prev_is_outside != is_outside &&
|
||||
|
||||
.map(|intersection_point| {
|
||||
intersection_points.push(intersection_point);
|
||||
if prev_is_outside {
|
||||
// If the previous point is outside, we know
|
||||
*point = intersection_point;
|
||||
} else {
|
||||
// i o i o
|
||||
//
|
||||
// i o (2)
|
||||
// i i/o o/i (3)
|
||||
//
|
||||
// i o i (3)
|
||||
// i i/o o/i i (4)
|
||||
//
|
||||
// i o i o (4)
|
||||
// i i/o o/i i i/o o/i (6)
|
||||
//
|
||||
// i o i o i (5)
|
||||
// i i/o o/i i i/o o/i i (7)
|
||||
//
|
||||
// i o i o i o (6)
|
||||
// i i/o o/i i i/o o/i i i/o o/i (9)
|
||||
current_point = intersection_point;
|
||||
}
|
||||
false
|
||||
})
|
||||
.is_none(),
|
||||
);
|
||||
// Save the previous point if it is either inside, or has been replaced by an intersection
|
||||
// point.
|
||||
!prev_is_outside || prev_is_total
|
||||
/* match (prev_is_outside, is_outside) {
|
||||
(true, true) => {
|
||||
prev_is_total
|
||||
},
|
||||
(true, false) => {
|
||||
// Outside to inside, so save the previous point only if it's been replaced by an
|
||||
// intersection point.
|
||||
do_intersection();
|
||||
prev_is_total
|
||||
},
|
||||
(false, true) => {
|
||||
// Inside to outside, so always save the previous point, and save the intersection
|
||||
// point only if we definitively intersect the plane edge.
|
||||
false
|
||||
},
|
||||
(false, false) => {
|
||||
// Both points inside the plane, so always save the previous point.
|
||||
false
|
||||
}
|
||||
} */ */
|
||||
});
|
||||
/* if !(is_total || is_outside) {
|
||||
points.push(current_point);
|
||||
}
|
||||
/* match (before_plane, is_outside) {
|
||||
(true, Previous::Outside) => {
|
||||
|
||||
}
|
||||
}
|
||||
let cur_is_outside = {
|
||||
if let Intersection::Inside = is_outside {
|
||||
} else {
|
||||
}
|
||||
let prev_is_outside = mem::replace(&mut is_outside, {
|
||||
let if let Intersection::Inside = is_outside {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
} point_before_plane(current_point) {
|
||||
});
|
||||
match (prev_is_outside, is_outside) {
|
||||
(true, Some(is_outside)) => {
|
||||
// Both points outside the plane, so save the previous point only if it's been
|
||||
// replaced by an intersection point.
|
||||
is_outside
|
||||
},
|
||||
(true, false) => {
|
||||
// Outside to inside, so calculate the intersection, and save it.
|
||||
intersect_points.push(*point);
|
||||
false
|
||||
},
|
||||
(false, true) => {
|
||||
// Inside to outside, so calculate the intersection, and save it and the current
|
||||
// point.
|
||||
intersect_points.push(*point);
|
||||
false
|
||||
},
|
||||
(false, false) => {
|
||||
// Both points inside the plane, so save previous point
|
||||
*point = *
|
||||
false
|
||||
}
|
||||
}
|
||||
if is_outside {
|
||||
if prev_is_outside {
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
if prev_is_outside {
|
||||
}
|
||||
}
|
||||
});*/ }*/
|
||||
last_is_outside
|
||||
}
|
||||
|
||||
@ -338,11 +196,14 @@ fn append_intersection_points<T: Float + core::fmt::Debug>(
|
||||
// We use floating points rounded to tolerance in order to make our HashMap
|
||||
// lookups work. Otherwise we'd have to use a sorted structure, like a
|
||||
// btree, which wouldn't be the end of the world but would have
|
||||
// theoretically worse complexity. NOTE: Definitely non-ideal that we
|
||||
// panic if the rounded value can't fit in an i64... TODO: If necessary,
|
||||
// let the caller specify how to hash these keys, since in cases where
|
||||
// we know the kind of floating point we're using we can just cast to bits or
|
||||
// something.
|
||||
// theoretically worse complexity.
|
||||
//
|
||||
// NOTE: Definitely non-ideal that we panic if the rounded value can't fit in an
|
||||
// i64...
|
||||
//
|
||||
// TODO: If necessary, let the caller specify how to hash these keys, since in
|
||||
// cases where we know the kind of floating point we're using we can
|
||||
// just cast to bits or something.
|
||||
point.map(|e| {
|
||||
(e * tol)
|
||||
.round()
|
||||
@ -362,45 +223,17 @@ fn append_intersection_points<T: Float + core::fmt::Debug>(
|
||||
// than lines).
|
||||
(u_key != make_key(v)).then_some((u_key, v))
|
||||
});
|
||||
// .map(|uv| (make_key(uv[0]), uv[1]))
|
||||
|
||||
if let Some((last_key, first)) = lines_iter.next()
|
||||
/* [last, first, rest @ ..] = &*intersection_points = &*intersection_points */
|
||||
{
|
||||
if let Some((last_key, first)) = lines_iter.next() {
|
||||
let lines = lines_iter.collect::<HashMap<_, _>>();
|
||||
/* if rest.len() < 4 {
|
||||
// You need at least 3 sides for a polygon
|
||||
return;
|
||||
}
|
||||
let lines = rest
|
||||
.chunks_exact(2)
|
||||
.filter_map(|uv| {
|
||||
let u_key = make_key(uv[0]);
|
||||
let v = uv[1];
|
||||
(u_key != make_key(v)).then_some((u_key, v))
|
||||
})
|
||||
// .map(|uv| (make_key(uv[0]), uv[1]))
|
||||
.collect::<HashMap<_, _>>(); */
|
||||
if lines.len() < 2 {
|
||||
// You need at least 3 sides for a polygon
|
||||
return;
|
||||
}
|
||||
// println!("lines@append_intersection_points before merging points (last={:?},
|
||||
// cur={:?}): {:?}", last, cur, lines);
|
||||
// let mut poly = Vec::with_capacity(lines.len() + 1);
|
||||
// poly.push(first);
|
||||
// NOTE: Guaranteed to terminate, provided we have no cycles besides the one
|
||||
// that touches every point (which should be the case given how these
|
||||
// points were generated).
|
||||
let /*mut */poly_iter = iter::successors(Some(first), |&cur| lines.get(&make_key(cur)).copied());
|
||||
/* poly.extend(poly_iter.next());
|
||||
// TODO: If we were smart and pre-tested whether (last, first) was a dup (guaranteeing we
|
||||
// started on a non-dup), we would not need the take_while part.
|
||||
poly.extend(poly_iter.take_while(|&cur| make_key(cur) != make_key(first)));
|
||||
/* while let Some(&v) = lines.get(&make_key(cur)) {
|
||||
cur = v;
|
||||
poly.push(cur);
|
||||
} */ */
|
||||
let poly_iter = iter::successors(Some(first), |&cur| lines.get(&make_key(cur)).copied());
|
||||
let poly: Vec<_> = poly_iter.collect();
|
||||
// We have to check to make sure we really went through the whole cycle.
|
||||
// TODO: Consider adaptively decreasing precision until we can make the cycle
|
||||
@ -421,7 +254,6 @@ pub fn clip_object_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
|
||||
polys.drain_filter(|points| {
|
||||
let len = intersection_points.len();
|
||||
let outside_first = clip_points_by_plane(points, plane, &mut intersection_points);
|
||||
// println!("points@clip_object_by_plane after clipping by {:?} (outside_first={:?}, intersection_points={:?}): {:?}", plane, outside_first, intersection_points, points);
|
||||
// Only remember intersections that are not coplanar with this side; i.e. those
|
||||
// that have segment length 2.
|
||||
if len + 2 != intersection_points.len() {
|
||||
@ -444,8 +276,6 @@ pub fn clip_object_by_plane<T: Float + MulAdd<T, T, Output = T> + core::fmt::Deb
|
||||
// Remove polygon if it was clipped away
|
||||
points.is_empty()
|
||||
});
|
||||
// println!("polys@clip_object_by_plane after clipping by {:?} (before appending
|
||||
// interection points {:?}): {:?}", plane, intersection_points, polys);
|
||||
// Add a polygon of all intersection points with the plane to close out the
|
||||
// object.
|
||||
append_intersection_points(polys, intersection_points, tolerance);
|
||||
@ -457,11 +287,8 @@ pub fn clip_object_by_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::Debu
|
||||
tolerance: T,
|
||||
) {
|
||||
let planes = aabb_to_planes(bounds);
|
||||
// println!("planes@clip_object_by_aabb: {:?}", planes);
|
||||
planes.iter().for_each(|&plane| {
|
||||
clip_object_by_plane(polys, plane, tolerance);
|
||||
// println!("polys@clip_object_by_aabb (after clipping by {:?}):
|
||||
// {:?}", plane, polys);
|
||||
});
|
||||
}
|
||||
|
||||
@ -469,7 +296,6 @@ pub fn clip_object_by_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::Debu
|
||||
/// test plane. Otherwise 'None' is returned in which case the line
|
||||
/// segment is entirely clipped.
|
||||
pub fn clip_test<T: Float + core::fmt::Debug>(p: T, q: T, (u1, u2): (T, T)) -> Option<(T, T)> {
|
||||
/* let res = */
|
||||
if p == T::zero() {
|
||||
if q >= T::zero() { Some((u1, u2)) } else { None }
|
||||
} else {
|
||||
@ -485,9 +311,7 @@ pub fn clip_test<T: Float + core::fmt::Debug>(p: T, q: T, (u1, u2): (T, T)) -> O
|
||||
} else {
|
||||
Some((u1, if r < u2 { r } else { u2 }))
|
||||
}
|
||||
} /*;
|
||||
// println!("clip_test@(p={:?}, q={:?}, (u1, u2)=({:?}. {:?})):
|
||||
// res={:?}", p, q, u1, u2, res); res*/
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intersection_line_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::Debug>(
|
||||
@ -495,9 +319,6 @@ pub fn intersection_line_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::D
|
||||
dir: Vec3<T>,
|
||||
bounds: Aabb<T>,
|
||||
) -> Option<Vec3<T>> {
|
||||
// println!("before@intersection_line_aabb: p={:?} dir={:?} bounds={:?}", p,
|
||||
// dir, bounds);
|
||||
/* let res = */
|
||||
clip_test(-dir.z, p.z - bounds.min.z, (T::zero(), T::infinity()))
|
||||
.and_then(|t| clip_test(dir.z, bounds.max.z - p.z, t))
|
||||
.and_then(|t| clip_test(-dir.y, p.y - bounds.min.y, t))
|
||||
@ -512,9 +333,7 @@ pub fn intersection_line_aabb<T: Float + MulAdd<T, T, Output = T> + core::fmt::D
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) /*;
|
||||
//println!("after@intersection_line_aabb (p={:?} dir={:?} bounds={:?}):
|
||||
// {:?}", p, dir, bounds, res); res */
|
||||
})
|
||||
}
|
||||
|
||||
pub fn include_object_light_volume<
|
||||
@ -525,12 +344,12 @@ pub fn include_object_light_volume<
|
||||
light_dir: Vec3<T>,
|
||||
bounds: Aabb<T>,
|
||||
) -> impl Iterator<Item = Vec3<T>> {
|
||||
/* obj.filter_map(move |pt| intersection_line_aabb(pt, -light_dir, bounds)) */
|
||||
// obj.map(move |pt| intersection_line_aabb(pt, -light_dir,
|
||||
// bounds).unwrap_or(pt))
|
||||
obj.flat_map(move |pt| iter::once(pt).chain(intersection_line_aabb(pt, -light_dir, bounds)))
|
||||
}
|
||||
|
||||
// NOTE: Currently specialized to skip extending to the end of the light ray,
|
||||
// since our light ray is already infinite. Correct code is commented out
|
||||
// below.
|
||||
pub fn calc_focused_light_volume_points<T: Float + MulAdd<T, T, Output = T> + core::fmt::Debug>(
|
||||
inv_proj_view: Mat4<T>,
|
||||
_light_dir: Vec3<T>,
|
||||
@ -538,13 +357,8 @@ pub fn calc_focused_light_volume_points<T: Float + MulAdd<T, T, Output = T> + co
|
||||
tolerance: T,
|
||||
) -> impl Iterator<Item = Vec3<T>> {
|
||||
let world_pts = calc_view_frustum_world_coord(inv_proj_view);
|
||||
// println!("world_pts: {:?}", world_pts);
|
||||
let mut world_frust_object = calc_view_frust_object(&world_pts);
|
||||
// println!("world_frust_object: {:?}", world_frust_object);
|
||||
clip_object_by_aabb(&mut world_frust_object, scene_bounding_box, tolerance);
|
||||
// println!("world_frust_object@clip_object_by_aabb: {:?}", world_frust_object);
|
||||
/* let object_points = world_frust_object.into_iter().flat_map(|e| e.into_iter());
|
||||
object_points.clone().chain(include_object_light_volume(object_points, light_dir, scene_bounding_box)) */
|
||||
world_frust_object.into_iter().flat_map(|e| e.into_iter())
|
||||
/* include_object_light_volume(
|
||||
world_frust_object.into_iter().flat_map(|e| e.into_iter()),
|
||||
@ -574,50 +388,4 @@ pub fn fit_psr<
|
||||
min: min.xyz(),
|
||||
max: max.xyz(),
|
||||
}
|
||||
/* let mut make_p = |x: f32, y: f32, z: f32| -> Vec3<f32> {
|
||||
do_p(mat * Vec4::new(x, y, z, 1.0))
|
||||
};
|
||||
let p1 = make_p(bounds.min.x, bounds.min.y, bounds.min.z);
|
||||
let p2 = make_p(bounds.max.x, bounds.min.y, bounds.min.z);
|
||||
let p3 = make_p(bounds.min.x, bounds.max.y, bounds.min.z);
|
||||
let p4 = make_p(bounds.max.x, bounds.max.y, bounds.min.z);
|
||||
let p5 = make_p(bounds.min.x, bounds.min.y, bounds.max.z);
|
||||
let p6 = make_p(bounds.max.x, bounds.min.y, bounds.max.z);
|
||||
let p7 = make_p(bounds.min.x, bounds.max.y, bounds.max.z);
|
||||
let p8 = make_p(bounds.max.x, bounds.max.y, bounds.max.z);
|
||||
// let p1: Vec4<f32> = mat * Vec4::new(bounds.min.x, bounds.min.y, bounds.min.z, 1.0);
|
||||
// let p2: Vec4<f32> = mat * Vec4::new(0.0, bounds.min.y, 0.0, 1.0);
|
||||
// let p3: Vec4<f32> = mat * Vec4::new(0.0, 0.0, bounds.min.z, 1.0);
|
||||
// let p4: Vec4<f32> = mat * Vec4::new(bounds.max.x, 0.0, 0.0, 1.0);
|
||||
// let p5: Vec4<f32> = mat * Vec4::new(0.0, bounds.max.y, 0.0, 1.0);
|
||||
// let p6: Vec4<f32> = mat * Vec4::new(bounds.max.x, bounds.max.y, bounds.max.z, 1.0);
|
||||
// println!("p1 p6 {:?} {:?}", p1, p6);
|
||||
// let xmin = p1.x.min(p6.x);
|
||||
// let xmax = p1.x.max(p6.x);
|
||||
// println!("p1 p2 p3 p4 p5 p6: {:?} {:?} {:?} {:?} {:?} {:?}", p1, p2, p3, p4, p5, p6);
|
||||
let xmin = p1.x.min(p2.x.min(p3.x.min(p4.x.min(p5.x.min(p6.x.min(p7.x.min(p8.x)))))));
|
||||
let xmax = p1.x.max(p2.x.max(p3.x.max(p4.x.max(p5.x.max(p6.x.max(p7.x.max(p8.x)))))));
|
||||
// let xmin = p1.x.min(p2.x.min(p3.x.min(p4.x.min(p5.x.min(p6.x)))));
|
||||
// let xmax = p1.x.max(p2.x.max(p3.x.max(p4.x.max(p5.x.max(p6.x)))));
|
||||
// println!("xmin: {:?}, xmax: {:?}", xmin, xmax);
|
||||
// let ymin = p1.y.min(p6.y);
|
||||
// let ymax = p1.y.max(p6.y);
|
||||
let ymin = p1.y.min(p2.y.min(p3.y.min(p4.y.min(p5.y.min(p6.y.min(p7.y.min(p8.y)))))));
|
||||
let ymax = p1.y.max(p2.y.max(p3.y.max(p4.y.max(p5.y.max(p6.y.max(p7.y.max(p8.y)))))));
|
||||
// println!("ymin: {:?}, ymax: {:?}", ymin, ymax);
|
||||
|
||||
// let p1: Vec4<f32> = view_mat * Vec4::new(scene_bounds.min.x, scene_bounds.min.y, scene_bounds.min.z, 1.0);
|
||||
// let p2: Vec4<f32> = view_mat * Vec4::new(0.0, scene_bounds.min.y, 0.0, 1.0);
|
||||
// let p3: Vec4<f32> = view_mat * Vec4::new(0.0, 0.0, scene_bounds.min.z, 1.0);
|
||||
// let p4: Vec4<f32> = view_mat * Vec4::new(scene_bounds.max.x, scene_bounds.max.y, scene_bounds.max.z, 1.0);
|
||||
// let p5: Vec4<f32> = view_mat * Vec4::new(0.0, scene_bounds.max.y, 0.0, 1.0);
|
||||
// let p6: Vec4<f32> = view_mat * Vec4::new(0.0, 0.0, scene_bounds.max.z, 1.0);
|
||||
// println!("p1 p2 p3 p4 p5 p6: {:?} {:?} {:?} {:?} {:?} {:?}", p1, p2, p3, p4, p5, p6);
|
||||
// println!("p1 p4 {:?} {:?}", p1, p4);
|
||||
let zmin = p1.z.min(p2.z.min(p3.z.min(p4.z.min(p5.z.min(p6.z.min(p7.z.min(p8.z)))))));
|
||||
let zmax = p1.z.max(p2.z.max(p3.z.max(p4.z.max(p5.z.max(p6.z.max(p7.z.max(p8.z)))))));
|
||||
Aabb {
|
||||
min: Vec3::new(xmin, ymin, zmin),
|
||||
max: Vec3::new(xmax, ymax, zmax),
|
||||
} */
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,8 +2,8 @@ use crate::{
|
||||
mesh::{greedy::GreedyMesh, Meshable},
|
||||
render::{
|
||||
create_pp_mesh, create_skybox_mesh, BoneMeshes, Consts, FigureModel, FigurePipeline,
|
||||
Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer, Shadow,
|
||||
ShadowLocals, SkyboxLocals, SkyboxPipeline,
|
||||
GlobalModel, Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer,
|
||||
Shadow, ShadowLocals, SkyboxLocals, SkyboxPipeline,
|
||||
},
|
||||
scene::{
|
||||
camera::{self, Camera, CameraMode},
|
||||
@ -68,10 +68,7 @@ struct PostProcess {
|
||||
}
|
||||
|
||||
pub struct Scene {
|
||||
globals: Consts<Globals>,
|
||||
lights: Consts<Light>,
|
||||
shadows: Consts<Shadow>,
|
||||
shadow_mats: Consts<ShadowLocals>,
|
||||
data: GlobalModel,
|
||||
camera: Camera,
|
||||
|
||||
skybox: Skybox,
|
||||
@ -105,18 +102,8 @@ impl Scene {
|
||||
|
||||
let map_bounds = Vec2::new(-65536.0, 131071.0);
|
||||
let map_border = [0.0, 0.0, 0.0, 0.0];
|
||||
/* let map_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel(
|
||||
1,
|
||||
1,
|
||||
image::Rgba([0, 0, 0, 0]),
|
||||
)); */
|
||||
let map_image = [0];
|
||||
let alt_image = [0];
|
||||
/* let horizon_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel(
|
||||
1,
|
||||
1,
|
||||
image::Rgba([0, 1, 0, 1]),
|
||||
)); */
|
||||
let horizon_image = [0x_00_01_00_01];
|
||||
|
||||
let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson);
|
||||
@ -127,10 +114,14 @@ impl Scene {
|
||||
let mut col_lights = FigureColLights::new(renderer);
|
||||
|
||||
Self {
|
||||
data: GlobalModel {
|
||||
globals: renderer.create_consts(&[Globals::default()]).unwrap(),
|
||||
lights: renderer.create_consts(&[Light::default(); 32]).unwrap(),
|
||||
shadows: renderer.create_consts(&[Shadow::default(); 32]).unwrap(),
|
||||
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]).unwrap(),
|
||||
shadow_mats: renderer
|
||||
.create_consts(&[ShadowLocals::default(); 6])
|
||||
.unwrap(),
|
||||
},
|
||||
|
||||
skybox: Skybox {
|
||||
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
|
||||
@ -142,8 +133,16 @@ impl Scene {
|
||||
.create_consts(&[PostProcessLocals::default()])
|
||||
.unwrap(),
|
||||
},
|
||||
lod: LodData::new(renderer, Vec2::new(1, 1), &map_image, &alt_image, &horizon_image, 1, map_border.into()),// Lod::new(renderer, client, settings),
|
||||
map_bounds,//: client.world_map.2,
|
||||
lod: LodData::new(
|
||||
renderer,
|
||||
Vec2::new(1, 1),
|
||||
&map_image,
|
||||
&alt_image,
|
||||
&horizon_image,
|
||||
1,
|
||||
map_border.into(),
|
||||
),
|
||||
map_bounds,
|
||||
|
||||
figure_model_cache: FigureModelCache::new(),
|
||||
figure_state: FigureState::new(renderer, CharacterSkeleton::default()),
|
||||
@ -173,21 +172,18 @@ impl Scene {
|
||||
&camera,
|
||||
&mut buf,
|
||||
);
|
||||
(
|
||||
model,
|
||||
state,
|
||||
)
|
||||
(model, state)
|
||||
}),
|
||||
col_lights,
|
||||
|
||||
camera,
|
||||
|
||||
turning: false,
|
||||
char_ori: /*0.0*/-start_angle,
|
||||
char_ori: -start_angle,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn globals(&self) -> &Consts<Globals> { &self.globals }
|
||||
pub fn globals(&self) -> &Consts<Globals> { &self.data.globals }
|
||||
|
||||
pub fn camera_mut(&mut self) -> &mut Camera { &mut self.camera }
|
||||
|
||||
@ -234,19 +230,18 @@ impl Scene {
|
||||
cam_pos,
|
||||
} = self.camera.dependents();
|
||||
const VD: f32 = 115.0; // View Distance
|
||||
// const MAP_BOUNDS: Vec2<f32> = Vec2::new(140.0, 2048.0);
|
||||
const TIME: f64 = 10.0 * 60.0 * 60.0; //43200.0; // 12 hours*3600 seconds
|
||||
const TIME: f64 = 10.0 * 60.0 * 60.0;
|
||||
const SHADOW_NEAR: f32 = 1.0;
|
||||
const SHADOW_FAR: f32 = 25.0;
|
||||
|
||||
if let Err(e) = renderer.update_consts(&mut self.globals, &[Globals::new(
|
||||
if let Err(e) = renderer.update_consts(&mut self.data.globals, &[Globals::new(
|
||||
view_mat,
|
||||
proj_mat,
|
||||
cam_pos,
|
||||
self.camera.get_focus_pos(),
|
||||
VD,
|
||||
self.lod.tgt_detail as f32,
|
||||
self.map_bounds, //MAP_BOUNDS,
|
||||
self.map_bounds,
|
||||
TIME,
|
||||
scene_data.time,
|
||||
renderer.get_resolution(),
|
||||
@ -338,10 +333,9 @@ impl Scene {
|
||||
) {
|
||||
renderer.render_skybox(
|
||||
&self.skybox.model,
|
||||
&self.globals,
|
||||
&self.data,
|
||||
&self.skybox.locals,
|
||||
&self.lod.alt,
|
||||
&self.lod.horizon,
|
||||
&self.lod,
|
||||
);
|
||||
|
||||
if let Some(body) = body {
|
||||
@ -361,14 +355,10 @@ impl Scene {
|
||||
renderer.render_figure(
|
||||
&model[0],
|
||||
&self.col_lights.texture(),
|
||||
&self.globals,
|
||||
&self.data,
|
||||
self.figure_state.locals(),
|
||||
self.figure_state.bone_consts(),
|
||||
&self.lights,
|
||||
&self.shadows,
|
||||
&self.shadow_mats,
|
||||
&self.lod.alt,
|
||||
&self.lod.horizon,
|
||||
&self.lod,
|
||||
);
|
||||
}
|
||||
|
||||
@ -376,20 +366,16 @@ impl Scene {
|
||||
renderer.render_figure(
|
||||
model,
|
||||
&self.col_lights.texture(),
|
||||
&self.globals,
|
||||
&self.data,
|
||||
state.locals(),
|
||||
state.bone_consts(),
|
||||
&self.lights,
|
||||
&self.shadows,
|
||||
&self.shadow_mats,
|
||||
&self.lod.alt,
|
||||
&self.lod.horizon,
|
||||
&self.lod,
|
||||
);
|
||||
}
|
||||
|
||||
renderer.render_post_process(
|
||||
&self.postprocess.model,
|
||||
&self.globals,
|
||||
&self.data.globals,
|
||||
&self.postprocess.locals,
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::{
|
||||
mesh::{greedy::GreedyMesh, Meshable},
|
||||
render::{
|
||||
ColLightFmt, ColLightInfo, Consts, FluidPipeline, Globals, Instances, Light, Mesh, Model,
|
||||
RenderError, Renderer, Shadow, ShadowLocals, ShadowPipeline, SpriteInstance, SpriteLocals,
|
||||
SpritePipeline, TerrainLocals, TerrainPipeline, Texture,
|
||||
ColLightFmt, ColLightInfo, Consts, FluidPipeline, GlobalModel, Instances, Mesh, Model,
|
||||
RenderError, Renderer, ShadowPipeline, SpriteInstance, SpriteLocals, SpritePipeline,
|
||||
TerrainLocals, TerrainPipeline, Texture,
|
||||
},
|
||||
};
|
||||
|
||||
@ -40,13 +40,8 @@ struct TerrainChunkData {
|
||||
load_time: f32,
|
||||
opaque_model: Model<TerrainPipeline>,
|
||||
fluid_model: Option<Model<FluidPipeline>>,
|
||||
// shadow_model: Model<ShadowPipeline>,
|
||||
// col_lights: Texture<ColLightFmt>,
|
||||
col_lights: guillotiere::AllocId,
|
||||
sprite_instances: HashMap<
|
||||
(BlockKind, usize),
|
||||
Instances<SpriteInstance>, /* RawBuffer*//*(Consts<SpriteInstance>, usize) */
|
||||
>,
|
||||
sprite_instances: HashMap<(BlockKind, usize), Instances<SpriteInstance>>,
|
||||
locals: Consts<TerrainLocals>,
|
||||
|
||||
visible: Visibility,
|
||||
@ -386,12 +381,10 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug>(
|
||||
volume: <VolGrid2d<V> as SampleVol<Aabr<i32>>>::Sample,
|
||||
max_texture_size: u16,
|
||||
range: Aabb<i32>,
|
||||
sprite_models: &HashMap<(BlockKind, usize), Vec</* Range<u32> */ SpriteData>>,
|
||||
sprite_models: &HashMap<(BlockKind, usize), Vec<SpriteData>>,
|
||||
) -> MeshWorkerResponse {
|
||||
let (opaque_mesh /* col_lights */, fluid_mesh, _shadow_mesh, (bounds, col_lights_info)) =
|
||||
let (opaque_mesh, fluid_mesh, _shadow_mesh, (bounds, col_lights_info)) =
|
||||
volume.generate_mesh((range, Vec2::new(max_texture_size, max_texture_size)));
|
||||
// println!("z_bounds{:?}, bounds: {:?}", z_bounds, (bounds.min.z,
|
||||
// bounds.max.z));
|
||||
MeshWorkerResponse {
|
||||
pos,
|
||||
z_bounds: (bounds.min.z, bounds.max.z),
|
||||
@ -422,23 +415,12 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug>(
|
||||
let sprite_data = &sprite_models[&key][0];
|
||||
let instance = SpriteInstance::new(
|
||||
Mat4::identity()
|
||||
/*sprite_models[&key][0].mat
|
||||
/* .scaled_3d(
|
||||
lod_scale
|
||||
) */
|
||||
/* .translated_3d(
|
||||
offset
|
||||
) */
|
||||
// * 1.0 / 11.0
|
||||
.rotated_z(f32::consts::PI * 0.25 * ori as f32)
|
||||
*/
|
||||
.translated_3d(sprite_data.offset)
|
||||
// .scaled_3d(SPRITE_SCALE)
|
||||
.rotated_z(f32::consts::PI * 0.25 * ori as f32)
|
||||
.translated_3d(
|
||||
(rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)) / SPRITE_SCALE,
|
||||
(rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0))
|
||||
/ SPRITE_SCALE,
|
||||
),
|
||||
// Rgb::broadcast(1.0),
|
||||
cfg.wind_sway,
|
||||
rel_pos,
|
||||
ori,
|
||||
@ -490,8 +472,7 @@ pub struct Terrain<V: RectRasterableVol> {
|
||||
mesh_todo: HashMap<Vec2<i32>, ChunkMeshState>,
|
||||
|
||||
// GPU data
|
||||
// sprite_model_data: Model<SpritePipeline>,
|
||||
sprite_models: Arc<HashMap<(BlockKind, usize), Vec</* Range<u32> */ SpriteData>>>,
|
||||
sprite_models: Arc<HashMap<(BlockKind, usize), Vec<SpriteData>>>,
|
||||
sprite_col_lights: Texture<ColLightFmt>,
|
||||
col_lights: Texture<ColLightFmt>,
|
||||
waves: Texture,
|
||||
@ -518,9 +499,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
let max_texture_size = renderer.max_texture_size();
|
||||
let max_size =
|
||||
guillotiere::Size::new(i32::from(max_texture_size), i32::from(max_texture_size));
|
||||
// let max_sprite_size = guillotiere::Size::new(128, 64);
|
||||
let mut greedy = GreedyMesh::new(max_size);
|
||||
// let mut mesh = Mesh::new();
|
||||
let mut locals_buffer = [SpriteLocals::default(); 8];
|
||||
let mut make_models = |(kind, variation), s, offset, lod_axes: Vec3<f32>| {
|
||||
let scaled = [1.0, 0.8, 0.6, 0.4, 0.2];
|
||||
@ -545,10 +524,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
scale
|
||||
}
|
||||
});
|
||||
/* println!(
|
||||
"model_size: {:?} (model_scale = {:?})",
|
||||
model_size, model_scale
|
||||
); */
|
||||
let wind_sway = sprite_config_for(kind).map(|c| c.wind_sway).unwrap_or(0.0);
|
||||
let sprite_mat: Mat4<f32> = Mat4::translation_3d(offset).scaled_3d(SPRITE_SCALE);
|
||||
(
|
||||
@ -556,45 +531,44 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
scaled
|
||||
.iter()
|
||||
.map(|&lod_scale_orig| {
|
||||
let lod_scale = model_scale * if lod_scale_orig == 1.0 {
|
||||
let lod_scale = model_scale
|
||||
* if lod_scale_orig == 1.0 {
|
||||
Vec3::broadcast(1.0)
|
||||
} else {
|
||||
lod_axes * lod_scale_orig + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 })
|
||||
lod_axes * lod_scale_orig
|
||||
+ lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 })
|
||||
};
|
||||
let opaque_model =
|
||||
Meshable::<SpritePipeline, &mut GreedyMesh>::generate_mesh(
|
||||
Segment::from(model.as_ref()).scaled_by(lod_scale),
|
||||
(&mut greedy, wind_sway >= 0.4 && lod_scale_orig == 1.0/*>= 0.8*//*lod_axes.x == 0.0 && lod_axes.y == 0.0*//* && lod_scale.z >= 0.8*//*, offset * lod_scale, Vec3::one() / lod_scale*/),
|
||||
(&mut greedy, wind_sway >= 0.4 && lod_scale_orig == 1.0),
|
||||
)
|
||||
.0;
|
||||
let sprite_scale = Vec3::one() / lod_scale;
|
||||
let sprite_mat: Mat4<f32> = sprite_mat * Mat4::scaling_3d(sprite_scale);
|
||||
locals_buffer.iter_mut().enumerate().for_each(|(ori, locals)| {
|
||||
let sprite_mat = sprite_mat.rotated_z(f32::consts::PI * 0.25 * ori as f32);
|
||||
*locals = SpriteLocals::new(sprite_mat, sprite_scale, offset, wind_sway);
|
||||
locals_buffer
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.for_each(|(ori, locals)| {
|
||||
let sprite_mat =
|
||||
sprite_mat.rotated_z(f32::consts::PI * 0.25 * ori as f32);
|
||||
*locals =
|
||||
SpriteLocals::new(sprite_mat, sprite_scale, offset, wind_sway);
|
||||
});
|
||||
|
||||
SpriteData {
|
||||
/* scale: sprite_scale, */
|
||||
offset,
|
||||
/* mat: sprite_mat, */
|
||||
model: renderer.create_model(&opaque_model)
|
||||
.unwrap(),
|
||||
locals: renderer.create_consts(&locals_buffer)
|
||||
model: renderer.create_model(&opaque_model).unwrap(),
|
||||
locals: renderer
|
||||
.create_consts(&locals_buffer)
|
||||
.expect("Failed to upload sprite locals to the GPU!"),
|
||||
}
|
||||
/* // NOTE: Safe because atlas size is an upper bound on vertex count, and atlas
|
||||
// width and height are at most u16::MAX.
|
||||
let start = mesh.vertices().len() as u32;
|
||||
let vbuf = (start..start + opaque_model.vertices().len() as u32);
|
||||
mesh.push_mesh(&opaque_model);
|
||||
vbuf */
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
};
|
||||
|
||||
let sprite_models: HashMap<(BlockKind, usize), /* Vec<Range<u32>> */ _> = vec![
|
||||
let sprite_models: HashMap<(BlockKind, usize), _> = vec![
|
||||
// Windows
|
||||
make_models(
|
||||
(BlockKind::Window1, 0),
|
||||
@ -2308,11 +2282,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
/* let sprite_model_data = renderer
|
||||
.create_model(&mesh)
|
||||
.expect("Failed to upload sprite vertex to the GPU!"); */
|
||||
// println!("{:?}, {:?}", sprite_model_data.vbuf,
|
||||
// sprite_model_data.vertex_range); println!("{:?}", sprite_models);
|
||||
let sprite_col_lights = ShadowPipeline::create_col_lights(renderer, greedy.finalize())
|
||||
.expect("Failed to upload sprite color and light data to the GPU!");
|
||||
Self {
|
||||
@ -2322,23 +2291,8 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
mesh_send_tmp: send,
|
||||
mesh_recv: recv,
|
||||
mesh_todo: HashMap::default(),
|
||||
// sprite_model_data,
|
||||
sprite_models: Arc::new(sprite_models),
|
||||
sprite_col_lights, /*renderer
|
||||
.create_texture_immutable_raw(
|
||||
gfx::texture::Kind::D2(
|
||||
tex_size.x,
|
||||
tex_size.y,
|
||||
gfx::texture::AaMode::Single,
|
||||
),
|
||||
gfx::texture::Mipmap::Provided,
|
||||
&[&tex],
|
||||
gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Bilinear,
|
||||
gfx::texture::WrapMode::Clamp,
|
||||
),
|
||||
)
|
||||
.expect("Failed to upload sprite color and light data to the GPU!"),*/
|
||||
sprite_col_lights,
|
||||
waves: renderer
|
||||
.create_texture(
|
||||
&assets::load_expect("voxygen.texture.waves"),
|
||||
@ -2358,14 +2312,12 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
let max_texture_size = renderer.max_texture_size();
|
||||
let atlas_size =
|
||||
guillotiere::Size::new(i32::from(max_texture_size), i32::from(max_texture_size));
|
||||
// let atlas_size = guillotiere::Size::new(1, 1);
|
||||
let atlas = AtlasAllocator::with_options(atlas_size, &guillotiere::AllocatorOptions {
|
||||
// TODO: Verify some good empirical constants.
|
||||
small_size_threshold: 128,
|
||||
large_size_threshold: 1024,
|
||||
..guillotiere::AllocatorOptions::default()
|
||||
});
|
||||
// renderer.flush();
|
||||
let texture = renderer.create_texture_raw(
|
||||
gfx::texture::Kind::D2(
|
||||
max_texture_size,
|
||||
@ -2373,8 +2325,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
gfx::texture::AaMode::Single,
|
||||
),
|
||||
1 as gfx::texture::Level,
|
||||
// gfx::memory::Upload,
|
||||
gfx::memory::Bind::SHADER_RESOURCE, /* | gfx::memory::Bind::TRANSFER_DST */
|
||||
gfx::memory::Bind::SHADER_RESOURCE,
|
||||
gfx::memory::Usage::Dynamic,
|
||||
(0, 0),
|
||||
gfx::format::Swizzle::new(),
|
||||
@ -2383,33 +2334,10 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
gfx::texture::WrapMode::Clamp,
|
||||
),
|
||||
)?;
|
||||
/* renderer.flush();
|
||||
let ten_millis = core::time::Duration::from_millis(10);
|
||||
std::thread::sleep(ten_millis);
|
||||
|
||||
renderer.update_texture(
|
||||
&texture,
|
||||
[0, 0],
|
||||
[max_texture_size, max_texture_size],
|
||||
&vec![[0u8; 4]; (usize::from(max_texture_size) * usize::from(max_texture_size))],
|
||||
//&[[255u8; 4]; 64 * 64],
|
||||
// NOTE: Cast is safe since the origin was a u16.
|
||||
)?;
|
||||
renderer.flush(); */
|
||||
// texture.cleanup();
|
||||
// Not sure if this is necessary...
|
||||
// renderer.flush();
|
||||
// texture.update();
|
||||
// // FIXME: Currently, there seems to be a bug where the very first texture
|
||||
// update always // fails. Not sure why, but we currently work around
|
||||
// it with a dummy allocation (which we // proceed to leak, in case the
|
||||
// bug can return after it's freed). let _ = atlas.allocate(guillotiere:
|
||||
// :Size::new(64, 64));
|
||||
Ok((atlas, texture))
|
||||
}
|
||||
|
||||
fn remove_chunk_meta(&mut self, _pos: Vec2<i32>, chunk: &TerrainChunkData) {
|
||||
/* println!("Terrain chunk already existed: {:?}", pos); */
|
||||
self.atlas.deallocate(chunk.col_lights);
|
||||
/* let (zmin, zmax) = chunk.z_bounds;
|
||||
self.z_index_up.remove(Vec3::from(zmin, pos.x, pos.y));
|
||||
@ -2426,15 +2354,13 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
}
|
||||
|
||||
fn remove_chunk(&mut self, pos: Vec2<i32>) {
|
||||
// println!("Terrain chunk removed: {:?}", pos);
|
||||
if let Some(chunk) = self.chunks.remove(&pos) {
|
||||
self.remove_chunk_meta(pos, &chunk);
|
||||
// Temporarily remember dead chunks for shadowing purposes.
|
||||
self.shadow_chunks.push((pos, chunk));
|
||||
}
|
||||
if let Some(_todo) = self.mesh_todo.remove(&pos) {
|
||||
/* println!("Terrain chunk was being meshed: {:?}",
|
||||
* (todo.pos, todo.started_tick)); */
|
||||
//Do nothing on todo mesh removal.
|
||||
}
|
||||
}
|
||||
|
||||
@ -2452,11 +2378,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
loaded_distance: f32,
|
||||
view_mat: Mat4<f32>,
|
||||
proj_mat: Mat4<f32>,
|
||||
) -> (
|
||||
Aabb<f32>,
|
||||
/* Aabb<f32>, Aabb<f32> */ Vec<math::Vec3<f32>>,
|
||||
math::Aabr<f32>,
|
||||
) {
|
||||
) -> (Aabb<f32>, Vec<math::Vec3<f32>>, math::Aabr<f32>) {
|
||||
let current_tick = scene_data.tick;
|
||||
let current_time = scene_data.state.get_time();
|
||||
let mut visible_bounding_box: Option<Aabb<f32>> = None;
|
||||
@ -2478,7 +2400,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
.map(|c| (false, c)),
|
||||
)
|
||||
{
|
||||
// println!("Terrain chunk change: {:?}", (modified, pos));
|
||||
// TODO: ANOTHER PROBLEM HERE!
|
||||
// What happens if the block on the edge of a chunk gets modified? We need to
|
||||
// spawn a mesh worker to remesh its neighbour(s) too since their
|
||||
@ -2500,7 +2421,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
}
|
||||
|
||||
if neighbours {
|
||||
// println!("Insert mesh_todo:: {:?}", (pos, current_tick));
|
||||
self.mesh_todo.insert(pos, ChunkMeshState {
|
||||
pos,
|
||||
started_tick: current_tick,
|
||||
@ -2521,7 +2441,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
.iter()
|
||||
.map(|(p, _)| *p)
|
||||
{
|
||||
// println!("Terrain block change: {:?}", pos);
|
||||
let chunk_pos = scene_data.state.terrain().pos_key(pos);
|
||||
// Only mesh if this chunk has all its neighbors
|
||||
let mut neighbours = true;
|
||||
@ -2535,7 +2454,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
}
|
||||
}
|
||||
if neighbours {
|
||||
// println!("Insert mesh_todo: {:?}", (chunk_pos, current_tick));
|
||||
self.mesh_todo.insert(chunk_pos, ChunkMeshState {
|
||||
pos: chunk_pos,
|
||||
started_tick: current_tick,
|
||||
@ -2566,8 +2484,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
}
|
||||
}
|
||||
if neighbours {
|
||||
// println!("Insert mesh_todo:: {:?}", (neighbour_chunk_pos,
|
||||
// current_tick));
|
||||
self.mesh_todo.insert(neighbour_chunk_pos, ChunkMeshState {
|
||||
pos: neighbour_chunk_pos,
|
||||
started_tick: current_tick,
|
||||
@ -2673,8 +2589,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
// data structure (convert the mesh to a model first of course).
|
||||
Some(todo) if response.started_tick <= todo.started_tick => {
|
||||
let started_tick = todo.started_tick;
|
||||
// println!("Finished meshing worker: (pos={:?}, response={:?}, todo={:?})",
|
||||
// response.pos, response.started_tick, todo.started_tick);
|
||||
let load_time = self
|
||||
.chunks
|
||||
.get(&response.pos)
|
||||
@ -2682,30 +2596,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
.unwrap_or(current_time as f32);
|
||||
// TODO: Allocate new atlas on allocation faillure.
|
||||
let (tex, tex_size) = response.col_lights_info;
|
||||
/* if self.chunks.len() == 0 {
|
||||
println!("{:?}\n{:?}", tex, tex_size);
|
||||
/*// HACK
|
||||
let (atlas_, col_lights_) = Self::make_atlas(renderer)
|
||||
.expect("Failed to create atlas texture");
|
||||
// renderer.flush();
|
||||
let ten_millis = core::time::Duration::from_millis(1000);
|
||||
std::thread::sleep(ten_millis);
|
||||
if let Err(err) = renderer.update_texture(
|
||||
&self.col_lights,
|
||||
// &col_lights,
|
||||
// NOTE: Cast is safe since the origin was a u16.
|
||||
[0, 0],
|
||||
[1, 1],
|
||||
&[[0u8; 4]],
|
||||
) {
|
||||
panic!("Ahhh {:?}", err);
|
||||
warn!("Failed to update texture: {:?}", err);
|
||||
}
|
||||
renderer.flush();
|
||||
std::thread::sleep(ten_millis);
|
||||
self.atlas = atlas_;
|
||||
self.col_lights = col_lights_; */
|
||||
} */
|
||||
let atlas = &mut self.atlas;
|
||||
let allocation = atlas
|
||||
.allocate(guillotiere::Size::new(
|
||||
@ -2713,57 +2603,13 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
i32::from(tex_size.y),
|
||||
))
|
||||
.expect("Not yet implemented: allocate new atlas on allocation faillure.");
|
||||
// println!("Allocation {:?} for {:?} (original size = {:?}... ugh)",
|
||||
// allocation, response.pos, tex_size); NOTE: Cast is safe
|
||||
// since the origin was a u16.
|
||||
// NOTE: Cast is safe since the origin was a u16.
|
||||
let atlas_offs = Vec2::new(
|
||||
allocation.rectangle.min.x as u16,
|
||||
allocation.rectangle.min.y as u16,
|
||||
);
|
||||
if atlas_offs == Vec2::zero() {
|
||||
// println!("Model: {:?}",
|
||||
// &response.opaque_mesh.vertices());
|
||||
// println!("Texture: {:?}", tex);
|
||||
}
|
||||
// let atlas_offs : Vec2<u16> = Vec2::zero();
|
||||
/* let col_lights = renderer
|
||||
.create_texture_immutable_raw(
|
||||
gfx::texture::Kind::D2(
|
||||
tex_size.x,
|
||||
tex_size.y,
|
||||
gfx::texture::AaMode::Single,
|
||||
),
|
||||
gfx::texture::Mipmap::Provided,
|
||||
&[&tex],
|
||||
gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Bilinear,
|
||||
gfx::texture::WrapMode::Clamp,
|
||||
),
|
||||
)
|
||||
.expect("Failed to upload terrain color and light data to the GPU!"); */
|
||||
/* let col_lights = renderer
|
||||
.create_texture_raw(
|
||||
gfx::texture::Kind::D2(
|
||||
tex_size.x,
|
||||
tex_size.y,
|
||||
gfx::texture::AaMode::Single,
|
||||
),
|
||||
1 as gfx::texture::Level,
|
||||
// gfx::memory::Upload,
|
||||
gfx::memory::Bind::SHADER_RESOURCE,
|
||||
gfx::memory::Usage::Dynamic,
|
||||
(0, 0),
|
||||
gfx::format::Swizzle::new(),
|
||||
gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Bilinear,
|
||||
gfx::texture::WrapMode::Clamp,
|
||||
),
|
||||
)
|
||||
.expect("Failed to upload col lights data to the GPU!"); */
|
||||
if let Err(err) = renderer.update_texture(
|
||||
&self.col_lights,
|
||||
// &col_lights,
|
||||
// NOTE: Cast is safe since the origin was a u16.
|
||||
atlas_offs.into_array(),
|
||||
tex_size.into_array(),
|
||||
&tex,
|
||||
@ -2785,27 +2631,10 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
/* shadow_model: renderer
|
||||
.create_model(&response.shadow_mesh)
|
||||
.expect("Failed to upload chunk mesh to the GPU!"), */
|
||||
col_lights: allocation.id,/*ShadowPipeline::create_col_lights(renderer, /*response.col_lights_info*/(tex, tex_size))
|
||||
.expect("Failed to upload chunk light-color texture to the GPU!"),*/
|
||||
/* sprite_instances: response
|
||||
.sprite_instances
|
||||
.into_iter()
|
||||
.map(|(kind, instances)| {
|
||||
(
|
||||
kind,
|
||||
(renderer./*create_consts_immutable*/create_consts(&instances).expect(
|
||||
"Failed to upload chunk sprite instances to the GPU!",
|
||||
), instances.len()),
|
||||
)
|
||||
})
|
||||
.collect(), */
|
||||
col_lights: allocation.id,
|
||||
sprite_instances: response
|
||||
.sprite_instances
|
||||
.into_iter()
|
||||
|
||||
.map(|(kind, instances)| {
|
||||
(
|
||||
kind,
|
||||
@ -2823,7 +2652,13 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
}),
|
||||
)
|
||||
.into_array(),
|
||||
atlas_offs: Vec4::new(i32::from(atlas_offs.x), i32::from(atlas_offs.y), 0, 0).into_array(),
|
||||
atlas_offs: Vec4::new(
|
||||
i32::from(atlas_offs.x),
|
||||
i32::from(atlas_offs.y),
|
||||
0,
|
||||
0,
|
||||
)
|
||||
.into_array(),
|
||||
load_time,
|
||||
}])
|
||||
.expect("Failed to upload chunk locals to the GPU!"),
|
||||
@ -2835,25 +2670,17 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
});
|
||||
|
||||
if response.started_tick == started_tick {
|
||||
// println!("Terrain chunk removed from meshing: {:?}", (response.pos,
|
||||
// response.started_tick));
|
||||
self.mesh_todo.remove(&response.pos);
|
||||
}
|
||||
},
|
||||
// Chunk must have been removed, or it was spawned on an old tick. Drop the mesh
|
||||
// since it's either out of date or no longer needed.
|
||||
Some(_todo) => {
|
||||
/* println!("Finished meshing worker: (pos={:?}, response={:?}, todo={:?})", response.pos, response.started_tick, todo.started_tick);
|
||||
println!("Terrain chunk removed from meshing due to being out of date: {:?}", (response.pos, response.started_tick));
|
||||
self.mesh_todo.remove(&response.pos); */
|
||||
},
|
||||
Some(_todo) => {},
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
|
||||
// Construct view frustum
|
||||
let _all_mat = proj_mat * view_mat;
|
||||
//.scaled_3d(Vec3::new(proj_mat[(0, 0)], proj_mat[(1, 1)], 1.0));
|
||||
let focus_off = focus_pos.map(|e| e.trunc());
|
||||
let frustum = Frustum::from_modelview_projection(
|
||||
(proj_mat * view_mat * Mat4::translation_3d(-focus_off)).into_col_arrays(),
|
||||
@ -2861,13 +2688,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
|
||||
// Update chunk visibility
|
||||
let chunk_sz = V::RECT_SIZE.x as f32;
|
||||
let _scene_bounding_box: Aabb<f32> = Aabb {
|
||||
min: focus_pos - 2.0, /*
|
||||
* - /0.5f32 */
|
||||
max: focus_pos + 2.0, /* + 0.5f32 */
|
||||
};
|
||||
/* let mut shadow_queue =
|
||||
* std::collections::VecDeque::with_capacity(self.chunks.len()); */
|
||||
for (pos, chunk) in &mut self.chunks {
|
||||
let chunk_pos = pos.map(|e| e as f32 * chunk_sz);
|
||||
|
||||
@ -2905,22 +2725,12 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
min: Vec3::from(chunk_min),
|
||||
max: Vec3::from(chunk_max),
|
||||
};
|
||||
// scene_bounding_box.expand_to_contain(chunk_box);
|
||||
|
||||
if in_frustum {
|
||||
/* let visible_box = Aabb {
|
||||
min: chunk_box.min - focus_off,
|
||||
max: chunk_box.max - focus_off,
|
||||
};
|
||||
let visible_box = super::fit_psr(all_mat, visible_box, |p| Vec3::from(p) / p.w/*.clamped(-p.w.abs(), p.w.abs())*/)
|
||||
.map(|e| e.clamped(-1.0, 1.0))
|
||||
; */
|
||||
let visible_box = chunk_box;
|
||||
visible_bounding_box = visible_bounding_box
|
||||
.map(|e| e.union(visible_box))
|
||||
.or(Some(visible_box));
|
||||
/* shadow_queue.push_back(chunk_box);
|
||||
// shadow_queue.push(chunk_min + chunk_sz * 0.5); */
|
||||
}
|
||||
// FIXME: Hack that only works when only the lantern casts point shadows
|
||||
// (and hardcodes the shadow distance). Should ideally exist per-light, too.
|
||||
@ -2929,17 +2739,11 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
|
||||
// PSRs: potential shadow receivers
|
||||
let visible_bounding_box = visible_bounding_box.unwrap_or(Aabb {
|
||||
min: focus_pos - 2.0, /*
|
||||
* - 0.5 */
|
||||
max: focus_pos + 2.0, /* + 0.5 */
|
||||
min: focus_pos - 2.0,
|
||||
max: focus_pos + 2.0,
|
||||
});
|
||||
|
||||
// PSCs: Potential shadow casters
|
||||
let _psc_bounding_box: Aabb<f32> = visible_bounding_box;
|
||||
/*Aabb {
|
||||
min: focus_pos - 0.5f32,
|
||||
max: focus_pos + 0.5f32,
|
||||
}; */
|
||||
let ray_direction = scene_data.get_sun_dir();
|
||||
let collides_with_aabr = |a: math::Aabr<f32>, b: math::Aabr<f32>| {
|
||||
a.min.partial_cmple(&b.max).reduce_and() && a.max.partial_cmpge(&b.min).reduce_and()
|
||||
@ -2956,9 +2760,8 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
min: math::Vec3::from(visible_bounding_box.min.map(f64::from)),
|
||||
max: math::Vec3::from(visible_bounding_box.max.map(f64::from)),
|
||||
};
|
||||
let inv_proj_view = math::Mat4::from_col_arrays(
|
||||
(proj_mat * view_mat/* * Mat4::translation_3d(-focus_off)*/).into_col_arrays(),
|
||||
)
|
||||
let inv_proj_view =
|
||||
math::Mat4::from_col_arrays((proj_mat * view_mat).into_col_arrays())
|
||||
.map(f64::from)
|
||||
.inverted();
|
||||
let ray_direction = math::Vec3::<f32>::from(ray_direction);
|
||||
@ -2971,44 +2774,16 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
.map(|v| v.map(|e| e as f32))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let cam_pos = math::Vec4::from(view_mat.inverted() * Vec4::unit_w()).xyz()/* + focus_off*/;
|
||||
/* let view_dir = (focus_pos.map(f32::fract)) - cam_pos;
|
||||
// let new_dir: Vec3<f32> = light_volume/*visible_light_volume*/.iter().map(|p|
|
||||
// p - cam_pos).sum();
|
||||
let new_dir = view_dir;
|
||||
let new_dir = new_dir.normalized();
|
||||
let dot_prod = f64::from(ray_direction.dot(new_dir));
|
||||
let sin_gamma = (1.0 - dot_prod * dot_prod).sqrt();
|
||||
// let sin_gamma = 0.0;
|
||||
let _new_dir = if sin_gamma > super::EPSILON_GAMMA {
|
||||
new_dir
|
||||
} else {
|
||||
Vec3::from(view_mat * Vec4::from_direction(Vec3::up())).normalized()
|
||||
}; */
|
||||
let up: math::Vec3<f32> = {
|
||||
/* (ray_direction)
|
||||
.cross(new_dir)
|
||||
.cross(ray_direction)
|
||||
.normalized() */
|
||||
math::Vec3::up()
|
||||
};
|
||||
let cam_pos = math::Vec4::from(view_mat.inverted() * Vec4::unit_w()).xyz();
|
||||
let up: math::Vec3<f32> = { math::Vec3::up() };
|
||||
|
||||
let ray_mat = math::Mat4::look_at_rh(
|
||||
cam_pos,
|
||||
cam_pos + ray_direction,
|
||||
up,
|
||||
// Vec3::up(),
|
||||
);
|
||||
// println!("old: {:?} new: {:?}", visible_bounding_box, visible_light_volume);
|
||||
let ray_mat = math::Mat4::look_at_rh(cam_pos, cam_pos + ray_direction, up);
|
||||
let visible_bounds = math::Aabr::from(math::fit_psr(
|
||||
ray_mat,
|
||||
/* super::aabb_to_points(visible_bounding_box).iter().copied() */
|
||||
visible_light_volume.iter().copied(),
|
||||
|p| p, //math::Vec3::from(p), /* / p.w */
|
||||
|p| p,
|
||||
));
|
||||
let ray_mat = ray_mat * math::Mat4::translation_3d(-focus_off);
|
||||
/* let visible_bounds_old = Aabr::from(super::fit_psr(ray_mat, super::aabb_to_points(visible_bounding_box).iter().copied(), |p| Vec3::from(p) / p.w));
|
||||
println!("old: {:?} new: {:?}", visible_bounds_old, visible_bounds); */
|
||||
|
||||
let can_shadow_sun = |pos: Vec2<i32>, chunk: &TerrainChunkData| {
|
||||
let chunk_pos = pos.map(|e| e as f32 * chunk_sz);
|
||||
@ -3026,20 +2801,9 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
let chunk_from_light = math::Aabr::from(math::fit_psr(
|
||||
ray_mat,
|
||||
math::aabb_to_points(chunk_box).iter().copied(),
|
||||
|p| p, /* math::Vec3::from(p)/* / p.w*/ */
|
||||
|p| p,
|
||||
));
|
||||
/* let chunk_from_light = Aabr {
|
||||
min: (ray_mat * Vec4::from_point(chunk_box.min)).xy(),
|
||||
max: (ray_mat * Vec4::from_point(chunk_box.max)).xy(),
|
||||
}.made_valid(); */
|
||||
/* let can_shadow_sun = */
|
||||
collides_with_aabr(chunk_from_light, visible_bounds)
|
||||
/* let can_shadow_sun_old = collides_with_aabr(chunk_from_light, visible_bounds_old);
|
||||
if can_shadow_sun != can_shadow_sun_old {
|
||||
println!("Different results for chunk {:?} (from light = {:?}):\n\
|
||||
old = {:?} new = {:?}",
|
||||
chunk_box, chunk_from_light, can_shadow_sun_old, can_shadow_sun);
|
||||
} */
|
||||
};
|
||||
|
||||
// Handle potential shadow casters (chunks that aren't visible, but are still in
|
||||
@ -3078,63 +2842,8 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
max: math::Vec2::zero(),
|
||||
})
|
||||
};
|
||||
/* let cam_pos = Vec3::from(view_mat.inverted() * Vec4::unit_w()) + focus_off; let look_at = visible_box.center();
|
||||
let view_dir = (focus_pos - cam_pos).normalized();
|
||||
let up_vec = ray_direction.cross(view_dir).cross(light_dir).normalized();
|
||||
let sun_light_mat = Mat4::look_at_rh(look_at - ray_direction, look_at, view_dir);
|
||||
let sun_bounding_box = super::fit_psr(all_mat, visible_box, |p| Vec3::from(p) / p.w/*.clamped(-p.w.abs(), p.w.abs())*/)
|
||||
Aabb {
|
||||
min: -0.5,
|
||||
max: 0.5,
|
||||
}; */
|
||||
/* if ray_direction.z < 0.0 && renderer.render_mode().shadow.is_map() {
|
||||
let ray = if ray_direction.x.abs() * scene_bounding_box.size().d > ray_direction.z.abs() * chunk_sz {
|
||||
-ray_direction / ray_direction.x * chunk_sz
|
||||
} else {
|
||||
/* -ray_direction / ray_direction.z * scene_bounding_box.size().d */
|
||||
Vec3::new(0.0, 0.0, scene_bounding_box.size().d)
|
||||
};
|
||||
while let Some(shadow_chunk) = shadow_queue.pop_front() {
|
||||
let collides_with_aabb = |a: Aabb<f32>, b: Aabb<f32>|
|
||||
a.min.partial_cmple(&b.max).reduce_and() &&
|
||||
a.max.partial_cmpge(&b.min).reduce_and();
|
||||
if !collides_with_aabb(scene_bounding_box, shadow_chunk) {
|
||||
continue;
|
||||
}
|
||||
let min_chunk_pos = Vec2::from(shadow_chunk.min.map(|e| (e / chunk_sz).floor()))
|
||||
.map(|e: f32| e as i32);
|
||||
let max_chunk_pos = Vec2::from(shadow_chunk.max.map(|e| (e / chunk_sz).ceil()))
|
||||
.map(|e: f32| e as i32);
|
||||
let mut check_chunk = |x, y| {
|
||||
if let Some(mut chunk) = self.chunks.get_mut(&Vec2::new(x, y)) {
|
||||
let (minz, maxz) = chunk.z_bounds;
|
||||
if minz <= shadow_chunk.max.z && maxz >= shadow_chunk.min.z {
|
||||
chunk.can_shadow_sun = true;
|
||||
// NOTE: These casts are safe because the maximum chunk index we are
|
||||
// currently considering is 16384.
|
||||
let x = x as f32;
|
||||
let y = y as f32;
|
||||
psc_bounding_box.expand_to_contain(shadow_chunk.intersection(Aabb {
|
||||
min: Vec3::new(x * chunk_sz, y * chunk_sz, minz),
|
||||
max: Vec3::new((x + 1.0) * chunk_sz, (y + 1.0) * chunk_sz, maxz),
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
(min_chunk_pos.y..max_chunk_pos.y).for_each(|y| {
|
||||
(min_chunk_pos.x..max_chunk_pos.x).for_each(|x| {
|
||||
check_chunk(x, y);
|
||||
})
|
||||
});
|
||||
shadow_queue.push_back(Aabb {
|
||||
min: shadow_chunk.min + ray,
|
||||
max: shadow_chunk.max + ray,
|
||||
});
|
||||
}
|
||||
} */
|
||||
|
||||
(
|
||||
/* scene_bounding_box, visible_bounding_box, psc_bounding_box */
|
||||
visible_bounding_box,
|
||||
visible_light_volume,
|
||||
visible_psr_bounds,
|
||||
@ -3155,11 +2864,8 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
pub fn render_shadows(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
globals: &Consts<Globals>,
|
||||
// lights: &Consts<Light>,
|
||||
shadow_mats: &Consts<ShadowLocals>,
|
||||
light_data: &[Light],
|
||||
is_daylight: bool,
|
||||
global: &GlobalModel,
|
||||
(is_daylight, light_data): super::LightData,
|
||||
focus_pos: Vec3<f32>,
|
||||
) {
|
||||
if !renderer.render_mode().shadow.is_map() {
|
||||
@ -3177,8 +2883,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
})
|
||||
.take(self.chunks.len());
|
||||
|
||||
// let is_daylight = sun_dir.z < 0.0/*0.6*/;
|
||||
|
||||
// Directed shadows
|
||||
//
|
||||
// NOTE: We also render shadows for dead chunks that were found to still be
|
||||
@ -3192,15 +2896,10 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
.for_each(|chunk| {
|
||||
// Directed light shadows.
|
||||
renderer.render_terrain_shadow_directed(
|
||||
// &chunk.shadow_model,
|
||||
&chunk.opaque_model,
|
||||
globals,
|
||||
global,
|
||||
&chunk.locals,
|
||||
shadow_mats,
|
||||
/* lights, */
|
||||
/* shadows,
|
||||
* &lod.alt,
|
||||
* &lod.horizon, */
|
||||
&global.shadow_mats,
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -3212,17 +2911,11 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
light_data.iter().take(1).for_each(|_light| {
|
||||
chunk_iter.clone().for_each(|chunk| {
|
||||
if chunk.can_shadow_point {
|
||||
// shadow_vertex_count += chunk.shadow_model.vertex_range.len();
|
||||
renderer.render_shadow_point(
|
||||
&chunk.opaque_model,
|
||||
// &chunk.shadow_model,
|
||||
globals,
|
||||
global,
|
||||
&chunk.locals,
|
||||
shadow_mats,
|
||||
/* lights, */
|
||||
/* shadows,
|
||||
* &lod.alt,
|
||||
* &lod.horizon, */
|
||||
&global.shadow_mats,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -3232,14 +2925,9 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
pub fn render(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
shadow_mats: &Consts<ShadowLocals>,
|
||||
global: &GlobalModel,
|
||||
lod: &LodData,
|
||||
focus_pos: Vec3<f32>,
|
||||
/* sun_dir: Vec3<f32>,
|
||||
* light_data: &[Light], */
|
||||
) {
|
||||
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
|
||||
(e as i32).div_euclid(sz as i32)
|
||||
@ -3252,105 +2940,23 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
})
|
||||
.take(self.chunks.len());
|
||||
|
||||
// // Flush renderer to synchronize commands sent on the main encoder with the
|
||||
// // start of the shadow encoder.
|
||||
// renderer.flush();
|
||||
|
||||
// Shadows
|
||||
|
||||
/*scene_data.thread_pool.execute(move || {
|
||||
let _ = send.send(mesh_worker(
|
||||
pos,
|
||||
(min_z as f32, max_z as f32),
|
||||
started_tick,
|
||||
volume,
|
||||
max_texture_size,
|
||||
aabb,
|
||||
));
|
||||
});*/
|
||||
// let mut shadow_vertex_count = 0;
|
||||
/* let is_daylight = sun_dir.z < 0.0/*0.6*/;
|
||||
|
||||
// Directed shadows
|
||||
for (_, chunk) in chunk_iter.clone() {
|
||||
if is_daylight {
|
||||
// Directed light shadows.
|
||||
renderer.render_shadow_directed(
|
||||
// &chunk.shadow_model,
|
||||
&chunk.opaque_model,
|
||||
globals,
|
||||
&chunk.locals,
|
||||
shadow_mats,
|
||||
// lights,
|
||||
// shadows,
|
||||
// &lod.alt,
|
||||
// &lod.horizon,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Point shadows
|
||||
for _light in light_data.iter().take(1) {
|
||||
for (_, chunk) in chunk_iter.clone() {
|
||||
if chunk.can_shadow_point {
|
||||
// shadow_vertex_count += chunk.shadow_model.vertex_range.len();
|
||||
renderer.render_shadow_point(
|
||||
&chunk.opaque_model,
|
||||
// &chunk.shadow_model,
|
||||
globals,
|
||||
&chunk.locals,
|
||||
shadow_mats,
|
||||
// lights,
|
||||
// shadows,
|
||||
// &lod.alt,
|
||||
// &lod.horizon,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flush shadows.
|
||||
if is_daylight || light_data.len() > 0 {
|
||||
renderer.flush_shadows();
|
||||
} */
|
||||
|
||||
// Terrain
|
||||
// let mut terrain_vertex_count = 0;
|
||||
for (_, chunk) in chunk_iter {
|
||||
// terrain_vertex_count += chunk.opaque_model.vertex_range.len();
|
||||
if chunk.visible == Visibility::Visible
|
||||
/* || chunk.can_shadow_sun() */
|
||||
{
|
||||
if chunk.visible == Visibility::Visible {
|
||||
renderer.render_terrain_chunk(
|
||||
&chunk.opaque_model,
|
||||
// &chunk.shadow_model,
|
||||
// &chunk.col_lights,
|
||||
&self.col_lights,
|
||||
globals,
|
||||
global,
|
||||
&chunk.locals,
|
||||
lights,
|
||||
shadows,
|
||||
shadow_mats,
|
||||
&lod.alt,
|
||||
&lod.horizon,
|
||||
lod,
|
||||
);
|
||||
}
|
||||
}
|
||||
/* println!(
|
||||
"Vertex count (shadow / terrain / ratio): {:?} / {:?} / {:?}",
|
||||
shadow_vertex_count,
|
||||
terrain_vertex_count,
|
||||
shadow_vertex_count as f64 / terrain_vertex_count as f64
|
||||
); */
|
||||
}
|
||||
|
||||
pub fn render_translucent(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
shadow_mats: &Consts<ShadowLocals>,
|
||||
global: &GlobalModel,
|
||||
lod: &LodData,
|
||||
focus_pos: Vec3<f32>,
|
||||
cam_pos: Vec3<f32>,
|
||||
@ -3394,10 +3000,13 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5,
|
||||
));
|
||||
if focus_dist_sqrd < sprite_render_distance.powf(2.0) {
|
||||
for (kind, /*(instances, instance_count)*/instances) in (&chunk.sprite_instances).into_iter()/*.take(1)*/ {
|
||||
let SpriteData { model, locals, .. } =
|
||||
if sprite_config_for(kind.0).map(|config| config.wind_sway >= 0.4).unwrap_or(false) && dist_sqrd <= chunk_mag
|
||||
|| dist_sqrd < sprite_high_detail_distance.powf(2.0) {
|
||||
for (kind, instances) in (&chunk.sprite_instances).into_iter() {
|
||||
let SpriteData { model, locals, .. } = if sprite_config_for(kind.0)
|
||||
.map(|config| config.wind_sway >= 0.4)
|
||||
.unwrap_or(false)
|
||||
&& dist_sqrd <= chunk_mag
|
||||
|| dist_sqrd < sprite_high_detail_distance.powf(2.0)
|
||||
{
|
||||
&self.sprite_models[&kind][0]
|
||||
} else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][1]
|
||||
@ -3409,34 +3018,13 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
&self.sprite_models[&kind][4]
|
||||
};
|
||||
renderer.render_sprites(
|
||||
/*Model {
|
||||
vbuf: self.sprite_model_data.vbuf.clone(),
|
||||
vertex_range: /*self.sprite_model_data.vertex_range()*/*/
|
||||
/* if sprite_config_for(kind.0).map(|config| config.wind_sway >= 0.4).unwrap_or(false) && dist_sqrd <= chunk_mag
|
||||
|| dist_sqrd < sprite_high_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][0].model
|
||||
} else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][1].model
|
||||
} else if dist_sqrd < sprite_mid_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][2].model
|
||||
} else if dist_sqrd < sprite_low_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][3].model
|
||||
} else {
|
||||
&self.sprite_models[&kind][4].model
|
||||
}/*.clone(),
|
||||
}*/,*/
|
||||
model,
|
||||
&self.sprite_col_lights,
|
||||
globals,
|
||||
global,
|
||||
&chunk.locals,
|
||||
locals,
|
||||
// *instance_count,
|
||||
&instances,
|
||||
lights,
|
||||
shadows,
|
||||
shadow_mats,
|
||||
&lod.alt,
|
||||
&lod.horizon,
|
||||
lod,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -3459,13 +3047,9 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
.for_each(|(model, locals)| {
|
||||
renderer.render_fluid_chunk(
|
||||
model,
|
||||
globals,
|
||||
global,
|
||||
locals,
|
||||
lights,
|
||||
shadows,
|
||||
shadow_mats,
|
||||
&lod.alt,
|
||||
&lod.horizon,
|
||||
lod,
|
||||
&self.waves,
|
||||
)
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user