On this page
tecs.gfx.layers
Depth bands, sorting, coordinate spaces, parallax, and lighting.
A layer occupies one of sixteen depth bands. Entities sort inside their band and never against another band. Higher layer numbers draw nearer, so a HUD on layer 8 covers a world on layer 1.
tecs.gfx.layers.configure(1, {sort = "topdown", parallax = 0.4})
tecs.gfx.layers.configure(
8, {sort = "z", screenSpace = true, unlit = true}
)
world:spawn(
tecs.Transform2D(16, 16, 0, 8, 0, 96, 24),
tecs.gfx.Tint(1.0, 1.0, 1.0, 1.0),
tecs.gfx.Renderable2D()
)The fourth Transform2D argument selects the layer.
Sort modes
"topdown" sorts by Y with Z for height. "z" ignores position. "isometric" combines X, Y, and Z for a diamond grid. Equal depths retain instance order.
maxZ and maxY define the authored extents that each sort maps into its band. Values past an extent clamp to its edge. They still draw, but clamped entities no longer sort against one another. Reduce an extent when Renderer:depthSortCollapse reports that the target depth format merges nearby values.
Coordinate spaces
World coordinates form the default. screenSpace uses target pixels and ignores the camera. virtualCoords stretches one virtualWidth by virtualHeight coordinate system to the target. ignoreZoom follows camera position while preserving drawn size. parallax scales camera movement.
One layer cannot combine screenSpace and virtualCoords. Virtual coordinates preserve the authored coordinate system but do not letterbox or preserve square pixels.
unlit bypasses scene lighting for UI, debug overlays, and other content that must retain its own color.
configure replaces the complete layer configuration. Any omitted option returns to its default.
Module contents
Types
| Type | Kind | Description |
|---|---|---|
Config |
record | Defines every decision a layer makes about its contents. |
Sort |
enum | Selects how a layer orders its contents within its own band. |
Functions
| Function | Kind | Description |
|---|---|---|
bandOf |
Static | Returns the two terms depthIn takes, resolved once for a layer. |
configure |
Static | Sets what a layer does with its contents. |
depthIn |
Static | Returns one entity's depth on a band bandOf already resolved. |
depthOf |
Static | Returns one entity's depth from zero to one, with zero nearest. |
depthResolution |
Static | Returns the smallest depth difference depthOf produces between two entities one unit apart, taken over every sort mode. |
entryOf |
Static | Returns the four floats that position and light one layer: its mode, its parallax offset factor, whether it ignores... |
isScreenSpace |
Static | Returns whether a layer uses screen-pixel coordinates. |
revision |
Static | Returns the layer table's configuration revision. |
sortOf |
Static | Returns a layer's sort as the identifier accepted by depthOf. |
viewCulled |
Static | Returns whether the camera's view rectangle culls this layer. |
Values
| Value | Type | Description |
|---|---|---|
MAX |
integer |
Read-only. Reports how many bands divide the depth range. |
maxY |
number |
Caller-writable. Sets half the expected world extent used to normalize position into a band. |
maxZ |
number |
Caller-writable. Sets the highest z a scene expects to use and the resulting resolution of sorting within a band. |
virtualHeight |
number |
Caller-writable. Sets the vertical resolution used to author a virtual-coordinate layer. |
virtualWidth |
number |
Caller-writable. Sets the horizontal resolution used to author a virtual-coordinate layer. |
Types
tecs.gfx.layers.Config record
Defines every decision a layer makes about its contents. A field left out takes its default, so this says what a layer is rather than amending what it was.
record tecs.gfx.layers.Config
sort: Sort
screenSpace: boolean
ignoreZoom: boolean
virtualCoords: boolean
unlit: boolean
parallax: number
endtecs.gfx.layers.Config.sort field
Caller-writable. Selects how contents sort within the layer's band. The caller must set this field.
tecs.gfx.layers.Config.screenSpace field
Caller-writable. Positions contents in screen pixels and ignores the camera entirely. What a HUD wants. Defaults to false.
tecs.gfx.layers.Config.screenSpace: booleantecs.gfx.layers.Config.ignoreZoom field
Caller-writable. Makes contents follow the camera's position but not its zoom, so they stay a constant size on screen while moving with the world. Defaults to false.
tecs.gfx.layers.Config.ignoreZoom: booleantecs.gfx.layers.Config.virtualCoords field
Caller-writable. Positions contents in virtualWidth by virtualHeight; Tecs scales that coordinate system to fill the target. Defaults to false and cannot combine with screenSpace.
tecs.gfx.layers.Config.virtualCoords: booleantecs.gfx.layers.Config.unlit field
Caller-writable. Makes contents bypass the lighting pass and appear at their own color. Defaults to false. A material can ask for the same thing, and a fragment is lit only where the material and the layer agree.
tecs.gfx.layers.Config.parallax field
Caller-writable. Sets how much the camera's position carries the contents. One moves them with the world; a half drifts them at half speed, which is what a background wants. Defaults to one.
tecs.gfx.layers.Sort enum
Selects how a layer orders its contents within its own band.
enum tecs.gfx.layers.Sort
"isometric"
"topdown"
"z"
endFunctions
tecs.gfx.layers.bandOf Static
Returns the two terms depthIn takes, resolved once for a layer.
What depthOf works out before it looks at an entity at all, and what a caller writing many depths on one layer should work out once instead of once a row: the band's near edge, and which sort decides where in the band a row lands.
function tecs.gfx.layers.bandOf(layer: integer): number, integerArguments
| Name | Type | Description |
|---|---|---|
layer |
integer |
One to MAX. Outside that range this resolves the nearest layer whole, exactly as depthOf does, so the sort answered here is the clamped layer's and not what sortOf answers for the same argument. |
Returns
| Type | Description |
|---|---|
number |
The band's near edge, then the sort identifier. |
integer |
tecs.gfx.layers.configure Static
Sets what a layer does with its contents.
Replaces the layer's configuration rather than amending it. A Config defines the whole layer, so each omitted field takes its default instead of retaining its previous value.
function tecs.gfx.layers.configure(
layer: integer, config: layers.Config
)Arguments
| Name | Type | Description |
|---|---|---|
layer |
integer |
One to MAX. Anything else raises. |
config |
layers.Config |
Raises on a missing or unknown sort, and on asking for screenSpace and virtualCoords together. |
Returns
None.
tecs.gfx.layers.depthIn Static
Returns one entity's depth on a band bandOf already resolved.
The per-row half of depthOf, split out so a caller writing a run of rows on one layer pays the band lookup once. Bit for bit what depthOf answers for the layer the two terms came from.
function tecs.gfx.layers.depthIn(
base: number, sort: integer, z: number, x: number, y: number
): numberArguments
| Name | Type | Description |
|---|---|---|
base |
number |
The band's near edge, from bandOf. |
sort |
integer |
The sort identifier, from bandOf. |
z |
number |
Height in the sort, against maxZ. Read by every sort mode. |
x |
number |
World x, read only by the isometric sort, against maxY. |
y |
number |
World y, read by the topdown and isometric sorts, against maxY. Larger is lower on screen and so nearer. |
Returns
| Type | Description |
|---|---|
number |
A depth inside the band, held to zero and one the same way depthOf holds its own. |
tecs.gfx.layers.depthOf Static
Returns one entity's depth from zero to one, with zero nearest.
Exact ties carry no tie-breaker. The renderer draws instances in index order and the depth test lets an equal fragment through, so two entities at the same depth already resolve the same way every frame: the later one wins. Nudging depth by identity would resolve them the other way, since a larger value is farther, and quietly invert the order a scene was built expecting.
function tecs.gfx.layers.depthOf(
layer: integer, z: number, x: number, y: number
): numberArguments
| Name | Type | Description |
|---|---|---|
layer |
integer |
One to MAX, which picks the band and, through sortOf, what the rest of the arguments mean. Outside that range this takes the nearest layer whole and goes on sorting within it, because a band is the only thing a depth can name. |
z |
number |
Height in the sort, against maxZ. Read by every sort mode. |
x |
number |
World x, read only by the isometric sort, against maxY. |
y |
number |
World y, read by the topdown and isometric sorts, against maxY. Larger is lower on screen and so nearer. |
Returns
| Type | Description |
|---|---|
number |
Returns a depth inside the layer's own band. The function normalizes and clamps each argument to zero through one, so a scene beyond the configured extent stops sorting instead of spilling into the next layer. |
tecs.gfx.layers.depthResolution Static
Returns the smallest depth difference depthOf produces between two entities one unit apart, taken over every sort mode.
A depth buffer must preserve this difference. A format with a larger step keeps the bands, so layer order remains safe, but loses the sort inside them: the two entities land on one depth value and draw in write order rather than their sorted order.
The calculation includes every mode because configure may assign any sort after the depth target exists. MAX, maxZ, and maxY determine the result, so raising an extent changes it.
function tecs.gfx.layers.depthResolution(): numberArguments
None.
Returns
| Type | Description |
|---|---|
number |
A depth difference, in the input that moves depth least. That is the topdown sort's y at the defaults, which spends the smallest share of a band on the widest range. |
tecs.gfx.layers.entryOf Static
Returns the four floats that position and light one layer: its mode, its parallax offset factor, whether it ignores zoom, and whether it is lit.
Returns these values together because consumers pack them together when revision changes, not every frame.
function tecs.gfx.layers.entryOf(
layer: integer
): number, number, number, numberArguments
| Name | Type | Description |
|---|---|---|
layer |
integer |
One to MAX. Outside that every return is nil, since only that range is ever filled in. |
Returns
| Type | Description |
|---|---|
number |
The positioning mode, then the camera position's multiplier, then one when the layer ignores zoom, then one when it is lit. |
number |
|
number |
|
number |
tecs.gfx.layers.isScreenSpace Static
Returns whether a layer uses screen-pixel coordinates.
function tecs.gfx.layers.isScreenSpace(layer: integer): booleanArguments
| Name | Type | Description |
|---|---|---|
layer |
integer |
One to MAX. Outside that this answers false, which is what an unconfigured layer answers too. |
Returns
| Type | Description |
|---|---|
boolean |
Whether configure selected screenSpace for the layer. |
tecs.gfx.layers.revision Static
Returns the layer table's configuration revision.
function tecs.gfx.layers.revision(): integerArguments
None.
Returns
| Type | Description |
|---|---|
integer |
A count that starts at zero and only rises. A consumer compares it against the value it packed at, so the number itself means nothing beyond having changed. |
tecs.gfx.layers.sortOf Static
Returns a layer's sort as the identifier accepted by depthOf.
function tecs.gfx.layers.sortOf(layer: integer): integerArguments
| Name | Type | Description |
|---|---|---|
layer |
integer |
One to MAX. Outside that this answers topdown rather than raising, since it is the default every layer starts on. |
Returns
| Type | Description |
|---|---|
integer |
The sort identifier, which is an internal number and not one of the Sort strings. |
tecs.gfx.layers.viewCulled Static
Returns whether the camera's view rectangle culls this layer.
False on a layer the camera does not place where its world bound says: screen-space and virtual-coordinate contents have no world position for the view to test, and parallax and ignore-zoom draw them somewhere the bound does not describe. Extraction reads this per row and gives those contents a bound that every view contains, so they draw regardless of camera position. Layers using none of these modes retain exact culling.
function tecs.gfx.layers.viewCulled(layer: integer): booleanArguments
| Name | Type | Description |
|---|---|---|
layer |
integer |
One to MAX. Outside that this answers true, which is what an unconfigured layer answers too. |
Returns
| Type | Description |
|---|---|
boolean |
Whether extraction should write this row's real world bound. |
Values
tecs.gfx.layers.MAX variable
Read-only. Reports how many bands divide the depth range.
Load-bearing at sixteen. A sort mode packs into two bits, this value sizes the vertex shader's table, and the shader recovers a layer by multiplying depth by it. LAYER_BANDS in assets/shaders/instance.vert.glsl is the same number, and the two only work while they agree. Raising it is not a constant change.
tecs.gfx.layers.MAX: integertecs.gfx.layers.maxY variable
Caller-writable. Sets half the expected world extent used to normalize position into a band. A scene larger than this still sorts, with entities beyond the edge compressed against it.
tecs.gfx.layers.maxY: numbertecs.gfx.layers.maxZ variable
Caller-writable. Sets the highest z a scene expects to use and the resulting resolution of sorting within a band. A scene reaching past this still draws, with entities beyond the edge resting on it and no longer sorting against each other.
tecs.gfx.layers.maxZ: numbertecs.gfx.layers.virtualHeight variable
Caller-writable. Sets the vertical resolution used to author a virtual-coordinate layer. Tecs scales it with virtualWidth to fill the target.
tecs.gfx.layers.virtualHeight: numbertecs.gfx.layers.virtualWidth variable
Caller-writable. Sets the horizontal resolution used to author a virtual-coordinate layer.
Every such layer shares one resolution because a game has one authored layout size. Tecs scales it to fill the target, so the layout keeps its internal proportions at any window size and stretches with the window's aspect.
tecs.gfx.layers.virtualWidth: number