Skip to content

Textures

Yahasi edited this page Jul 6, 2026 · 1 revision

🌐 English · Русский

← World Format · GPU Renderer →

Textures

Any object can wear a PNG image texture. The whole pipeline renders identically on CPU and GPU (validated by the gputest self-test), and textures sync over the network, so a peer without the file still sees the image.

PNG loading

  • Supported PNGs: 8-bit, non-interlaced, colour type 2 (RGB) or 6 (RGBA). The decoder is built into the app (via .NET's System.IO.Compression.ZLibStream) — no third-party image library.
  • Textures live in SampleGame/textures/. Reference one from a world by setting "texture": "<file>.png" on an object.
  • A missing or unsupported file is logged and the object falls back to its flat colour (no crash). The logs name the exact reason.
  • The #1 "textures don't load" cause is a JPEG/GIF/BMP/WebP that was simply renamed to .png — the decoder detects and names the real format in the log. The fix is to re-export as a real PNG, not a code change.

UV mapping per object type

Textures map by per-corner UVs, generated procedurally for the primitives and read from the .obj for imported meshes:

  • Cube — each of the 6 faces maps the full texture; TexFace can restrict it to one side.
  • Ramp / pyramid — mesh primitives with per-corner UVs; the sloped/triangular faces are unwrapped along their own edges. Bit-exact CPU↔GPU.
  • Cylinder / cone — side unwraps as angle × height; caps are wrapped onto a texture disc.
  • Sphere — an equirectangular (lat/long) map computed at the hit from the surface direction in the sphere's local frame, so the texture rotates with the object.
  • Flat picture — a two-sided vertical quad that maps the full texture right-side-up (mirrored on the back), non-colliding — a poster / billboard.
  • Imported mesh — maps by the UVs authored in the .obj (vt lines), with the OBJ→image v-flip applied so models map right-side-up. A vt-less file renders untextured, byte-identically to before.

Per-object parameters

  • textureScale (TexScale) — UV tiling: 2 tiles the image 2×2, 0.5 shows half.
  • textureFace (TexFace) — which face wears the texture (-1 = all; a cube's 05 select one side; other shapes are a single face).
  • textureFilter (TexFilter):
    • 0 nearest — no smoothing (default).
    • 1 bilinear — interpolates neighbouring texels (smooths magnification).
    • 2 mipmapped — trilinear minification off a box-filtered mip chain, so distant / grazing surfaces don't shimmer.

Nearest and bilinear are bit-identical CPU↔GPU on mesh primitives; the sphere's analytic UV allows a thin seam/pole band, and a mipmapped object allows a thin band (level selection is float). Edit all of these live in the Inspector (Texture / TexScale / TexFace / TexFilter) — see Controls.

Network texture sync

A textured object's texture is a file name, but its PNG bytes stream to peers so a client without the file still sees it:

  1. World sync — when a client joins, every referenced texture is streamed to it (small ones inline, large ones in chunks) before the world.
  2. Runtime push — on a live texture edit (or a spawn), the authority streams the bytes to peers before the edit that names them, so the peer materializes the file first.

Received textures are written to received/textures/ on the client. See Multiplayer.

Clone this wiki locally