Skip to content

Port the three asset-dependent examples (106 → 109) - #7

Merged
burinc merged 4 commits into
mainfrom
arc/shader-texture-examples
Aug 23, 2026
Merged

Port the three asset-dependent examples (106 → 109)#7
burinc merged 4 commits into
mainfrom
arc/shader-texture-examples

Conversation

@burinc

@burinc burinc commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Ports the three examples that were waiting on the asset files added in PR #4,
so those assets are now actually used. 106 → 109.

The three

tiled-drawing — tiles one patch of a texture atlas across the window,
with pattern, tint, scale and rotation selectable.

The substance is DrawTextureTiled, which is a helper defined inside the C
example rather than raylib API, so it's implemented here. Four cases (tile
larger than the area in both axes, larger in one, smaller in both), each
drawing partial tiles along its edges that crop the source proportionally so
a truncated tile shows less pattern rather than a squashed one.

Written as a pure function returning (source, dest) pairs instead of nested
draw loops, which is what makes it checkable: across all four cases the
tiles cover the destination area exactly
, to within 1e-6, with every tile
inside it — verified at 500×400 (56 tiles), 528×396 (exact multiples, 48
tiles, no partials), 50×400, 500×40, 40×40, and scales 5.0 and 0.25 (4 and 800
tiles). The degenerate cases matter more than usual: the C's guard carries the
comment "Wanna see a infinite loop?!...just delete this line!". All four
inputs that trip it return empty.

palette-switch — eight bands drawn in near-black greys that a fragment
shader remaps through a palette. The colour on screen is never drawn by the
program; the red channel carries an index.

This is the example that finally exercises set-shader-value-ints!, whose GL
path was untested when I added it — the commit introducing it said so. It
works: 3-BIT RGB renders exactly black/red/green/blue/cyan/magenta/yellow/
white, which is only possible if all 24 ints reached the uniform in the right
order and grouping.

ascii-rendering — the scene rendered to an offscreen target, then
post-processed into ASCII glyphs. Nothing in the Clojure draws a glyph.

Verification

Shaders fail silentlyLoadShader returns an id whether or not the GLSL
compiled — so these were checked by screenshot, not assertion. Before that,
each shader's uniforms were probed: nil for the vertex shader marshals to
NULL and raylib substitutes its default (the C passes 0 for the same
reason), palette resolves to location 1, and a deliberately absent uniform
returns -1. Both examples check their locations before use rather than
assuming success.

Gate: 138 namespaces, 0 lint errors, 69 warnings (unchanged backlog).

Also

  • set-shader-value-vec2! — the namespace had float, vec3, vec4 and int
    helpers but no vec2, so a resolution uniform had nowhere to go.
  • A texture-filter enumset-texture-filter! previously took a bare
    int with no named constants.

Demos

ascii-rendering records well (44 frames, self-animating). tiled-drawing
and palette-switch come out at 2 distinct frames — the state does change
(10% and 6% of pixels differ end to end) but most keypresses don't land, the
known synthetic-input intermittency already documented in the manifest.
tiled-drawing's pattern and colour are chosen by clicking, which the
recorder can't deliver at all, so its timeline drives scale and rotation
instead. Both are candidates for a hand-recorded replacement.

Note on patterns.png

tiled-drawing depends on the one asset with no stated licence upstream,
flagged in resources/LICENSE.md. If you'd rather keep that directory
uniformly attributed, dropping the file costs exactly this one example.

burinc added 4 commits August 23, 2026 15:04
Tiles one patch of a texture atlas across the window with selectable pattern,
tint, scale and rotation. Uses patterns.png, one of the assets added earlier.

The substance is DrawTextureTiled, which is a helper defined inside the C
example rather than raylib API, so it is implemented here rather than bound.
It has four cases - tile larger than the area in both axes, larger in one
axis, or smaller in both - and each case draws partial tiles along its edges,
cropping the SOURCE proportionally so a truncated tile shows less pattern
rather than a squashed one.

Written as a pure function returning (source, dest) pairs instead of nested
draw loops, which is what makes it checkable: across all four cases the tiles
cover the destination area EXACTLY, to within 1e-6, and every tile stays
inside it. Verified at 500x400 (grid, 56 tiles), 528x396 (exact multiples, 48
tiles and no partials), 50x400 (single column), 500x40 (single row), 40x40
(one cropped tile), and at scales 5.0 and 0.25 (4 and 800 tiles).

