gsdf

package module
v0.0.0-...-b0fcba2 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: BSD-3-Clause Imports: 14 Imported by: 0

README

gsdf

go.dev reference Go Report Card codecov Go sourcegraph

gsdf is a CAD 3D design library for Go that uses SDFs for shape definition. Rendering can be done on GPU or CPU for visualization or 3D printing file outputs. Quick jump to usage: bolt example.

All images and shapes in readme were generated using this library.

bolt-example circle text

Requirements

  • Go
  • Optional: See latest requirements on go-glfw if using GPU

Features

  • High test coverage (when GPU available, not the case in CI)

  • NEW!: Reusable GLSL code between shaders. See glbuild/glsllib

  • Extremely coherent API design.

  • UI for visualizing parts, rendered directly from shaders. See UI example by running go run ./examples/ui-mandala

  • Generate visualization for your parts as shaders.

  • GPU and CPU implementations for all shapes and operations. CPU implementations are actually faster for simple parts.

  • Include arbitrary buffers into GPU calculation. See Shader interface.

  • Heapless algorithms for everything. No usage of GC in happy path.

  • Heapless Octree triangle renderer. Is stupid fast.

    • Design your part using one API, switch between CPU and GPU after design.
  • TinyGo supported for CPU evaluation :)

Package layout/structure

  • gsdf: Top level package defines exact SDFs primitives and operations for use on CPU or GPU workloads. Consumes glbuild interfaces and logic to build shaders.
  • glbuild: Automatic shader generation interfaces and logic.
  • gleval: SDF evaluation interfaces and facilities, both CPU and GPU bound.
  • glrender: Triangle rendering logic which consumes gleval. STL generation.
  • forge: Engineering applications. Composed of subpackages.
    • textsdf package for text generation.
    • threads package for generating screw threads.
  • gsdfaux: High level helper functions to get users started up with gsdf. See examples.

Examples

Find examples under examples directory. Run on GPU with: -gpu flag.

Most 3D examples output two files:

  • example-name.glsl: Visualization shader that can be copy pasted into shadertoy to visualize the part, or rendered within your editor with an extension such as the Shader Toy Visual Studio Code extension.
  • example-name.stl: Triangle model file used in 3D printing software such as Cura. Can be visualized online in sites such as View STL.

CPU output and timings on 12th Gen Intel i5-12400F (12) @ 4.400GHz. GPU timings on AMD ATI Radeon RX 6800 (may be outdated).

simplesdf Python-like API

The simplesdf package provides a extremely simplified API for use by makers who want a more Python-like API. This is particularily useful for short one-off scripts. Note this API uses panics to help track down errors and also is not thread-safe. See examples/simple-knurled-cylinder.

package main

import (
	"math"
	"runtime"

	. "github.com/soypat/gsdf/gsdfaux/simplesdf"
)

func init() { runtime.LockOSThread() } // Required if using GPU to render shapes or using UI.

func main() {
	// main body
	f := Cylinder(1, 5, 0.1)

	// knurling
	x := Box(1, 1, 4, 0).RotateZ(math.Pi / 4)
	x = x.Translate(1.6, 0, 0)              // radial placement (fogleman circular_array offset)
	x = x.CircArray(24, 24)                 // 24 instances evenly around the circle
	x = x.Twist(0.75).Union(x.Twist(-0.75)) // diamond pattern via mirrored twist
	f = f.Diff(x.K(0.1))

	// central hole
	f = f.Diff(Cylinder(0.5, 7, 0).K(0.1))

	// vent holes
	c := Cylinder(0.25, 3, 0).RotateY(math.Pi / 2) // orient along X
	f = f.Diff(c.Translate(0, 0, -2.5).K(0.1))
	f = f.Diff(c.Translate(0, 0, 2.5).K(0.1))

	f.Save("knurling.stl", STLConfig{ResolutionDivisions: 200})
}

npt-flange

This was converted from the original sdf library example.

GPU rendering in 1.1 seconds. 0.4M triangles
 time go run ./examples/npt-flange -resdiv 400 -gpu
