Entry 152
The field's depth shades, and model Z at the GS's scale
Filescrates/piney-draw/src/lib.rscrates/piney-gs/src/lib.rscrates/piney-gs/src/convert.rscrates/piney-desktop/src/soft.rscrates/piney-desktop/src/noiz.rscrates/piney-desktop/src/layers.rscrates/piney-world/src/field_area.rsdocs/engine/field.mddocs/engine/render.md
A GAPS drawing item: WORLD_MAN's two ccBufferSamplings, which every
WORLD::Draw sends first. field.md said they made "a depth shade from
the z buffer" and that the renderer could not read Z as a texture. Neither
was right. They soften the distance.
What the game draws
WORLD_MAN::WORLD_MAN calls the seven-argument SetShade(page, x, y, tw, th, z, colour) (main 0x00106c70): (0, 896, 0, 8, 7, 3000, 0x48808080)
and (0, 896, 0, 7, 6, 6000, 0x48808080). That sets texuse (+0x2e) to 1,
a texture of their own at x 896 of buffer 0. MakePacket was run in eemu
(test_stream_rs's machine, sysLayer's view) and its GIF packets decoded.
For each shade it sends:
- A context-2 strip that draws the whole 512 x 448 picture being drawn into 256 x 128 (or 128 x 64) at that address: bilinear, no tests, no blend, Z masked.
- That texture drawn back over the view's box: bilinear, CLAMP,
(Cs - Cd) As + Cdat 0x48, alpha NEVER with FB_ONLY, and Z GEQUAL at the Z of depth 3,000 (or 6,000), with no Z write.
Every pixel farther than 3,000 thus takes 56% of a quarter-size copy of
the frame, and beyond 6,000 again of an eighth-size one. Both go on
sysLayer, which draws after the field's objLayer. ccLayer::Add (0x00108930)
keeps the root list in descending priority with a new layer after the
equal ones, and AddAll reverses it, so of two layers of one priority the
newer draws first. sysLayer is made at start-up and objLayer by GO, both
priority 0. The sky, the ground and the objects soften; the characters
and effects, on later layers, stay sharp. MakePacket prepends, so the
3,000 shade draws before the 6,000 one.
The port
- piney-draw. New
TexRef::ScaledFrame { width, height }: the frame as the command finds it, resampled as the context-2 strip would. - piney-gs. The command copies the whole frame, as for
FrameBuffer. Under a newParams::SCALEDbit the shader reads that copy through the smaller grid: each of the four bilinear taps of the small texture is itself a bilinear read of the frame at that texel's centre. No extra pass is needed. - Software renderer. It builds the small image the same way.
- piney-desktop.
Sampling::shade_own(tw, th, z, colour)gives the draw-back strip.Layers::olderholds an older layer's groups, drawn after everything else of that priority. - piney-world.
FieldArea::drawputs the two strips onolder(0).
Model Z was a sixteenth of the GS's
The first shots softened the ground right at Kite's feet. VU1 divides by
w and converts the whole vector with ftoi4, so a model's GS Z is 16 z/w
(render.md). The port took z/w. The strips' Z and the effects' sprites
(rot_trans_pers, piney-effect's fixed) are already at the GS's scale,
so all of those compared as nearer than any model. piney_draw::MODEL_Z_SCALE
(16) now scales model depth in piney-gs and in the software renderer. Models
against models are unchanged. The fix also makes effect sprites, the
blades' trails and the rays hide behind the models in front of them, as
the game's do.
Checks
the_field_shades_draw_their_own_texture_back:shade_own's strips against the game's packets from eemu, for both shades. The corners, Z (0x00ae43a3, 0x0056e1d9), UVs and colour are equal.a_scaled_frame_reads_through_the_smaller_copy(piney-gs, on the GPU): a black/red split frame read through a half-width copy gives black, one pixel halfway, then red.Layers' order test coversolder.- Field 14 shots with and without the shades: before the Z fix 95% of the
near ground changed; after it, nothing below the horizon band changes,
and the far hills, the horn, the sky and the distant ground soften. A
dungeon fight shot (
target_cursor_shot) draws as before, cursor included. - All 585 workspace tests pass.
no picture of the game's own field was compared. The GS's bilinear weights (a few fraction bits) and its reads past the frame are not modelled. Model Z past ftoi4's signed range (w below about 16) is clamped at 2^32 here, where the VU saturates it.