All posts
Releases

Natiny 0.9.0

Web rendering now matches desktop, while capsules, rotation locks, and in-place resource reloads make projects easier to build and iterate on.

Natiny 0.9.0

Natiny 0.9.0 closes the gap between web and desktop. Scale modes now mean the same thing on both, shaders that failed only in WebGPU work again, and new physics and resource APIs shorten the path from an edit to a running result.

Web scale modes now match desktop

This is the change existing projects are most likely to notice. The web build used to size its drawing buffer in CSS pixels, which magnified SCALE_MODE_HIDPI and SCALE_MODE_STRETCH and left SCALE_MODE_PIXELS below the display's native resolution. It now draws in physical pixels: all three modes match desktop, mouse coordinates follow the selected mode, and browser zoom updates while the program runs.

There is one compatibility note. A web project that relied on the old default SCALE_MODE_PIXELS appears devicePixelRatio times larger after updating. Set SCALE_MODE_HIDPI to restore its previous size.

Web audio now opens its device on the first click or touch, when the browser allows an AudioContext to start. The public audio API does not change.

Resources reload in place

texture.update, shader.reload, mesh.reload, and clip.reload replace a resource without replacing its handle. Materials, models, draw calls, and playing audio keep their bindings; surface.resize keeps its colour and depth texture handles too. If an update fails, the old resource remains usable.

Capsules are ready for character controllers

natiny.mesh.capsule and natiny.physics.capsule arrived together and take the same two numbers, a radius and a total height end to end, so the mesh and collider line up without a hidden offset. Heights at or below twice the radius produce a sphere in both APIs.

A body can also be kept upright with natiny.physics.set_fixed_rotation, or locked one axis at a time with natiny.physics.set_rotation_locks. For a typical character controller, lock pitch and roll while leaving yaw free:

Lua
natiny.physics.set_rotation_locks(player, true, false, true)

natiny.entity.get_position completes the loop. It returns three numbers instead of allocating a table, so it is safe to read every frame.

WebGPU accepts more ordinary NSL

Some valid NSL shaders compiled on desktop but produced a black frame in WebGPU. Three translation errors behind that split are fixed:

  • Local names such as dpdx no longer collide with WebGPU's spelling of a builtin such as dFdx.
  • Ordinary names such as target are renamed when WGSL reserves them instead of causing the shader to fail.
  • Scalar compound assignments to a swizzle, such as v.xy *= s, are translated correctly.

One WebGPU rule still belongs to shader authors: do not put a texture sample or derivative inside a branch that neighbouring pixels may take differently. Move the sample or dFdx above the branch, then use its result inside.

Explore the Waterpool

The new Waterpool example brings floating beach balls, reflections, refraction, caustics, and adaptive exposure together in one endless underground pool.

Natiny 0.9.0 bundles for every platform are on the download page.

More posts