Skip to content

Rasterize

rasterize

Tile-binned triangle rasterizer with exact fixed-point coverage, plus interpolation.

rasterize_triangles

rasterize_triangles(vertices: array, faces: array, width: int, height: int, depth_prior: array | None = ..., occlusion_truncation: float = ..., cull: Literal['none', 'back', 'front'] = ..., return_depth: Literal[False] = ..., _tile_size: int | None = ...) -> tuple[array, array]
rasterize_triangles(vertices: array, faces: array, width: int, height: int, depth_prior: array | None = ..., occlusion_truncation: float = ..., cull: Literal['none', 'back', 'front'] = ..., *, return_depth: Literal[True], _tile_size: int | None = ...) -> tuple[array, array, array]
rasterize_triangles(vertices: array, faces: array, width: int, height: int, depth_prior: array | None = None, occlusion_truncation: float = 1e-06, cull: Literal['none', 'back', 'front'] = 'none', return_depth: bool = False, _tile_size: int | None = None) -> tuple[array, array] | tuple[array, array, array]

Rasterize projected triangles with depth-aware z-buffering.

Parameters:

Name Type Description Default
vertices array

(N, 4) float32, clip-space homogeneous (x, y, z, w).

required
faces array

(F, 3) int32, triangle vertex indices.

required
width int

Image width in pixels, at most 16384.

required
height int

Image height in pixels, at most 16384.

required
depth_prior array | None

Optional (H, W) float32 depth map for occlusion culling, expected in NDC z (pre-mapping): it is mapped internally the same way vertex z is mapped for rasterization. The depth returned by return_depth=True is already post-mapping, so feeding a previously returned depth map straight back in as a prior double-maps it and culls the wrong geometry — convert it back to NDC first.

None
occlusion_truncation float

Depth threshold for occlusion.

1e-06
cull Literal['none', 'back', 'front']

Discard faces by orientation. "none" keeps everything, which is the default and matches earlier releases. A face is front-facing when its vertices wind counter-clockwise in NDC (equivalently, in the returned image's coordinate system, since to_screen maps both axes monotonically increasing and does not flip the winding) — the OpenGL convention. "back" discards clockwise faces and keeps counter-clockwise ones; "front" does the reverse.

'none'
return_depth bool

Also return the winning face's interpolated depth.

False
_tile_size int | None

Force the binning tile size. Private test hook — results are invariant to it.

None

Returns:

Name Type Description
face_indices tuple[array, array] | tuple[array, array, array]

(H, W) int32 — 1-indexed face ID per pixel (0 = background).

barycentric tuple[array, array] | tuple[array, array, array]

(H, W, 3) float32 — perspective-correct barycentrics.

depth tuple[array, array] | tuple[array, array, array]

(H, W) float32, only when return_depth — +inf on background pixels.

Raises:

Type Description
ValueError

on an unknown cull mode, an out-of-range vertex index, an image larger than 16384px per axis, or projected vertex coordinates outside the representable range (most likely geometry crossing or approaching the near plane).

MemoryError

if the mesh needs more (tile, face) pairs than the budget allows even at the coarsest tiling.

interpolate

interpolate

interpolate(attributes: array, face_indices: array, barycentric: array, faces: array) -> array

Interpolate per-vertex attributes at rasterized pixels.

Parameters:

Name Type Description Default
attributes array

(N, C) float32 per-vertex data (normals, UVs, colors, ...).

required
face_indices array

(H, W) int32 from rasterize_triangles (1-indexed, 0=background).

required
barycentric array

(H, W, 3) float32 from rasterize_triangles.

required
faces array

(F, 3) int32 triangle vertex indices.

required

Returns:

Type Description
array

(H, W, C) float32 interpolated attributes per pixel.

rasterize

Metal triangle rasterizer with z-buffering for Apple Silicon.

Tile-binned: faces are bucketed into screen tiles so each tile tests only the faces that can touch it, instead of every thread scanning every face. Coverage uses exact int64 edge functions over 1/16-pixel fixed-point coordinates and the top-left fill rule, so adjacent triangles cannot both claim a shared edge, nor leave a crack between them.

Note that this function synchronizes: the number of (tile, face) pairs has to reach the host to size the pair buffer, so it cannot stay lazy in an MLX graph.

rasterize_triangles

rasterize_triangles(vertices: array, faces: array, width: int, height: int, depth_prior: array | None = ..., occlusion_truncation: float = ..., cull: Literal['none', 'back', 'front'] = ..., return_depth: Literal[False] = ..., _tile_size: int | None = ...) -> tuple[array, array]
rasterize_triangles(vertices: array, faces: array, width: int, height: int, depth_prior: array | None = ..., occlusion_truncation: float = ..., cull: Literal['none', 'back', 'front'] = ..., *, return_depth: Literal[True], _tile_size: int | None = ...) -> tuple[array, array, array]
rasterize_triangles(vertices: array, faces: array, width: int, height: int, depth_prior: array | None = None, occlusion_truncation: float = 1e-06, cull: Literal['none', 'back', 'front'] = 'none', return_depth: bool = False, _tile_size: int | None = None) -> tuple[array, array] | tuple[array, array, array]

Rasterize projected triangles with depth-aware z-buffering.

Parameters:

Name Type Description Default
vertices array

(N, 4) float32, clip-space homogeneous (x, y, z, w).

required
faces array

(F, 3) int32, triangle vertex indices.

required
width int

Image width in pixels, at most 16384.

required
height int

Image height in pixels, at most 16384.

required
depth_prior array | None

Optional (H, W) float32 depth map for occlusion culling, expected in NDC z (pre-mapping): it is mapped internally the same way vertex z is mapped for rasterization. The depth returned by return_depth=True is already post-mapping, so feeding a previously returned depth map straight back in as a prior double-maps it and culls the wrong geometry — convert it back to NDC first.

None
occlusion_truncation float

Depth threshold for occlusion.

1e-06
cull Literal['none', 'back', 'front']

Discard faces by orientation. "none" keeps everything, which is the default and matches earlier releases. A face is front-facing when its vertices wind counter-clockwise in NDC (equivalently, in the returned image's coordinate system, since to_screen maps both axes monotonically increasing and does not flip the winding) — the OpenGL convention. "back" discards clockwise faces and keeps counter-clockwise ones; "front" does the reverse.

'none'
return_depth bool

Also return the winning face's interpolated depth.

False
_tile_size int | None

Force the binning tile size. Private test hook — results are invariant to it.

None

Returns:

Name Type Description
face_indices tuple[array, array] | tuple[array, array, array]

(H, W) int32 — 1-indexed face ID per pixel (0 = background).

barycentric tuple[array, array] | tuple[array, array, array]

(H, W, 3) float32 — perspective-correct barycentrics.

depth tuple[array, array] | tuple[array, array, array]

(H, W) float32, only when return_depth — +inf on background pixels.

Raises:

Type Description
ValueError

on an unknown cull mode, an out-of-range vertex index, an image larger than 16384px per axis, or projected vertex coordinates outside the representable range (most likely geometry crossing or approaching the near plane).

MemoryError

if the mesh needs more (tile, face) pairs than the budget allows even at the coarsest tiling.