rasterGenerated
Category: Packages · Manifest: use "kernels/";
Triangles turned into the surface a camera sees, drawn alike on every backend.
Description
Section titled “Description”Triangles turned into the surface a camera sees, drawn alike on every
backend: plain, tiled and through a cutout mask; and translucent
triangles over it, in any order. native.rasterize, and native.cover
for the keys alone, are its fast paths.
Layer: Graphics. Uses: parallel.
use "raster.entpkg";Kernels
Section titled “Kernels”kernels/clip.ent— Triangles cut at the near plane, before the rasterizer, which skips whole a triangle reaching behind it. Kernels:raster.clip_near@1,raster.clip_plane@1,raster.clip_faces@1.kernels/cutout.ent— Triangles drawn through a mask. Kernels:raster.cover_cutout@3,raster.cover_cutout@4,raster.cover_cutout_tiles@2.kernels/tile.ent— Triangles larger than a tile cut across many. Kernels:raster.boxes@1,raster.tiles@2,raster.offsets@1,raster.total@1,raster.cover_tiles@2.kernels/triangle.ent— Rasterization as Kernels. Kernels:raster.cover@3,raster.cover@4,raster.resolve@2.kernels/veil.ent— Translucent triangles over an opaque surface: the light they add and the share of the surface left showing, summed so any order of triangles gives the same pixel. Kernels:raster.unveiled@1,raster.veil@1,raster.veiled@1.
Graph presets
Section titled “Graph presets”graphs/canvas.esn— The raster preset over a canvas.graphs/cutout.esn— The raster preset with a cutout.graphs/cutout_tiled.esn— The tiled form ofcutout.esn.graphs/cutout_tiled_window.esn— The tiled form ofcutout_window.esn.graphs/cutout_window.esn— The cutout preset at the window’s size, aswindow.esnis the plain one’s.graphs/surface.esn— Vertex and triangle rows in, the surface out.graphs/tiled.esn— The tiled form ofsurface.esn.graphs/tiled_window.esn— The tiled form ofwindow.esn.graphs/veil.esn— Translucent triangles, their tints and the opaque surface in; the light and what shows through out.graphs/window.esn— The raster preset at the window’s size.
tests/ holds scenes and their replays, run on every backend:
clip.replay, degenerate.replay, near.replay,
tiles.replay, veil.replay. Every Kernel of the package is
reached by one of them.
Used by the animation, culled, mesh, mipmap, surface, voxel examples.
Kernels
Section titled “Kernels”| Kernel | Mode | Brief |
|---|---|---|
raster.boxes@1 |
map | Each triangle’s box on the canvas, found once: none for one that is skipped. Every later step reads it. |
raster.clip_faces@1 |
map | The two faces over each triangle’s four corners (domain = count(triangles) * 2). |
raster.clip_near@1 |
map | Each triangle’s four corners after the cut (domain = count(triangles) * 4): the polygon in front of the near plane in the triangle’s winding, its first corner again past its last (a triangle’s fourth is its third); a triangle wholly behind keeps corners at w -1, which the rasterizer skips. |
raster.clip_plane@1 |
map | Each triangle’s four corners cut by a plane (domain = count(triangles) * 4), as raster.clip_near cuts at the near plane: what lies on the side of plane (its first row, in clip space: a corner is kept where dot(plane, clip) is not below 0) a world plane drawn through the lens has (light.entpkg’s surface.lens_clip_plane); a mirror’s pass keeps what stands over the water, not the bed under it. |
raster.cover@3 |
scatter into input 3 with min | Every pixel’s nearest fragment as one key: each triangle walks its box and emits a key a pixel it covers. With a tile, only the triangles whose box is one tile or less; the larger ones are left to raster.cover_tiles@2, which takes these keys as its own start, so the least of both is kept. |
raster.cover@4 |
scatter into input 2 with min | Every pixel’s nearest fragment as one key, with no tiles: each triangle finds its own box and walks it, emitting a key a pixel it covers. No other step reads the box, so it is found here alone. |
raster.cover_cutout@3 |
scatter into input 4 with min | The same pair with a cutout: a fragment whose alpha in mask, read at its own uv as at_linear(mask, uv * size(mask)) reads it, is below cutout is not drawn — it emits no key, so it settles no depth and what is behind a leaf’s edge is seen through it. |
raster.cover_cutout@4 |
scatter into input 3 with min | The same with a cutout and no tiles: each triangle finds its own box, as raster.cover@4 does. |
raster.cover_cutout_tiles@2 |
scatter into input 7 with min | |
raster.cover_tiles@2 |
scatter into input 6 with min | Every pixel’s nearest fragment as one key, of the large triangles, a tile of one’s box at a time, so a triangle that fills the canvas is covered by as many invocations as it has tiles rather than by one. The node’s domain is a pool of invocations sized by the canvas, each taking every nth tile, so how many tiles there are this frame is read on the device and never waited for. It starts from the keys raster.cover@3 left, and keeps the least. |
raster.offsets@1 |
prefix with sum | Where each triangle’s tiles begin: an inclusive prefix of the counts, so triangle t’s tiles end before offsets[t]. |
raster.resolve@2 |
map | The surface: at each covered pixel, the depth its key holds and the winner’s attributes interpolated at the pixel’s center, perspective-correct. |
raster.tiles@2 |
map | How many tiles each triangle’s box is cut into: none for one of a tile or less, which raster.cover@3 covers whole. |
raster.total@1 |
map | How many tiles there are, which sizes the next node: the last offset. |
raster.unveiled@1 |
map | The sums to start from: nothing drawn, one for each pixel of surface (or of the node’s domain, for sums of another size). |
raster.veil@1 |
scatter into input 4 with sum | Every pixel’s sums of light and absorption over the translucent triangles in front of surface, added to light. |
raster.veiled@1 |
map | The sums read back: the light the translucent triangles add (rgb) and the share of the opaque surface left showing through them (a). A picture is the surface’s color times a, plus rgb. |
Methods
Section titled “Methods”Types and structs
Section titled “Types and structs”| Name | Syntax |
|---|---|
TilePlace |
struct TilePlace { t: Int; x0: Int; y0: Int; w: Int; h: Int; } |
Corner |
struct Corner { clip: Vec4; normal: Vec3; uv: Vec2; } |
Face |
struct Face { a: Int; b: Int; c: Int; } |
Corners |
struct Corners |
Surface |
struct Surface { depth: Float; normal: Vec3; uv: Vec2; id: Int; } |
Box |
struct Box { x0: Int; y0: Int; w: Int; h: Int; } |
Graph presets
Section titled “Graph presets”| Name | Interface | Description |
|---|---|---|
canvas |
input vertices: Rows<Corner>input triangles: Rows<Face>input canvas: Grid<Long>output surface <- resolved.result |
The raster preset over a canvas: as surface.esn, the surface the extent of canvas, an empty canvas (every key 9223372036854775807l, as surface.esn’s empty makes) another node sized, so a surface follows a size the scene computes. Place it with node raster: graph “../../packages/raster.entpkg/graphs/canvas.esn” { vertices <- project.result; triangles <- faces.result; canvas <- empty.result; } and read raster.surface where native.rasterize@3 gave surface. |
cutout |
input vertices: Rows<Corner>input triangles: Rows<Face>input mask: Imageparam cutout: Float = 0.5param width: Int = 320param height: Int = 240output surface <- resolved.result |
The raster preset with a cutout: as surface.esn, except that a fragment whose alpha in mask at its own uv is below cutout is not drawn, so what is behind it shows — leaves, fences, hair. Place it with node raster: graph “../../packages/raster.entpkg/graphs/cutout.esn” { vertices <- project.result; triangles <- faces.result; mask <- leaves; cutout = 0.5; } and read raster.surface where native.rasterize@2 gave surface. |
cutout_tiled |
input vertices: Rows<Corner>input triangles: Rows<Face>input mask: Imageparam cutout: Float = 0.5param width: Int = 320param height: Int = 240param tile: Int = 16param pool: Int = 4096output surface <- resolved.result |
The tiled form of cutout.esn: a triangle whose box is larger than a tile is covered a tile to an invocation, by a pool of pool invocations, so a mesh of few large triangles (a model close to the camera, a quad filling the screen) draws in parallel on a device. It costs a pass over every triangle, a prefix and a pass more, so a mesh of small triangles draws faster with cutout.esn. |
cutout_tiled_window |
input vertices: Rows<Corner>input triangles: Rows<Face>input mask: Imageparam cutout: Float = 0.5param tile: Int = 16param pool: Int = 4096output surface <- resolved.result |
The tiled form of cutout_window.esn: a triangle whose box is larger than a tile is covered a tile to an invocation, by a pool of pool invocations, so a mesh of few large triangles (a model close to the camera, a quad filling the screen) draws in parallel on a device. It costs a pass over every triangle, a prefix and a pass more, so a mesh of small triangles draws faster with cutout_window.esn. |
cutout_window |
input vertices: Rows<Corner>input triangles: Rows<Face>input mask: Imageparam cutout: Float = 0.5output surface <- resolved.result |
The cutout preset at the window’s size, as window.esn is the plain one’s: the surface follows the window when it is resized. |
surface |
input vertices: Rows<Corner>input triangles: Rows<Face>param width: Int = 320param height: Int = 240output surface <- resolved.result |
Vertex and triangle rows in, the surface out: for every pixel, the nearest triangle’s depth, normal and uv, perspective-correct, and its row as id. Place it with node raster: graph “../../packages/raster.entpkg/graphs/surface.esn” { vertices <- project.result; triangles <- faces.result; width = 320; height = 240; } and read raster.surface where native.rasterize@1 gave surface. |
tiled |
input vertices: Rows<Corner>input triangles: Rows<Face>param width: Int = 320param height: Int = 240param tile: Int = 16param pool: Int = 4096output surface <- resolved.result |
The tiled form of surface.esn: a triangle whose box is larger than a tile is covered a tile to an invocation, by a pool of pool invocations, so a mesh of few large triangles (a model close to the camera, a quad filling the screen) draws in parallel on a device. It costs a pass over every triangle, a prefix and a pass more, so a mesh of small triangles draws faster with surface.esn. |
tiled_window |
input vertices: Rows<Corner>input triangles: Rows<Face>param tile: Int = 16param pool: Int = 4096output surface <- resolved.result |
The tiled form of window.esn: a triangle whose box is larger than a tile is covered a tile to an invocation, by a pool of pool invocations, so a mesh of few large triangles (a model close to the camera, a quad filling the screen) draws in parallel on a device. It costs a pass over every triangle, a prefix and a pass more, so a mesh of small triangles draws faster with window.esn. |
veil |
input vertices: Rows<Corner>input triangles: Rows<Face>input tints: Rows<Vec4>input surface: Grid<Surface>param soft: Float = 0.0output light <- veiled.result |
Translucent triangles over an opaque surface (kernels/veil.ent): the light they add and the share of the surface left showing, in any order. Place it with node glow: graph “../../packages/raster.entpkg/graphs/veil.esn” { vertices <- sparks.result; triangles <- spark_faces.result; tints <- spark_tints.result; surface <- raster.surface; } and read glow.light: a picture is the surface’s color times its a, plus its rgb. |
window |
input vertices: Rows<Corner>input triangles: Rows<Face>output surface <- resolved.result |
The raster preset at the window’s size: the surface is the window’s extent in pixels, and follows it when it is resized, as a node of domain = window(); does. Place it with node raster: graph “../../packages/raster.entpkg/graphs/window.esn” { vertices <- project.result; triangles <- faces.result; } and read raster.surface. |
Kernel descriptions
Section titled “Kernel descriptions”raster.boxes@1
Section titled “raster.boxes@1”Each triangle’s box on the canvas, found once: none for one that is skipped. Every later step reads it.
| Mode | map |
| Requires | field.read, field.write |
| Inputs | triangles: Rows<Face>, vertices: Rows<Corner>, canvas: Grid<Long> |
| Params | — |
| Outputs | result: Rows<Box> |
| Source | packages/raster.entpkg/kernels/tile.ent |
raster.clip_faces@1
Section titled “raster.clip_faces@1”The two faces over each triangle’s four corners (domain = count(triangles) * 2).
| Mode | map |
| Requires | field.read, field.write |
| Inputs | triangles: Rows<Face> |
| Params | — |
| Outputs | result: Rows<Face> |
| Source | packages/raster.entpkg/kernels/clip.ent |
raster.clip_near@1
Section titled “raster.clip_near@1”Each triangle’s four corners after the cut (domain = count(triangles) * 4): the polygon in front of the near plane in the triangle’s winding, its first corner again past its last (a triangle’s fourth is its third); a triangle wholly behind keeps corners at w -1, which the rasterizer skips.
| Mode | map |
| Requires | field.read, field.write |
| Inputs | vertices: Rows<Corner>, triangles: Rows<Face> |
| Params | — |
| Outputs | result: Rows<Corner> |
| Source | packages/raster.entpkg/kernels/clip.ent |
raster.clip_plane@1
Section titled “raster.clip_plane@1”Each triangle’s four corners cut by a plane (domain = count(triangles) * 4), as raster.clip_near cuts at the near plane: what lies on the side of plane (its first row, in clip space: a corner is kept where dot(plane, clip) is not below 0) a world plane drawn through the lens has (light.entpkg’s surface.lens_clip_plane); a mirror’s pass keeps what stands over the water, not the bed under it.
| Mode | map |
| Requires | field.read, field.write |
| Inputs | vertices: Rows<Corner>, triangles: Rows<Face>, plane: Rows<Vec4> |
| Params | — |
| Outputs | result: Rows<Corner> |
| Source | packages/raster.entpkg/kernels/clip.ent |
raster.cover@3
Section titled “raster.cover@3”Every pixel’s nearest fragment as one key: each triangle walks its box and emits a key a pixel it covers. With a tile, only the triangles whose box is one tile or less; the larger ones are left to raster.cover_tiles@2, which takes these keys as its own start, so the least of both is kept.
| Mode | scatter into input 3 with min |
| Requires | field.read, field.write |
| Inputs | triangles: Rows<Face>, vertices: Rows<Corner>, boxes: Rows<Box>, keys: Grid<Long> |
| Params | tile: Int = 0 |
| Outputs | result: Grid<Long> |
| Source | packages/raster.entpkg/kernels/triangle.ent |
raster.cover@4
Section titled “raster.cover@4”Every pixel’s nearest fragment as one key, with no tiles: each triangle finds its own box and walks it, emitting a key a pixel it covers. No other step reads the box, so it is found here alone.
| Mode | scatter into input 2 with min |
| Requires | field.read, field.write |
| Inputs | triangles: Rows<Face>, vertices: Rows<Corner>, keys: Grid<Long> |
| Params | — |
| Outputs | result: Grid<Long> |
| Source | packages/raster.entpkg/kernels/triangle.ent |
raster.cover_cutout@3
Section titled “raster.cover_cutout@3”The same pair with a cutout: a fragment whose alpha in mask, read at its own uv as at_linear(mask, uv * size(mask)) reads it, is below cutout is not drawn — it emits no key, so it settles no depth and what is behind a leaf’s edge is seen through it.
| Mode | scatter into input 4 with min |
| Requires | field.read, field.write |
| Inputs | triangles: Rows<Face>, vertices: Rows<Corner>, boxes: Rows<Box>, mask: Image, keys: Grid<Long> |
| Params | cutout: Float = 0.5, tile: Int = 0 |
| Outputs | result: Grid<Long> |
raster.cover_cutout@4
Section titled “raster.cover_cutout@4”The same with a cutout and no tiles: each triangle finds its own box, as raster.cover@4 does.
| Mode | scatter into input 3 with min |
| Requires | field.read, field.write |
| Inputs | triangles: Rows<Face>, vertices: Rows<Corner>, mask: Image, keys: Grid<Long> |
| Params | cutout: Float = 0.5 |
| Outputs | result: Grid<Long> |
raster.cover_cutout_tiles@2
Section titled “raster.cover_cutout_tiles@2”| Mode | scatter into input 7 with min |
| Requires | field.read, field.write |
| Inputs | triangles: Rows<Face>, vertices: Rows<Corner>, boxes: Rows<Box>, counts: Rows<Int>, offsets: Rows<Int>, total: Rows<Int>, mask: Image, keys: Grid<Long> |
| Params | cutout: Float = 0.5, tile: Int = 16 |
| Outputs | result: Grid<Long> |
raster.cover_tiles@2
Section titled “raster.cover_tiles@2”Every pixel’s nearest fragment as one key, of the large triangles, a tile of one’s box at a time, so a triangle that fills the canvas is covered by as many invocations as it has tiles rather than by one. The node’s domain is a pool of invocations sized by the canvas, each taking every nth tile, so how many tiles there are this frame is read on the device and never waited for. It starts from the keys raster.cover@3 left, and keeps the least.
| Mode | scatter into input 6 with min |
| Requires | field.read, field.write |
| Inputs | triangles: Rows<Face>, vertices: Rows<Corner>, boxes: Rows<Box>, counts: Rows<Int>, offsets: Rows<Int>, total: Rows<Int>, keys: Grid<Long> |
| Params | tile: Int = 16 |
| Outputs | result: Grid<Long> |
| Source | packages/raster.entpkg/kernels/tile.ent |
raster.offsets@1
Section titled “raster.offsets@1”Where each triangle’s tiles begin: an inclusive prefix of the counts, so triangle t’s tiles end before offsets[t].
| Mode | prefix with sum |
| Requires | field.read, field.write |
| Inputs | counts: Rows<Int> |
| Params | — |
| Outputs | result: Rows<Int> |
| Source | packages/raster.entpkg/kernels/tile.ent |
raster.resolve@2
Section titled “raster.resolve@2”The surface: at each covered pixel, the depth its key holds and the winner’s attributes interpolated at the pixel’s center, perspective-correct.
| Mode | map |
| Requires | field.read, field.write |
| Inputs | keys: Grid<Long>, triangles: Rows<Face>, vertices: Rows<Corner> |
| Params | — |
| Outputs | result: Grid<Surface> |
| Source | packages/raster.entpkg/kernels/triangle.ent |
raster.tiles@2
Section titled “raster.tiles@2”How many tiles each triangle’s box is cut into: none for one of a tile or less, which raster.cover@3 covers whole.
| Mode | map |
| Requires | field.read, field.write |
| Inputs | boxes: Rows<Box> |
| Params | tile: Int = 16 |
| Outputs | result: Rows<Int> |
| Source | packages/raster.entpkg/kernels/tile.ent |
raster.total@1
Section titled “raster.total@1”How many tiles there are, which sizes the next node: the last offset.
| Mode | map |
| Requires | field.read, field.write |
| Inputs | offsets: Rows<Int> |
| Params | — |
| Outputs | result: Rows<Int> |
| Source | packages/raster.entpkg/kernels/tile.ent |
raster.unveiled@1
Section titled “raster.unveiled@1”The sums to start from: nothing drawn, one for each pixel of surface (or of the node’s domain, for sums of another size).
| Mode | map |
| Requires | field.read, field.write |
| Inputs | surface: Grid<Surface> |
| Params | — |
| Outputs | result: Grid<IVec4> |
| Source | packages/raster.entpkg/kernels/veil.ent |
raster.veil@1
Section titled “raster.veil@1”Every pixel’s sums of light and absorption over the translucent triangles in front of surface, added to light.
| Mode | scatter into input 4 with sum |
| Requires | field.read, field.write |
| Inputs | triangles: Rows<Face>, vertices: Rows<Corner>, tints: Rows<Vec4>, surface: Grid<Surface>, light: Grid<IVec4> |
| Params | soft: Float = 0.0 |
| Outputs | result: Grid<IVec4> |
| Source | packages/raster.entpkg/kernels/veil.ent |
raster.veiled@1
Section titled “raster.veiled@1”The sums read back: the light the translucent triangles add (rgb) and the share of the opaque surface left showing through them (a). A picture is the surface’s color times a, plus rgb.
| Mode | map |
| Requires | field.read, field.write |
| Inputs | sums: Grid<IVec4> |
| Params | — |
| Outputs | result: Image |
| Source | packages/raster.entpkg/kernels/veil.ent |
clip.replay, degenerate.replay, near.replay, tiles.replay, veil.replay