[-] using GPU   ᵍᵒᵗᵗᵃ ᵍᵒ ᶠᵃˢᵗ
[53.54ms] init GL with compute invocation size  1024
[7.73ms] GPU shader generated and compiled
[61.3ms] instantiating evaluation SDF took
[109.4µs] wrote nptflange.glsl
[706ms] evaluated SDF 46148745 times and rendered 423852 triangles with 95.7 percent evaluations omitted in octree pruning step with resolution 0.21679485
[371ms] wrote nptflange.stl
[1.14s] render done
finished npt-flange example
go run ./examples/npt-flange -resdiv 400 -gpu  0,75s user 0,49s system 102% cpu 1,219 total
CPU rendering in 0.7 seconds. 0.4M triangles
time go run ./examples/npt-flange -resdiv 400
[-] using CPU
[29.7µs] instantiating evaluation SDF took
[-] CPU parallel evaluation on 11 goroutines
[101.6µs] wrote nptflange.glsl
[313ms] evaluated SDF 6711686 times and rendered 423852 triangles with resolution 0.21679485
[341ms] wrote nptflange.stl
[654ms] render done
finished npt-flange example
go run ./examples/npt-flange -resdiv 400  2,78s user 0,38s system 422% cpu 0,747 total

npt-flange-example

fibonacci-showerhead

Note that the amount of triangles is very similar to the NPT flange example, but this part is more computationally complex.

GPU rendering in 0.7 seconds. 0.3M triangles
time go run ./examples/fibonacci-showerhead -resdiv 350 -gpu
[-] using GPU   ᵍᵒᵗᵗᵃ ᵍᵒ ᶠᵃˢᵗ
[47.1ms] init GL with compute invocation size  1024
[62.9ms] GPU shader generated and compiled
[110ms] instantiating evaluation SDF took
[539.3µs] wrote showerhead.glsl
[337ms] evaluated SDF 14646431 times and rendered 309872 triangles with 89.08 percent evaluations omitted in octree pruning step with resolution 0.2979682
[252ms] wrote showerhead.stl
[701ms] render done
showerhead example done
go run ./examples/fibonacci-showerhead -resdiv 350 -gpu  0,60s user 0,36s system 118% cpu 0,814 total
CPU rendering in 1.3 seconds. 0.3M triangles
time go run ./examples/fibonacci-showerhead -resdiv 350
[-] using CPU
[34µs] instantiating evaluation SDF took
[-] CPU parallel evaluation on 11 goroutines
[326.4µs] wrote showerhead.glsl
[909ms] evaluated SDF 1512025 times and rendered 309872 triangles with resolution 0.2979682
[255ms] wrote showerhead.stl
[1.16s] render done
showerhead example done
go run ./examples/fibonacci-showerhead -resdiv 350  8,00s user 0,29s system 663% cpu 1,248 total

fibonacci-showerhead

More examples

iso-screw array-triangles geb-book-cover

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Builder

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

Builder wraps all SDF primitive and operation logic generation. Provides error handling strategies with panics or error accumulation during shape generation.

func (*Builder) Annulus

func (bld *Builder) Annulus(s glbuild.Shader2D, sub float32) glbuild.Shader2D

Annulus makes a 2D shape annular by emptying it's center. It is the equivalent of the 3D Shell operation but in 2D.

func (*Builder) Array

func (bld *Builder) Array(s glbuild.Shader3D, spacingX, spacingY, spacingZ float32, nx, ny, nz int) glbuild.Shader3D

Array is the domain repetition operation. It repeats domain centered around the origin (x,y,z)=(0,0,0).

func (*Builder) Array2D

func (bld *Builder) Array2D(s glbuild.Shader2D, spacingX, spacingY float32, nx, ny int) glbuild.Shader2D

Array is the domain repetition operation. It repeats domain centered around (x,y)=(0,0).

func (*Builder) Bend

func (bld *Builder) Bend(s glbuild.Shader3D, R float32) glbuild.Shader3D

Bend applies a constant-curvature bend: the child's +x axis curls toward +y for positive R (toward -y for negative R) onto a circle of radius |R| centered on the line (0, R, z). Distance to the center line and the z coordinate are preserved; the child's own x extent bends entirely (partial bends are boolean compositions).

The warp is the INVERSE of that image map — itself a polar transform about the same center (radius r = |p - center|, angle φ = atan2): the probe maps to child (|R|·φ, |R| - r), with rigid (isometric) tails beyond the child's x extent — the elongate clamp pattern — so the domain never folds or wraps. The inverse's Jacobian has singular values exactly (|R|/ρ, 1, 1), so evaluated distances are divided by lip = max(1, |R|/ρ_min). The bend axis must not cross the child's y extent (|R| smaller than the toward-center half-extent would fold the domain through the center line).

func (*Builder) CircularArray

func (bld *Builder) CircularArray(s glbuild.Shader3D, numInstances, circleDiv int) glbuild.Shader3D

CircularArray is the circular domain repetition operation around the origin (x,y,z)=(0,0,0). It repeats the shape numInstances times and the spacing angle is defined by circleDiv such that angle = 2*pi/circleDiv. The operation is defined this way so that the argument shape is evaluated only twice per circular array evaluation, regardless of instances.

func (*Builder) CircularArray2D

func (bld *Builder) CircularArray2D(s glbuild.Shader2D, numInstances, circleDiv int) glbuild.Shader2D

CircularArray2D is the circular domain repetition operation around the origin (x,y)=(0,0). It repeats the shape numInstances times and the spacing angle is defined by circleDiv such that angle = 2*pi/circleDiv. The operation is defined this way so that the argument shape is evaluated only twice per circular array evaluation, regardless of instances.

func (*Builder) ClearErrors

func (bld *Builder) ClearErrors()

ClearErrors clears accumulated errors such that Builder.Err returns nil on next call.

func (*Builder) Difference

func (bld *Builder) Difference(a, b glbuild.Shader3D) glbuild.Shader3D

Difference is the SDF difference of a-b. Does not produce a true SDF.

func (*Builder) Difference2D

func (bld *Builder) Difference2D(a, b glbuild.Shader2D) glbuild.Shader2D

Difference2D is the SDF difference of a-b. Does not produce a true SDF.

func (*Builder) Elongate

func (bld *Builder) Elongate(s glbuild.Shader3D, dirX, dirY, dirZ float32) glbuild.Shader3D

Elongate "stretches" the SDF in a direction by splitting it on the origin in the plane perpendicular to the argument direction. The part of the shape in the negative plane is discarded and replaced with the elongated positive part.

Arguments are distances, so zero-valued arguments are no-op.

func (*Builder) Elongate2D

func (bld *Builder) Elongate2D(s glbuild.Shader2D, dirX, dirY float32) glbuild.Shader2D

Elongate2D "stretches" the SDF in a direction by splitting it on the origin in the plane perpendicular to the argument direction. The part of the shape in the negative plane is discarded and replaced with the elongated positive part.

Arguments are distances, so zero-valued arguments are no-op.

func (*Builder) Err

func (bld *Builder) Err() error

Err returns errors accumulated during SDF primitive creation and operations. The returned error implements `Unwrap() []error`.

func (*Builder) Extrude

func (bld *Builder) Extrude(s glbuild.Shader2D, h float32) glbuild.Shader3D

Extrude converts a 2D SDF into a 3D extrusion. Extrudes in both positive and negative Z direction, half of h both ways.

func (*Builder) Flags

func (bld *Builder) Flags() Flags

func (*Builder) Intersection

func (bld *Builder) Intersection(a, b glbuild.Shader3D) glbuild.Shader3D

Intersection is the SDF intersection of a ^ b. Does not produce an exact SDF.

func (*Builder) Intersection2D

func (bld *Builder) Intersection2D(a, b glbuild.Shader2D) glbuild.Shader2D

Intersection2D is the SDF intersection of a ^ b. Does not produce an exact SDF.

func (*Builder) NewArc

func (bld *Builder) NewArc(radius, arcAngle, thick float32) glbuild.Shader2D

NewArc returns a 2D arc centered at the origin (x,y)=(0,0) for a given radius and arc angle and thickness of the arc. The arc begins opening at (x,y)=(0,r) in both positive and negative x direction.

func (*Builder) NewBoundsBoxFrame

func (bld *Builder) NewBoundsBoxFrame(bb ms3.Box) glbuild.Shader3D

NewBoundsBoxFrame creates a BoxFrame from a bb (ms3.Box) such that the BoxFrame envelops the bb. Useful for debugging bounding boxes of glbuild.Shader3D primitives and operations.

func (*Builder) NewBox

func (bld *Builder) NewBox(x, y, z, round float32) glbuild.Shader3D

NewBox creates a box centered at the origin with x,y,z dimensions and a rounding parameter to round edges.

func (*Builder) NewBoxFrame

func (bld *Builder) NewBoxFrame(dimX, dimY, dimZ, e float32) glbuild.Shader3D

NewBoxFrame creates a framed box with the frame being composed of square beams of thickness e.

func (*Builder) NewCircle

func (bld *Builder) NewCircle(radius float32) glbuild.Shader2D

NewCircle creates a circle of a radius centered at the origin (x,y)=(0,0).

func (*Builder) NewCubicBezier2D

func (bld *Builder) NewCubicBezier2D(points []ms2.Vec, segments int, thick float32) glbuild.Shader2D

NewCubicBezier2D creates a 2D SDF for a chain of cubic Bezier spans stroked with the given thickness (the tube of half-width thick around the curve). points holds 3n+1 control points: spans share endpoints, so (p0,p1,p2,p3), (p3,p4,p5,p6), ... Each span is evaluated exactly like NewQuadraticBezier2D does per segment, after splitting it into `segments` quadratic sub-spans — the authored facet dial of the section (deviation from the analytic cubic is O(1/segments²); no adaptive subdivision).

func (*Builder) NewCylinder

func (bld *Builder) NewCylinder(r, h, rounding float32) glbuild.Shader3D

NewCylinder creates a cylinder centered at the origin with given radius and height. The cylinder's axis points in z direction.

func (*Builder) NewDiamond2D

func (bld *Builder) NewDiamond2D(x_width, y_height float32) glbuild.Shader2D

NewDiamond2D creates a diamond (rhombus) centered at (x,y)=(0,0) with given x and y width and height dimensions, respectively.

func (*Builder) NewEllipse

func (bld *Builder) NewEllipse(a, b float32) glbuild.Shader2D

NewEllipse creates a 2D ellipse SDF with a and b ellipse parameters.

func (*Builder) NewEquilateralTriangle

func (bld *Builder) NewEquilateralTriangle(triangleHeight float32) glbuild.Shader2D

NewEquilateralTriangle creates an equilater triangle with a given height with it's centroid located at the origin.

func (*Builder) NewHexagon

func (bld *Builder) NewHexagon(side float32) glbuild.Shader2D

NewHexagon creates a regular hexagon centered at (x,y)=(0,0) with sides of length `side`.

func (*Builder) NewHexagonalPrism

func (bld *Builder) NewHexagonalPrism(face2Face, h float32) glbuild.Shader3D

NewHexagonalPrism creates a hexagonal prism given a face-to-face dimension and height. The hexagon's length is in the z axis.

func (*Builder) NewLine2D

func (bld *Builder) NewLine2D(x0, y0, x1, y1, width float32) glbuild.Shader2D

NewLine2D creates a straight line between (x0,y0) and (x1,y1) with a given thickness.

func (*Builder) NewLines2D

func (bld *Builder) NewLines2D(segments [][2]ms2.Vec, width float32) glbuild.Shader2D

NewLines2D creates sequential straight lines between the argument points.

func (*Builder) NewOctagon

func (bld *Builder) NewOctagon(constrain float32) glbuild.Shader2D

NewOctagon returns a regular octagon 2D SDF with form that extend up to -constrain and constrain in both x and y axes.

func (*Builder) NewPolygon

func (bld *Builder) NewPolygon(vertices []ms2.Vec) glbuild.Shader2D

NewPolygon creates a polygon from a set of vertices. The polygon can be self-intersecting.

func (*Builder) NewQuadraticBezier2D

func (bld *Builder) NewQuadraticBezier2D(a, b, c ms2.Vec, thick float32) glbuild.Shader2D

NewQuadraticBezier2D creats an exact quadratic bezier SDF with three control points a, b, c. a and c lie on the bezier, b is a slope control point. Thick is the thickness of the curve.

func (*Builder) NewRectangle

func (bld *Builder) NewRectangle(x, y, r float32) glbuild.Shader2D

NewRectangle creates a rectangle centered at (x,y)=(0,0) with given x and y dimensions and r radius rounding.

func (*Builder) NewRoundedX

func (bld *Builder) NewRoundedX(width, thick float32) glbuild.Shader2D

NewRoundedX creates a two-dimensional X centered at (x,y)=(0,0) with given width and thickness/radius of lines.

func (*Builder) NewSphere

func (bld *Builder) NewSphere(r float32) glbuild.Shader3D

NewSphere creates a sphere centered at the origin of radius r.

func (*Builder) NewTorus

func (bld *Builder) NewTorus(greaterRadius, lesserRadius float32) glbuild.Shader3D

NewTorus creates a 3D torus given 2 radii to define the radius across (greaterRadius) and the "solid" radius (lesserRadius). If the radius were cut and stretched straight to form a cylinder the lesser radius would be the radius of the cylinder. The torus' axis is in the z axis.

func (*Builder) NewTriangularPrism

func (bld *Builder) NewTriangularPrism(triHeight, extrudeLength float32) glbuild.Shader3D

NewTriangularPrism creates a 3D triangular prism with a given triangle cross-sectional height (2D) and a extrude length. The prism's extrude axis is in the z axis direction.

func (*Builder) Offset

func (bld *Builder) Offset(s glbuild.Shader3D, sdfAdd float32) glbuild.Shader3D

Offset adds sdfAdd to the entire argument SDF. If sdfAdd is negative this will round edges and increase the dimension of flat surfaces of the SDF by the absolute magnitude. See Inigo's youtube video on the subject.

func (*Builder) Offset2D

func (bld *Builder) Offset2D(s glbuild.Shader2D, sdfAdd float32) glbuild.Shader2D

Offset2D adds sdfAdd to the entire argument SDF. If sdfAdd is negative this will round edges and increase the dimension of flat surfaces of the SDF by the absolute magnitude. See Inigo's youtube video on the subject.

func (*Builder) Revolve

func (bld *Builder) Revolve(s glbuild.Shader2D, axisOffset float32) glbuild.Shader3D

Revolve revolves a 2D SDF around the y axis, offsetting the axis of revolution by axisOffset.

func (*Builder) Rotate

func (bld *Builder) Rotate(s glbuild.Shader3D, radians float32, axis ms3.Vec) glbuild.Shader3D

Rotate is the rotation of radians angle around an axis vector.

func (*Builder) Rotate2D

func (bld *Builder) Rotate2D(s glbuild.Shader2D, theta float32) glbuild.Shader2D

Rotate2D returns the argument shape rotated around the origin by theta (radians).

func (*Builder) Scale

func (bld *Builder) Scale(s glbuild.Shader3D, scaleFactor float32) glbuild.Shader3D

Scale scales s by scaleFactor around the origin.

func (*Builder) Scale2D

func (bld *Builder) Scale2D(s glbuild.Shader2D, scale float32) glbuild.Shader2D

ScaleXY scales s by scaleFactor around the origin.

func (*Builder) SetFlags

func (bld *Builder) SetFlags(flags Flags) error

func (*Builder) Shell

func (bld *Builder) Shell(s glbuild.Shader3D, thickness float32) glbuild.Shader3D

Shell carves the interior of the SDF leaving only the exterior shell of the part: the outer surface is preserved and an inner cavity is hollowed at the given wall thickness. The result fits inside the child's bounds.

func (*Builder) SmoothDifference

func (bld *Builder) SmoothDifference(k float32, s1, s2 glbuild.Shader3D) glbuild.Shader3D

SmoothDifference performs the difference of two SDFs with a smoothing parameter.

func (*Builder) SmoothDifferenceIn

func (bld *Builder) SmoothDifferenceIn(k float32, s1, s2, region glbuild.Shader3D) glbuild.Shader3D

SmoothDifferenceIn subtracts sub from s with a region-scaled smoothing blend (see SmoothUnionIn for the region semantics).

func (*Builder) SmoothDifferenceRamp

func (bld *Builder) SmoothDifferenceRamp(k0, k1 float32, s1, s2, region glbuild.Shader3D) glbuild.Shader3D

SmoothDifferenceRamp subtracts sub from s with a ramped smoothing blend (see SmoothUnionRamp for the region and ramp semantics).

func (*Builder) SmoothIntersect

func (bld *Builder) SmoothIntersect(k float32, s1, s2 glbuild.Shader3D) glbuild.Shader3D

SmoothIntersect performs the intesection of two SDFs with a smoothing parameter.

func (*Builder) SmoothIntersectIn

func (bld *Builder) SmoothIntersectIn(k float32, s1, s2, region glbuild.Shader3D) glbuild.Shader3D

SmoothIntersectIn intersects two shapes with a region-scaled smoothing blend (see SmoothUnionIn for the region semantics).

func (*Builder) SmoothIntersectRamp

func (bld *Builder) SmoothIntersectRamp(k0, k1 float32, s1, s2, region glbuild.Shader3D) glbuild.Shader3D

SmoothIntersectRamp intersects two shapes with a ramped smoothing blend (see SmoothUnionRamp for the region and ramp semantics).

func (*Builder) SmoothUnion

func (bld *Builder) SmoothUnion(k float32, s1, s2 glbuild.Shader3D) glbuild.Shader3D

SmoothUnion joins the shapes of two shaders into one with a smoothing blend.

func (*Builder) SmoothUnionIn

func (bld *Builder) SmoothUnionIn(k float32, s1, s2, region glbuild.Shader3D) glbuild.Shader3D

SmoothUnionIn joins two shapes with a smoothing blend that is scaled by a region field: the blend is the full smooth-union kernel where region is negative (inside the region), tapers to the plain union where region exceeds k/2, and interpolates between over a transition width of k — one knob for both blend radius and falloff. This is the selective-fillet primitive: SmoothUnionIn(k, a, b, capsuleAroundTheEdge) rounds only that seam.

func (*Builder) SmoothUnionRamp

func (bld *Builder) SmoothUnionRamp(k0, k1 float32, s1, s2, region glbuild.Shader3D) glbuild.Shader3D

SmoothUnionRamp joins two shapes with a smooth-union blend whose radius ramps linearly from k0 to k1 across a region field — the styling fillet that grows along a seam (2 mm meeting a shell, 6 mm at the handle root). The mask is the same SDF-region mechanism SmoothUnionIn uses, but its value both gates and positions: k_eff = S·lerp(k0, k1, S), S = smoothstep(clamp(0.5 − r/w)), w = max(k0, k1) — the blend tapers to the plain union over the transition (zero radius outside the region, no residual k0 blend beyond the mask) and reaches the full k1 kernel deep inside it. k0 == k1 degenerates exactly to SmoothUnionIn. k_eff is monotone in S for k1 ≥ k0; a strongly shrinking ramp (k0 > 2·k1) overshoots k1 by at most k0²/(4(k0−k1)) − k1 before settling — a non-monotone radius profile wants a composition of ramps over stacked regions, not this op. Shape the region so its iso-surfaces cross the seam on the stretch that ramps: a tilted slab sweeps k0→k1 along its slope.

func (*Builder) Symmetry

func (bld *Builder) Symmetry(s glbuild.Shader3D, mirrorX, mirrorY, mirrorZ bool) glbuild.Shader3D

Symmetry reflects the SDF around one or more cartesian planes.

func (*Builder) Symmetry2D

func (bld *Builder) Symmetry2D(s glbuild.Shader2D, mirrorX, mirrorY bool) glbuild.Shader2D

Symmetry reflects the SDF around x or y (or both) axis.

func (*Builder) Taper

func (bld *Builder) Taper(s glbuild.Shader3D, k0, k1 float32) glbuild.Shader3D

Taper applies a scale field varying linearly along the child's own z extent: x and y are scaled by k0 at the child's z-min and k1 at its z-max (clamped outside), z untouched. This is the drafting warp — model in the natural axis, draft at export; rotate into place for other axes, as with Twist.

Lipschitz convention: the pullback's Jacobian is triangular [[1/s, 0, -x s'/s²], [0, 1/s, -y s'/s²], [0, 0, 1]] with s the local scale and s' its gradient, so distances can over-report by its spectral norm and are divided by a bound on it (the twist rule): σ² ≤ max row sum of JᵀJ over the child's extent = max(a²+aβ, β²+√2·aβ+1) with a = 1/min(k0,k1) and β = r_max·|k1-k0|/h / min(k0,k1)². The zero level set is lip-independent (division by a positive constant moves no surface), so the bound only affects culling aggressiveness, never geometry.

func (*Builder) Transform

func (bld *Builder) Transform(s glbuild.Shader3D, m ms3.Mat4) glbuild.Shader3D

Transform applies a 4x4 matrix transformation to the argument shader by inverting the argument matrix.

func (*Builder) Translate

func (bld *Builder) Translate(s glbuild.Shader3D, dirX, dirY, dirZ float32) glbuild.Shader3D

Translate moves the SDF s in the given direction (dirX, dirY, dirZ) and returns the result.

func (*Builder) Translate2D

func (bld *Builder) Translate2D(s glbuild.Shader2D, dirX, dirY float32) glbuild.Shader2D

Translate2D moves the SDF s in the given direction.

func (*Builder) TranslateMulti2D

func (bld *Builder) TranslateMulti2D(s glbuild.Shader2D, displacements []ms2.Vec) glbuild.Shader2D

TranslateMulti2D displaces N instances of s SDF to positions given by displacements of length N.

func (*Builder) Twist

func (bld *Builder) Twist(s glbuild.Shader3D, k float32) glbuild.Shader3D

Twist applies a twist deformation around the Z axis. The XY plane is rotated by k*z radians at height z.

Lipschitz convention: every operation is either 1-Lipschitz by construction (booleans min/max; offset ±d; shell max(d,-d-t); elongate clamp; symmetry mirror; array modulo; transforms via the inverse's spectral-norm renormalization) or carries a lip bound on its distance scaling and divides evaluated distances by it (transform, twist). Any future warp (bend, taper, ...) must follow one of the two and say which in a one-line comment.

func (*Builder) Union

func (bld *Builder) Union(shaders ...glbuild.Shader3D) glbuild.Shader3D

Union joins the shapes of several 3D SDFs into one. Is exact. Union aggregates nested Union results into its own. To prevent this behaviour use OpUnion directly.

func (*Builder) Union2D

func (*Builder) Union2D(shaders ...glbuild.Shader2D) glbuild.Shader2D

Union joins the shapes of several 2D SDFs into one. Is exact. Union aggregates nested Union results into its own.

func (*Builder) Xor

func (bld *Builder) Xor(s1, s2 glbuild.Shader3D) glbuild.Shader3D

Xor is the mutually exclusive boolean operation and results in an exact SDF.

func (*Builder) Xor2D

func (bld *Builder) Xor2D(s1, s2 glbuild.Shader2D) glbuild.Shader2D

Xor2D is the mutually exclusive boolean operation and results in an exact SDF.

type Flags

type Flags uint64

Flags is a bitmask of values to control the functioning of the Builder type.

const (
	// FlagNoDimensionPanic controls panicking behavior on invalid shape dimension errors.
	// If set then these errors do not panic, instead storing the error for later inspection with [Builder.Err].
	FlagNoDimensionPanic Flags = 1 << iota
	// FlagUseShaderBuffers enforces the use of shader object for all newly built
	// SDFs which require a dynamic array(s) to be rendered correctly.
	FlagUseShaderBuffers
	// FlagNoShaderBuffers if set will cause the Builder to avoid all shader buffer usage, instead depending on
	// the shader program entirely for shape definition.
	FlagNoShaderBuffers
)

type GridSDF

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

GridSDF is a signed distance field sampled on a dense axis-aligned lattice: (nx+1)*(ny+1)*(nz+1) corner values at `cell` spacing from `origin`, evaluated by trilinear interpolation. It is the substitution target for re-normalized fields (eikonal sweeps, baked grids): build the lattice, sweep, hand the grid to the mesher.

Outside the lattice box the field is conservative: the clamped interpolated edge value plus the distance to the box (axis-summed, an upper bound of Euclidean) on the outside — never under-reporting, so meshers keep every surface cube.

GridSDF is CPU-eval only: AppendShaderBody emits a clearly-marked placeholder (1e9) so accidental GLSL export of a grid model fails visibly at the surface, not silently at mesh time. AppendShaderName hashes the lattice geometry (origin/cell/dims) — values are not hashed, which is safe because the grid never evaluates on the GPU.

func NewGridSDF

func NewGridSDF(origin ms3.Vec, cell float32, nx, ny, nz int, vals []float32) (*GridSDF, error)

NewGridSDF builds a GridSDF from a corner-value lattice: vals holds (nx+1)*(ny+1)*(nz+1) samples at origin + cell*(i, j, k), indexed i + j*(nx+1) + k*(nx+1)*(ny+1) (x fastest). The slice is retained, not copied — callers own immutability while the grid is in use.

func (*GridSDF) AppendShaderBody

func (g *GridSDF) AppendShaderBody(b []byte) []byte

AppendShaderBody emits the CPU-eval-only placeholder: a grid in a GLSL export is a modeling error, and a huge distance fails visibly (empty render) instead of silently.

func (*GridSDF) AppendShaderName

func (g *GridSDF) AppendShaderName(b []byte) []byte

AppendShaderName hashes the lattice geometry (origin, cell, dims); values are not hashed — the grid never evaluates on the GPU.

func (*GridSDF) AppendShaderObjects

func (g *GridSDF) AppendShaderObjects(objects []glbuild.ShaderObject) []glbuild.ShaderObject

AppendShaderObjects: no GPU objects.

func (*GridSDF) Bounds

func (g *GridSDF) Bounds() ms3.Box

Bounds returns the lattice box: origin .. origin + cell*(nx, ny, nz).

func (*GridSDF) Evaluate

func (g *GridSDF) Evaluate(pos []ms3.Vec, dist []float32, _ any) error

Evaluate interpolates the lattice trilinearly. Outside the lattice box it returns the clamped interpolated value plus the axis-summed distance to the box when that value is non-negative — conservative in the mesher's favor (never under-reports distance to a solid).

func (*GridSDF) ForEachChild

func (g *GridSDF) ForEachChild(_ any, _ func(any, *glbuild.Shader3D) error) error

ForEachChild: a grid has no children.

type OpUnion

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

OpUnion is the result of the [Union] operation. Prefer using [Union] to using this type directly.

Normally primitives and results of operations in this package are not exported since their concrete type provides relatively little value. The result of Union is the exception to the rule since it is the most common operation to perform on SDFs and can provide several benefits to users seeking to optimize their SDFs creatively such as creating sectioned SDFs where conditional evaluation may be performed depending on the bounding boxes of the SDFs being evaluated.

By exporting OpUnion users can traverse a glbuild.Shader3D tree looking for OpUnion elements and checking how heavy their computation cost is and evaluating if sectioning their bounding box is effective.

func (*OpUnion) AppendShaderBody

func (u *OpUnion) AppendShaderBody(b []byte) []byte

AppendShaderBody implements glbuild.Shader.

func (*OpUnion) AppendShaderName

func (u *OpUnion) AppendShaderName(b []byte) []byte

AppendShaderName implements glbuild.Shader.

func (*OpUnion) AppendShaderObjects

func (u *OpUnion) AppendShaderObjects(objects []glbuild.ShaderObject) []glbuild.ShaderObject

AppendShaderObjects implements glbuild.Shader. This method returns the argument buffer with no modifications. See glbuild.Shader for more information.

func (*OpUnion) Bounds

func (u *OpUnion) Bounds() ms3.Box

Bounds returns the union of all joined SDFs. Implements glbuild.Shader3D and gleval.SDF3.

func (*OpUnion) CullGapSafe

func (u *OpUnion) CullGapSafe() bool

func (*OpUnion) Evaluate

func (u *OpUnion) Evaluate(pos []ms3.Vec, dist []float32, userData any) error

Evaluate implements gleval.SDF3. Children are culled per point: when the running distance at a point is already <= the gap to a child's bounding box (a lower bound on that child's distance), evaluating the child cannot lower the minimum, so the point is skipped for that child. Skipped points keep their value, so the result is bit-identical to evaluating every child.

func (*OpUnion) ForEachChild

func (u *OpUnion) ForEachChild(userData any, fn func(userData any, s *glbuild.Shader3D) error) error

ForEachChild implements glbuild.Shader3D.

type OpUnion2D

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

OpUnion2D is the result of [Union2D]. This type is exported for special reasons, see OpUnion documentation.

func (*OpUnion2D) AppendShaderBody

func (u *OpUnion2D) AppendShaderBody(b []byte) []byte

AppendShaderBody implements glbuild.Shader.

func (*OpUnion2D) AppendShaderName

func (u *OpUnion2D) AppendShaderName(b []byte) []byte

AppendShaderName implements glbuild.Shader.

func (*OpUnion2D) AppendShaderObjects

func (u *OpUnion2D) AppendShaderObjects(objects []glbuild.ShaderObject) []glbuild.ShaderObject

AppendShaderObjects implements glbuild.Shader. This method returns the argument buffer with no modifications. See glbuild.Shader for more information.

func (*OpUnion2D) Bounds

func (u *OpUnion2D) Bounds() ms2.Box

Bounds returns the union of all joined SDFs. Implements glbuild.Shader2D and gleval.SDF2.

func (*OpUnion2D) Evaluate

func (u *OpUnion2D) Evaluate(pos []ms2.Vec, dist []float32, userData any) error

Evaluate implements gleval.SDF2. Same per-point child culling as OpUnion.Evaluate, gated on the same cull-safety property.

func (*OpUnion2D) ForEach2DChild

func (u *OpUnion2D) ForEach2DChild(userData any, fn func(userData any, s *glbuild.Shader2D) error) error

ForEachChild implements glbuild.Shader2D.

Directories

Path Synopsis
examples
bolt command
gasket command
image command
image-text command
metric-spacers command
mop-joint command
npt-flange command
plantpot command
template-makers command
test command
ui-bolt command
ui-geb command
ui-mandala command
ui-text command
forge
wgsl/wgsllib
Package wgsllib is the WGSL twin of glbuild/glsllib: one hand-ported WGSL function per GLSL library function, same names, same parameters, same arithmetic (f32 throughout).
Package wgsllib is the WGSL twin of glbuild/glsllib: one hand-ported WGSL function per GLSL library function, same names, same parameters, same arithmetic (f32 throughout).

Jump to

Keyboard shortcuts

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