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() { if let Some(col) = vox.get_color() {
vol::push_vox_verts( vol::push_vox_verts(
&mut mesh, &mut mesh,
self, faces_to_make(self, pos, true, |vox| vox.is_empty()),
pos,
offs + pos.map(|e| e as f32), offs + pos.map(|e| e as f32),
&[[[Rgba::from_opaque(col); 3]; 3]; 3], &[[[Rgba::from_opaque(col); 3]; 3]; 3],
|origin, norm, col, ao, light| { |origin, norm, col, ao, light| {
@ -39,7 +38,6 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
0, 0,
) )
}, },
true,
&{ &{
let mut ls = [[[0.0; 3]; 3]; 3]; let mut ls = [[[0.0; 3]; 3]; 3];
for x in 0..3 { for x in 0..3 {
@ -59,7 +57,6 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
} }
ls ls
}, },
|vox| vox.is_empty(),
); );
} }
} }
@ -83,8 +80,7 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
if let Some(col) = vox.get_color() { if let Some(col) = vox.get_color() {
vol::push_vox_verts( vol::push_vox_verts(
&mut mesh, &mut mesh,
self, faces_to_make(self, pos, true, |vox| vox.is_empty()),
pos,
offs + pos.map(|e| e as f32), offs + pos.map(|e| e as f32),
&[[[Rgba::from_opaque(col); 3]; 3]; 3], &[[[Rgba::from_opaque(col); 3]; 3]; 3],
|origin, norm, col, ao, light| { |origin, norm, col, ao, light| {
@ -94,9 +90,7 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
linear_to_srgb(srgb_to_linear(col) * ao * light), linear_to_srgb(srgb_to_linear(col) * ao * light),
) )
}, },
true,
&[[[1.0; 3]; 3]; 3], &[[[1.0; 3]; 3]; 3],
|vox| vox.is_empty(),
); );
} }
} }
@ -104,3 +98,27 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
(mesh, Mesh::new()) (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()) .unwrap_or(Rgba::zero())
}; };
let mut blocks = [[[None; 3]; 3]; 3];
let mut colors = [[[Rgba::zero(); 3]; 3]; 3]; let mut colors = [[[Rgba::zero(); 3]; 3]; 3];
for i in 0..3 { for i in 0..3 {
for j in 0..3 { for j in 0..3 {
for k in 0..3 { for k in 0..3 {
colors[k][j][i] = get_color( let block = vol_cached
vol_cached .get(
.get( Vec3::new(x, y, range.min.z)
Vec3::new(x, y, range.min.z) + Vec3::new(i as i32, j as i32, k as i32)
+ Vec3::new(i as i32, j as i32, k as i32) - 1,
- 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[0] = lights[1];
lights[1] = lights[2]; lights[1] = lights[2];
blocks[0] = blocks[1];
blocks[1] = blocks[2];
colors[0] = colors[1]; colors[0] = colors[1];
colors[1] = colors[2]; colors[1] = colors[2];
@ -213,44 +217,39 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
} }
for i in 0..3 { for i in 0..3 {
for j in 0..3 { for j in 0..3 {
colors[2][j][i] = get_color( let block = vol_cached
vol_cached .get(pos + Vec3::new(i as i32, j as i32, 2) - 1)
.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 // Create mesh polygons
if block.map(|vox| vox.is_opaque()).unwrap_or(false) { if block.map(|vox| vox.is_opaque()).unwrap_or(false) {
vol::push_vox_verts( vol::push_vox_verts(
&mut opaque_mesh, &mut opaque_mesh,
self, faces_to_make(&blocks, false, |vox| !vox.is_opaque()),
pos,
offs, offs,
&colors, //&[[[colors[1][1][1]; 3]; 3]; 3], &colors, //&[[[colors[1][1][1]; 3]; 3]; 3],
|pos, norm, col, ao, light| { |pos, norm, col, ao, light| {
TerrainVertex::new(pos, norm, col, light.min(ao)) TerrainVertex::new(pos, norm, col, light.min(ao))
}, },
false,
&lights, &lights,
|vox| !vox.is_opaque(),
); );
} else if block.map(|vox| vox.is_fluid()).unwrap_or(false) { } else if block.map(|vox| vox.is_fluid()).unwrap_or(false) {
vol::push_vox_verts( vol::push_vox_verts(
&mut fluid_mesh, &mut fluid_mesh,
self, faces_to_make(&blocks, false, |vox| vox.is_air()),
pos,
offs, offs,
&colors, &colors,
|pos, norm, col, _ao, light| { |pos, norm, col, _ao, light| {
FluidVertex::new(pos, norm, col, light, 0.3) FluidVertex::new(pos, norm, col, light, 0.3)
}, },
false,
&lights, &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> { impl<V: BaseVol<Vox = Block> + ReadVol + Debug> Meshable for VolGrid3d<V> {
type Pipeline = TerrainPipeline; type Pipeline = TerrainPipeline;

View File

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