package main
import (
"fmt"
"image"
"image/color"
"math"
"os"
)
const (
width = 200
height = 200
scale = 40.0
octaves = 3
persistence = 0.5
lacunarity = 2.0
)
func main() {
img := image.NewRGBA(image.Rect(0, 0, width, height))
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
noiseValue := perlinNoise(float64(x)/scale, float64(y)/scale, octaves, persistence, lacunarity)
grayscale := uint8((noiseValue + 1) / 2 * 255)
col := color.RGBA{grayscale, grayscale, grayscale, 255}
img.Set(x, y, col)
}
}
f, err := os.Create("perlin_noise.png")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
if err := png.Encode(f, img); err != nil {
fmt.Println(err)
return
}
fmt.Println("Perlin noise image generated!")
}
func perlinNoise(x, y float64, octaves int, persistence, lacunarity float64) float64 {
var total float64 = 0.0
var frequency float64 = 1.0
var amplitude float64 = 1.0
var maxValue float64 = 0.0
for i := 0; i < octaves; i++ {
total += interpolatedNoise(xfrequency, yfrequency) * amplitude
maxValue += amplitude
amplitude *= persistence
frequency *= lacunarity
}
return total / maxValue
}
func interpolatedNoise(x, y float64) float64 {
xInt := int(x)
yInt := int(y)
fractionalX := x - float64(xInt)
fractionalY := y - float64(yInt)
v1 := smoothNoise(xInt, yInt)
v2 := smoothNoise(xInt+1, yInt)
v3 := smoothNoise(xInt, yInt+1)
v4 := smoothNoise(xInt+1, yInt+1)
i1 := interpolate(v1, v2, fractionalX)
i2 := interpolate(v3, v4, fractionalX)
return interpolate(i1, i2, fractionalY)
}
func smoothNoise(x, y int) float64 {
corners := (noise(x-1, y-1) + noise(x+1, y-1) + noise(x-1, y+1) + noise(x+1, y+1)) / 16.0
sides := (noise(x-1, y) + noise(x+1, y) + noise(x, y-1) + noise(x, y+1)) / 8.0
center := noise(x, y) / 4.0
return corners + sides + center
}
func noise(x, y int) float64 {
n := x + y*57
n = (n << 13) ^ n
return (1.0 - ((float64(n(nn*15731+789221)+1376312589) & 0x7fffffff) / 1073741824.0))
}
func interpolate(a, b, x float64) float64 {
ft := x * math.Pi
f := (1 - math.Cos(ft)) * 0.5
return a(1-f) + bf
}