Venus Lua API › Rendering
Material
Shader + textures + constants — colors, UV transforms, render queue.
lua/venus_lua/src/lua_material.rs
Material
A material resource: a shader plus its bound textures, up to 16 color/vector slots, per-slot UV
scale/offset, and a render queue. Materials are named manager resources (not scene components) —
created by name, looked up by name, cloned, and destroyed. Colors are stored linear internally;
the Color/MainColor accessors convert to and from sRGB at the boundary, while
SetColorLinear bypasses conversion.
Static calls use the type table (Material.Create("name")); instance methods use colon syntax on a
handle (material:SetShader(...)).
Types
Material — an opaque handle (userdata) to a material resource. A handle may be null or
stale (its resource destroyed); it is safe to keep and pass around, and a method never raises on
one. Null/stale behavior is not uniform: ID() logs a warning and returns nil, but the color,
UV, and render-queue getters return a silent default (see the known issue below), and every setter
silently no-ops. Passing a non-Material value where a method expects self raises a Lua type
error. tostring(material) yields Material{name}, or Material{NULL} if the handle is dead.
Known issue — dead-handle reads fail silently. Only
ID()reports a null/stale handle (logs
NotFound, returnsnil). The other getters return a manager default with no warning:
MainColor()/Color()return transparent black(0,0,0,0),UVScaleOffset()returns
(1,1,0,0), andRenderQueue()returns65535(RENDER_QUEUE_USE_DEFAULT). Out-of-range color
indices and UV slots behave the same way, and every setter no-ops without warning
(material_manager.rs:375,:392,:518,:547). UseMaterial.Exists(mat)to test liveness —
do not infer it from a getter’s result.
Creation & Destruction
Material.Create( string name ) : Material
Creates a new named material resource. Returns nil and logs InvalidArgument on failure — a
duplicate name (AlreadyExists) or pool exhaustion (OutOfMemory) both surface as the same log.
Material.Get( string name ) : Material
Looks up an existing material by name. Returns nil if none matches (no warning — a miss is a valid result).
Material.Exists( Material material ) : boolean
Returns true if the handle refers to a live material. Safe on null, stale, or foreign (non-material
userdata / nil) arguments — returns false without raising or warning. This is the reliable
liveness check.
Material.Clone( Material material ) : Material
Duplicates material into a new anonymous resource (not registered by name; gets its own GPU
slot) and returns it. Returns nil and logs NotFound if the source is null/stale. Note this is a
static call — Material.Clone(mat), not mat:Clone().
material:Destroy( ) : boolean
Marks the material for deferred destruction. Returns true if the handle was valid and got marked,
false if it was already null/invalid. (Unlike most instance methods, this one returns a value.)
Functions
Read-only queries. See the known issue above — only ID() reports a dead handle; the rest return
silent defaults.
material:ID( ) : string
The material’s unique name. Returns nil and logs NotFound on a null/stale handle, or on an
anonymous clone (which has no registered name).
Properties (get / set)
Setters return void and silently no-op on a null/stale handle or out-of-range index (no
warning). Color indices and UV/texture slots are 0-based: color indices 0..15
(MAX_MATERIAL_COLORS = 16), UV slots 0..7 (MAX_MATERIAL_TEXTURES = 8).
RenderQueue
material:RenderQueue( ) : integer — the material’s render-queue override, or 65535
(use-shader-default) if unset or the handle is dead.
material:SetRenderQueue( integer queue ) : void — stores the raw 16-bit override (recomputes
the effective 8-bit sort key internally).
MainColor
material:MainColor( ) : Vector4 — color slot 0 as sRGB RGBA.
material:SetMainColor( Vector4 srgba ) : void — accepts sRGB RGBA (stored linear).
Alias for Color(0) / SetColor(0, …) — the same slot-0 color (material_manager.rs:365, :370).
Color
material:Color( integer index ) : Vector4 — the color at 0-based index (0..15) as sRGB
RGBA. Out-of-range or dead handle → (0,0,0,0).
material:SetColor( integer index, Vector4 srgba ) : void — sets 0-based index from sRGB
RGBA (stored linear).
UVScaleOffset
material:UVScaleOffset( integer slot ) : Vector4 — (scaleU, scaleV, offsetU, offsetV) for
0-based texture slot (0..7). Out-of-range or dead handle → (1,1,0,0).
material:SetUVScale( integer slot, number scaleU, number scaleV ) : void — sets scale only,
preserving the existing offset.
material:SetUVOffset( integer slot, number offsetU, number offsetV ) : void — sets offset
only, preserving the existing scale.
Methods
Actions that mutate the material. All silently no-op on a null/stale handle (no warning).
material:SetShader( Shader shader ) : void
Sets the material’s shader, pulling the pipeline handle, texture count, and default render queue from
the ShaderManager. No-ops and logs NotFound if the shader handle does not resolve.
material:SetTexture( integer slot, Texture texture ) : void
Binds texture at the given 0-based texture slot (0..7), copying its GPU image/sampler and
dimensions. No-ops and logs NotFound if the texture handle does not resolve.
material:SetColorLinear( integer index, Vector4 linearRgba ) : void
Sets the color at 0-based index to a linear-space value, verbatim (no sRGB conversion). The
counterpart write path to SetColor; there is no linear getter exposed to Lua (read back through
Color, which re-applies sRGB).
Example
-- Clone a base material and tint it, then swap its albedo texture and tile the UVs.
function Script.OnEnable(self)
local mat = Material.Clone(Material.Get("crate"))
mat:SetMainColor(Vector4.new(0.9, 0.2, 0.2, 1.0)) -- sRGB red tint (== SetColor(0, ...))
mat:SetTexture(0, Texture.Get("crate_red")) -- a registered texture, by name
mat:SetUVScale(0, 2.0, 2.0) -- slot 0, 2x2 tiling
self.material = mat
end
function Script.OnDisable(self)
if Material.Exists(self.material) then
self.material:Destroy()
end
end