Venus Lua API › Rendering
Texture
GPU texture handle, plus CPU-editable dynamic textures.
lua/venus_lua/src/lua_texture.rs
Texture
A handle to a GPU texture. Most textures are loaded assets you look up by name and read dimensions
from. Dynamic textures (created via CreateDynamic / CreateDynamic3D) add a CPU-side staging
copy you can edit pixel-by-pixel and push to the GPU with Apply.
Static calls use the type table (Texture.Get(...)); instance methods use colon syntax on a handle
(tex:SetPixel(...)).
Types
Texture — an opaque handle (userdata) to a texture. A handle may be null or stale (its
texture destroyed); it is safe to keep and pass around. tostring(tex) yields Texture{name}, or
Texture{NULL} if dead.
The pixel-editing methods only apply to dynamic textures; on a non-dynamic or dead texture they
log InvalidArgument and no-op. Pixel coordinates are 0-based texel indices (x in 0 ..
Width()-1, y in 0 .. Height()-1, z in 0 .. Depth()-1); an out-of-range coordinate is
rejected by the manager (logs InvalidArgument). Color components are integers in 0–255 (see
the known issue below), not normalized floats.
Creation & Destruction
Texture.Get( string name ) : Texture
Looks up a texture by its unique name. Returns nil if none exists (no warning — a miss is a valid result).
Texture.Exists( Texture texture ) : boolean
Returns true if the handle refers to a live texture. Safe on null / stale / foreign handles
(returns false, never warns).
Texture.CreateDynamic( string name, integer width, integer height, integer format ) : Texture
Creates a 2D dynamic (CPU-editable) texture. format is a Texture.PixelFormat value. Returns the
new handle, or nil (logs InvalidArgument) if the format is unknown, the name is taken, or GPU
allocation fails.
Texture.CreateDynamic3D( string name, integer width, integer height, integer depth, integer format ) : Texture
Creates a 3D dynamic texture (a 2D texture when depth <= 1). format is a Texture.PixelFormat
value. Returns the new handle, or nil (logs InvalidArgument) on failure.
tex:Destroy( ) : void
Releases the GPU image (if any) and destroys the texture. No-op on a null handle.
Functions
Read-only queries. Instance getters log NotFound and return nil on a dead handle unless noted.
Texture.IsDynamic( Texture texture ) : boolean
true if texture is a dynamic (CPU-editable) texture. Safe on null / foreign handles (returns
false).
tex:ID( ) : string
The texture’s unique name.
tex:Width( ) : integer
Width in texels.
tex:Height( ) : integer
Height in texels.
tex:Depth( ) : integer
Depth in texels (1 for 2D textures). Returns 0 (not nil) on error.
tex:AspectRatio( ) : number
Width / height. Returns nil on error.
tex:GetPixel( integer x, integer y ) : integer, integer, integer, integer
Reads a texel from the current frame’s CPU staging copy of a dynamic texture as four 0–255
components r, g, b, a. Returns 0, 0, 0, 0 and logs InvalidArgument on error (non-dynamic, dead,
or out-of-range coordinate).
tex:GetPixel3D( integer x, integer y, integer z ) : integer, integer, integer, integer
As GetPixel, for a 3D dynamic texture. Returns 0, 0, 0, 0 on error.
tex:GetPixelData( ) : string
Returns the entire CPU staging buffer as a raw byte string — the texels packed in the texture’s
pixel format (e.g. 4 bytes/texel for RGBA8), row-major. Returns an empty string (logs NotFound)
on error.
Methods
Mutating actions on dynamic textures. They log InvalidArgument on a non-dynamic or dead
texture. Edits touch the current frame’s CPU staging copy; call Apply to schedule the GPU upload.
tex:SetPixel( integer x, integer y, integer r, integer g, integer b, integer a ) : void
Writes one RGBA texel into the staging copy. Components are integers (see the known issue).
tex:SetPixel3D( integer x, integer y, integer z, integer r, integer g, integer b, integer a ) : void
Writes one RGBA texel into a 3D dynamic texture.
tex:SetPixelData( string bytes ) : void
Overwrites the whole staging buffer from a raw byte string (must match the buffer’s size and format
layout, else InvalidArgument).
tex:SetPixelDataRange( integer offset, string bytes ) : void
Writes bytes into the staging buffer starting at byte offset. A negative offset logs
InvalidArgument and is rejected; an offset + length past the buffer end is rejected by the manager.
tex:Apply( ) : void
Drains the accumulated dirty region and marks it on the GPU image so the backend can issue a
targeted subregion copy for the current frame. No-op on a null handle or a texture with no GPU image.
Known issue — components are integers cast to
u8, no clamp (verified in source).
SetPixel/SetPixel3Dread each ofr, g, b, awithluaL_checkinteger(...) as u8
(lua_texture.rs:387-390,:433-436). Two consequences: (1) they are integers, not
normalized floats — pass255, not1.0(a fractional Lua number such as0.5raises “number
has no integer representation”); (2) values outside 0–255 wrap modulo 256 rather than
clamping (256 -> 0,-1 -> 255). Clamp/round in Lua (e.g.math.floorinto0..255) before
calling.
Constants
Texture.PixelFormat — pixel format discriminants passed to CreateDynamic / CreateDynamic3D.
An unrecognized value fails creation with InvalidArgument.
None (0), BGRA8_sRGB (1), R8 (2), RG8 (3), R16F (4), BGRA8 (5), RG16F (6),
R32F (7), RGBA16F (8), RG32F (9), D32 (10), D32_S8 (11), BC1 (12), BC1_sRGB (13),
BC2 (14), BC2_sRGB (15), BC3 (16), BC3_sRGB (17), BC4 (18), BC5 (19), BC6 (20),
BC7 (21), BC7_sRGB (22), RGBA8 (23), RGBA8_sRGB (24).
Example
-- Walk a colored texel across a 64x64 dynamic texture each frame.
-- (Adapted from data/scripts/dyn_texture_demo.lua.)
local px, py, frame = 0, 0, 0
function Script.Update(self)
local tex = Texture.Get("dyn_demo")
if not tex then return end
-- Integer 0-255 components (math.floor keeps them in range).
local r = math.floor((px / 64) * 255)
local g = math.floor((py / 64) * 255)
local b = frame % 256
tex:SetPixel(px, py, r, g, b, 255)
tex:Apply()
px = px + 1
if px >= 64 then px, py = 0, (py + 1) % 64 end
frame = frame + 1
end