"""dpl_sampler.py -- the authentic IG-board texture-value model, distilled from the shipped Division library headers (BT411 engine/MUNGA_L4/libDPL/dpl/dpltypes.h `dpl_TEX_VALUE` + dpl.h `dpl_SetTextureProperty`) cross-checked against the real renderer (dpl3-revive patha/vrview_gl.py, stage_assets.py, vrboard.py). The board applies a texmap over a polygon under per-texture PROPERTY values (`dpl_TEX_PROP` set to a `dpl_TEX_VALUE`). Two affect the rasterizer's *output*: * WRAP (dpl_tex_prop_wrap / wrapu / wrapv): dpl_tex_value_repeat -> texel index wraps modulo the map size (default) dpl_tex_value_clamp -> texel index clamps to the edge A tiling terrain uses REPEAT; a one-shot decal / HUD label / emblem CLAMPs (tiling a "PLAYER 1" label is the tell-tale wrong-wrap artefact). * ALPHA / cutout (dpl_tex_prop_alpha, dpl_tex_value_cut): the texel word is [pad, B, G, R] (SVT xbgr) -- there is NO stored alpha channel. The board realises `dpl_tex_value_cut` (PUNCH: the cockpit / effect-card cutout that retires the "opaque rectangle" bug) by NEAR-BLACK KEYING at draw time: a texel whose R+G+B is <= a small threshold is a HOLE (the poly is not drawn there, and does not claim z). Ground truth: patha/vrview_gl.py ("alpha cutout (texel sum <= 24/255)"). Filtering (point/bilinear/...) is a quality axis; pvision runs texmode 0 = point (nearest), which is what the rasterizer models. Pure + numpy-vectorized so the frame renderer applies it over a whole tile at once; independent of the wire capture so it is conformance-tested on synthetic input (see __main__). """ import numpy as np # dpl_TEX_VALUE tokens we act on (names mirror dpltypes.h) WRAP_REPEAT = 'repeat' WRAP_CLAMP = 'clamp' CUT_OFF = 'off' # dpl_tex_value off -> opaque CUT_KEY = 'cut' # dpl_tex_value_cut -> near-black keying (PUNCH) # Near-black cutout threshold (R+G+B), from patha/vrview_gl.py (sum <= 24/255). CUT_THRESHOLD = 24 # The wire's per-texmap `mode` word (0x1a upload header word[4]) selects the # board's internal storage path (mode 1 = 8-bit). It is NOT reliably a cutout # flag -- cutout is a per-MATERIAL property (dpl_SetTextureProperty), which the # wire capture does not yet expose per drawn surface. So wrap defaults to REPEAT # (the board default) and cutout defaults to OFF until a SetTextureProperty # stream is decoded; callers can override per texmap. def mode_to_texflags(mode): """Decode a wire texmap `mode` word into (wrap_u, wrap_v, cut_mode).""" return WRAP_REPEAT, WRAP_REPEAT, CUT_OFF def wrap_index(coord, size, wrap): """Vectorized texel index for integer texel coords under a wrap mode.""" c = np.asarray(coord, dtype=np.int64) if wrap == WRAP_CLAMP: return np.clip(c, 0, size - 1) return np.mod(c, size) # REPEAT (default) def composite(dst_rgb, inside, src_rgb, cut_mode, cut_thresh=CUT_THRESHOLD): """Apply a textured polygon's texels to the framebuffer under the board texture-value model. Returns the boolean DRAW mask (pixels the poly actually owns -- the caller gates the z-buffer write with it so CUT holes don't claim z). dst_rgb : HxWx3 uint8 framebuffer (modified in place on the draw mask) inside : HxW bool -- candidate pixels (edge AND z test already done) src_rgb : HxWx3 -- sampled texel colour (RGB) cut_mode : CUT_OFF (opaque) or CUT_KEY (near-black keying) """ if cut_mode == CUT_KEY: lum = src_rgb.astype(np.int32).sum(axis=2) draw = inside & (lum > cut_thresh) # near-black texels are holes else: draw = inside dst_rgb[draw] = src_rgb[draw] return draw def composite_masked(dst_rgb, sel, src_rgb_compact, cut_mode, cut_thresh=CUT_THRESHOLD): """Like composite(), but src_rgb_compact holds only the SEL-true samples (shape (K, C), K = sel.sum()), in the order sel's True entries appear under numpy boolean indexing. Lets a caller sample/composite only the pixels a texture actually covers instead of the whole frame -- the same board texture-value model, just without doing (frame_size / coverage) redundant work when many textures each cover a small fraction of the frame (see gpu_raster.Renderer.frame, where this was the dominant per-frame cost). """ if cut_mode == CUT_KEY: lum = src_rgb_compact.astype(np.int32).sum(axis=1) keep = lum > cut_thresh idx = np.flatnonzero(sel)[keep] dst_rgb.reshape(-1, dst_rgb.shape[-1])[idx] = src_rgb_compact[keep] else: dst_rgb[sel] = src_rgb_compact if __name__ == '__main__': # -- wrap conformance -- assert list(wrap_index([-1, 0, 3, 4], 4, WRAP_REPEAT)) == [3, 0, 3, 0] assert list(wrap_index([-1, 0, 3, 4], 4, WRAP_CLAMP)) == [0, 0, 3, 3] # -- cutout conformance on a 2x2 scene -- dst = np.zeros((2, 2, 3), np.uint8) inside = np.ones((2, 2), bool) # (0,0) near-black (hole under CUT), others bright src = np.array([[[2, 3, 4], [200, 10, 10]], [[10, 200, 10], [10, 10, 200]]], np.uint8) # OFF: everything drawn, keying ignored d = dst.copy(); m = composite(d, inside, src, CUT_OFF) assert m.all() and (d[0, 0] == [2, 3, 4]).all() # CUT: the near-black texel (sum 9 <= 24) is a hole (not drawn, no z claim) d = dst.copy(); m = composite(d, inside, src, CUT_KEY) assert not m[0, 0] and m[0, 1] and m[1, 0] and m[1, 1] assert (d[0, 0] == 0).all() and (d[0, 1] == [200, 10, 10]).all() # -- composite_masked must match composite() exactly, on a partial `sel` # (a subset of `inside`, as gpu_raster.Renderer.frame uses it per texture) -- sel = np.array([[True, False], [True, True]]) # skip (0,1) this time for cm in (CUT_OFF, CUT_KEY): d_full = dst.copy(); composite(d_full, sel, src, cm) d_masked = dst.copy(); composite_masked(d_masked, sel, src[sel], cm) assert (d_full == d_masked).all(), (cm, d_full, d_masked) print("composite_masked matches composite() on a partial mask, both cut modes: PASS") print("dpl_sampler conformance PASS " "(repeat/clamp wrap + off/cut near-black keying)")