A blur already worked with Sample texture, but only by wiring every
sample by hand: 25 nodes for a 5x5. Averaging their colours also gave
a dark seam wherever a neighbour was transparent. The Blur node writes
the loop itself and averages the right way.
- Blur takes radius (pixels of the picture, 0 to 8, fractions allowed)
and u/v like Sample texture, and gives color and alpha.
- Kind is Box (default) or Gaussian, Direction is Both, Horizontal or
Vertical. Both are arguments of one prelude helper, blur().
- The samples are averaged premultiplied and only then made straight,
so a transparent neighbour lowers the opacity and adds no black.
- The outermost ring counts by the part of the radius that reaches
it, so a radius from a Property changes smoothly and compiles
nothing again.
- A node may now declare prepare, a vec4 the compiler works out once
into a local. Color and alpha read that one sum instead of blurring
twice.
- A reached Blur counts as a shifted sample, so the picture comes
with the Output's Edge. It cannot feed the Vertex output.
- Both perf tools take GM_PERF_BLUR=<radius>.
Wider blurs and bloom need several passes. That is #301.
Measured on stein2 (HD 630, one run per value, fps), Box blur:
- 48x48 sprites at 100/400/800: radius 2 59.8/58.4/55.6,
radius 4 53.1/51.4/36.3, radius 8 46.6/24.4/14.4.
- 256x256 field shaders at 1/10/50: radius 2 60.2/56.0/49.0,
radius 4 60.1/49.0/27.1, radius 8 52.4/34.9/11.4.
Tests:
- Gate: 224 files, 3467 tests, CHECK EXIT 0 (+7).
- e2e 28: ALL PASSED, 94 checks (+5 in 28l-vi). Pixels match the
arithmetic to 1: the last red texel at radius 0.5/1/4 reads
187/173/154 (expected 188/173/154).
- Counter-checks: Blur not counted as shifted fails 1 unit test.
Blur output left premultiplied fails the seam and spot checks.
- e2e total 1712 is computed (1707 + 5).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI run 217 for 592ea94 failed three checks in block 47i. In the full
run the texture list is longer than in a single module run, so the
picker click missed "halves" and the texture stayed empty.
- The check now types "halves" into the menu search field and picks
it with Enter, independent of the list length.
- FIND_HALVES looks the image up by name. Matching only by size had
picked the 32 px image "wedge" in the full run.
- The texture fill check forces a redraw before reading pixels. After
the work of earlier modules the vector tab does not redraw once the
texture has loaded. That bug is tracked in #196, and the forced
redraw goes away with it.
Tests:
- ./check.sh: CHECK EXIT 0
- npm run build: BUILD EXIT 0
- GM_STEPS=47 (fresh seed): ALL PASSED, 54 checks
- Full run not repeated locally. CI decides.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four new rows on sprite, text, collider and container (block TRANSFORM):
scale, rotation in degrees clockwise, mirrorX, mirrorY. As properties they
get override/reset/apply, loading of old projects, write-back after play and
the Properties node for free; camera and behavior have none.
The hierarchy composes T*R*S per level (composeAlongChain replaces
sumAlongChain), so children rotate and scale with their parent. Reparenting
and grouping keep the look (carriedTransform). Drawing goes through
placeNode, the gizmo is a polygon, cull and objectRect use the AABB, drags
are computed in the parent's system.
Colliders are oriented boxes: SAT for box/box, box-circle in the box frame;
exitDistance replaces axisSeparation/axisCorrection, moveAndSlide moves along
the object's own axes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>