The degenerate cases matter more than usual here. The C's guard carries the
comment "Wanna see a infinite loop?!...just delete this line!" - without it
the loops never advance. All four inputs that trip it return an empty seq: a
non-positive scale, a zero-width or zero-height source, and a scale small
enough that the tile size truncates to zero.

Also adds a texture-filter enum to textures/texture-loading; set-texture-filter!
previously took a bare int with no named constants.
Eight bands drawn in near-black greys, RGB (0,0,0) through (7,7,7), which a
fragment shader remaps through a palette. The colour on screen is never drawn
by the program: the red channel carries an index and the shader looks it up.
Left and right switch between 3-bit RGB, a GameBoy-like AMMO-8, and a
two-strip film RKBV.

This is the example that finally exercises
raylib.core.shaders/set-shader-value-ints!, whose GL path was untested when
it was added - the commit that introduced it said as much. It works: the
3-BIT RGB palette renders exactly black/red/green/blue/cyan/magenta/yellow/
white, which is only possible if all 24 ints reached the uniform in the right
order and grouping.

Verified before the visual: nil for the vertex shader marshals to NULL and
raylib substitutes its default (the C passes 0 for the same reason), the
palette uniform resolves to location 1, and a deliberately absent uniform
returns -1 - so the guard in init distinguishes a real lookup from a failed
one rather than assuming success. All three palettes are 24 ints, 8 colours,
every component in 0..255.

line-height is 56, so eight bands cover 448 of 450 pixels. That 2px gap is
the C's own integer division and is kept.
A post-processing effect: the scene is drawn into an offscreen render
texture, then that whole texture is drawn once through a fragment shader that
replaces each cell with an ASCII glyph sized by a uniform. Uses fudesumi.png
and raysan.png, two of the assets added earlier.

Nothing in the Clojure draws a glyph. The scene is two ordinary textures;
every character on screen comes from the shader sampling the render texture
per cell and picking by brightness. Verified visually rather than by
assertion, since that is the only thing that distinguishes a working shader
from a silently unapplied one.

The source rect used to blit the render texture carries a NEGATIVE height.
That is the standard flip for a bottom-up GL target, not a typo, and it is
called out in the source so nobody tidies it away.

Also adds set-shader-value-vec2!, which was missing: the namespace had float,
vec3, vec4 and int helpers but no vec2, so the resolution uniform had nowhere
to go.

init distinguishes a real uniform lookup from a failed one rather than
assuming success - a missing uniform returns -1, and both locations here are
checked before use.
Counts re-derived from the registry and bb check rather than incremented:
109 examples (37 core, 28 shapes, 21 models, 9 games, 4 textures, 4 audio,
3 text, 3 shaders), 138 namespaces, 98 of 109 starting an embedded nREPL.

Validated: 109 catalog rows, 109 gallery entries, 109 GIFs, every registry
alias present in the catalog, no broken preview links or anchors, and each
section header matching its own row count.

On the demos: ascii-rendering animates unaided and records well at 44 frames.
tiled-drawing and palette-switch come out at 2 distinct frames each - the
state does change (10% and 6% of pixels differ between first and last), but
most keypresses do not land, which is the known synthetic-input
intermittency already documented at the top of the manifest. tiled-drawing's
pattern and colour are chosen by CLICKING, which the recorder cannot deliver
at all, so its timeline drives scale and rotation instead. Both are
candidates for a hand-recorded replacement.
@burinc
burinc merged commit 296b723 into main Aug 23, 2026
1 check passed
burinc added a commit that referenced this pull request Aug 23, 2026
Regenerated against main after PR #7 landed, rather than merged hunk by hunk.
Both branches were cut from the same commit and both bumped example counts in
the same thirteen files, so git had "106 -> 107" against "106 -> 109" with no
way to pick. Counts are re-derived from the registry and bb check either way,
so regenerating is both simpler and less error-prone than resolving.

110 examples (22 models now), 140 namespaces, 99 of 110 starting an embedded
nREPL. Adds raylib.models to the module layout in the architecture guide.

Validated after the rebase: catalog rows, gallery entries, GIFs and registry
all agree at 110, every registry alias is in the catalog, no broken preview
links or anchors, and each section header matches its own row count. The four
examples that collided across the two branches were re-run together.

The demo leans on mouse LOOK rather than clicks: pointer moves land reliably
where button presses do not, so first-person motion carries the preview and
the single click is opportunistic. 30 frames.
@burinc
burinc deleted the arc/shader-texture-examples branch August 23, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant