texture_ref
The GPU key a material's texture slot binds by, resolved from whatever form the author wrote it in.
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
- Procedural —
color:/default:/runtime:. The GPU texture cache produces these itself, so they pass through untouched. - The reference itself — a guid, an asset identity, a bare name, or a
.texturepath, resolved throughasset.resolve(ref, "texture"). - The imported container — when the reference is a loose raster path
(
png/jpg/jpeg/webp), the sibling<stem>.texturethe 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. - The alternate identity — a slot's stable identity, passed by the
.materialpath so a binding whose guid was orphaned by a delete + recreate still finds the texture the author named. - 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.
Scoped to this part · feeds back into the world's score.