raster

package
v0.25.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 23, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package raster provides CPU-based triangle rasterization for the software backend.

The raster package implements the core rendering pipeline using the Edge Function algorithm (Pineda, 1988). This approach is chosen for its simplicity, correctness, and potential for parallelization.

Algorithm Overview

Triangle rasterization uses three edge functions to determine if a pixel is inside a triangle. For each candidate pixel, we evaluate:

E01(x,y) = (y0-y1)*x + (x1-x0)*y + (x0*y1 - x1*y0)
E12(x,y) = (y1-y2)*x + (x2-x1)*y + (x1*y2 - x2*y1)
E20(x,y) = (y2-y0)*x + (x0-x2)*y + (x2*y0 - x0*y2)

A pixel is inside the triangle if all three edge functions are non-negative (for counter-clockwise winding).

Fill Rule

The rasterizer implements the top-left fill rule to avoid double-drawing pixels on shared triangle edges. An edge is "top" if horizontal and above the triangle, or "left" if going up.

Depth Testing

The depth buffer stores float32 values in the range [0, 1], where 0 is the near plane and 1 is the far plane. Depth testing compares interpolated fragment depth against the stored value using the configured compare function.

Usage

pipeline := raster.NewPipeline(800, 600)
pipeline.Clear(0.1, 0.1, 0.1, 1.0)
pipeline.ClearDepth(1.0)
pipeline.SetDepthTest(true, raster.CompareLess)
pipeline.DrawTriangles(triangles, [4]float32{1, 0, 0, 1}) // Red triangles
pixels := pipeline.GetColorBuffer() // RGBA8 data

Index

Constants

View Source
const DefaultGuardBandX = 2.0

DefaultGuardBandX is the default guard band multiplier for X coordinates. A value of 2.0 means the guard band extends to 2x the viewport width.

View Source
const DefaultGuardBandY = 2.0

DefaultGuardBandY is the default guard band multiplier for Y coordinates.

View Source
const TileSize = 8

TileSize is the size of each tile in pixels (8x8). This value balances work distribution with cache efficiency.

Variables

View Source
var (
	// BlendDisabled disables blending (source replaces destination).
	BlendDisabled = BlendState{Enabled: false}

	// BlendSourceOver implements standard alpha blending (Porter-Duff Source Over).
	// Formula: out = src * srcAlpha + dst * (1 - srcAlpha)
	BlendSourceOver = BlendState{
		Enabled:  true,
		SrcColor: BlendFactorSrcAlpha,
		DstColor: BlendFactorOneMinusSrcAlpha,
		ColorOp:  BlendOpAdd,
		SrcAlpha: BlendFactorOne,
		DstAlpha: BlendFactorOneMinusSrcAlpha,
		AlphaOp:  BlendOpAdd,
	}

	// BlendPremultiplied implements premultiplied alpha blending.
	// Assumes source color is already multiplied by alpha.
	// Formula: out = src + dst * (1 - srcAlpha)
	BlendPremultiplied = BlendState{
		Enabled:  true,
		SrcColor: BlendFactorOne,
		DstColor: BlendFactorOneMinusSrcAlpha,
		ColorOp:  BlendOpAdd,
		SrcAlpha: BlendFactorOne,
		DstAlpha: BlendFactorOneMinusSrcAlpha,
		AlphaOp:  BlendOpAdd,
	}

	// BlendAdditive implements additive blending.
	// Formula: out = src + dst
	BlendAdditive = BlendState{
		Enabled:  true,
		SrcColor: BlendFactorOne,
		DstColor: BlendFactorOne,
		ColorOp:  BlendOpAdd,
		SrcAlpha: BlendFactorOne,
		DstAlpha: BlendFactorOne,
		AlphaOp:  BlendOpAdd,
	}

	// BlendMultiply implements multiplicative blending.
	// Formula: out = src * dst
	BlendMultiply = BlendState{
		Enabled:  true,
		SrcColor: BlendFactorDst,
		DstColor: BlendFactorZero,
		ColorOp:  BlendOpAdd,
		SrcAlpha: BlendFactorDstAlpha,
		DstAlpha: BlendFactorZero,
		AlphaOp:  BlendOpAdd,
	}

	// BlendScreen implements screen blending.
	// Formula: out = 1 - (1 - src) * (1 - dst) = src + dst - src*dst
	BlendScreen = BlendState{
		Enabled:  true,
		SrcColor: BlendFactorOne,
		DstColor: BlendFactorOneMinusSrc,
		ColorOp:  BlendOpAdd,
		SrcAlpha: BlendFactorOne,
		DstAlpha: BlendFactorOneMinusSrcAlpha,
		AlphaOp:  BlendOpAdd,
	}
)

Common blend presets.

View Source
var (
	// ClipPlaneNear clips against z >= 0 (near plane).
	// Equation: z >= 0, so z + 0*w >= 0, meaning (0, 0, 1, 0).
	ClipPlaneNear = ClipPlane{0, 0, 1, 0}

	// ClipPlaneFar clips against z <= w (far plane).
	// Equation: z <= w, so -z + w >= 0, meaning (0, 0, -1, 1).
	ClipPlaneFar = ClipPlane{0, 0, -1, 1}

	// ClipPlaneLeft clips against x >= -w (left plane).
	// Equation: x >= -w, so x + w >= 0, meaning (1, 0, 0, 1).
	ClipPlaneLeft = ClipPlane{1, 0, 0, 1}

	// ClipPlaneRight clips against x <= w (right plane).
	// Equation: x <= w, so -x + w >= 0, meaning (-1, 0, 0, 1).
	ClipPlaneRight = ClipPlane{-1, 0, 0, 1}

	// ClipPlaneBottom clips against y >= -w (bottom plane).
	// Equation: y >= -w, so y + w >= 0, meaning (0, 1, 0, 1).
	ClipPlaneBottom = ClipPlane{0, 1, 0, 1}

	// ClipPlaneTop clips against y <= w (top plane).
	// Equation: y <= w, so -y + w >= 0, meaning (0, -1, 0, 1).
	ClipPlaneTop = ClipPlane{0, -1, 0, 1}
)

Standard frustum planes in clip space. After vertex shader, clip space coordinates satisfy: -w <= x <= w, -w <= y <= w, 0 <= z <= w (for depth [0,1] range)

AllFrustumPlanes contains all 6 frustum clipping planes.

View Source
var NearFarPlanes = []ClipPlane{
	ClipPlaneNear,
	ClipPlaneFar,
}

NearFarPlanes contains only near and far clipping planes.

Functions

func BinTrianglesToTiles

func BinTrianglesToTiles(triangles []Triangle, grid *TileGrid) map[int][]Triangle

