feat: expanded perlin bg. gen. randomization
- wider scale ranges for more visible pattern variations - larger offset ranges for more unique starting points - randomized noise weights instead of fixed 0.6/0.3/0.1 ratios - randomized gradient strength & direction (30% chance of reverse for each axis) - randomized light-to-dark effects - multiple combination methods: - standard linear blend (cur.) - multiplicative blend (flowing, organic patterns) - maximum blend (sharper, more contrasted patterns) - turbulence (chaotic, cloud-like patterns) - 30% chance for additional subtle sine/cosine distortion
This commit is contained in:
parent
04d6693c37
commit
fb8c0f12d5
95
banner.go
95
banner.go
@ -5,6 +5,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/png"
|
"image/png"
|
||||||
|
"math"
|
||||||
"math/rand/v2"
|
"math/rand/v2"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -256,36 +257,96 @@ func genPerlinBG() *image.RGBA {
|
|||||||
img := image.NewRGBA(image.Rect(0, 0, config.BannerWidth, config.BannerHeight))
|
img := image.NewRGBA(image.Rect(0, 0, config.BannerWidth, config.BannerHeight))
|
||||||
|
|
||||||
// noise params for interesting patterns
|
// noise params for interesting patterns
|
||||||
scale1 := 0.01 + rand.Float64()*0.02 // primary pattern scale (adjusted by lib)
|
scale1 := 0.005 + rand.Float64()*0.025 // primary pattern scale (adjusted by lib)
|
||||||
scale2 := 0.03 + rand.Float64()*0.03 // secondary detail
|
scale2 := 0.02 + rand.Float64()*0.04 // secondary detail
|
||||||
scale3 := 0.08 + rand.Float64()*0.05 // fine detail
|
scale3 := 0.06 + rand.Float64()*0.08 // fine detail
|
||||||
|
|
||||||
// variation offsets
|
// variation offsets
|
||||||
offsetX := rand.Float64() * 1000
|
offsetX := rand.Float64() * 5000
|
||||||
offsetY := rand.Float64() * 1000
|
offsetY := rand.Float64() * 5000
|
||||||
|
|
||||||
log.Infof("Generating background with theme: %s, scales: %.4f, %.4f, %.4f", theme, scale1, scale2, scale3)
|
// noise layer weights for different effects
|
||||||
|
weight1 := 0.4 + rand.Float64()*0.4
|
||||||
|
weight2 := 0.2 + rand.Float64()*0.3
|
||||||
|
weight3 := 0.1 + rand.Float64()*0.2
|
||||||
|
|
||||||
|
// normalize weights to sum to 1.0
|
||||||
|
totalWeight := weight1 + weight2 + weight3
|
||||||
|
weight1 /= totalWeight
|
||||||
|
weight2 /= totalWeight
|
||||||
|
weight3 /= totalWeight
|
||||||
|
|
||||||
|
gradientStrengthX := rand.Float64() * 0.4
|
||||||
|
gradientStrengthY := rand.Float64() * 0.3
|
||||||
|
gradientDirectionX := 1.0
|
||||||
|
gradientDirectionY := 1.0
|
||||||
|
|
||||||
|
// sometimes reverse gradient direction for variety
|
||||||
|
if rand.Float64() < 0.3 {
|
||||||
|
gradientDirectionX = -1.0
|
||||||
|
}
|
||||||
|
if rand.Float64() < 0.3 {
|
||||||
|
gradientDirectionY = -1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// randomize noise combination method
|
||||||
|
combineMethod := rand.IntN(4)
|
||||||
|
|
||||||
|
useDistortion := rand.Float64() < 0.3 // 30% chance
|
||||||
|
distortionStrength := rand.Float64() * 0.1
|
||||||
|
|
||||||
|
log.Debugf("BG theme: %s / Scales: %.4f, %.4f, %.4f / Weights: %.3f, %.3f, %.3f",
|
||||||
|
theme, scale1, scale2, scale3, weight1, weight2, weight3)
|
||||||
|
log.Debugf("Gradient: X=%.3f*%.0f, Y=%.3f*%.0f / Combine method: %d / Distortion %t (%.3f)",
|
||||||
|
gradientStrengthX, gradientDirectionX, gradientStrengthY, gradientDirectionY,
|
||||||
|
combineMethod, useDistortion, distortionStrength)
|
||||||
|
|
||||||
for y := range config.BannerHeight {
|
for y := range config.BannerHeight {
|
||||||
for x := range config.BannerWidth {
|
for x := range config.BannerWidth {
|
||||||
// multi-octave noise
|
baseX := float64(x) + offsetX
|
||||||
fx := (float64(x) + offsetX) * scale1
|
baseY := float64(y) + offsetY
|
||||||
fy := (float64(y) + offsetY) * scale1
|
|
||||||
|
// optional distortion for more organic patterns
|
||||||
|
if useDistortion {
|
||||||
|
baseX += math.Sin(float64(y)*0.01) * distortionStrength * 100
|
||||||
|
baseY += math.Cos(float64(x)*0.01) * distortionStrength * 100
|
||||||
|
}
|
||||||
|
|
||||||
|
// multi-octave noise with randomized scales
|
||||||
|
fx1 := baseX * scale1
|
||||||
|
fy1 := baseY * scale1
|
||||||
|
fx2 := baseX * scale2
|
||||||
|
fy2 := baseY * scale2
|
||||||
|
fx3 := baseX * scale3
|
||||||
|
fy3 := baseY * scale3
|
||||||
|
|
||||||
// noise values at different scales
|
// noise values at different scales
|
||||||
noise1 := perlinNoise.Noise2D(fx, fy)
|
noise1 := perlinNoise.Noise2D(fx1, fy1)
|
||||||
noise2 := perlinNoise.Noise2D(fx/scale1*scale2, fy/scale1*scale2)
|
noise2 := perlinNoise.Noise2D(fx2, fy2)
|
||||||
noise3 := perlinNoise.Noise2D(fx/scale1*scale3, fy/scale1*scale3)
|
noise3 := perlinNoise.Noise2D(fx3, fy3)
|
||||||
|
|
||||||
// combined noise layers with different weights
|
// different combination methods for variety
|
||||||
combined := noise1*0.6 + noise2*0.3 + noise3*0.1
|
var combined float64
|
||||||
|
switch combineMethod {
|
||||||
|
case 0: // standard linear combination
|
||||||
|
combined = noise1*weight1 + noise2*weight2 + noise3*weight3
|
||||||
|
case 1: // multiplicative blend
|
||||||
|
combined = (noise1*weight1)*(1+noise2*weight2)*(1+noise3*weight3) - 1
|
||||||
|
case 2: // maximum blend (creates sharper patterns)
|
||||||
|
values := []float64{noise1 * weight1, noise2 * weight2, noise3 * weight3}
|
||||||
|
combined = math.Max(math.Max(values[0], values[1]), values[2])
|
||||||
|
case 3: // turbulence (abs. values create more chaotic patterns)
|
||||||
|
combined = math.Abs(noise1)*weight1 + math.Abs(noise2)*weight2 + math.Abs(noise3)*weight3
|
||||||
|
}
|
||||||
|
|
||||||
// position-based gradient for a more dynamic look
|
// randomized gradient with variable direction and strength
|
||||||
gradientX := float64(x) / float64(config.BannerWidth) * 0.2
|
gradientX := (float64(x) / float64(config.BannerWidth)) * gradientStrengthX * gradientDirectionX
|
||||||
gradientY := float64(y) / float64(config.BannerHeight) * 0.1
|
gradientY := (float64(y) / float64(config.BannerHeight)) * gradientStrengthY * gradientDirectionY
|
||||||
|
|
||||||
// combined and normalized to [0, 1] range
|
// combined and normalized to [0, 1] range
|
||||||
noise := (combined + gradientX + gradientY + 1) / 2
|
noise := (combined + gradientX + gradientY + 1) / 2
|
||||||
|
|
||||||
|
// clamp to valid range
|
||||||
if noise < 0 {
|
if noise < 0 {
|
||||||
noise = 0
|
noise = 0
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user