Skip to content

Commit 6b9a46d

Browse files
EliCDaviskalebpace
andauthored
Texturing Overhaul (#115)
* Start of texturing nodes * Scale along normal now can sample texture for values * New noise functions, serializing and rendering textures in graph view * output images now update * color test fixes * fix: better sri CI handling (#117) - Renames "update-sris" -> "sri-check-up" - Refactors this script so that it both handles updating the SRIs when run locally, but also prints the SRI difference to the log when in CI. - Uses this script in workflows to check the SRIs before continuing with expensive build and release steps. - Refactors the 'apps' section into main let expression for use in build phases if needed. example output seen in CI: ```bash $: nix run .#sri-check-up package-lock.json.sri mismatch specified: sha256-uea6z39yYjpLTjq+ne3NJdabTQ/N91tLtBqfQMSYcAI= got: sha256-gF8IDK1WKmNwXcIfm62kkDSzSxIceKgpSxuwzQDlmcQ= If this difference is expected, please replace the SRI hash in this file with the one we got ``` * hash update * fix: oopsie (#118) * node outputs are now threadsafe * WebColor => Color, fix torus UVs * noise node * Radial Gradient, ApplyGradient, add and scale color, new terrain example * fixing examples --------- Co-authored-by: Kaleb Pace <[email protected]>
1 parent 3c33901 commit 6b9a46d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+3344
-494
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ jobs:
2727
- uses: DeterminateSystems/nix-installer-action@main
2828
- uses: DeterminateSystems/flakehub-cache-action@main
2929

30-
- name: Restore Nix-cached Release Artifacts
31-
run: nix build .#release -Lo ./artifacts
30+
- name: Build Nix-cached Release Artifacts
31+
run: |
32+
nix run .#sri-check-up --print-build-logs
33+
nix build .#release --print-build-logs --out-link ./artifacts
3234
3335
pages:
3436
runs-on: ubuntu-latest
@@ -37,5 +39,7 @@ jobs:
3739
- uses: DeterminateSystems/nix-installer-action@main
3840
- uses: DeterminateSystems/flakehub-cache-action@main
3941

40-
- name: Restore Nix-cached Pages Artifacts
41-
run: nix build .#pages -Lo ./dist
42+
- name: Build Nix-cached Pages Artifacts
43+
run: |
44+
nix run .#sri-check-up --print-build-logs
45+
nix build .#pages --print-build-logs --out-link ./dist

.github/workflows/release.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,10 @@ jobs:
2727
- uses: DeterminateSystems/nix-installer-action@main
2828
- uses: DeterminateSystems/flakehub-cache-action@main
2929

30-
- name: Restore Nix-cached Release Artifacts
31-
run: nix build .#release -Lo ./artifacts
32-
33-
- name: Publish GitHub Release
30+
- name: Push Nix-cached Release Artifacts
3431
run: |
35-
gh release upload $GITHUB_REF_NAME ./artifacts/* --clobber
32+
nix run .#sri-check-up --print-build-logs
33+
nix run .#release --print-build-logs
3634
3735
deploy:
3836
runs-on: ubuntu-latest
@@ -45,7 +43,9 @@ jobs:
4543
- uses: DeterminateSystems/flakehub-cache-action@main
4644

4745
- name: Restore Nix-cached Pages Artifacts
48-
run: nix build .#pages -Lo ./dist
46+
run: |
47+
nix run .#sri-check-up --print-build-logs
48+
nix build .#pages --print-build-logs --out-link ./dist
4949
5050
- name: Setup Pages
5151
uses: actions/configure-pages@v4

cmd/polyform/main.go

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package main
22

33
import (
44
"fmt"
5+
"image"
6+
"image/color"
7+
"math"
58
"os"
69
"strings"
710

@@ -12,6 +15,8 @@ import (
1215
// Import these so they register their nodes with the generator
1316
"github.com/EliCDavis/polyform/drawing/coloring"
1417
_ "github.com/EliCDavis/polyform/drawing/coloring"
18+
"github.com/EliCDavis/polyform/drawing/texturing"
19+
_ "github.com/EliCDavis/polyform/drawing/texturing"
1520
_ "github.com/EliCDavis/polyform/drawing/texturing/normals"
1621

1722
_ "github.com/EliCDavis/polyform/formats/colmap"
@@ -23,9 +28,12 @@ import (
2328
_ "github.com/EliCDavis/polyform/formats/spz"
2429
_ "github.com/EliCDavis/polyform/formats/stl"
2530

31+
"github.com/EliCDavis/polyform/generator/manifest"
32+
"github.com/EliCDavis/polyform/generator/manifest/basics"
2633
_ "github.com/EliCDavis/polyform/generator/manifest/basics"
2734
_ "github.com/EliCDavis/polyform/generator/parameter"
2835
"github.com/EliCDavis/polyform/generator/schema"
36+
"github.com/EliCDavis/polyform/generator/serialize"
2937
"github.com/EliCDavis/polyform/generator/variable"
3038

3139
_ "github.com/EliCDavis/polyform/math"
@@ -53,6 +61,47 @@ import (
5361
)
5462

5563
func main() {
64+
nodeSerializer := &serialize.TypeSwitch[manifest.Entry]{}
65+
66+
serialize.Register(nodeSerializer, func(i image.Image) manifest.Entry {
67+
return manifest.Entry{Artifact: basics.Image{Image: i}}
68+
})
69+
70+
serialize.Register(nodeSerializer, func(tex texturing.Texture[float64]) manifest.Entry {
71+
return manifest.Entry{Artifact: texturing.Artifact[float64]{
72+
Texture: tex,
73+
Conversion: func(v float64) color.Color {
74+
b := byte(math.Min(math.Max(v, 0), 1) * 255)
75+
return color.RGBA{R: b, G: b, B: b, A: 255}
76+
},
77+
}}
78+
})
79+
80+
serialize.Register(nodeSerializer, func(tex texturing.Texture[bool]) manifest.Entry {
81+
return manifest.Entry{Artifact: texturing.Artifact[bool]{
82+
Texture: tex,
83+
Conversion: func(b bool) color.Color {
84+
var v byte = 0
85+
if b {
86+
v = 255
87+
}
88+
return color.RGBA{R: v, G: v, B: v, A: 255}
89+
},
90+
}}
91+
})
92+
93+
serialize.Register(nodeSerializer, func(i texturing.Texture[color.Color]) manifest.Entry {
94+
return manifest.Entry{Artifact: texturing.Artifact[color.Color]{
95+
Texture: i,
96+
Conversion: func(b color.Color) color.Color {
97+
if b == nil {
98+
return color.RGBA{R: 0, G: 0, B: 0, A: 255}
99+
}
100+
return b
101+
},
102+
}}
103+
})
104+
56105
app := generator.App{
57106
Name: "Polyform",
58107
Description: "Immutable mesh processing pipelines",
@@ -65,7 +114,7 @@ func main() {
65114
},
66115
},
67116
},
68-
117+
NodeOutputSerialization: nodeSerializer,
69118
VariableFactory: func(variableType string) (variable.Variable, error) {
70119
switch strings.ToLower(variableType) {
71120
case "float64":
@@ -98,8 +147,8 @@ func main() {
98147
case "geometry.aabb":
99148
return &variable.TypeVariable[geometry.AABB]{}, nil
100149

101-
case "coloring.webcolor":
102-
return &variable.TypeVariable[coloring.WebColor]{}, nil
150+
case "coloring.color":
151+
return &variable.TypeVariable[coloring.Color]{}, nil
103152

104153
case "image.image":
105154
return &variable.ImageVariable{}, nil

cmd/polywasm/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func serverCommand() *cli.Command {
3636
fs := http.FileServer(http.Dir(dir))
3737
log.Print("Serving " + dir + " on http://" + url)
3838
return http.ListenAndServe(url, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
39-
resp.Header().Add("Cache-Control", "no-cache")
39+
resp.Header().Add("Cache-Control", "no-store")
4040
if strings.HasSuffix(req.URL.Path, ".wasm") {
4141
resp.Header().Set("content-type", "application/wasm")
4242
}

docs/resources/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ Resources either directly contributing to the code, or are just interesting find
1414
- Tiling Noise
1515
- [ _Tiling Noise_ by Ronja](https://www.ronja-tutorials.com/post/029-tiling-noise/)
1616
- [gamedev.stackexchange _How do you generate tileable Perlin noise?_](https://gamedev.stackexchange.com/questions/23625/how-do-you-generate-tileable-perlin-noise)
17+
- Buncha noise functions
18+
- https://github.com/RodZill4/material-maker/blob/3b18267f29f0ead260aae1d3cf0d731db492981a/addons/material_maker/nodes/fbm2.mmg#L449
19+
- [_Fractional Brownian Motion_ by Inigo Quilez](https://iquilezles.org/articles/fbm/)
1720
- Sampling and Distribution
1821
- Quasirandom
1922
- [The Unreasonable Effectiveness of Quasirandom Sequences](https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/)

drawing/coloring/colors.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
package coloring
22

3-
func Black() WebColor {
4-
return WebColor{0, 0, 0, 255}
3+
func Black() Color {
4+
return Color{0, 0, 0, 1}
55
}
66

7-
func Grey(b byte) WebColor {
8-
return WebColor{b, b, b, 255}
7+
func Grey(b float64) Color {
8+
return Color{b, b, b, 1}
99
}
1010

11-
func White() WebColor {
12-
return WebColor{255, 255, 255, 255}
11+
func White() Color {
12+
return Color{1, 1, 1, 1}
1313
}
1414

1515
// func Red() WebColor {
16-
// return WebColor{255, 0, 0, 255}
16+
// return WebColor{1, 0, 0, 1}
1717
// }
1818

1919
// func Green() WebColor {
20-
// return WebColor{0, 255, 0, 255}
20+
// return WebColor{0, 1, 0, 1}
2121
// }
2222

2323
// func Blue() WebColor {
24-
// return WebColor{0, 0, 255, 255}
24+
// return WebColor{0, 0, 1, 1}
2525
// }

drawing/coloring/colors_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ import (
99

1010
func TestColor(t *testing.T) {
1111
tests := map[string]struct {
12-
input coloring.WebColor
13-
wantR byte
14-
wantG byte
15-
wantB byte
16-
wantA byte
12+
input coloring.Color
13+
wantR float64
14+
wantG float64
15+
wantB float64
16+
wantA float64
1717
}{
18-
"black": {input: coloring.Black(), wantR: 0, wantG: 0, wantB: 0, wantA: 255},
19-
"white": {input: coloring.White(), wantR: 255, wantG: 255, wantB: 255, wantA: 255},
20-
// "red": {input: coloring.Red(), wantR: 255, wantG: 0, wantB: 0, wantA: 255},
21-
// "green": {input: coloring.Green(), wantR: 0, wantG: 255, wantB: 0, wantA: 255},
22-
// "blue": {input: coloring.Blue(), wantR: 0, wantG: 0, wantB: 255, wantA: 255},
18+
"black": {input: coloring.Black(), wantR: 0, wantG: 0, wantB: 0, wantA: 1},
19+
"white": {input: coloring.White(), wantR: 1, wantG: 1, wantB: 1, wantA: 1},
20+
// "red": {input: coloring.Red(), wantR: 1, wantG: 0, wantB: 0, wantA: 1},
21+
// "green": {input: coloring.Green(), wantR: 0, wantG: 1, wantB: 0, wantA: 1},
22+
// "blue": {input: coloring.Blue(), wantR: 0, wantG: 0, wantB: 1, wantA: 1},
2323
}
2424

2525
for name, tc := range tests {

drawing/coloring/gradient.go

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,55 @@
11
package coloring
22

33
import (
4-
"image/color"
54
"sort"
5+
6+
"github.com/EliCDavis/vector"
7+
"github.com/EliCDavis/vector/vector1"
8+
"github.com/EliCDavis/vector/vector2"
9+
"github.com/EliCDavis/vector/vector3"
10+
"github.com/EliCDavis/vector/vector4"
611
)
712

8-
type GradientKey struct {
13+
type GradientKey[T any] struct {
914
Time float64
10-
Color color.Color
15+
Value T
1116
}
1217

13-
type normalizedGradientKey struct {
18+
type normalizedGradientKey[T any] struct {
1419
Time float64
15-
Color color.Color
20+
Color T
21+
}
22+
23+
func NewGradient1D(keys ...GradientKey[float64]) Gradient[float64] {
24+
return NewGradient(vector1.Space[float64]{}, keys...)
25+
}
26+
27+
func NewGradient2D(keys ...GradientKey[vector2.Float64]) Gradient[vector2.Float64] {
28+
return NewGradient(vector2.Space[float64]{}, keys...)
29+
}
30+
31+
func NewGradient3D(keys ...GradientKey[vector3.Float64]) Gradient[vector3.Float64] {
32+
return NewGradient(vector3.Space[float64]{}, keys...)
33+
}
34+
35+
func NewGradient4D(keys ...GradientKey[vector4.Float64]) Gradient[vector4.Float64] {
36+
return NewGradient(vector4.Space[float64]{}, keys...)
1637
}
1738

18-
func NewGradient(keys ...GradientKey) Gradient {
39+
func NewGradientColor(keys ...GradientKey[Color]) Gradient[Color] {
40+
return NewGradient(Space{}, keys...)
41+
}
42+
43+
func NewGradient[T any](space vector.Space[T], keys ...GradientKey[T]) Gradient[T] {
1944
if len(keys) == 0 {
20-
return Gradient{keys: []normalizedGradientKey{}}
45+
return Gradient[T]{
46+
space: space,
47+
keys: []normalizedGradientKey[T]{},
48+
}
2149
}
2250

2351
// Create a copy to avoid modifying the original slice
24-
keysCopy := make([]GradientKey, len(keys))
52+
keysCopy := make([]GradientKey[T], len(keys))
2553
copy(keysCopy, keys)
2654

2755
// Sort keys by time
@@ -35,28 +63,33 @@ func NewGradient(keys ...GradientKey) Gradient {
3563
timeRange := maxTime - minTime
3664

3765
// Create normalized keys
38-
normalizedKeys := make([]normalizedGradientKey, len(keysCopy))
66+
normalizedKeys := make([]normalizedGradientKey[T], len(keysCopy))
3967
for i, key := range keysCopy {
4068
normalizedTime := 0.0
4169
if timeRange > 0 {
4270
normalizedTime = (key.Time - minTime) / timeRange
4371
}
44-
normalizedKeys[i] = normalizedGradientKey{
72+
normalizedKeys[i] = normalizedGradientKey[T]{
4573
Time: normalizedTime,
46-
Color: key.Color,
74+
Color: key.Value,
4775
}
4876
}
4977

50-
return Gradient{keys: normalizedKeys}
78+
return Gradient[T]{
79+
keys: normalizedKeys,
80+
space: space,
81+
}
5182
}
5283

53-
type Gradient struct {
54-
keys []normalizedGradientKey
84+
type Gradient[T any] struct {
85+
keys []normalizedGradientKey[T]
86+
space vector.Space[T]
5587
}
5688

57-
func (g Gradient) Sample(t float64) color.Color {
89+
func (g Gradient[T]) Sample(t float64) T {
5890
if len(g.keys) == 0 {
59-
return color.RGBA{0, 0, 0, 255} // Default to black
91+
var t T
92+
return t
6093
}
6194

6295
if len(g.keys) == 1 {
@@ -96,23 +129,8 @@ func (g Gradient) Sample(t float64) color.Color {
96129
factor := (t - leftKey.Time) / timeRange
97130

98131
// Interpolate between the two colors
99-
return interpolateColors(leftKey.Color, rightKey.Color, factor)
100-
}
101-
102-
// Helper function to interpolate between two colors
103-
func interpolateColors(c1, c2 color.Color, factor float64) color.Color {
104-
r1, g1, b1, a1 := c1.RGBA()
105-
r2, g2, b2, a2 := c2.RGBA()
106-
107-
// Convert to 8-bit values for easier arithmetic
108-
r1, g1, b1, a1 = r1>>8, g1>>8, b1>>8, a1>>8
109-
r2, g2, b2, a2 = r2>>8, g2>>8, b2>>8, a2>>8
110-
111-
// Linear interpolation
112-
r := uint8(float64(r1)*(1-factor) + float64(r2)*factor)
113-
g := uint8(float64(g1)*(1-factor) + float64(g2)*factor)
114-
b := uint8(float64(b1)*(1-factor) + float64(b2)*factor)
115-
a := uint8(float64(a1)*(1-factor) + float64(a2)*factor)
116-
117-
return color.RGBA{r, g, b, a}
132+
return g.space.Add(
133+
g.space.Scale(leftKey.Color, 1-factor),
134+
g.space.Scale(rightKey.Color, factor),
135+
)
118136
}

0 commit comments

Comments
 (0)