BinTrianglesToTiles assigns each triangle to the tiles it overlaps. Returns a map from tile index to the list of triangles in that tile. A triangle may appear in multiple tiles if it spans tile boundaries.

func BinTrianglesToTilesWithTest

func BinTrianglesToTilesWithTest(triangles []Triangle, grid *TileGrid) map[int][]Triangle

BinTrianglesToTilesWithTest is like BinTrianglesToTiles but uses hierarchical tile-triangle testing to reject tiles that don't actually overlap the triangle.

func Blend

func Blend(src, dst [4]float32, state BlendState) [4]float32

Blend blends source color with destination color using the blend state. All colors are in float32 RGBA format with values in [0, 1]. Returns the blended color, clamped to [0, 1].

func BlendBytes

func BlendBytes(srcR, srcG, srcB, srcA, dstR, dstG, dstB, dstA byte, state BlendState) (r, g, b, a byte)

BlendBytes blends source color with destination color, working with byte values. This is a convenience function for working with RGBA8 framebuffers.

func BlendFloatToByte

func BlendFloatToByte(src [4]float32, dstR, dstG, dstB, dstA byte, state BlendState) (r, g, b, a byte)

BlendFloatToByte blends a float source color with a byte destination color. Source is in float [0,1], destination is in bytes [0,255]. Returns the result as bytes.

func ClipTriangle

func ClipTriangle(tri [3]ClipSpaceVertex) [][3]ClipSpaceVertex

ClipTriangle clips a triangle against all 6 frustum planes. Returns a list of clipped triangles (may be 0 to many).

func ClipTriangleAgainstPlane

func ClipTriangleAgainstPlane(tri [3]ClipSpaceVertex, plane ClipPlane) [][3]ClipSpaceVertex

ClipTriangleAgainstPlane clips a triangle against a single plane. Returns a slice of triangles (0, 1, or 2) after clipping.

Cases:

  • All 3 vertices inside: returns 1 triangle (original)
  • All 3 vertices outside: returns 0 triangles
  • 1 vertex inside: returns 1 triangle
  • 2 vertices inside: returns 2 triangles (quad split)

func ClipTriangleAgainstPlanes

func ClipTriangleAgainstPlanes(tri [3]ClipSpaceVertex, planes []ClipPlane) [][3]ClipSpaceVertex

ClipTriangleAgainstPlanes clips a triangle against the specified planes.

func ClipTriangleFast

func ClipTriangleFast(tri [3]ClipSpaceVertex) [][3]ClipSpaceVertex

ClipTriangleFast clips a triangle with optimized fast paths. Uses trivial accept/reject tests before full clipping.

func ClipTriangleNearFar

func ClipTriangleNearFar(tri [3]ClipSpaceVertex) [][3]ClipSpaceVertex

ClipTriangleNearFar clips a triangle against only the near and far planes. This is faster than full frustum clipping and is sufficient for many cases where triangles are known to be within the X/Y bounds.

func ComputeClipSpaceTriangleArea2D

func ComputeClipSpaceTriangleArea2D(tri [3]ClipSpaceVertex) float32

ComputeClipSpaceTriangleArea2D computes the signed 2D area of a triangle using only the x and y components of clip space coordinates. This is useful for quick degenerate triangle detection.

func ComputeClipSpaceTriangleAreaNDC

func ComputeClipSpaceTriangleAreaNDC(tri [3]ClipSpaceVertex) float32

ComputeClipSpaceTriangleAreaNDC computes the signed area in NDC space. This performs perspective divide first to get accurate area in normalized coordinates. Returns 0 if any vertex has w <= 0 (behind camera).

func ComputeScreenTriangleArea

func ComputeScreenTriangleArea(tri Triangle) float32

ComputeScreenTriangleArea computes the signed area of a triangle in screen space. Positive values indicate CCW winding, negative values indicate CW winding. The actual area is half this value (this returns 2*area for efficiency).

func ComputeTriangleArea

func ComputeTriangleArea(v0, v1, v2 ScreenVertex) float32

ComputeTriangleArea returns the signed area of a triangle. Positive for CCW winding, negative for CW winding in screen space.

func DegenerateTriangleCull

func DegenerateTriangleCull(tri [3]ClipSpaceVertex) bool

DegenerateTriangleCull returns true if the triangle has zero or near-zero area. Works in clip space before perspective divide.

func FrustumCull

func FrustumCull(tri [3]ClipSpaceVertex) bool

FrustumCull performs coarse frustum culling on a triangle in clip space. Returns true if the triangle is definitely outside the frustum and should be culled. This uses the bounding box of the triangle for a conservative test.

func GetFragmentSlice

func GetFragmentSlice() *[]Fragment

GetFragmentSlice obtains a fragment slice from the pool.

func GuardBandCull

func GuardBandCull(tri [3]ClipSpaceVertex, guardBandX, guardBandY float32) bool

GuardBandCull performs guard-band culling for triangles. The guard band extends beyond the viewport to allow larger triangles to pass without clipping, which can improve performance. Returns true if the triangle is completely outside the guard band.

func InterpolateAttributes

func InterpolateAttributes(
	attrs0, attrs1, attrs2 []float32,
	b0, b1, b2, w0, w1, w2 float32,
) []float32

InterpolateAttributes interpolates all attributes for a fragment with perspective correction. Returns nil if any input slice has different length than the others.

func InterpolateAttributesLinear

func InterpolateAttributesLinear(
	attrs0, attrs1, attrs2 []float32,
	b0, b1, b2 float32,
) []float32

InterpolateAttributesLinear interpolates all attributes without perspective correction. Returns nil if any input slice has different length than the others.

func InterpolateDepth

func InterpolateDepth(
	z0, z1, z2 float32,
	b0, b1, b2 float32,
	w0, w1, w2 float32,
) float32

InterpolateDepth interpolates depth with perspective correction. Depth is stored in Z, and W contains 1/w for perspective correction.

func InterpolateFloat32

func InterpolateFloat32(
	v0, v1, v2 float32,
	b0, b1, b2 float32,
	w0, w1, w2 float32,
) float32

InterpolateFloat32 interpolates a single float32 attribute with perspective correction. b0, b1, b2 are barycentric coordinates. w0, w1, w2 are 1/w values from vertices (for perspective correction).

The formula for perspective-correct interpolation:

result = (v0*b0*w0 + v1*b1*w1 + v2*b2*w2) / (b0*w0 + b1*w1 + b2*w2)

Where w0, w1, w2 store 1/w from clip space division.

func InterpolateFloat32Linear

func InterpolateFloat32Linear(
	v0, v1, v2 float32,
	b0, b1, b2 float32,
) float32

