Issue #3: wreck scorch quad ramp + RGBA4444 alpha cutout (the 'dark square')

MECHMD's scorch base (basev:bvx9_mtl, bexp9_tex = BEXP.BSL RGBA4444
slice 8, ramp cdusty) drew as a hard-edged dark square for two stacked
reasons:

1. The blanket 'truecolor BSL slice (channel >= 6) never ramps' gate
   blocked its cdusty ramp.  Corpus scan: only 4 shipped textures use
   truecolor slices; bexp9/bdet9 are grayscale in RGB (100% / 98.8%
   r==g==b) and their materials author ramps -- only bdam8 (damage
   sheet) is truly coloured.  bgfload rampableSlice() now probes the
   decoded slice: a truecolor slice ramps iff effectively gray (>=95%),
   keeping bdam8's colour protected.

2. The RGBA4444 authored alpha channel -- a binary 0/240 cutout mask
   (the splat silhouette, 78.5% transparent) -- was never alpha-tested,
   so the quad's transparent surround rendered as an opaque rectangle.
   New BgfDrawBatch.texAlpha (channel >= 8) routes these batches
   through the PUNCH alpha-test draw states, WITHOUT the black-texel
   keying (which would hole the near-black charred centre).  Side
   benefit: tree9 (tree/leaf cards) + bdet9 (trans-rail lattice) get
   their authored cutouts too.

Pixel-verified (ram-kill run, BT_SHOT): irregular char splat, dark
brown (71,44,34) lifting to near-terrain tan (115,100,91 vs terrain
131,119,108), no rectangle; pre-death frames unregressed (vehicles
stay lit/diffuse -- hasNormals gate untouched).  Awaiting human
verification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-19 10:39:43 -05:00
co-authored by Claude Fable 5
parent 557e9fd243
commit 9fff079df4
4 changed files with 83 additions and 13 deletions
+10 -2
View File
@@ -437,7 +437,12 @@ d3d_OBJECT* d3d_OBJECT::LoadObjectBGF(LPDIRECT3DDEVICE9 device, char *fileName)
// become alpha-0 holes below; DrawMesh alpha-TESTS them in the opaque pass.
static int s_punch = -1;
if (s_punch < 0) { const char *pv = getenv("BT_PUNCH"); s_punch = (pv == 0 || pv[0] != '0') ? 1 : 0; }
object->mDrawOps[i].punchThrough = (s_punch && data.batches[i].punch);
// PUNCH batches alpha-test load-KEYED holes (black texels). TEXTURE-ALPHA
// batches (RGBA4444 BSL slice, issue #3: the wreck scorch splat / rail
// lattice / tree cards) alpha-test their AUTHORED alpha channel -- same
// draw states, no keying (the near-black splat centre must stay opaque).
object->mDrawOps[i].punchThrough =
(s_punch && data.batches[i].punch) || data.batches[i].texAlpha;
object->mDrawOps[i].copRole = data.batches[i].copRole; // punch stencil-cut kit (task #55)
object->mDrawOps[i].texture.texture = NULL;
object->mDrawOps[i].texture.wrap_u = L4TEXOP::REPEAT;
@@ -493,7 +498,10 @@ d3d_OBJECT* d3d_OBJECT::LoadObjectBGF(LPDIRECT3DDEVICE9 device, char *fileName)
{
// PUNCH keying: black texels of a punch batch become alpha 0
// (holes). Keyed on the ORIGINAL texel, before any ramp.
const bool punchKey = object->mDrawOps[i].punchThrough;
// NOT applied to texture-alpha (RGBA4444) batches -- their
// cutout is the authored alpha channel, and black-keying
// would hole the scorch splat's charred (near-black) centre.
const bool punchKey = (s_punch && data.batches[i].punch);
if (useRamp)
{
// Colorize: for each texel, index the low->high ramp by