Skip to content

Textures & Terrain

This page covers how imported images are decoded, capped, and stored device-neutrally, and how a Unity terrain is baked from a heightmap and splat maps into a real textured ground mesh.

Texture decode

Whatever the source - a dropped image, a texture inside an engine pack, or a map referenced by a material - Awaken decodes it to RGBA8 pixels:

  • PNG, JPG/JPEG, WebP, BMP, GIF decode through the browser's image pipeline.
  • TGA (Targa) is decoded by Awaken directly: truecolor 24-bit or 32-bit, uncompressed or RLE, with the file's BGR(A) channel order corrected and bottom-left origin flipped to top-down.
  • Unreal Texture2D source is BGRA-ordered, so its red and blue channels are swapped back on decode.

The size cap

Every decoded texture is downscaled to fit a maximum longest-side limit, chosen in the Import Dialog for packs (and fixed at the recommended default for direct image imports).

OptionLongest side
Lowest256 px
Low512 px
Medium (recommended, default)1024 px
High2048 px
FullSource resolution

The default is 1024 px. The reason is memory: an uncompressed 4096² texture is 64 MB of VRAM, and stylized/painterly art rarely needs anything near full resolution. Downscaling happens during the decode draw (no full-size readback), and it's the main lever for keeping a whole pack's texture memory in check. Bumping the cap costs quadratically.

Device-neutral storage

Awaken stores each texture as device-neutral RGBA8 pixels plus a role (albedo, normal, or mask). It does not bake in a GPU-specific compressed format at import. Instead, the renderer decides compression per device, at upload - so a project authored on one machine ships safely to any device rather than carrying one GPU's format. The role picks the compression scheme (albedo, normal, and mask channels each want different treatment) with an uncompressed RGBA fallback where a device can't compress.

This is why the size cap is described as an authoring-resolution choice: it fixes the pixel dimensions, independent of whatever compression the target GPU ends up using.

Unity terrain

A Unity Terrain doesn't have a mesh - it's a heightfield plus splat (paint) layers. Awaken bakes both into assets a normal ground shader can draw.

Heightmap → mesh

The terrain's heightfield is turned into a ground mesh (capped at 257×257 resolution), placed at the terrain's world position. This gives you a real, collidable, renderable surface instead of a special-cased terrain object.

Splat → albedo

Unity paints terrain with per-layer control maps (which layer shows where) and tiled diffuse textures (grass, dirt, path). Awaken's single-texture ground shader can't run Unity's multi-layer terrain shader, so it bakes the splat into one 512×512 ground albedo:

  1. For each output texel, read the layer weights from the control maps.
  2. Blend the tiled layer diffuse colours by those weights (each layer tiled by its own metres-per-tile).
  3. Write the blended colour; bare/unpainted texels fall back to a muted green.

The result reproduces Unity's grass/dirt/path zones in a single texture pointed at the ground mesh. The baked texture has a stable per-pack name, so re-importing the pack overwrites it rather than piling up duplicates. Terrain layer textures are read from each layer's .terrainlayer asset (diffuse map and tile size).

Terrain import is Unity-only - Godot and Unreal terrains aren't imported.

📸 Screenshot - save as img/import-terrain-baked.png

An imported Unity terrain in the Awaken viewport, showing the baked grass/dirt/path albedo blended across the ground mesh.

See also

Awaken — browser-native WebGPU game engine.