InterpolateFloat32Linear performs linear interpolation without perspective correction. This is faster but incorrect for perspective projections.

func InterpolateVec2

func InterpolateVec2(
	v0, v1, v2 [2]float32,
	b0, b1, b2, w0, w1, w2 float32,
) [2]float32

InterpolateVec2 interpolates a 2D vector (e.g., UV coordinates) with perspective correction.

func InterpolateVec2Linear

func InterpolateVec2Linear(
	v0, v1, v2 [2]float32,
	b0, b1, b2 float32,
) [2]float32

InterpolateVec2Linear performs linear interpolation of a 2D vector.

func InterpolateVec3

func InterpolateVec3(
	v0, v1, v2 [3]float32,
	b0, b1, b2, w0, w1, w2 float32,
) [3]float32

InterpolateVec3 interpolates a 3D vector (e.g., normals, RGB) with perspective correction.

func InterpolateVec3Linear

func InterpolateVec3Linear(
	v0, v1, v2 [3]float32,
	b0, b1, b2 float32,
) [3]float32

InterpolateVec3Linear performs linear interpolation of a 3D vector.

func InterpolateVec4

func InterpolateVec4(
	v0, v1, v2 [4]float32,
	b0, b1, b2, w0, w1, w2 float32,
) [4]float32

InterpolateVec4 interpolates a 4D vector (e.g., RGBA colors) with perspective correction.

func InterpolateVec4Linear

func InterpolateVec4Linear(
	v0, v1, v2 [4]float32,
	b0, b1, b2 float32,
) [4]float32

InterpolateVec4Linear performs linear interpolation of a 4D vector.

func IsBackFacing

func IsBackFacing(tri Triangle, frontFace FrontFace) bool

IsBackFacing returns true if the triangle is back-facing. This depends on the front face definition and the triangle's winding.

func IsBackFacingClipSpace

func IsBackFacingClipSpace(tri [3]ClipSpaceVertex, frontFace FrontFace) bool

IsBackFacingClipSpace returns true if the triangle is back-facing in clip space. Uses the NDC area to determine facing.

func IsCompletelyInside

func IsCompletelyInside(tri [3]ClipSpaceVertex) bool

IsCompletelyInside returns true if all vertices are inside all planes. This means no clipping is needed.

func IsCompletelyOutside

func IsCompletelyOutside(tri [3]ClipSpaceVertex) bool

IsCompletelyOutside returns true if all vertices are outside any single plane. This is a fast rejection test.

func PutFragmentSlice

func PutFragmentSlice(s *[]Fragment)

PutFragmentSlice returns a fragment slice to the pool.

func Rasterize

func Rasterize(tri Triangle, viewport Viewport, callback RasterCallback)

Rasterize generates fragments for all pixels inside the triangle. It uses the edge function algorithm with top-left fill rule. The callback is invoked for each fragment with interpolated attributes.

func RasterizeIncremental

func RasterizeIncremental(tri Triangle, viewport Viewport, callback RasterCallback)

RasterizeIncremental uses incremental edge evaluation for better performance. This is faster than the standard Rasterize function for larger triangles because it avoids per-pixel multiplication.

func RasterizeTile

func RasterizeTile(tri Triangle, tile Tile, callback RasterCallback)

RasterizeTile rasterizes a triangle within a specific tile. This is optimized for tile-based parallel rasterization where each tile is processed independently.

func ShouldCull

func ShouldCull(tri Triangle, cullMode CullMode, frontFace FrontFace) bool

ShouldCull returns true if the triangle should be culled.

func ShouldCullClipSpace

func ShouldCullClipSpace(tri [3]ClipSpaceVertex, cullMode CullMode, frontFace FrontFace) bool

ShouldCullClipSpace returns true if the triangle should be culled in clip space.

func SmallTriangleCull

func SmallTriangleCull(tri Triangle, minArea float32) bool

SmallTriangleCull returns true if the triangle is too small to render. This culls subpixel triangles that would produce no fragments. The triangle should be in screen space.

func TileTriangleTest

func TileTriangleTest(tile Tile, e01, e12, e20 EdgeFunction) int

TileTriangleTest tests if a tile potentially overlaps with a triangle. It uses the edge functions evaluated at tile corners for a hierarchical test.

Returns:

  • -1: tile is completely outside the triangle (reject)
  • 0: tile partially overlaps the triangle (needs per-pixel testing)
  • 1: tile is completely inside the triangle (can skip edge tests for all pixels)

func TriangleTrivialAccept

func TriangleTrivialAccept(tri [3]ClipSpaceVertex) bool

TriangleTrivialAccept returns true if the triangle can be trivially accepted. All vertices must be inside the frustum.

func TriangleTrivialReject

func TriangleTrivialReject(tri [3]ClipSpaceVertex) bool

TriangleTrivialReject returns true if the triangle can be trivially rejected. Uses Cohen-Sutherland style outcode testing for fast rejection.

Types

type BlendFactor

type BlendFactor uint8

BlendFactor specifies the blend factor for source or destination color. These match WebGPU blend factors.

const (
	// BlendFactorZero multiplies by 0.
	BlendFactorZero BlendFactor = iota

	// BlendFactorOne multiplies by 1.
	BlendFactorOne

	// BlendFactorSrc multiplies by source color.
	BlendFactorSrc

	// BlendFactorOneMinusSrc multiplies by (1 - source color).
	BlendFactorOneMinusSrc

	// BlendFactorSrcAlpha multiplies by source alpha.
	BlendFactorSrcAlpha

	// BlendFactorOneMinusSrcAlpha multiplies by (1 - source alpha).
	BlendFactorOneMinusSrcAlpha

	// BlendFactorDst multiplies by destination color.
	BlendFactorDst

	// BlendFactorOneMinusDst multiplies by (1 - destination color).
	BlendFactorOneMinusDst

	// BlendFactorDstAlpha multiplies by destination alpha.
	BlendFactorDstAlpha

	// BlendFactorOneMinusDstAlpha multiplies by (1 - destination alpha).
	BlendFactorOneMinusDstAlpha

	// BlendFactorSrcAlphaSaturated multiplies by min(srcAlpha, 1-dstAlpha).
	BlendFactorSrcAlphaSaturated

	// BlendFactorConstant multiplies by a constant color.
	BlendFactorConstant

	// BlendFactorOneMinusConstant multiplies by (1 - constant color).
	BlendFactorOneMinusConstant
)

type BlendOperation

type BlendOperation uint8

BlendOperation specifies how to combine source and destination after applying factors.

const (
	// BlendOpAdd computes src + dst.
	BlendOpAdd BlendOperation = iota

	// BlendOpSubtract computes src - dst.
	BlendOpSubtract

	// BlendOpReverseSubtract computes dst - src.
	BlendOpReverseSubtract

	// BlendOpMin computes min(src, dst).
	BlendOpMin

	// BlendOpMax computes max(src, dst).
	BlendOpMax
)

type BlendState

type BlendState struct {
	// Enabled indicates whether blending is active.
	Enabled bool

	// SrcColor is the blend factor for the source color (RGB).
	SrcColor BlendFactor

	// DstColor is the blend factor for the destination color (RGB).
	DstColor BlendFactor

	// ColorOp is the operation to combine source and destination colors.
	ColorOp BlendOperation

	// SrcAlpha is the blend factor for the source alpha.
	SrcAlpha BlendFactor

	// DstAlpha is the blend factor for the destination alpha.
	DstAlpha BlendFactor

	// AlphaOp is the operation to combine source and destination alphas.
	AlphaOp BlendOperation

	// Constant is the constant color used for BlendFactorConstant.
	Constant [4]float32
}

BlendState configures color blending for a render target.

type ClipPlane

type ClipPlane struct {
	A, B, C, D float32
}

ClipPlane represents a clipping plane in homogeneous clip space. The plane equation is: A*x + B*y + C*z + D*w = 0 Points with A*x + B*y + C*z + D*w >= 0 are considered inside.

func (ClipPlane) Distance

func (p ClipPlane) Distance(v ClipSpaceVertex) float32

Distance returns the signed distance from a vertex to the plane. Positive values indicate the vertex is inside (on the positive side). Negative values indicate the vertex is outside. Zero indicates the vertex is exactly on the plane.

func (ClipPlane) Intersect

func (p ClipPlane) Intersect(v0, v1 ClipSpaceVertex) (ClipSpaceVertex, float32)

Intersect computes the intersection point between an edge and the plane. The edge goes from v0 to v1. Returns the interpolated vertex at the intersection and the parameter t in [0, 1] where intersection occurs. Assumes the edge actually crosses the plane (one vertex inside, one outside).

func (ClipPlane) IsInside

func (p ClipPlane) IsInside(v ClipSpaceVertex) bool

IsInside returns true if the vertex is inside or on the plane.

type ClipSpaceVertex

type ClipSpaceVertex struct {
	// Position in clip space. After perspective divide:
	// x/w, y/w are in [-1, 1] (NDC), z/w is depth [0, 1].
	Position [4]float32

	// Attributes are values to be interpolated across the triangle.
	// Common uses: color (RGBA), texture coordinates (UV), normals, etc.
	Attributes []float32
}

ClipSpaceVertex is the output of vertex shader processing. Position is in homogeneous clip space coordinates (x, y, z, w).

type CompareFunc

type CompareFunc uint8

CompareFunc specifies the comparison function for depth/stencil testing.

const (
	// CompareNever always fails the test.
	CompareNever CompareFunc = iota

	// CompareLess passes if source < destination.
	CompareLess

	// CompareEqual passes if source == destination.
	CompareEqual

	// CompareLessEqual passes if source <= destination.
	CompareLessEqual

	// CompareGreater passes if source > destination.
	CompareGreater

	// CompareNotEqual passes if source != destination.
	CompareNotEqual

	// CompareGreaterEqual passes if source >= destination.
	CompareGreaterEqual

	// CompareAlways always passes the test.
	CompareAlways
)

type CullMode

type CullMode uint8

CullMode specifies which triangle faces to cull.

const (
	// CullNone disables face culling.
	CullNone CullMode = iota

	// CullFront culls front-facing triangles.
	CullFront

	// CullBack culls back-facing triangles.
	CullBack
)

type DepthBuffer

type DepthBuffer struct {
	// contains filtered or unexported fields
}

DepthBuffer stores depth values for the software rasterizer. Depth values are float32 in the range [0, 1] where 0 is near and 1 is far. The buffer is thread-safe for concurrent access.

func NewDepthBuffer

func NewDepthBuffer(width, height int) *DepthBuffer

NewDepthBuffer creates a new depth buffer with the given dimensions. All values are initialized to 1.0 (far plane).

func (*DepthBuffer) Clear

func (d *DepthBuffer) Clear(value float32)

Clear fills the entire depth buffer with the given value. Typically called with 1.0 to reset to the far plane.

func (*DepthBuffer) Get

func (d *DepthBuffer) Get(x, y int) float32

Get returns the depth value at pixel (x, y). Returns 1.0 if coordinates are out of bounds.

func (*DepthBuffer) GetData

func (d *DepthBuffer) GetData() []float32

GetData returns a copy of the raw depth buffer data. The data is in row-major order (y * width + x).

func (*DepthBuffer) Height

func (d *DepthBuffer) Height() int

Height returns the height of the depth buffer.

func (*DepthBuffer) Set

func (d *DepthBuffer) Set(x, y int, depth float32)

Set writes a depth value at pixel (x, y). Out-of-bounds coordinates are silently ignored.

func (*DepthBuffer) Test

func (d *DepthBuffer) Test(x, y int, depth float32, compare CompareFunc) bool

Test performs a depth test at pixel (x, y). Returns true if the test passes (fragment should be drawn). This does NOT modify the depth buffer.

func (*DepthBuffer) TestAndSet

func (d *DepthBuffer) TestAndSet(x, y int, depth float32, compare CompareFunc, write bool) bool

TestAndSet performs a depth test and updates the buffer if the test passes. Returns true if the test passed and the buffer was updated. This is an atomic test-and-write operation.

func (*DepthBuffer) Width

func (d *DepthBuffer) Width() int

Width returns the width of the depth buffer.

type EdgeFunction

type EdgeFunction struct {
	// A is the coefficient for x (equals y0 - y1).
	A float32

	// B is the coefficient for y (equals x1 - x0).
	B float32

	// C is the constant term (equals x0*y1 - x1*y0).
	C float32
}

EdgeFunction represents a linear edge equation: Ax + By + C = 0. Points on the left side of the edge (inside for CCW triangles) yield positive values.

func NewEdgeFunction

func NewEdgeFunction(x0, y0, x1, y1 float32) EdgeFunction

NewEdgeFunction creates an edge function from two vertices. The edge goes from (x0, y0) to (x1, y1). Points on the left side of this directed edge will have positive values.

func (EdgeFunction) Evaluate

func (e EdgeFunction) Evaluate(x, y float32) float32

Evaluate returns the signed distance from point (x, y) to the edge. Positive values indicate the point is on the inside (left) of the edge. Zero indicates the point is exactly on the edge. Negative values indicate the point is on the outside (right) of the edge.

func (EdgeFunction) IsTopLeft

