Files
benilla-octo/crates/benilla-formats/examples/batch_alpha.rs
T
SamandClaude Fable 5 90efd4efad the voidwalker's eyes come back, and skinning becomes ours
- The voidwalker's eye glow vanished whenever the camera rose above eye level.
  Three investigations said depth; measuring the depth buffer inside the live
  quads said otherwise — the fragments reached the framebuffer every frame, and
  the body's own transparent batches painted over them. The real client draws a
  model's particles after that model's batches, always. Ours now does: every
  effect carries a draw-order rung sized to clear exactly its own model.
- Widened to every effect family after asking "what else does this fix": ribbon
  trails (a wisp's streamers wove six batches deep into its own body and
  flickered as the head whipped) and 3-D model particles (Cone of Cold's
  shards). A census over all 9,691 models found 967 whose own body could paint
  over their effects; all take the rung now.
- The skinning lane is ours end to end: every rig's joint matrices live in our
  shared GPU buffer, written only when a rig actually moved, and our shader
  reads them. The engine's lane rewrote the entire joint buffer every frame and
  swept every entity in the world for changed transforms — that machinery now
  runs against empty sets. Another 6.7 CPU ms off the worst reported dungeon
  spot, which now holds a flat 60 fps with p99 under 19 ms.
- Getting around while developing: Ctrl+Cmd+G lands your character where the
  free-fly camera is, and Alt-clicking the world map teleports you there (both
  ride the server's own teleport, GM-gated). The frozen-body coordinates the
  panel used to copy while flying now follow the camera.
- A stuck main thread now diagnoses itself: a watchdog samples our own stacks
  and prints where the time went, and a hung teardown names its last system
  instead of hanging the window.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 19:38:40 +07:00

50 lines
2.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Print every render batch's **animated material alpha** across a named sequence — the factor the
//! renderer multiplies into the instance's render alpha (`A = instanceAlpha × colourAlpha × weight`).
//!
//! `cargo run -p benilla-formats --example batch_alpha -- 'Creature\Voidwalker\Voidwalker.m2' 0`
//!
//! The number that matters is whether a batch ever reads **exactly 1.0**: benilla swaps a faded
//! entity onto its `AlphaMode::Blend` twin whenever `alpha < 1.0`, and that twin forces depth-write
//! ON. A batch whose authored weight never reaches 1.0 therefore never returns to the steady
//! material — so a `no_depth_write` batch (M2 flag 0x10) starts writing depth it must never write.
fn main() -> anyhow::Result<()> {
let mut args = std::env::args().skip(1);
let virt = args
.next()
.ok_or_else(|| anyhow::anyhow!("usage: batch_alpha <m2 path> [sequence slot]"))?;
let slot: usize = args.next().and_then(|s| s.parse().ok()).unwrap_or(0);
let data = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../WoW/Data");
let mut chain = benilla_formats::open_chain(&data)?;
let bytes = chain.read_file(&virt)?;
let subs = benilla_formats::parse_m2_render_submeshes(&bytes, "", &[])?;
println!("sequence slot {slot} — {} batches", subs.len());
for (i, s) in subs.iter().enumerate() {
let Some(a) = s.alpha_anim.as_ref() else {
println!(
" batch {i:2}: no alpha_anim (static 1.0) depth_write={}",
!s.no_depth_write
);
continue;
};
let samples: Vec<f32> = (0..24u16)
.map(|k| a.sample(Some(slot), 3.0 * f32::from(k) / 24.0))
.collect();
let lo = samples.iter().copied().fold(f32::MAX, f32::min);
let hi = samples.iter().copied().fold(f32::MIN, f32::max);
let ever_one = samples.iter().any(|&v| v >= 1.0);
println!(
" batch {i:2}: alpha {lo:.4}..{hi:.4} ever==1.0: {ever_one:<5} \
depth_write={:<5} additive={:<5} {}",
!s.no_depth_write,
s.additive,
if ever_one {
""
} else {
"<-- STUCK on the blend twin"
}
);
}
Ok(())
}