Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

texture_ref

The GPU key a material's texture slot binds by, resolved from whatever form the author wrote it in.

The renderer binds a texture slot by exact GPU-cache key, and that key is the guid an upload lands under. A reference in any other form — an asset identity (wall.texture), a bare name, a .texture path, the image path a texture was imported from — names a real texture the cache has never heard of. Bound as written it leaves the slot on the shader's declared fallback: white for a base_color_texture, black for a sky panorama. The material then renders as though nothing was bound, and nothing distinguishes that from a texture the author meant to be dark.

This module is the single place that answers "what key does this reference bind by", so the same string binds the same texture wherever it is written.

Consumed by material.assetType (the .material asset path), renderer.material.create, and renderer.material.setTexture.

API

local TextureRef = require("modules.texture_ref")

TextureRef.resolve("wall.texture")          -- "9f2c…", "asset"
TextureRef.resolve("9f2c…")                 -- "9f2c…", "asset"   (idempotent)
TextureRef.resolve("/source/sky/pano.png")  -- "f181…", "asset"   (→ pano.texture)
TextureRef.resolve("color:1,0,0,1")         -- unchanged, "procedural"
TextureRef.resolve("video_0")               -- unchanged, "live"
TextureRef.resolve("nothing_here")          -- unchanged, "unresolved"

TextureRef.isProcedural("default:white")    -- true
TextureRef.unresolvedMessage(ref, "renderer.material.setTexture")

resolve also materialises the texture (Disk→CPU→GPU via texRef:handle()) — the guid only becomes a cache key once the upload has landed.

Resolution order

  1. Procedural — color: / default: / runtime:. The GPU texture cache produces these itself, so they pass through untouched.
  2. The reference itself — a guid, an asset identity, a bare name, or a .texture path, resolved through asset.resolve(ref, "texture").
  3. The imported container — when the reference is a loose raster path (png / jpg / jpeg / webp), the sibling <stem>.texture the texture importer promotes it into. The importer removes the loose original, so the path an author copied out of an import log names a file that no longer exists; this step follows the image to where its texture actually went.
  4. The alternate identity — a slot's stable identity, passed by the .material path so a binding whose guid was orphaned by a delete + recreate still finds the texture the author named.
  5. A resident GPU key — a live texture with no asset behind it: a video frame (video_0), a rasterised text texture, a render target. Binds exactly as written.

Anything left is "unresolved". The reference is still returned unchanged — a texture that lands later is picked up by the renderer's own pending retry — but the caller has the outcome and reports it with unresolvedMessage instead of letting the slot fall back in silence.