func (e EdgeFunction) IsTopLeft() bool

IsTopLeft returns true if this edge is a "top" or "left" edge. Used for the top-left fill rule to avoid double-drawing shared edges.

In screen coordinates (Y increases downward): - Left edge: edge going upward (A > 0), meaning Y decreases along the edge - Top edge: horizontal edge going leftward (A == 0 && B < 0)

Note: B < 0 means the edge goes from right to left (x decreases along edge).

type Fragment

type Fragment struct {
	// X is the integer horizontal pixel coordinate.
	X int

	// Y is the integer vertical pixel coordinate.
	Y int

	// Depth is the interpolated depth value in [0, 1].
	Depth float32

	// Bary holds barycentric coordinates [w0, w1, w2].
	// These sum to 1.0 and indicate the fragment's position within the triangle.
	Bary [3]float32

	// Attributes are perspective-correct interpolated values.
	Attributes []float32
}

Fragment is a candidate pixel generated during rasterization.

type FrontFace

type FrontFace uint8

FrontFace specifies the winding order for front-facing triangles.

const (
	// FrontFaceCCW treats counter-clockwise winding as front-facing.
	FrontFaceCCW FrontFace = iota

	// FrontFaceCW treats clockwise winding as front-facing.
	FrontFaceCW
)

type IncrementalEdge

type IncrementalEdge struct {
	// A is the coefficient for x (equals y0 - y1).
	// Used for stepping in the X direction.
	A float32

	// B is the coefficient for y (equals x1 - x0).
	// Used for stepping in the Y direction.
	B float32

	// C is the constant term (equals x0*y1 - x1*y0).
	C float32
	// contains filtered or unexported fields
}

IncrementalEdge optimizes edge function evaluation by using incremental stepping instead of per-pixel computation.

The edge function E(x, y) = A*x + B*y + C can be evaluated incrementally:

  • E(x+1, y) = E(x, y) + A (step right)
  • E(x, y+1) = E(x, y) + B (step down)

This reduces per-pixel work from 2 multiplications + 2 additions to just 1 addition per pixel.

func NewIncrementalEdge

func NewIncrementalEdge(e EdgeFunction) IncrementalEdge

NewIncrementalEdge creates an incremental edge from an EdgeFunction.

func NewIncrementalEdgeFromPoints

func NewIncrementalEdgeFromPoints(x0, y0, x1, y1 float32) IncrementalEdge

NewIncrementalEdgeFromPoints creates an incremental edge from two vertices.

func (*IncrementalEdge) IsTopLeft

func (ie *IncrementalEdge) IsTopLeft() bool

IsTopLeft returns true if this edge is a "top" or "left" edge. Same logic as EdgeFunction.IsTopLeft().

func (*IncrementalEdge) NextRow

func (ie *IncrementalEdge) NextRow()

NextRow advances to the next scanline. This moves to (startX, y+1) where startX was the x passed to SetRow.

func (*IncrementalEdge) SetRow

func (ie *IncrementalEdge) SetRow(x, y float32)

SetRow initializes the edge for a new scanline starting at (x, y). Call this at the beginning of each row.

func (*IncrementalEdge) StepX

func (ie *IncrementalEdge) StepX()

StepX advances to the next pixel in the row (x+1). Call this after processing each pixel to move right.

func (*IncrementalEdge) Value

func (ie *IncrementalEdge) Value() float32

Value returns the current edge function value.

type IncrementalTriangle

type IncrementalTriangle struct {
	// E01 is the edge from V0 to V1 (opposite to V2).
	E01 IncrementalEdge

	// E12 is the edge from V1 to V2 (opposite to V0).
	E12 IncrementalEdge

	// E20 is the edge from V2 to V0 (opposite to V1).
	E20 IncrementalEdge

	// InvArea is 1 / (2 * triangle area), used for barycentric normalization.
	InvArea float32
	// contains filtered or unexported fields
}

IncrementalTriangle manages three incremental edges for a triangle. It provides efficient per-pixel testing and barycentric coordinate computation.

func NewIncrementalTriangle

func NewIncrementalTriangle(tri Triangle) IncrementalTriangle

NewIncrementalTriangle creates an incremental triangle from screen-space vertices.

func (*IncrementalTriangle) Area

func (it *IncrementalTriangle) Area() float32

Area returns the signed area of the triangle. Positive for CCW, negative for CW.

func (*IncrementalTriangle) Barycentric

func (it *IncrementalTriangle) Barycentric() (b0, b1, b2 float32)

Barycentric returns the current barycentric coordinates. The coordinates (b0, b1, b2) sum to 1.0 and represent weights for vertices V0, V1, V2 respectively.

func (*IncrementalTriangle) EdgeValues

func (it *IncrementalTriangle) EdgeValues() (w0, w1, w2 float32)

EdgeValues returns the current edge function values (w0, w1, w2). These are not normalized barycentric coordinates.

func (*IncrementalTriangle) IsDegenerate

func (it *IncrementalTriangle) IsDegenerate() bool

IsDegenerate returns true if the triangle has zero area.

func (*IncrementalTriangle) IsInside

func (it *IncrementalTriangle) IsInside() bool

IsInside returns true if the current point is inside the triangle. This applies the top-left fill rule.

func (*IncrementalTriangle) NextRow

func (it *IncrementalTriangle) NextRow()

NextRow advances all edges to the next scanline.

func (*IncrementalTriangle) SetRow

func (it *IncrementalTriangle) SetRow(x, y float32)

SetRow initializes all edges for a scanline starting at (x, y).

func (*IncrementalTriangle) StepX

func (it *IncrementalTriangle) StepX()

StepX advances all edges to the next pixel in the row.

type Outcode

type Outcode uint8

OutcodeVertex computes the outcode for a vertex. Each bit indicates which plane the vertex is outside of. 0 means the vertex is inside all planes.

const (
	// OutcodeNear indicates the vertex is outside the near plane.
	OutcodeNear Outcode = 1 << iota
	// OutcodeFar indicates the vertex is outside the far plane.
	OutcodeFar
	// OutcodeLeft indicates the vertex is outside the left plane.
	OutcodeLeft
	// OutcodeRight indicates the vertex is outside the right plane.
	OutcodeRight
	// OutcodeBottom indicates the vertex is outside the bottom plane.
	OutcodeBottom
	// OutcodeTop indicates the vertex is outside the top plane.
	OutcodeTop
)

func ComputeOutcode

func ComputeOutcode(v ClipSpaceVertex) Outcode

ComputeOutcode computes the outcode for a clip space vertex.

type ParallelConfig

