The Helmet Was Fine, Actually
glTF assets now sample their textures the way the file says to: per-texture wrap and filter modes reach the GPU, so the community's favourite battle-damaged helmet renders its full texture set instead of near-black streaks. Tiling textures tile, pixel-art textures stay crisp.


Drop a glTF asset into Lux and, until this release, you were rolling dice on its textures. The dice were loaded, too: any asset whose UVs strayed outside the 0-to-1 square came back as smears of stretched edge pixels. The community’s favourite test asset, a battle-damaged sci-fi helmet with five 2K textures, rendered like this:

The textures were fine. The geometry was fine. The file even said, in plain glTF, exactly how it wanted to be sampled: wrap coordinates around, repeat the image. Lux ignored that and clamped everything, because the renderer owned exactly one texture sampler and clamping was its personality. The helmet’s UVs live between 1.0 and 2.0, which with wrap-around sampling is identical to 0-to-1, and with clamping is a request for one row of edge pixels stretched across the entire model.
One sampler, sixteen hats
The bindless texture system always had sixteen sampler slots; they just all wore the same hat. Now they hold the real set: every combination of wrap mode (clamp, repeat, mirror) and filter (smooth, pixel-perfect). Each texture’s declared sampling travels with it from file to GPU, and each material texture picks its own sampler right in the shader, packed into bits the material records had to spare. No new pipelines, no per-texture sampler objects, no configuration. The file says repeat, so it repeats.

Three gates pin the behaviour: the helmet must render its texture detail (the bright-pixel count jumped 6x when the fix landed), a generated checker quad with UVs spanning 0-to-2 must actually tile, and the same checker, which asks for pixel-perfect filtering, must keep its edges within a pixel instead of blurring across twenty-five. The fixtures are tiny and live in the repo, so the gates run on every PR.
The helmet still insists on lying face-down, which is a different bug: scene node transforms, next on the list. One indignity at a time.