Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·originates fromworld 07158574-5…

texture_ref

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

by◐lumi·posted 2mo ago
What it does

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.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

module TextureRef The GPU key a material's texture slot binds by, resolved from whatever form the author wrote it in. Every path that accepts a texture reference — the `.material` assetType, `renderer.material.create`, `renderer.material.setTexture` — resolves through here, so the same string binds the same texture wherever it is written.

isProcedural(ref: string) → boolean

Whether a reference is one the GPU texture cache resolves on its own (`color:` / `default:` / `runtime:`), so it must be passed through untouched rather than looked up as an asset.

argtypedescription
refstringThe reference string.

examples

TextureRef.isProcedural("color:1,0,0,1") -- true

containerForImagePath(ref: string) → string

The `.texture` container the texture importer promotes a loose image into: `<dir>/<stem>.<ext>` → `<dir>/<stem>.texture`. Returns nil for anything that is not a loose raster path, so a reference is only rewritten when the importer's own naming contract says where its texture went.

argtypedescription
refstring

residentGuidOf(candidate: string) → string

Resolve one candidate to a materialised guid, or nil when it names no texture.

argtypedescription
candidatestring

resolve(ref: any, altIdentity: string?) →

Resolve a texture reference to the resident GPU key the renderer binds a slot by, materialising the texture on the way. Accepts a guid, an asset identity, a bare name, a `.texture` path, or the image path a texture was imported from. `color:` / `default:` / `runtime:` forms and live GPU handles (a video frame, a render target) pass through untouched. nothing — a slot's stable identity, so a binding whose guid was orphaned by a delete + recreate still finds the texture the author named. unchanged), and the outcome: `"procedural"`, `"asset"`, `"live"`, or `"unresolved"`.

argtypedescription
refanyThe authored reference.
altIdentitystring?Optional second candidate, tried when `ref` resolves to

examples

TextureRef.resolve("wall.texture") -- "9f2c…", "asset"

unresolvedMessage(ref: string, what: string) → string

The message describing a reference that names no texture. Bound anyway, the slot renders the shader's declared fallback, so the caller says this rather than letting the material render as though nothing was asked for.

argtypedescription
refstringThe unresolved reference.
whatstringThe call being made, for the message's subject.

examples

TextureRef.unresolvedMessage("sky.jpg", "renderer.material.setTexture")

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

2items
This part has no composite children. See the Files segment for its leaf payloads.
backing path · modules/texture_ref.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.