type ParallelConfig struct {
	// Workers is the number of worker goroutines.
	// If 0, defaults to runtime.NumCPU().
	Workers int

	// TileSize is the tile size for work distribution.
	// If 0, uses the default TileSize constant.
	TileSize int

	// MinTriangles is the minimum number of triangles to parallelize.
	// Below this threshold, single-threaded execution is used to avoid overhead.
	// If 0, defaults to 10.
	MinTriangles int
}

ParallelConfig configures parallel rasterization.

func DefaultParallelConfig

func DefaultParallelConfig() ParallelConfig

DefaultParallelConfig returns sensible defaults for parallel rasterization.

type ParallelRasterizer

type ParallelRasterizer struct {
	// contains filtered or unexported fields
}

ParallelRasterizer handles parallel rasterization of triangles. It divides the framebuffer into tiles and distributes work across workers.

func NewParallelRasterizer

func NewParallelRasterizer(width, height int, config ParallelConfig) *ParallelRasterizer

NewParallelRasterizer creates a new parallel rasterizer for the given dimensions.

func (*ParallelRasterizer) Close

func (r *ParallelRasterizer) Close()

Close shuts down the parallel rasterizer and releases resources.

func (*ParallelRasterizer) Config

func (r *ParallelRasterizer) Config() ParallelConfig

Config returns the current parallel configuration.

func (*ParallelRasterizer) Grid

func (r *ParallelRasterizer) Grid() *TileGrid

Grid returns the tile grid.

func (*ParallelRasterizer) ParallelForEachTile

func (r *ParallelRasterizer) ParallelForEachTile(fn func(tile Tile))

ParallelForEachTile executes a function for each tile in parallel. This is useful for operations that need to process all tiles.

func (*ParallelRasterizer) RasterizeParallel

func (r *ParallelRasterizer) RasterizeParallel(
	triangles []Triangle,
	callback func(tile Tile, triangles []Triangle),
)

RasterizeParallel rasterizes triangles in parallel by tile. The callback is invoked for each tile with its assigned triangles. Each tile is processed by exactly one goroutine, so no synchronization is needed for tile-local writes.

func (*ParallelRasterizer) Resize

func (r *ParallelRasterizer) Resize(width, height int)

Resize updates the tile grid for new dimensions.

type Pipeline

type Pipeline struct {
	// contains filtered or unexported fields
}

Pipeline is a basic software rendering pipeline. It manages the color buffer, depth buffer, and rendering state.

func NewPipeline

func NewPipeline(width, height int) *Pipeline

NewPipeline creates a new rendering pipeline with the given dimensions. The color buffer is initialized to black, and depth buffer to 1.0 (far).

func (*Pipeline) Clear

func (p *Pipeline) Clear(r, g, b, a float32)

Clear fills the color buffer with the specified RGBA values. Color components are in the range [0, 1].

func (*Pipeline) ClearDepth

func (p *Pipeline) ClearDepth(value float32)

ClearDepth fills the depth buffer with the specified value. Typically use 1.0 (far plane) to reset the depth buffer.

func (*Pipeline) ClearStencil

func (p *Pipeline) ClearStencil(value uint8)

ClearStencil fills the stencil buffer with the specified value.

func (*Pipeline) Close

func (p *Pipeline) Close()

Close releases resources used by the pipeline. This should be called when the pipeline is no longer needed.

func (*Pipeline) DrawTriangles

func (p *Pipeline) DrawTriangles(triangles []Triangle, color [4]float32)

DrawTriangles rasterizes the given triangles with a solid color. Color is in RGBA format with values in [0, 1].

func (*Pipeline) DrawTrianglesInterpolated

func (p *Pipeline) DrawTrianglesInterpolated(triangles []Triangle)

DrawTrianglesInterpolated rasterizes triangles using interpolated vertex colors. Each vertex should have 4 attributes (RGBA).

func (*Pipeline) DrawTrianglesParallel

func (p *Pipeline) DrawTrianglesParallel(triangles []Triangle, color [4]float32)

DrawTrianglesParallel uses tile-based parallel rasterization. This can significantly speed up rendering for large numbers of triangles by distributing work across multiple CPU cores.

Note: Parallel rendering requires EnableParallel(true) to be called first. If parallel is not enabled, this falls back to DrawTriangles.

func (*Pipeline) EnableParallel

func (p *Pipeline) EnableParallel(enabled bool)

EnableParallel enables or disables parallel rasterization. When enabled, triangles are rasterized using tile-based parallelization.

func (*Pipeline) GetBlendState

func (p *Pipeline) GetBlendState() BlendState

GetBlendState returns the current blend state.

func (*Pipeline) GetColorBuffer

func (p *Pipeline) GetColorBuffer() []byte

GetColorBuffer returns a copy of the RGBA8 color buffer. The data is in row-major order with 4 bytes per pixel (RGBA).

func (*Pipeline) GetDepthBuffer

func (p *Pipeline) GetDepthBuffer() *DepthBuffer

GetDepthBuffer returns the depth buffer.

func (*Pipeline) GetParallelConfig

func (p *Pipeline) GetParallelConfig() ParallelConfig

GetParallelConfig returns the current parallel configuration.

func (*Pipeline) GetPixel

func (p *Pipeline) GetPixel(x, y int) (r, g, b, a byte)

GetPixel returns the RGBA color at the specified pixel. Returns (0, 0, 0, 0) for out-of-bounds coordinates.

func (*Pipeline) GetScissor

func (p *Pipeline) GetScissor() *Rect

GetScissor returns the current scissor rectangle. Returns nil if scissor testing is disabled.

func (*Pipeline) GetStencilBuffer

func (p *Pipeline) GetStencilBuffer() *StencilBuffer

GetStencilBuffer returns the current stencil buffer.

func (*Pipeline) GetStencilState

func (p *Pipeline) GetStencilState() StencilState

GetStencilState returns the current stencil state.

func (*Pipeline) GetViewport

func (p *Pipeline) GetViewport() Viewport

GetViewport returns the current viewport.

func (*Pipeline) Height

func (p *Pipeline) Height() int

Height returns the framebuffer height.

func (*Pipeline) IsClippingEnabled

func (p *Pipeline) IsClippingEnabled() bool

IsClippingEnabled returns whether frustum clipping is enabled.

func (*Pipeline) IsParallelEnabled

func (p *Pipeline) IsParallelEnabled() bool

IsParallelEnabled returns whether parallel rasterization is enabled.

func (*Pipeline) Resize

func (p *Pipeline) Resize(width, height int)

Resize changes the dimensions of both buffers. This clears all existing data.

func (*Pipeline) SetBlendState

func (p *Pipeline) SetBlendState(state BlendState)

SetBlendState sets the blending configuration.

