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
- Variables
- func BinTrianglesToTiles(triangles []Triangle, grid *TileGrid) map[int][]Triangle
- func BinTrianglesToTilesWithTest(triangles []Triangle, grid *TileGrid) map[int][]Triangle
- func Blend(src, dst [4]float32, state BlendState) [4]float32
- func BlendBytes(srcR, srcG, srcB, srcA, dstR, dstG, dstB, dstA byte, state BlendState) (r, g, b, a byte)
- func BlendFloatToByte(src [4]float32, dstR, dstG, dstB, dstA byte, state BlendState) (r, g, b, a byte)
- func ClipTriangle(tri [3]ClipSpaceVertex) [][3]ClipSpaceVertex
- func ClipTriangleAgainstPlane(tri [3]ClipSpaceVertex, plane ClipPlane) [][3]ClipSpaceVertex
- func ClipTriangleAgainstPlanes(tri [3]ClipSpaceVertex, planes []ClipPlane) [][3]ClipSpaceVertex
- func ClipTriangleFast(tri [3]ClipSpaceVertex) [][3]ClipSpaceVertex
- func ClipTriangleNearFar(tri [3]ClipSpaceVertex) [][3]ClipSpaceVertex
- func ComputeClipSpaceTriangleArea2D(tri [3]ClipSpaceVertex) float32
- func ComputeClipSpaceTriangleAreaNDC(tri [3]ClipSpaceVertex) float32
- func ComputeScreenTriangleArea(tri Triangle) float32
- func ComputeTriangleArea(v0, v1, v2 ScreenVertex) float32
- func DegenerateTriangleCull(tri [3]ClipSpaceVertex) bool
- func FrustumCull(tri [3]ClipSpaceVertex) bool
- func GetFragmentSlice() *[]Fragment
- func GuardBandCull(tri [3]ClipSpaceVertex, guardBandX, guardBandY float32) bool
- func InterpolateAttributes(attrs0, attrs1, attrs2 []float32, b0, b1, b2, w0, w1, w2 float32) []float32
- func InterpolateAttributesLinear(attrs0, attrs1, attrs2 []float32, b0, b1, b2 float32) []float32
- func InterpolateDepth(z0, z1, z2 float32, b0, b1, b2 float32, w0, w1, w2 float32) float32
- func InterpolateFloat32(v0, v1, v2 float32, b0, b1, b2 float32, w0, w1, w2 float32) float32
- func InterpolateFloat32Linear(v0, v1, v2 float32, b0, b1, b2 float32) float32
- func InterpolateVec2(v0, v1, v2 [2]float32, b0, b1, b2, w0, w1, w2 float32) [2]float32
- func InterpolateVec2Linear(v0, v1, v2 [2]float32, b0, b1, b2 float32) [2]float32
- func InterpolateVec3(v0, v1, v2 [3]float32, b0, b1, b2, w0, w1, w2 float32) [3]float32
- func InterpolateVec3Linear(v0, v1, v2 [3]float32, b0, b1, b2 float32) [3]float32
- func InterpolateVec4(v0, v1, v2 [4]float32, b0, b1, b2, w0, w1, w2 float32) [4]float32
- func InterpolateVec4Linear(v0, v1, v2 [4]float32, b0, b1, b2 float32) [4]float32
- func IsBackFacing(tri Triangle, frontFace FrontFace) bool
- func IsBackFacingClipSpace(tri [3]ClipSpaceVertex, frontFace FrontFace) bool
- func IsCompletelyInside(tri [3]ClipSpaceVertex) bool
- func IsCompletelyOutside(tri [3]ClipSpaceVertex) bool
- func PutFragmentSlice(s *[]Fragment)
- func Rasterize(tri Triangle, viewport Viewport, callback RasterCallback)
- func RasterizeIncremental(tri Triangle, viewport Viewport, callback RasterCallback)
- func RasterizeTile(tri Triangle, tile Tile, callback RasterCallback)
- func ShouldCull(tri Triangle, cullMode CullMode, frontFace FrontFace) bool
- func ShouldCullClipSpace(tri [3]ClipSpaceVertex, cullMode CullMode, frontFace FrontFace) bool
- func SmallTriangleCull(tri Triangle, minArea float32) bool
- func TileTriangleTest(tile Tile, e01, e12, e20 EdgeFunction) int
- func TriangleTrivialAccept(tri [3]ClipSpaceVertex) bool
- func TriangleTrivialReject(tri [3]ClipSpaceVertex) bool
- type BlendFactor
- type BlendOperation
- type BlendState
- type ClipPlane
- type ClipSpaceVertex
- type CompareFunc
- type CullMode
- type DepthBuffer
- func (d *DepthBuffer) Clear(value float32)
- func (d *DepthBuffer) Get(x, y int) float32
- func (d *DepthBuffer) GetData() []float32
- func (d *DepthBuffer) Height() int
- func (d *DepthBuffer) Set(x, y int, depth float32)
- func (d *DepthBuffer) Test(x, y int, depth float32, compare CompareFunc) bool
- func (d *DepthBuffer) TestAndSet(x, y int, depth float32, compare CompareFunc, write bool) bool
- func (d *DepthBuffer) Width() int
- type EdgeFunction
- type Fragment
- type FrontFace
- type IncrementalEdge
- type IncrementalTriangle
- func (it *IncrementalTriangle) Area() float32
- func (it *IncrementalTriangle) Barycentric() (b0, b1, b2 float32)
- func (it *IncrementalTriangle) EdgeValues() (w0, w1, w2 float32)
- func (it *IncrementalTriangle) IsDegenerate() bool
- func (it *IncrementalTriangle) IsInside() bool
- func (it *IncrementalTriangle) NextRow()
- func (it *IncrementalTriangle) SetRow(x, y float32)
- func (it *IncrementalTriangle) StepX()
- type Outcode
- type ParallelConfig
- type ParallelRasterizer
- func (r *ParallelRasterizer) Close()
- func (r *ParallelRasterizer) Config() ParallelConfig
- func (r *ParallelRasterizer) Grid() *TileGrid
- func (r *ParallelRasterizer) ParallelForEachTile(fn func(tile Tile))
- func (r *ParallelRasterizer) RasterizeParallel(triangles []Triangle, callback func(tile Tile, triangles []Triangle))
- func (r *ParallelRasterizer) Resize(width, height int)
- type Pipeline
- func (p *Pipeline) Clear(r, g, b, a float32)
- func (p *Pipeline) ClearDepth(value float32)
- func (p *Pipeline) ClearStencil(value uint8)
- func (p *Pipeline) Close()
- func (p *Pipeline) DrawTriangles(triangles []Triangle, color [4]float32)
- func (p *Pipeline) DrawTrianglesInterpolated(triangles []Triangle)
- func (p *Pipeline) DrawTrianglesParallel(triangles []Triangle, color [4]float32)
- func (p *Pipeline) EnableParallel(enabled bool)
- func (p *Pipeline) GetBlendState() BlendState
- func (p *Pipeline) GetColorBuffer() []byte
- func (p *Pipeline) GetDepthBuffer() *DepthBuffer
- func (p *Pipeline) GetParallelConfig() ParallelConfig
- func (p *Pipeline) GetPixel(x, y int) (r, g, b, a byte)
- func (p *Pipeline) GetScissor() *Rect
- func (p *Pipeline) GetStencilBuffer() *StencilBuffer
- func (p *Pipeline) GetStencilState() StencilState
- func (p *Pipeline) GetViewport() Viewport
- func (p *Pipeline) Height() int
- func (p *Pipeline) IsClippingEnabled() bool
- func (p *Pipeline) IsParallelEnabled() bool
- func (p *Pipeline) Resize(width, height int)
- func (p *Pipeline) SetBlendState(state BlendState)
- func (p *Pipeline) SetClipping(enabled bool)
- func (p *Pipeline) SetCullMode(mode CullMode)
- func (p *Pipeline) SetDepthTest(enabled bool, compare CompareFunc)
- func (p *Pipeline) SetDepthWrite(enabled bool)
- func (p *Pipeline) SetFrontFace(face FrontFace)
- func (p *Pipeline) SetParallelConfig(config ParallelConfig)
- func (p *Pipeline) SetPixel(x, y int, r, g, b, a byte)
- func (p *Pipeline) SetScissor(rect *Rect)
- func (p *Pipeline) SetStencilBuffer(buf *StencilBuffer)
- func (p *Pipeline) SetStencilState(state StencilState)
- func (p *Pipeline) SetViewport(v Viewport)
- func (p *Pipeline) Width() int
- type RasterCallback
- type Rect
- type ScreenVertex
- type StencilBuffer
- func (s *StencilBuffer) Apply(x, y int, op StencilOp, state StencilState)
- func (s *StencilBuffer) Clear(value uint8)
- func (s *StencilBuffer) Get(x, y int) uint8
- func (s *StencilBuffer) GetData() []uint8
- func (s *StencilBuffer) Height() int
- func (s *StencilBuffer) Resize(width, height int)
- func (s *StencilBuffer) Set(x, y int, value uint8)
- func (s *StencilBuffer) Test(x, y int, state StencilState) bool
- func (s *StencilBuffer) TestAndApply(x, y int, depthPassed bool, state StencilState) bool
- func (s *StencilBuffer) Width() int
- type StencilOp
- type StencilState
- type Tile
- type TileCorners
- type TileGrid
- func (g *TileGrid) GetAllTiles() []Tile
- func (g *TileGrid) GetTile(tx, ty int) Tile
- func (g *TileGrid) GetTileAt(px, py int) (tx, ty int)
- func (g *TileGrid) GetTilesForRect(minX, minY, maxX, maxY int) []Tile
- func (g *TileGrid) GetTilesForTriangle(tri Triangle) []Tile
- func (g *TileGrid) TileCount() int
- func (g *TileGrid) TileIndex(tx, ty int) int
- func (g *TileGrid) TilesX() int
- func (g *TileGrid) TilesY() int
- type Triangle
- type Viewport
- type WorkerPool
Constants ¶
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.
const DefaultGuardBandY = 2.0
DefaultGuardBandY is the default guard band multiplier for Y coordinates.
const TileSize = 8
TileSize is the size of each tile in pixels (8x8). This value balances work distribution with cache efficiency.
Variables ¶
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.
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)
var AllFrustumPlanes = []ClipPlane{ ClipPlaneNear, ClipPlaneFar, ClipPlaneLeft, ClipPlaneRight, ClipPlaneBottom, ClipPlaneTop, }
AllFrustumPlanes contains all 6 frustum clipping planes.
var NearFarPlanes = []ClipPlane{ ClipPlaneNear, ClipPlaneFar, }
NearFarPlanes contains only near and far clipping planes.
Functions ¶
func BinTrianglesToTiles ¶
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 ¶
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 ¶
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 ¶
InterpolateAttributesLinear interpolates all attributes without perspective correction. Returns nil if any input slice has different length than the others.
func InterpolateDepth ¶
InterpolateDepth interpolates depth with perspective correction. Depth is stored in Z, and W contains 1/w for perspective correction.
func InterpolateFloat32 ¶
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 ¶
InterpolateFloat32Linear performs linear interpolation without perspective correction. This is faster but incorrect for perspective projections.
func InterpolateVec2 ¶
InterpolateVec2 interpolates a 2D vector (e.g., UV coordinates) with perspective correction.
func InterpolateVec2Linear ¶
InterpolateVec2Linear performs linear interpolation of a 2D vector.
func InterpolateVec3 ¶
InterpolateVec3 interpolates a 3D vector (e.g., normals, RGB) with perspective correction.
func InterpolateVec3Linear ¶
InterpolateVec3Linear performs linear interpolation of a 3D vector.
func InterpolateVec4 ¶
InterpolateVec4 interpolates a 4D vector (e.g., RGBA colors) with perspective correction.
func InterpolateVec4Linear ¶
InterpolateVec4Linear performs linear interpolation of a 4D vector.
func IsBackFacing ¶
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 ¶
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 ¶
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 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.
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 ¶
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 ¶
Clear fills the color buffer with the specified RGBA values. Color components are in the range [0, 1].
func (*Pipeline) ClearDepth ¶
ClearDepth fills the depth buffer with the specified value. Typically use 1.0 (far plane) to reset the depth buffer.
func (*Pipeline) ClearStencil ¶
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 ¶
DrawTriangles rasterizes the given triangles with a solid color. Color is in RGBA format with values in [0, 1].
func (*Pipeline) DrawTrianglesInterpolated ¶
DrawTrianglesInterpolated rasterizes triangles using interpolated vertex colors. Each vertex should have 4 attributes (RGBA).
func (*Pipeline) DrawTrianglesParallel ¶
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 ¶
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 ¶
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 ¶
GetPixel returns the RGBA color at the specified pixel. Returns (0, 0, 0, 0) for out-of-bounds coordinates.
func (*Pipeline) GetScissor ¶
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 ¶
GetViewport returns the current viewport.
func (*Pipeline) IsClippingEnabled ¶
IsClippingEnabled returns whether frustum clipping is enabled.
func (*Pipeline) IsParallelEnabled ¶
IsParallelEnabled returns whether parallel rasterization is enabled.
func (*Pipeline) Resize ¶
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 ¶
SetClipping enables or disables frustum clipping. When enabled, triangles are clipped against the view frustum before rasterization.
func (*Pipeline) SetCullMode ¶
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 ¶
SetDepthWrite enables or disables writing to the depth buffer.
func (*Pipeline) SetFrontFace ¶
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 ¶
SetPixel sets the RGBA color at the specified pixel. Out-of-bounds coordinates are silently ignored.
func (*Pipeline) SetScissor ¶
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 ¶
SetViewport sets the rendering viewport.
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).
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 ¶
NewTileGrid creates a new tile grid for the given framebuffer dimensions. The grid is divided into TileSize x TileSize tiles.
func (*TileGrid) GetAllTiles ¶
GetAllTiles returns all tiles in the grid. The tiles are ordered row by row (Y-major order).
func (*TileGrid) GetTile ¶
GetTile returns the tile at grid coordinates (tx, ty). Returns an empty tile if coordinates are out of bounds.
func (*TileGrid) GetTilesForRect ¶
GetTilesForRect returns all tiles that overlap with the given pixel rectangle. The rectangle is defined by [minX, maxX) x [minY, maxY).
func (*TileGrid) GetTilesForTriangle ¶
GetTilesForTriangle returns tiles overlapping a screen-space triangle. It computes the bounding box of the triangle and returns all tiles in that region.
type Triangle ¶
type Triangle struct {
V0 ScreenVertex
V1 ScreenVertex
V2 ScreenVertex
}
Triangle represents three screen-space vertices forming a triangle.
func CreateScreenTriangle ¶
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.