diff --git a/field.go b/field.go index 1277f4d..a6b6bef 100644 --- a/field.go +++ b/field.go @@ -19,16 +19,16 @@ type ScaleField struct { } func (f *ScaleField) Get(x, y float32) float32 { - return f.field.Get(x / f.scale, y / f.scale) + return f.field.Get(x/f.scale, y/f.scale) } type TranslateField struct { field Field - x, y float32 + x, y float32 } func (f *TranslateField) Get(x, y float32) float32 { - return f.field.Get(x + f.x, y + f.y) + return f.field.Get(x+f.x, y+f.y) } // NOISE FIELDS @@ -44,13 +44,13 @@ func (f *SimplexNoiseField) Get(x, y float32) float32 { // IMAGE FIELDS type ImageField struct { - image *rl.Image - pixels ImagePixels + image *rl.Image + pixels ImagePixels offsetX, offsetY float32 } type ImagePixels struct { - w, h int + w, h int colors []rl.Color } @@ -61,22 +61,22 @@ func (p *ImagePixels) Get(x, y int) rl.Color { if y < 0 || y >= p.h { return rl.Black } - return p.colors[x + y * p.w] + return p.colors[x+y*p.w] } func NewImageField(path string) ImageField { image := rl.LoadImage(path) colors := rl.LoadImageColors(image) - pixels := ImagePixels { - w: int(image.Width), - h: int(image.Height), + pixels := ImagePixels{ + w: int(image.Width), + h: int(image.Height), colors: colors, } offsetX := float32(image.Width / 2) offsetY := float32(image.Height / 2) - return ImageField { - image: image, - pixels: pixels, + return ImageField{ + image: image, + pixels: pixels, offsetX: offsetX, offsetY: offsetY, } @@ -84,6 +84,6 @@ func NewImageField(path string) ImageField { func (f *ImageField) Get(x, y float32) float32 { // todo : blend colors - c := f.pixels.Get(int(x+f.offsetX), int(y + f.offsetY)) + c := f.pixels.Get(int(x+f.offsetX), int(y+f.offsetY)) return Brightness(c) } diff --git a/main.go b/main.go index bfd6cc2..77a84e0 100644 --- a/main.go +++ b/main.go @@ -13,12 +13,48 @@ import ( ) const ( - screenWidth = 3000 - screenHeight = 2000 + screenWidth = 800 + screenHeight = 600 + sourceWidth = 10000 + sourceHeight = 10000 displayScale = 2 snapshotsDir = "snapshots" ) +func main3() { + rl.InitWindow(800, 600, "rt test") + defer rl.CloseWindow() + + rt := rl.LoadRenderTexture(512, 512) + defer rl.UnloadRenderTexture(rt) + + for !rl.WindowShouldClose() { + // draw into offscreen buffer + rl.BeginTextureMode(rt) + rl.ClearBackground(rl.Blank) + rl.DrawCircle(256, 256, 100, rl.Red) + rl.EndTextureMode() + + // draw to screen + rl.BeginDrawing() + rl.ClearBackground(rl.RayWhite) + + src := rl.Rectangle{ + X: 0, Y: 0, + Width: float32(rt.Texture.Width), + Height: -float32(rt.Texture.Height), + } + dst := rl.Rectangle{ + X: 0, Y: 0, + Width: 800, + Height: 600, + } + + rl.DrawTexturePro(rt.Texture, src, dst, rl.Vector2{}, 0, rl.White) + rl.EndDrawing() + } +} + func main() { os.MkdirAll(snapshotsDir, 0755) @@ -47,32 +83,29 @@ func main() { } /* - field := - ScaleField { - Scale: 50.0, - Field: &SimplexNoiseField { - Noise: opensimplex.NewNormalized32(0), - }, - } + field := + ScaleField { + Scale: 50.0, + Field: &SimplexNoiseField { + Noise: opensimplex.NewNormalized32(0), + }, + } + + imgf := NewImageField("/home/d/Dropbox/art/passage/data/david.png") + + imageField := + ScaleField{ + field: &imgf, + scale: 0.5, + } */ - imgf := NewImageField("/home/d/Dropbox/art/passage/data/david.png") - imageField := - ScaleField { - field: &imgf, - scale: 0.5, - } + //rng := rand.New(rand.NewSource(0)) - rng := rand.New(rand.NewSource(0)) + //contourSketch := NewContourLayer(rng, &imageField) - contourSketch := NewContourLayer(rng, &imageField) - - sketch := Sketch { - layers: []Layer { - &contourSketch, - //&FieldSketch { Field: &imageField }, - }, - } + sketch := NewSketch() + sketch.CreateLayer("testPattern", &TestPattern{}, sourceWidth, sourceHeight) rl.SetTargetFPS(60) @@ -90,30 +123,33 @@ func main() { updateCamera(&camera) // begin drawing - rl.BeginDrawing() - //rl.ClearBackground(rl.Black) - rl.BeginMode2D(camera) - rl.BeginBlendMode(rl.BlendAdditive) t := time.Since(t0).Seconds() // set up RenderCtx renderCtx := &RenderCtx{ - Width: int32(w), - Height: int32(h), - Time: t, - Ports: ports.Eval(t), - Cam: camera, + TargetWidth: int32(w), + TargetHeight: int32(h), + SourceWidth: int32(sourceWidth), + SourceHeight: int32(sourceHeight), + Time: t, + Ports: ports.Eval(t), + Cam: camera, } /** MAIN DRAWING **/ + rl.BeginDrawing() + rl.ClearBackground(rl.Blank) - rl.PushMatrix() + //rl.PushMatrix() sketch.Draw(renderCtx) - rl.PopMatrix() - rl.DrawCircle(0, 0, 10, rl.Green) + rl.DrawText("Mouse right button drag to move, mouse wheel to zoom", 10, 10, 20, rl.White) + //rl.PopMatrix() + + rl.EndDrawing() + //rl.DrawCircle(0, 0, 10, rl.Green) if rl.IsKeyDown(rl.KeySpace) { if _, err := storage.Save(); err != nil { @@ -121,12 +157,9 @@ func main() { } } - rl.EndBlendMode() - rl.EndMode2D() + //rl.EndMode2D() // HUD - rl.DrawText("Mouse right button drag to move, mouse wheel to zoom", 10, 10, 20, rl.Black) - rl.EndDrawing() } rl.CloseWindow() @@ -138,9 +171,9 @@ type FieldSketch struct { func (s *FieldSketch) Draw(ctx *RenderCtx) { fmt.Printf("drawing field") - for x := range ctx.Width { - for y := range ctx.Height { - screen := rl.Vector2 { X: float32(x), Y: float32(y) } + for x := range ctx.TargetWidth { + for y := range ctx.TargetHeight { + screen := rl.Vector2{X: float32(x), Y: float32(y)} world := rl.GetScreenToWorld2D(screen, ctx.Cam) v := s.Field.Get(world.X, world.Y) clr := GrayCurve(v, 1.0) @@ -150,7 +183,7 @@ func (s *FieldSketch) Draw(ctx *RenderCtx) { } type ContourLayer struct { - field Field + field Field actors []*Actor } @@ -158,16 +191,16 @@ func NewContourLayer(rng *rand.Rand, field Field) ContourLayer { actors := make([]*Actor, 20000) for i := range len(actors) { - actors[i] = - &Actor { + actors[i] = + &Actor{ position: RandRadialVec(rng, 0, 500, 0, 360), - field: field, + field: field, stepSize: 1, - color: rl.NewColor(11, 35, 176, 100), + color: rl.NewColor(11, 35, 176, 100), } } - return ContourLayer { + return ContourLayer{ actors: actors, } } @@ -178,29 +211,27 @@ func (s *ContourLayer) Draw(ctx *RenderCtx) { } } - type Actor struct { position rl.Vector2 - field Field + field Field stepSize float32 - color rl.Color + color rl.Color } func (a *Actor) Draw() { v := a.field.Get(a.position.X, a.position.Y) - rad := rl.Remap(v, 0, 1, 0, 3 * math.Pi) - nextPosition := rl.Vector2 { X: a.position.X + a.stepSize*float32(math.Cos(float64(rad))), Y: a.position.Y + a.stepSize*float32(math.Sin(float64(rad))) } + rad := rl.Remap(v, 0, 1, 0, 3*math.Pi) + nextPosition := rl.Vector2{X: a.position.X + a.stepSize*float32(math.Cos(float64(rad))), Y: a.position.Y + a.stepSize*float32(math.Sin(float64(rad)))} rl.DrawLineV(a.position, nextPosition, a.color) //fmt.Printf("position %v -> nextPosition %v \n", a.position, nextPosition) a.position = nextPosition } - func RandRadialVec(rng *rand.Rand, minRadius float32, maxRadius float32, loAngle float32, hiAngle float32) rl.Vector2 { r := float64(rl.Remap(rng.Float32(), 0, 1, minRadius, maxRadius)) deg := float64(rl.Remap(rng.Float32(), 0, 1, loAngle, hiAngle)) rad := rl.Deg2rad * deg - return rl.Vector2 { X: float32(r * math.Cos(rad)), Y: float32(r * math.Sin(rad)) } + return rl.Vector2{X: float32(r * math.Cos(rad)), Y: float32(r * math.Sin(rad))} } func updateCamera(camera *rl.Camera2D) { @@ -237,11 +268,11 @@ func updateCamera(camera *rl.Camera2D) { } type Worm struct { - position rl.Vector2 - angles []float32 + position rl.Vector2 + angles []float32 angleIndex int - stepSize int - renderPct float32 + stepSize int + renderPct float32 } func (w *Worm) Draw(ctx *RenderCtx) { @@ -256,7 +287,7 @@ func (w *Worm) Draw(ctx *RenderCtx) { deltaAngle := angle - lastAngle if !nudged { rad := float64(deltaAngle * math.Pi / 180.0) - nudge := rl.Vector2 { X: float32(w.stepSize) * float32(math.Cos(rad)), Y: float32(w.stepSize) * float32(math.Sin(rad)) } + nudge := rl.Vector2{X: float32(w.stepSize) * float32(math.Cos(rad)), Y: float32(w.stepSize) * float32(math.Sin(rad))} w.position = rl.Vector2Add(w.position, nudge) nudged = true } diff --git a/sketch.go b/sketch.go index 2d985f1..4423b67 100644 --- a/sketch.go +++ b/sketch.go @@ -5,21 +5,75 @@ import ( ) type Sketch struct { - layers []Layer + layerTools map[string]LayerTools } -func (s *Sketch) Draw(ctx *RenderCtx) { - for _, layer := range s.layers { - layer.Draw(ctx) +func NewSketch() Sketch { + return Sketch { + layerTools: make(map[string]LayerTools), } } +func (s *Sketch) CreateLayer(name string, layer Layer, sourceWidth int32, sourceHeight int32) { + texture := rl.LoadRenderTexture(sourceWidth, sourceHeight) + s.layerTools[name] = LayerTools { + name: name, + texture: &texture, + layer: layer, + } +} +func (s *Sketch) Draw(ctx *RenderCtx) { + // render onto all layer textures + for _, instance := range s.layerTools { + layer := instance.layer + rl.BeginTextureMode(*instance.texture) + layer.Draw(ctx) + rl.EndTextureMode() + } + // composite all layers to screen + + src := rl.Rectangle { + X: 0, Y: 0, + Width: float32(ctx.SourceWidth), + Height: -float32(ctx.SourceHeight), + } + dst := rl.Rectangle { + X: 0, Y: 0, + Width: float32(ctx.TargetWidth), + Height: float32(ctx.TargetHeight), + } + + for _, instance := range s.layerTools { + rl.DrawTexturePro(instance.texture.Texture, src, dst, rl.Vector2{}, 0, rl.White) + } + +} + +type LayerTools struct { + name string + layer Layer + texture *rl.RenderTexture2D +} + + +/** Layer **/ type Layer interface { Draw(ctx *RenderCtx) } +type TestPattern struct { } + +func (tp *TestPattern) Draw(ctx *RenderCtx) { + rl.DrawRectangle(0, 0, int32(ctx.SourceWidth), int32(ctx.SourceHeight), rl.Magenta) + rl.PushMatrix() + rl.Translatef(float32(ctx.SourceWidth)/2.0, float32(ctx.SourceHeight)/2.0, 0.0) + rl.DrawRectangle(-100, -100, 200, 200, rl.Green) + rl.PopMatrix() +} + + /** Ports **/ type Ports map[string]Signal @@ -42,8 +96,10 @@ func (p Ports) Eval(t float64) map[string]float64 { /** RenderCtx **/ type RenderCtx struct { - Width int32 - Height int32 + TargetWidth int32 + TargetHeight int32 + SourceWidth int32 + SourceHeight int32 Time float64 Ports map[string]float64 Cam rl.Camera2D diff --git a/utils.go b/utils.go index 6321248..ef2c340 100644 --- a/utils.go +++ b/utils.go @@ -1,8 +1,8 @@ package main import ( - "math" "github.com/gen2brain/raylib-go/raylib" + "math" ) func clamp01(v float32) float32 { @@ -27,4 +27,3 @@ func Brightness(c rl.Color) float32 { b := float32(c.B) / 255 return 0.2126*r + 0.7152*g + 0.0722*b } -