func (*Pipeline) SetClipping

func (p *Pipeline) SetClipping(enabled bool)

SetClipping enables or disables frustum clipping. When enabled, triangles are clipped against the view frustum before rasterization.

func (*Pipeline) SetCullMode

func (p *Pipeline) SetCullMode(mode CullMode)

SetCullMode sets the face culling mode.

func (*Pipeline) SetDepthTest

func (p *Pipeline) SetDepthTest(enabled bool, compare CompareFunc)

SetDepthTest enables or disables depth testing and sets the compare function.

func (*Pipeline) SetDepthWrite

func (p *Pipeline) SetDepthWrite(enabled bool)

SetDepthWrite enables or disables writing to the depth buffer.

func (*Pipeline) SetFrontFace

func (p *Pipeline) SetFrontFace(face FrontFace)

SetFrontFace sets which winding order is considered front-facing.

func (*Pipeline) SetParallelConfig

func (p *Pipeline) SetParallelConfig(config ParallelConfig)

SetParallelConfig sets the parallel rasterization configuration. If enabled, the pipeline will use tile-based parallel rasterization.

func (*Pipeline) SetPixel

func (p *Pipeline) SetPixel(x, y int, r, g, b, a byte)

SetPixel sets the RGBA color at the specified pixel. Out-of-bounds coordinates are silently ignored.

func (*Pipeline) SetScissor

func (p *Pipeline) SetScissor(rect *Rect)

SetScissor sets the scissor rectangle for clipping fragments. Pass nil to disable the scissor test.

func (*Pipeline) SetStencilBuffer

func (p *Pipeline) SetStencilBuffer(buf *StencilBuffer)

SetStencilBuffer sets the stencil buffer to use for stencil testing. Pass nil to disable stencil testing.

func (*Pipeline) SetStencilState

func (p *Pipeline) SetStencilState(state StencilState)

SetStencilState sets the stencil testing configuration.

func (*Pipeline) SetViewport

func (p *Pipeline) SetViewport(v Viewport)

SetViewport sets the rendering viewport.

func (*Pipeline) Width

func (p *Pipeline) Width() int

Width returns the framebuffer width.

type RasterCallback

type RasterCallback func(frag Fragment)

RasterCallback is called for each fragment generated during rasterization.

type Rect

type Rect struct {
	// X is the left edge of the rectangle in pixels.
	X int

	// Y is the top edge of the rectangle in pixels.
	Y int

	// Width of the rectangle in pixels.
	Width int

	// Height of the rectangle in pixels.
	Height int
}

Rect defines a rectangular region in screen space.

type ScreenVertex

type ScreenVertex struct {
	// X is the horizontal screen coordinate in pixels.
	X float32

	// Y is the vertical screen coordinate in pixels.
	Y float32

	// Z is the depth value in range [0, 1], where 0 is near and 1 is far.
	Z float32

	// W stores 1/w from the original clip space vertex.
	// Used for perspective-correct interpolation.
	W float32

	// Attributes are values to be interpolated.
	// These are pre-divided by the original W for perspective correction.
	Attributes []float32
}

ScreenVertex is a vertex after perspective divide and viewport transform. Coordinates are in screen space (pixels).

type StencilBuffer

type StencilBuffer struct {
	// contains filtered or unexported fields
}

StencilBuffer stores stencil values for the software rasterizer. Stencil values are uint8 in the range [0, 255]. The buffer is thread-safe for concurrent access.

func NewStencilBuffer

func NewStencilBuffer(width, height int) *StencilBuffer

NewStencilBuffer creates a new stencil buffer with the given dimensions. All values are initialized to 0.

func (*StencilBuffer) Apply

func (s *StencilBuffer) Apply(x, y int, op StencilOp, state StencilState)

Apply applies a stencil operation to the buffer at pixel (x, y). This modifies the stencil buffer based on the operation.

func (*StencilBuffer) Clear

func (s *StencilBuffer) Clear(value uint8)

Clear fills the entire stencil buffer with the given value.

func (*StencilBuffer) Get

func (s *StencilBuffer) Get(x, y int) uint8

Get returns the stencil value at pixel (x, y). Returns 0 if coordinates are out of bounds.

func (*StencilBuffer) GetData

func (s *StencilBuffer) GetData() []uint8

GetData returns a copy of the raw stencil buffer data. The data is in row-major order (y * width + x).

func (*StencilBuffer) Height

func (s *StencilBuffer) Height() int

Height returns the height of the stencil buffer.

func (*StencilBuffer) Resize

func (s *StencilBuffer) Resize(width, height int)

Resize resizes the stencil buffer and clears all contents.

func (*StencilBuffer) Set

func (s *StencilBuffer) Set(x, y int, value uint8)

Set writes a stencil value at pixel (x, y). Out-of-bounds coordinates are silently ignored.

func (*StencilBuffer) Test

func (s *StencilBuffer) Test(x, y int, state StencilState) bool

Test performs a stencil test at pixel (x, y). Returns true if the test passes (fragment should proceed to depth test). This does NOT modify the stencil buffer.

func (*StencilBuffer) TestAndApply

func (s *StencilBuffer) TestAndApply(x, y int, depthPassed bool, state StencilState) bool

TestAndApply performs the stencil test and applies the appropriate operation. Returns true if the stencil test passed.

Operations applied based on test results:

  • Stencil test fails: FailOp
  • Stencil passes, depth fails: DepthFailOp
  • Both pass: PassOp

func (*StencilBuffer) Width

func (s *StencilBuffer) Width() int

Width returns the width of the stencil buffer.

type StencilOp

type StencilOp uint8

StencilOp specifies the operation to perform on the stencil buffer.

const (
	// StencilOpKeep keeps the current stencil value.
	StencilOpKeep StencilOp = iota

	// StencilOpZero sets the stencil value to zero.
	StencilOpZero

	// StencilOpReplace sets the stencil value to the reference value.
	StencilOpReplace

	// StencilOpIncrementClamp increments the stencil value, clamping to max (255).
	StencilOpIncrementClamp

	// StencilOpDecrementClamp decrements the stencil value, clamping to 0.
	StencilOpDecrementClamp

	// StencilOpInvert bitwise inverts the stencil value.
	StencilOpInvert

	// StencilOpIncrementWrap increments the stencil value, wrapping to 0 on overflow.
	StencilOpIncrementWrap

	// StencilOpDecrementWrap decrements the stencil value, wrapping to 255 on underflow.
	StencilOpDecrementWrap
)

type StencilState

