tecs.gfx.images
Image identity, residency, and the commands that carry pixels to the backend.
A game names an image, hands over its pixels, and receives a small integer that a Sprite stores. The backend owns the texture, the view, the sampler, and the bind group; nothing native reaches game code.
const id = tecs.gfx.images.upload({
name = "tiles/grass",
width = 2,
height = 2,
pixels = grassRgba8,
filter = "nearest",
})
world:spawn(
tecs.ecs.Transform2D(64, 64, 0, 1, 0, 32, 32),
tecs.gfx.Tint(1, 1, 1, 1),
tecs.gfx.Sprite(id),
tecs.gfx.Renderable2D
)An id is permanent and process-wide, in the same way component identity is, so a snapshot stores the name and resolves the id again on load. Uploading a name twice replaces the image behind that same id, and every sprite already pointing at it draws the new pixels on the next frame.
Residency is observed rather than waited on. upload queues a command and answers immediately with "pending"; the host drains the command, reports the outcome, and stateOf then answers "resident" or "failed". Extraction draws a sprite whose image is not resident against the backend's opaque white fallback, so a missing asset is a visibly untextured quad rather than a dropped entity or a raised error.
Pixels are eight-bit RGBA with unassociated alpha, four bytes per texel, in rows running top to bottom. That is the only accepted layout, and the command names it so a later format costs a value rather than a command shape.
Module contents
Types
| Type | Kind | Description |
|---|---|---|
Address | type | Selects what sampling outside the zero-to-one range returns. |
Command | type | |
Filter | type | Selects minification and magnification filtering. |
Format | type | The pixel layout an upload carries. |
MaterialMaps | type | Optional companion images; omitted channels use neutral material values. |
MaterialMapsCommand | record | One queued residency request. |
ReleaseImageCommand | record | Asks the backend to drop one image and everything bound to it. |
State | type | Reports where one named image stands with the backend. |
UploadImageCommand | record | Asks the backend to make one image resident under an id. |
UploadOptions | type | The options upload accepts. |
Functions
| Function | Kind | Description |
|---|---|---|
complete | function | Records the backend's outcome for one drained command. |
drain | function | Removes the queued residency commands for the host to apply. |
failureOf | function | Returns why the backend rejected one image. |
id | function | Returns the permanent id one image name resolves to. |
load | function | Decodes a PNG or JPEG file and queues its RGBA pixels for upload. |
nameOf | function | Returns the name one image id was interned under. |
release | function | Queues one image for release. |
residencyRevision | function | Returns the revision of image residency and sampling metadata. |
samplerIndex | function | Returns the sampler index one filter and address mode select. |
samplerOf | function | Returns the sampler index extraction writes for one image. |
setMaterialMaps | function | Associates normal, emission and packed occlusion/roughness/metallic images. |
sizeOf | function | Returns the texel dimensions the last accepted upload declared. |
stateOf | function | Returns where one image stands with the backend. |
upload | function | Queues one image for residency and returns its permanent id. |
Values
| Value | Kind | Description |
|---|---|---|
SAMPLER_COUNT | variable | The number of distinct samplers a backend must create. |
Types#
Addresstype#
type Address = "clamp" | "repeat" | "mirror"Selects what sampling outside the zero-to-one range returns.
These identifiers reach configuration a developer writes and are a compatibility surface.
Commandtype#
type Command = UploadImageCommand | ReleaseImageCommand | MaterialMapsCommandFiltertype#
type Filter = "nearest" | "linear"Selects minification and magnification filtering.
These identifiers reach configuration a developer writes and are a compatibility surface.
Formattype#
type Format = "rgba8"The pixel layout an upload carries.
This value crosses to the backend inside a command and is a compatibility surface.
MaterialMapstype#
type MaterialMaps = {
normalMap: integer?,
emissionMap: integer?,
ormMap: integer?
}Optional companion images; omitted channels use neutral material values.
MaterialMapsCommandrecord#
record MaterialMapsCommand
kind: string
serial: integer
image: integer
normalMap: integer
emissionMap: integer
ormMap: integer
endOne queued residency request.
Fields
kind#
kind: stringserial#
serial: integerimage#
image: integernormalMap#
normalMap: integeremissionMap#
emissionMap: integerormMap#
ormMap: integerReleaseImageCommandrecord#
Asks the backend to drop one image and everything bound to it.
Fields
Statetype#
type State = "unknown" | "pending" | "resident" | "failed" | "released"Reports where one named image stands with the backend.
UploadImageCommandrecord#
record UploadImageCommand
kind: string
serial: integer
image: integer
width: integer
height: integer
format: Format
sampler: integer
pixels: string
endAsks the backend to make one image resident under an id.
Fields
UploadOptionstype#
type UploadOptions = {
name: string,
width: integer,
height: integer,
pixels: string,
filter: Filter?,
address: Address?
}The options upload accepts.
Functions#
completefunction#
function complete(image: integer, serial: integer, ok: boolean, reason: string?): nilRecords the backend's outcome for one drained command.
A completion that no longer matches the image's newest serial is discarded, so a replacement queued before the previous upload completed keeps its own state.
Arguments
| Name | Type | Description |
|---|---|---|
image | integer | the process-wide image id the command named |
serial | integer | the command serial the host applied |
ok | boolean | whether the backend accepted the command |
reason | string? | the non-empty host failure, required when |
Returns
| Type | Description |
|---|---|
nil |
Raises
when a rejection carries no reason
drainfunction#
function drain(): {Command}Removes the queued residency commands for the host to apply.
Returns
| Type | Description |
|---|---|
{Command} | the ordered command batch, which the caller owns |
failureOffunction#
function failureOf(image: integer): string?Returns why the backend rejected one image.
Arguments
| Name | Type | Description |
|---|---|---|
image | integer | the process-wide image id |
Returns
| Type | Description |
|---|---|
string? | the host failure reason, or nil unless the state is |
idfunction#
function id(name: string): integerReturns the permanent id one image name resolves to.
Interning a name does not make it resident. A sprite may be built against an id whose pixels arrive later, or never.
Arguments
| Name | Type | Description |
|---|---|---|
name | string | the stable image name, which a snapshot stores |
Returns
| Type | Description |
|---|---|
integer | the process-wide image id, which is always greater than zero |
Raises
when the name is empty
loadfunction#
function load(path: string, name: string?): integerDecodes a PNG or JPEG file and queues its RGBA pixels for upload.
Arguments
| Name | Type | Description |
|---|---|---|
path | string | the image file path |
name | string? | the stable image name; omitted uses the file path |
Returns
| Type | Description |
|---|---|
integer | the image id, whose dimensions are immediately available |
Raises
when the file cannot be decoded
nameOffunction#
function nameOf(image: integer): string?Returns the name one image id was interned under.
Arguments
| Name | Type | Description |
|---|---|---|
image | integer | the process-wide image id |
Returns
| Type | Description |
|---|---|
string? | the name, or nil when no image carries that id |
releasefunction#
function release(name: string): boolean, string?Queues one image for release.
The id survives the release, so a later upload under the same name makes the same id resident again. Sprites pointing at a released image draw the backend's fallback until then.
Arguments
| Name | Type | Description |
|---|---|---|
name | string | the stable image name |
Returns
| Type | Description |
|---|---|
boolean | whether a release was queued, which is false for a name nothing uploaded |
string? | why nothing was queued, when unsuccessful |
residencyRevisionfunction#
function residencyRevision(): integerReturns the revision of image residency and sampling metadata.
Returns
| Type | Description |
|---|---|
integer | A monotonic count that changes when residency or sampling changes. |
samplerIndexfunction#
Returns the sampler index one filter and address mode select.
Arguments
| Name | Type | Description |
|---|---|---|
filter | Filter? | the filtering mode, defaulting to |
address | Address? | the addressing mode, defaulting to |
Returns
| Type | Description |
|---|---|
integer | the sampler index, from zero to |
Raises
when either mode is not one of its declared values
samplerOffunction#
function samplerOf(image: integer): integerReturns the sampler index extraction writes for one image.
Arguments
| Name | Type | Description |
|---|---|---|
image | integer | the process-wide image id |
Returns
| Type | Description |
|---|---|
integer | the sampler index, which is nearest filtering with clamped edges for an unknown id |
setMaterialMapsfunction#
function setMaterialMaps(image: integer, maps: MaterialMaps): nilAssociates normal, emission and packed occlusion/roughness/metallic images. All supplied maps must have the albedo image dimensions. Applies to sprites and TileChunks using that image; replacement pixels keep the association.
Arguments
| Name | Type | Description |
|---|---|---|
image | integer | |
maps | MaterialMaps |
Returns
| Type | Description |
|---|---|
nil |
sizeOffunction#
function sizeOf(image: integer): integer, integerReturns the texel dimensions the last accepted upload declared.
Arguments
| Name | Type | Description |
|---|---|---|
image | integer | the process-wide image id |
Returns
| Type | Description |
|---|---|
integer | the width and then the height in texels, both zero before an upload |
integer |
stateOffunction#
function stateOf(image: integer): StateReturns where one image stands with the backend.
Arguments
| Name | Type | Description |
|---|---|---|
image | integer | the process-wide image id |
Returns
| Type | Description |
|---|---|
State | the residency state, which is |
uploadfunction#
function upload(options: UploadOptions): integerQueues one image for residency and returns its permanent id.
Uploading a name that is already resident replaces its pixels behind the same id, so every sprite pointing at it draws the new image once the host reports the replacement complete.
Arguments
| Name | Type | Description |
|---|---|---|
options | UploadOptions | the name, texel dimensions, RGBA8 pixels, and sampling modes |
Returns
| Type | Description |
|---|---|
integer | the process-wide image id |
Raises
when the name is empty, a dimension is not positive, a sampling mode is unknown, or the pixel length is not four bytes per texel
Values#
SAMPLER_COUNTvariable#
const SAMPLER_COUNT: integerThe number of distinct samplers a backend must create.
Every filter paired with every address mode, so a sampler is selected by index and never created on demand.