Skip to content

Commit

Permalink
fix uninitialized Font crash; fix polygon self-closing case; admit mu…
Browse files Browse the repository at this point in the history
…ltiple identical SSBOs; color conversion additions
  • Loading branch information
soypat committed Dec 8, 2024
1 parent b4c7e83 commit 825bde6
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 86 deletions.
28 changes: 3 additions & 25 deletions examples/image-text/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import (
"runtime"
"time"

"github.com/chewxy/math32"
"github.com/soypat/glgl/math/ms1"
"github.com/soypat/gsdf"
"github.com/soypat/gsdf/forge/textsdf"
"github.com/soypat/gsdf/glbuild"
Expand Down Expand Up @@ -66,32 +64,12 @@ func main() {

charHeight := sdf2.Bounds().Size().Y
edgeAliasing := charHeight / 1000
conversion := gsdfaux.ColorConversionLinearGradient(edgeAliasing, color.Black, color.White)
start := time.Now()
err = gsdfaux.RenderPNGFile(filename, sdf2, 300, blackAndWhite(edgeAliasing))
err = gsdfaux.RenderPNGFile(filename, sdf2, 300, conversion)
if err != nil {
log.Fatal(err)
}
_ = conversion
fmt.Println("PNG file rendered to", filename, "in", time.Since(start))
}

func blackAndWhite(edgeSmooth float32) func(d float32) color.Color {
if edgeSmooth <= 0 {
return blackAndWhiteNoSmoothing
}
return func(d float32) color.Color {
// Smoothstep anti-aliasing near the edge
blend := 0.5 + 0.5*math32.Tanh(d/edgeSmooth)
// Clamp blend to [0, 1] for valid grayscale values
blend = ms1.Clamp(blend, 0, 1)
// Convert blend to grayscale
grayValue := uint8(blend * 255)
return color.Gray{Y: grayValue}
}
}

func blackAndWhiteNoSmoothing(d float32) color.Color {
if d < 0 {
return color.Black
}
return color.White
}
5 changes: 3 additions & 2 deletions forge/textsdf/font.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ func (f *Font) Configure(cfg FontConfig) error {
f.reltol = cfg.RelativeGlyphTolerance
if cfg.Builder != nil {
f.bld = cfg.Builder
} else {
f.bld = defaultBuilder
}
return nil
}
Expand Down Expand Up @@ -76,6 +74,9 @@ func (f *Font) reset() {
if f.reltol == 0 {
f.reltol = 0.15
}
if f.bld == nil {
f.bld = defaultBuilder
}
}

type glyph struct {
Expand Down
53 changes: 41 additions & 12 deletions glbuild/glbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,33 +268,49 @@ func (p *Programmer) writeShaders(w io.Writer, nodes []Shader) (n int, objs []Sh
clear(p.names)
p.scratch = p.scratch[:0]
p.objsScratch = p.objsScratch[:0]
currentBase := 2
const startBase = 2
currentBase := startBase
objIdx := 0
for i := len(nodes) - 1; i >= 0; i-- {
// Start by generating Shader Objects.
// Start by generating all Shader Objects.
node := nodes[i]
prevIdx := len(p.objsScratch)
p.objsScratch = node.AppendShaderObjects(p.objsScratch)
newObjects := p.objsScratch[prevIdx:]
for i := range newObjects {
if newObjects[i].Binding != -1 {
return n, nil, fmt.Errorf("shader buffer object binding should be set to -1 until shader generated for %T, %q", unwraproot(node), newObjects[i].NamePtr)
newObjs := p.objsScratch[objIdx:]
OBJWRITE:
for i := range newObjs {
obj := &newObjs[i]
if obj.Binding != -1 {
return n, nil, fmt.Errorf("shader buffer object binding should be set to -1 until shader generated for %T, %q", unwraproot(node), obj.NamePtr)
}
newObjects[i].Binding = currentBase
currentBase++
obj := newObjects[i]
nameHash := hash(obj.NamePtr, 0)
_, nameConflict := p.names[nameHash]
if nameConflict {
oldObjs := p.objsScratch[:objIdx]
for _, old := range oldObjs {
conflictFound := nameHash == hash(old.NamePtr, 0)
if !conflictFound {
continue
}
// Conflict found!
if obj.Data == old.Data && obj.Size == old.Size && obj.Element == old.Element {
continue OBJWRITE // Skip this object, is duplicate and already has been added.
}
break // Conflict is not identical.
}
return n, nil, fmt.Errorf("shader buffer object name conflict resolution not implemented: %T has buffer conflicting name %q of type %s", unwraproot(node), obj.NamePtr, obj.Element.String())
}
obj.Binding = currentBase
currentBase++
p.names[nameHash] = nameHash
blockName := unsafe.String(&obj.NamePtr[0], len(obj.NamePtr)) + "Buffer"
p.scratch, err = AppendShaderBufferDecl(p.scratch, blockName, "", obj)
blockName := string(obj.NamePtr) + "Buffer"
p.scratch, err = AppendShaderBufferDecl(p.scratch, blockName, "", *obj)
if err != nil {
return n, nil, err
}
}
objIdx += len(newObjs)
}

if len(p.scratch) > 0 {
// Write shader buffer declarations if any.
ngot, err := w.Write(p.scratch)
Expand Down Expand Up @@ -602,6 +618,7 @@ func AppendAllNodes(dst []Shader, root Shader) ([]Shader, error) {
children := []Shader{root}
nextChild := 0
nilChild := errors.New("got nil child in AppendAllNodes")
// found := make(map[Shader]struct{})
for len(children[nextChild:]) > 0 {
newChildren := children[nextChild:]
for _, obj := range newChildren {
Expand All @@ -618,6 +635,10 @@ func AppendAllNodes(dst []Shader, root Shader) ([]Shader, error) {
if s == nil || *s == nil {
return nilChild
}
// if _, skip := found[*s]; skip {
// return nil
// }
// found[*s] = struct{}{}
children = append(children, *s)
return nil
})
Expand All @@ -627,6 +648,10 @@ func AppendAllNodes(dst []Shader, root Shader) ([]Shader, error) {
if s == nil || *s == nil {
return nilChild
}
// if _, skip := found[*s]; skip {
// return nil
// }
// found[*s] = struct{}{}
children = append(children, *s)
return nil
})
Expand All @@ -638,6 +663,10 @@ func AppendAllNodes(dst []Shader, root Shader) ([]Shader, error) {
if s == nil || *s == nil {
return nilChild
}
// if _, skip := found[*s]; skip {
// return nil
// }
// found[*s] = struct{}{}
children = append(children, *s)
return nil
})
Expand Down
13 changes: 6 additions & 7 deletions gsdf2d.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ type poly2D struct {

// NewPolygon creates a polygon from a set of vertices. The polygon can be self-intersecting.
func (bld *Builder) NewPolygon(vertices []ms2.Vec) glbuild.Shader2D {
err := bld.validatePolygon(vertices)
vertices, err := bld.validatePolygon(vertices)
if err != nil {
bld.shapeErrorf(err.Error())
}
Expand All @@ -550,26 +550,25 @@ func (bld *Builder) NewPolygon(vertices []ms2.Vec) glbuild.Shader2D {
return &poly
}

func (bld *Builder) validatePolygon(vertices []ms2.Vec) error {
func (bld *Builder) validatePolygon(vertices []ms2.Vec) ([]ms2.Vec, error) {
prevIdx := len(vertices) - 1
if vertices[0] == vertices[prevIdx] {
vertices = vertices[:prevIdx] // Discard last vertex if equal to first (this algorithm closes automatically).
prevIdx--
}
if len(vertices) < 3 {
return errors.New("polygon needs at least 3 distinct vertices")

return vertices, errors.New("polygon needs at least 3 distinct vertices")
}
for i := range vertices {
if math32.IsNaN(vertices[i].X) || math32.IsNaN(vertices[i].Y) {
return errors.New("NaN value in vertices")
return vertices, errors.New("NaN value in vertices")
}
if vertices[i] == vertices[prevIdx] {
return errors.New("found two consecutive equal vertices in polygon")
return vertices, errors.New("found two consecutive equal vertices in polygon")
}
prevIdx = i
}
return nil
return vertices, nil
}

func (c *poly2D) Bounds() ms2.Box {
Expand Down
8 changes: 8 additions & 0 deletions gsdf_gpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ func testGsdfGPU() error {
if t.fail {
return fmt.Errorf("%s: test failed", getFnName(test))
}
bldErr := cfg.bld.Err()
if bldErr != nil {
return fmt.Errorf("%s: got Builder error %q", getFnName(test), bldErr.Error())
}
}
return nil
}
Expand Down Expand Up @@ -226,12 +230,15 @@ func testPrimitives2D(t *tb, cfg *shaderTestConfig) {

// Non-SSBO shapes which use dynamic buffers.
poly := bld.NewPolygon(vertices)
polySelfClosed := bld.NewPolygon([]ms2.Vec{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}})

// Create shapes to test usage of dynamic buffers as SSBOs.
bld.SetFlags(bld.Flags() | FlagUseShaderBuffers)

polySSBO := bld.NewPolygon(vertices)
linesSSBO := bld.NewLines2D(segments, 0.1)
displaceSSBO := bld.TranslateMulti2D(poly, vertices)

bld.SetFlags(bld.Flags() &^ FlagUseShaderBuffers)

var primitives = []glbuild.Shader2D{
Expand All @@ -243,6 +250,7 @@ func testPrimitives2D(t *tb, cfg *shaderTestConfig) {
bld.NewEquilateralTriangle(maxdim),
bld.NewEllipse(1, 2), // Is incorrect.
poly,
polySelfClosed,
polySSBO,
linesSSBO,
displaceSSBO,
Expand Down
Loading

0 comments on commit 825bde6

Please sign in to comment.