type StencilState struct {
	// Enabled indicates whether stencil testing is active.
	Enabled bool

	// ReadMask is AND-ed with the stencil value before comparison.
	ReadMask uint8

	// WriteMask is AND-ed with the value before writing to the buffer.
	WriteMask uint8

	// Compare is the comparison function for the stencil test.
	Compare CompareFunc

	// FailOp is applied when the stencil test fails.
	FailOp StencilOp

	// DepthFailOp is applied when stencil passes but depth test fails.
	DepthFailOp StencilOp

	// PassOp is applied when both stencil and depth tests pass.
	PassOp StencilOp

	// Reference is the reference value for stencil comparison and StencilOpReplace.
	Reference uint8
}

StencilState configures stencil testing for a render pass.

func DefaultStencilState

func DefaultStencilState() StencilState

DefaultStencilState returns a default stencil state with testing disabled.

type Tile

type Tile struct {
	// X is the tile coordinate (not pixel coordinate).
	X int

	// Y is the tile coordinate (not pixel coordinate).
	Y int

	// MinX is the left pixel boundary (inclusive).
	MinX int

	// MinY is the top pixel boundary (inclusive).
	MinY int

	// MaxX is the right pixel boundary (exclusive).
	MaxX int

	// MaxY is the bottom pixel boundary (exclusive).
	MaxY int
}

Tile represents a rectangular region of the framebuffer. Tiles are used for work distribution in parallel rasterization.

func (Tile) Corners

func (t Tile) Corners() TileCorners

Corners returns the four corner pixels of the tile. Corner coordinates are at pixel centers (x+0.5, y+0.5).

func (Tile) Height

func (t Tile) Height() int

Height returns the height of the tile in pixels.

func (Tile) Width

func (t Tile) Width() int

Width returns the width of the tile in pixels.

type TileCorners

type TileCorners struct {
	// TL is the top-left corner (MinX, MinY).
	TL [2]float32

	// TR is the top-right corner (MaxX-1, MinY).
	TR [2]float32

	// BL is the bottom-left corner (MinX, MaxY-1).
	BL [2]float32

	// BR is the bottom-right corner (MaxX-1, MaxY-1).
	BR [2]float32
}

TileCorners holds the four corner pixel coordinates of a tile. Used for hierarchical tile-triangle overlap testing.

type TileGrid

type TileGrid struct {
	// contains filtered or unexported fields
}

TileGrid manages tiles for the framebuffer. It divides the framebuffer into a grid of tiles for parallel processing.

func NewTileGrid

func NewTileGrid(width, height int) *TileGrid

NewTileGrid creates a new tile grid for the given framebuffer dimensions. The grid is divided into TileSize x TileSize tiles.

func (*TileGrid) GetAllTiles

func (g *TileGrid) GetAllTiles() []Tile

GetAllTiles returns all tiles in the grid. The tiles are ordered row by row (Y-major order).

func (*TileGrid) GetTile

func (g *TileGrid) GetTile(tx, ty int) Tile

GetTile returns the tile at grid coordinates (tx, ty). Returns an empty tile if coordinates are out of bounds.

func (*TileGrid) GetTileAt

func (g *TileGrid) GetTileAt(px, py int) (tx, ty int)

GetTileAt returns the tile grid coordinates containing pixel (px, py).

func (*TileGrid) GetTilesForRect

func (g *TileGrid) GetTilesForRect(minX, minY, maxX, maxY int) []Tile

GetTilesForRect returns all tiles that overlap with the given pixel rectangle. The rectangle is defined by [minX, maxX) x [minY, maxY).

func (*TileGrid) GetTilesForTriangle

func (g *TileGrid) GetTilesForTriangle(tri Triangle) []Tile

GetTilesForTriangle returns tiles overlapping a screen-space triangle. It computes the bounding box of the triangle and returns all tiles in that region.

func (*TileGrid) TileCount

func (g *TileGrid) TileCount() int

TileCount returns the total number of tiles in the grid.

func (*TileGrid) TileIndex

func (g *TileGrid) TileIndex(tx, ty int) int

TileIndex returns the linear index of a tile in the grid.

func (*TileGrid) TilesX

func (g *TileGrid) TilesX() int

TilesX returns the number of tiles in the horizontal direction.

func (*TileGrid) TilesY

func (g *TileGrid) TilesY() int

TilesY returns the number of tiles in the vertical direction.

type Triangle

type Triangle struct {
	V0 ScreenVertex
	V1 ScreenVertex
	V2 ScreenVertex
}

Triangle represents three screen-space vertices forming a triangle.

func CreateScreenTriangle

func CreateScreenTriangle(x0, y0, z0, x1, y1, z1, x2, y2, z2 float32) Triangle

CreateScreenTriangle creates a Triangle from screen coordinates. This is a helper for testing - positions should already be in screen space.

func CreateScreenTriangleWithColor

func CreateScreenTriangleWithColor(
	x0, y0, z0 float32, c0 [4]float32,
	x1, y1, z1 float32, c1 [4]float32,
	x2, y2, z2 float32, c2 [4]float32,
) Triangle

CreateScreenTriangleWithColor creates a Triangle with vertex colors. Colors are in RGBA format with values in [0, 1].

type Viewport

type Viewport struct {
	// X is the left edge of the viewport in pixels.
	X int

	// Y is the top edge of the viewport in pixels.
	Y int

	// Width of the viewport in pixels.
	Width int

	// Height of the viewport in pixels.
	Height int

	// MinDepth is the near depth value (typically 0.0).
	MinDepth float32

	// MaxDepth is the far depth value (typically 1.0).
	MaxDepth float32
}

Viewport defines the rectangular area of the framebuffer to render into.

type WorkerPool

type WorkerPool struct {
	// contains filtered or unexported fields
}

WorkerPool manages a pool of worker goroutines for parallel execution. Tasks are submitted via channels and executed concurrently.

func NewWorkerPool

func NewWorkerPool(workers int) *WorkerPool

NewWorkerPool creates a new worker pool with the specified number of workers. If workers <= 0, it defaults to runtime.NumCPU().

func (*WorkerPool) Close

func (p *WorkerPool) Close()

Close shuts down the worker pool. It signals all workers to stop and waits for pending tasks.

func (*WorkerPool) Start

func (p *WorkerPool) Start()

Start launches the worker goroutines. It is safe to call Start multiple times; subsequent calls are no-ops.

func (*WorkerPool) Submit

func (p *WorkerPool) Submit(task func())

Submit adds a task to the worker pool. The task will be executed by one of the workers. This method blocks if the task queue is full.

func (*WorkerPool) Wait

func (p *WorkerPool) Wait()

Wait blocks until all submitted tasks have completed.

func (*WorkerPool) Workers

func (p *WorkerPool) Workers() int

Workers returns the number of workers in the pool.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL