Merge branch 'imbris/mesh-speed' into 'master'

Speed up terrain meshing ~20%

See merge request veloren/veloren!625
This commit is contained in:
Imbris 2019-10-25 02:22:03 +00:00
commit c18fe8042b
3 changed files with 78 additions and 68 deletions

View File

@ -27,8 +27,7 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
if let Some(col) = vox.get_color() {
vol::push_vox_verts(
&mut mesh,
self,
pos,
faces_to_make(self, pos, true, |vox| vox.is_empty()),
offs + pos.map(|e| e as f32),
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|origin, norm, col, ao, light| {
@ -39,7 +38,6 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
0,
)
},
true,
&{
let mut ls = [[[0.0; 3]; 3]; 3];
for x in 0..3 {
@ -59,7 +57,6 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
}
ls
},
|vox| vox.is_empty(),
);
}
}
@ -83,8 +80,7 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
if let Some(col) = vox.get_color() {
vol::push_vox_verts(
&mut mesh,
self,
pos,
faces_to_make(self, pos, true, |vox| vox.is_empty()),
offs + pos.map(|e| e as f32),
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|origin, norm, col, ao, light| {
@ -94,9 +90,7 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
linear_to_srgb(srgb_to_linear(col) * ao * light),
)
},
true,
&[[[1.0; 3]; 3]; 3],
|vox| vox.is_empty(),
);
}
}
@ -104,3 +98,27 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
(mesh, Mesh::new())
}
}
/// Use the 6 voxels/blocks surrounding the one at the specified position
/// to detemine which faces should be drawn
fn faces_to_make<V: ReadVol>(
seg: &V,
pos: Vec3<i32>,
error_makes_face: bool,
should_add: impl Fn(&V::Vox) -> bool,
) -> [bool; 6] {
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
let make_face = |offset| {
seg.get(pos + offset)
.map(|v| should_add(v))
.unwrap_or(error_makes_face)
};
[
make_face(-x),
make_face(x),
make_face(-y),
make_face(y),
make_face(-z),
make_face(z),
]
}

View File

@ -180,19 +180,21 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
.unwrap_or(Rgba::zero())
};
let mut blocks = [[[None; 3]; 3]; 3];
let mut colors = [[[Rgba::zero(); 3]; 3]; 3];
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
colors[k][j][i] = get_color(
vol_cached
let block = vol_cached
.get(
Vec3::new(x, y, range.min.z)
+ Vec3::new(i as i32, j as i32, k as i32)
- 1,
)
.ok(),
);
.ok()
.copied();
colors[k][j][i] = get_color(block.as_ref());
blocks[k][j][i] = block;
}
}
}
@ -203,6 +205,8 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
lights[0] = lights[1];
lights[1] = lights[2];
blocks[0] = blocks[1];
blocks[1] = blocks[2];
colors[0] = colors[1];
colors[1] = colors[2];
@ -213,44 +217,39 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
}
for i in 0..3 {
for j in 0..3 {
colors[2][j][i] = get_color(
vol_cached
let block = vol_cached
.get(pos + Vec3::new(i as i32, j as i32, 2) - 1)
.ok(),
);
.ok()
.copied();
colors[2][j][i] = get_color(block.as_ref());
blocks[2][j][i] = block;
}
}
let block = vol_cached.get(pos).ok();
let block = blocks[1][1][1];
// Create mesh polygons
if block.map(|vox| vox.is_opaque()).unwrap_or(false) {
vol::push_vox_verts(
&mut opaque_mesh,
self,
pos,
faces_to_make(&blocks, false, |vox| !vox.is_opaque()),
offs,
&colors, //&[[[colors[1][1][1]; 3]; 3]; 3],
|pos, norm, col, ao, light| {
TerrainVertex::new(pos, norm, col, light.min(ao))
},
false,
&lights,
|vox| !vox.is_opaque(),
);
} else if block.map(|vox| vox.is_fluid()).unwrap_or(false) {
vol::push_vox_verts(
&mut fluid_mesh,
self,
pos,
faces_to_make(&blocks, false, |vox| vox.is_air()),
offs,
&colors,
|pos, norm, col, _ao, light| {
FluidVertex::new(pos, norm, col, light, 0.3)
},
false,
&lights,
|vox| vox.is_air(),
);
}
}
@ -261,6 +260,28 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
}
}
/// Use the 6 voxels/blocks surrounding the center
/// to detemine which faces should be drawn
/// Unlike the one in segments.rs this uses a provided array of blocks instead
/// of retrieving from a volume
/// blocks[z][y][x]
fn faces_to_make(
blocks: &[[[Option<Block>; 3]; 3]; 3],
error_makes_face: bool,
should_add: impl Fn(Block) -> bool,
) -> [bool; 6] {
// Faces to draw
let make_face = |opt_v: Option<Block>| opt_v.map(|v| should_add(v)).unwrap_or(error_makes_face);
[
make_face(blocks[1][1][0]),
make_face(blocks[1][1][2]),
make_face(blocks[1][0][1]),
make_face(blocks[1][2][1]),
make_face(blocks[0][1][1]),
make_face(blocks[2][1][1]),
]
}
/*
impl<V: BaseVol<Vox = Block> + ReadVol + Debug> Meshable for VolGrid3d<V> {
type Pipeline = TerrainPipeline;

View File

@ -1,7 +1,5 @@
use vek::*;
use common::vol::ReadVol;
use crate::render::{
mesh::{Mesh, Quad},
Pipeline,
@ -151,25 +149,18 @@ fn create_quad<P: Pipeline, F: Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32) -> P
}
}
pub fn push_vox_verts<V: ReadVol, P: Pipeline>(
pub fn push_vox_verts<P: Pipeline>(
mesh: &mut Mesh<P>,
vol: &V,
pos: Vec3<i32>,
faces: [bool; 6],
offs: Vec3<f32>,
cols: &[[[Rgba<u8>; 3]; 3]; 3],
vcons: impl Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32) -> P::Vertex,
error_makes_face: bool,
darknesses: &[[[f32; 3]; 3]; 3],
should_add: impl Fn(&V::Vox) -> bool,
) {
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
// -x
if vol
.get(pos - Vec3::unit_x())
.map(|v| should_add(v))
.unwrap_or(error_makes_face)
{
if faces[0] {
mesh.push_quad(create_quad(
offs,
Vec3::unit_z(),
@ -181,11 +172,7 @@ pub fn push_vox_verts<V: ReadVol, P: Pipeline>(
));
}
// +x
if vol
.get(pos + Vec3::unit_x())
.map(|v| should_add(v))
.unwrap_or(error_makes_face)
{
if faces[1] {
mesh.push_quad(create_quad(
offs + Vec3::unit_x(),
Vec3::unit_y(),
@ -197,11 +184,7 @@ pub fn push_vox_verts<V: ReadVol, P: Pipeline>(
));
}
// -y
if vol
.get(pos - Vec3::unit_y())
.map(|v| should_add(v))
.unwrap_or(error_makes_face)
{
if faces[2] {
mesh.push_quad(create_quad(
offs,
Vec3::unit_x(),
@ -213,11 +196,7 @@ pub fn push_vox_verts<V: ReadVol, P: Pipeline>(
));
}
// +y
if vol
.get(pos + Vec3::unit_y())
.map(|v| should_add(v))
.unwrap_or(error_makes_face)
{
if faces[3] {
mesh.push_quad(create_quad(
offs + Vec3::unit_y(),
Vec3::unit_z(),
@ -229,11 +208,7 @@ pub fn push_vox_verts<V: ReadVol, P: Pipeline>(
));
}
// -z
if vol
.get(pos - Vec3::unit_z())
.map(|v| should_add(v))
.unwrap_or(error_makes_face)
{
if faces[4] {
mesh.push_quad(create_quad(
offs,
Vec3::unit_y(),
@ -245,11 +220,7 @@ pub fn push_vox_verts<V: ReadVol, P: Pipeline>(
));
}
// +z
if vol
.get(pos + Vec3::unit_z())
.map(|v| should_add(v))
.unwrap_or(error_makes_face)
{
if faces[5] {
mesh.push_quad(create_quad(
offs + Vec3::unit_z(),
Vec3::unit_x(),