Remains of the dead in one mesh: drawing stays fast with hundreds of them
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6886b2e1a4
commit
a8284ca85c
1 file changed
+42
-18
+42
-18
@@ -1767,44 +1767,68 @@ impl R3d {
|
|||||||
// a broken blade; machines, stone and clockwork: splinters and rubble instead of blood);
|
// a broken blade; machines, stone and clockwork: splinters and rubble instead of blood);
|
||||||
// dust puffs where a body hits the ground
|
// dust puffs where a body hits the ground
|
||||||
fn draw_remains(&self, g: &Game) {
|
fn draw_remains(&self, g: &Game) {
|
||||||
|
// all remains in one mesh (hundreds of them would cost hundreds of draw calls):
|
||||||
|
// boxes on the floor with the colour of their stuff, seen from above and the sides
|
||||||
|
// (several meshes: one holds at most 65536 corners)
|
||||||
|
let mut meshes: Vec<MB> = vec![MB::new()];
|
||||||
|
let mut put = |lo: Vec3, hi: Vec3, c: [u8; 4]| {
|
||||||
|
if meshes.last().map_or(0, |m| m.v.len()) > 60000 {
|
||||||
|
meshes.push(MB::new());
|
||||||
|
}
|
||||||
|
let mb = meshes.last_mut().unwrap();
|
||||||
|
let (x0, y0, z0, x1, y1, z1) = (lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
|
||||||
|
let dark = [(c[0] as f32 * 0.7) as u8, (c[1] as f32 * 0.7) as u8, (c[2] as f32 * 0.7) as u8, 255];
|
||||||
|
let uv = [Vec2::ZERO; 4];
|
||||||
|
mb.quad([vec3(x0, y1, z0), vec3(x1, y1, z0), vec3(x1, y1, z1), vec3(x0, y1, z1)], uv, [c; 4], [Vec3::Y; 4]);
|
||||||
|
mb.quad([vec3(x0, y0, z1), vec3(x1, y0, z1), vec3(x1, y1, z1), vec3(x0, y1, z1)], uv, [dark; 4], [Vec3::Z; 4]);
|
||||||
|
mb.quad([vec3(x1, y0, z0), vec3(x1, y0, z1), vec3(x1, y1, z1), vec3(x1, y1, z0)], uv, [dark; 4], [Vec3::X; 4]);
|
||||||
|
mb.quad([vec3(x0, y0, z0), vec3(x1, y0, z0), vec3(x1, y1, z0), vec3(x0, y1, z0)], uv, [dark; 4], [-Vec3::Z; 4]);
|
||||||
|
mb.quad([vec3(x0, y0, z0), vec3(x0, y0, z1), vec3(x0, y1, z1), vec3(x0, y1, z0)], uv, [dark; 4], [-Vec3::X; 4]);
|
||||||
|
};
|
||||||
|
let at = |p: Vec3, s: Vec3| (p - s * 0.5, p + s * 0.5);
|
||||||
for &(x, z, since, kind, seed) in &self.remains {
|
for &(x, z, since, kind, seed) in &self.remains {
|
||||||
let age = g.time - since;
|
let age = g.time - since;
|
||||||
if age < 0.0 || !g.map.shown(idx(x as i32, z as i32)) {
|
if age < 0.0 || !g.map.shown(idx(x as i32, z as i32)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let hero = crate::gfx::is_hero_kind(kind);
|
let hero = crate::gfx::is_hero_kind(kind);
|
||||||
let sink = 0.0;
|
|
||||||
let lifeless = matches!(kind, EK::Ram | EK::Catapult | EK::Gargoyle | EK::Cogling);
|
let lifeless = matches!(kind, EK::Ram | EK::Catapult | EK::Gargoyle | EK::Cogling);
|
||||||
let off0 = |k: u32| ((((seed.wrapping_mul(2654435761) ^ k.wrapping_mul(40503)) >> 7) % 1000) as f32 / 1000.0 - 0.5) * 0.4;
|
let off = |k: u32| ((((seed.wrapping_mul(2654435761) ^ k.wrapping_mul(40503)) >> 7) % 1000) as f32 / 1000.0 - 0.5) * 0.4;
|
||||||
if lifeless {
|
if lifeless {
|
||||||
let wood = if matches!(kind, EK::Ram | EK::Catapult) { Color::from_rgba(110, 76, 44, 255) } else { Color::from_rgba(96, 94, 100, 255) };
|
let c = if matches!(kind, EK::Ram | EK::Catapult) { [110, 76, 44, 255] } else { [96, 94, 100, 255] };
|
||||||
for k in 0..5u32 {
|
for k in 0..5u32 {
|
||||||
crate::props::auto_cube(vec3(x + off0(k + 20) * 1.2, 0.02, z + off0(k + 30) * 1.2), vec3(0.09, 0.04, 0.05 + (k % 2) as f32 * 0.08), wood);
|
let (lo, hi) = at(vec3(x + off(k + 20) * 1.2, 0.02, z + off(k + 30) * 1.2), vec3(0.09, 0.04, 0.05 + (k % 2) as f32 * 0.08));
|
||||||
|
put(lo, hi, c);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// the pool of blood, spread a little in the first seconds
|
// the pool of blood, spread a little in the first seconds
|
||||||
let spread = (age / 2.0).min(1.0);
|
let spread = (age / 2.0).min(1.0);
|
||||||
for k in 0..4u32 {
|
for k in 0..4u32 {
|
||||||
let r = (0.12 + off0(k + 40).abs() * 0.4) * (0.5 + 0.5 * spread);
|
let r = (0.12 + off(k + 40).abs() * 0.4) * (0.5 + 0.5 * spread);
|
||||||
draw_cube(vec3(x + off0(k + 50) * 0.6, 0.006 + k as f32 * 0.001, z + off0(k + 60) * 0.6), vec3(r, 0.004, r * 0.8), None, Color::from_rgba(92, 10, 14, 255));
|
let (lo, hi) = at(vec3(x + off(k + 50) * 0.6, 0.006 + k as f32 * 0.001, z + off(k + 60) * 0.6), vec3(r, 0.004, r * 0.8));
|
||||||
|
put(lo, hi, [92, 10, 14, 255]);
|
||||||
}
|
}
|
||||||
let off = off0;
|
let bone = [214, 204, 182, 255];
|
||||||
let bone = Color::from_rgba(214, 204, 182, 255);
|
let iron = [120, 122, 132, 255];
|
||||||
let iron = Color::from_rgba(120, 122, 132, 255);
|
|
||||||
for k in 0..3u32 {
|
for k in 0..3u32 {
|
||||||
let p = vec3(x + off(k * 2), 0.02 - sink, z + off(k * 2 + 1));
|
let p = vec3(x + off(k * 2), 0.02, z + off(k * 2 + 1));
|
||||||
if k % 2 == 0 {
|
let (lo, hi) = at(p, if k % 2 == 0 { vec3(0.16, 0.03, 0.03) } else { vec3(0.03, 0.03, 0.14) });
|
||||||
crate::props::auto_cube(p, vec3(0.16, 0.03, 0.03), bone);
|
put(lo, hi, bone);
|
||||||
} else {
|
|
||||||
crate::props::auto_cube(p, vec3(0.03, 0.03, 0.14), bone);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if hero {
|
if hero {
|
||||||
crate::props::auto_cube(vec3(x + off(7), 0.04 - sink, z + off(8)), vec3(0.1, 0.07, 0.1), iron);
|
let (lo, hi) = at(vec3(x + off(7), 0.04, z + off(8)), vec3(0.1, 0.07, 0.1));
|
||||||
crate::props::auto_cube(vec3(x + off(9), 0.015 - sink, z + off(10)), vec3(0.2, 0.02, 0.03), iron);
|
put(lo, hi, iron);
|
||||||
|
let (lo, hi) = at(vec3(x + off(9), 0.015, z + off(10)), vec3(0.2, 0.02, 0.03));
|
||||||
|
put(lo, hi, iron);
|
||||||
} else {
|
} else {
|
||||||
crate::props::auto_cube(vec3(x + off(7), 0.04 - sink, z + off(8)), vec3(0.08, 0.07, 0.08), bone);
|
let (lo, hi) = at(vec3(x + off(7), 0.04, z + off(8)), vec3(0.08, 0.07, 0.08));
|
||||||
|
put(lo, hi, bone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for mb in meshes {
|
||||||
|
if let Some(m) = mb.into_plain_mesh() {
|
||||||
|
draw_mesh(&m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// dust where the dying hit the ground
|
// dust where the dying hit the ground
|
||||||
|
|||||||
Reference in new issue
Block a user