noise

package module
v0.1.0-rc1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 26, 2022 License: MIT Imports: 4 Imported by: 1

README

Go Reference

Go-Noise

go-noise is a Go package for generating a gradient noise between -1 and 1.

It is a wrapper to facilitate the use of go-perlin and opensimplex-go. And also to understand them better.

1D Example

In the example below, 1 dimmentional method noise.Generator.Eval64(x) was used to generate the noise value y at the position (x).

// import "github.com/KEINOS/go-noise"
//
// const seed = 100       // noise pattern ID
// const smoothness = 100 // noise smoothness
//
// // noiseType choises
// noiseType := noise.Perlin
// noiseType := noise.OpenSimplex
// noiseType := noise.Custom
n, err := noise.New(noiseType, seed)

yy := n.Eval64(x / smoothness) // yy is between -1.0 and 1.0 of float64
y := (yy + 1) / 2 * 500        // y is between 0 and 500

2D Example

// Obtain the noise value at the position (x, y)
n, err := noise.New(noiseType, seed)
v := n.Eval64(x, y) // v is between -1.0 and 1.0 of float64

To create a 2D image, plot the v value at the position (x, y) in the 2D space. The 2D image example is equivalent to a frame of the 3D image example below.

3D Example

In the example below, three dimmentional method noise.Generator.Eval64(x, y, z) was used to generate the noise value at the position (x, y, z).

The x and y are the axes of 2D image and the z is the axis for "time", or animation frame, of the 3D noise sample.

Perlin Noise Sample
// Obtain the noise value at the position (x, y, z)
n, err := noise.New(noise.Perlin, seed)
v := n.Eval64(x, y, z) // v is between -1.0 and 1.0 of float64

OpenSimplex Noise Sample
// Obtain the noise value at the position (x, y, z)
n, err := noise.New(noise.OpenSimplex, seed)
v := n.Eval64(x, y, z) // v is between -1.0 and 1.0 of float64

Note

This package ONLY supports up to 3 dimensions. If more than 3 dimentions were given, such as noise.Generator.Eval64(w, x, y, z), it will retrun a 0 (zero) value.

Usage

Require module
go get "github.com/KEINOS/go-noise"
Constructor
noise.New(noiseType noise.Algo, seed int64) (noise.Generator, error)
import "github.com/KEINOS/go-noise"

// Seed is like pattern ID.
// If the seed values are the same, the noise pattern will also be the
// same.
const seed = 100

// Noise generator for Perlin noise
genNoise, err := noise.New(noise.Perlin, seed)
import "github.com/KEINOS/go-noise"

// Seed is like pattern ID.
// If the seed values are the same, the noise pattern will also be the
// same.
const seed = 100

// Noise generator for OpenSimplex noise
genNoise, err := noise.New(noise.OpenSimplex, seed)
Methods
a := genNoise.Eval32(x)       // 1D noise. Generate noise at x.
b := genNoise.Eval32(x, y)    // 2D noise. Generate noise at x, y.
c := genNoise.Eval32(x, y, z) // 3D noise. Generate noise at x, y, z.

// a, b, c, x, y, z are float32.
// Noises a, b, c are between -1.0 and 1.0.
a := genNoise.Eval64(x)       // 1D noise. Generate noise at x.
b := genNoise.Eval64(x, y)    // 2D noise. Generate noise at x, y.
c := genNoise.Eval64(x, y, z) // 3D noise. Generate noise at x, y, z.

// a, b, c, x, y, z are float64.
// Noises a, b, c are between -1.0 and 1.0.
Brief Example
import "github.com/KEINOS/go-noise"

const seed = 100
const frame = 50

// Create new noise generator of Perlin type
genNoise, err := noise.New(noise.Perlin, seed)

if err != nil {
    // error handle
}

for z := 0; z < frame; z++ {
    zz := float64(z) / 5 // smoothness between frames

    /* Here create a new image of a frame */

    for y := 0; y < height; y++ {
        yy := float64(y) / 25 // smoothness between plotting points

        for x := 0; x < width; x++ {
            xx := float64(x) / 25 // smoothness between plotting points

            // n is a float64 value between -1 and 1
            n := genNoise.Eval64(xx, yy, zz)

            // Convert n to 0-255 scale
            grayColor := ((1. - in) / 2.) * 255.

            pixelToPlot := color.Gray{Y: uint8(grayColor)}

            /* Here plot the pixel to the current image */
        }
    }

    /* Here save the current frame/image to a file */
}

/* Here animate the frames if you want */

Contribute

Go Reference

  • Pull Request:
    • Any PR for improvement is welcome! We will merge it as soon as it passes the CIs and not a prank-kind implementation. ;-)
    • PR Branch: main
      • It is recommended to do a "Draft-PR" before the actual implementation if the fix is big. However, feel free to discard it as well!
    • CI/CD: Github Actions
      • go test ./...
      • golangci-lint run
      • golint ./...
      • Code coverage check: 100% of coverage.
  • Bug reports:
    • Issues
    • If possible, please attach a simple reproduction code sample of the error. PRs for the fixes are much appreciated. 🙏
Statuses

PlatformTests golangci-lint CodeQL codecov Go Report Card

Weekly Update Opened Issues PR

License

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Algo

type Algo int

Algo represents the algorithm of the noise to generate.

const (
	// Unknown noise type.
	Unknown Algo = iota
	// Perlin noise type.
	Perlin
	// OpenSimplex noise type.
	OpenSimplex
	// Custom uses the user-defined function to generate noise.
	Custom
)

type Generator

type Generator interface {
	// Eval32 returns a float32 noise value at given coordinates. The maximum
	// number of arguments is three.
	//
	// Example:
	//   Eval32(x)
	//   Eval32(x, y)
	//   Eval32(x, y, z)
	//
	// Implementations of this method must return the same value if the seed
	// value is the same.
	Eval32(dim ...float32) float32
	// Eval64 returns a float64 noise value at given coordinates. The maximum
	// number of arguments is three.
	//
	// Example:
	//   Eval64(x)
	//   Eval64(x, y)
	//   Eval64(x, y, z)
	//
	// Implementations of this method must return the same value if the seed
	// value is the same.
	Eval64(dim ...float64) float64
	SetEval32(f func(seed int64, dim ...float32) float32) error
	SetEval64(f func(seed int64, dim ...float64) float64) error
}

Generator is an interface for noise generator.

func New

func New(noiseType Algo, seed int64) (Generator, error)

New returns a new noise generator.

Example
//nolint:gosec // Example value
seed := rand.Int63()

noise, err := noise.New(noise.OpenSimplex, seed)
if err != nil {
	log.Fatal(err)
}

w, h := 100, 100

heightmap := make([]float64, w*h)

for y := 0; y < h; y++ {
	for x := 0; x < w; x++ {
		xFloat := float64(x / w)
		yFloat := float64(y / h)

		heightmap[(y*w)+x] = noise.Eval64(xFloat, yFloat)
	}
}
Output:

Example (Assign_user_defined_function)
const seed = 100

// Create a noise generator.
gen, err := noise.New(noise.Custom, seed)
if err != nil {
	log.Fatal(err)
}

// rnd is a random number generator.
var rnd *rand.Rand

// Define user function to generate custom noise.
// Here we define a function that returns a pseudo-random value from the
// given seed and itereate 'dim' times.
myFunc := func(seed int64, dim ...float32) float32 {
	if rnd == nil {
		//nolint:gosec // Use of weak random number generation is intended here.
		rnd = rand.New(rand.NewSource(seed))
	}

	for i := 0; i < len(dim); i++ {
		max := int(dim[i])

		for ii := 0; ii < max; ii++ {
			_ = rnd.Float32()
		}
	}

	// Generate a pseudo-random number.
	v := rnd.Float32()

	return v*2 - 1 // Convert [0.0,1.0] to [-1.0,1.0]
}

// Assign user-defined function
if err := gen.SetEval32(myFunc); err != nil {
	log.Fatal(err)
}

// Get noise value at (1, 2, 3)
fmt.Println(gen.Eval32(1, 2, 3))
Output:

-0.1159181
Example (One_dimension_opensimplex_in_float64)
const seed = 100

gen, err := noise.New(noise.OpenSimplex, seed)
if err != nil {
	log.Fatal(err)
}

for x := float64(0); x < 3; x++ {
	fmt.Printf("%0.4f;%0.4f\n",
		x/10,
		gen.Eval64(x/10),
	)
}
Output:

0.0000;0.0000
0.1000;0.0950
0.2000;0.1385
Example (One_dimension_opensimplex_noise_in_float32)
const seed = 100

gen, err := noise.New(noise.OpenSimplex, seed)
if err != nil {
	log.Fatal(err)
}

for x := float32(0); x < 3; x++ {
	fmt.Printf(
		"%0.0f;%0.4f\n",
		x,
		gen.Eval32(x/10),
	)
}
Output:

0;0.0000
1;0.0950
2;0.1385
Example (One_dimension_perlin_noise_in_float32)
const seed = 100

gen, err := noise.New(noise.Perlin, seed)
if err != nil {
	log.Fatal(err)
}

for x := float32(0); x < 3; x++ {
	fmt.Printf("%0.0f;%0.4f\n", x, gen.Eval32(x/100))
}
Output:

0;0.0000
1;-0.0026
2;-0.0046
Example (One_dimension_perlin_noise_in_float64)
const seed = 100

gen, err := noise.New(noise.Perlin, seed)
if err != nil {
	log.Fatal(err)
}

for x := float64(0); x < 3; x++ {
	fmt.Printf("%0.0f;%0.4f\n", x, gen.Eval64(x/10))
}
Output:

0;0.0000
1;-0.0086
2;-0.0017
Example (Three_dimension_opensimplex_noise_in_float32)
const seed = 100

gen, err := noise.New(noise.OpenSimplex, seed)
if err != nil {
	log.Fatal(err)
}

for x := float32(0); x < 2; x++ {
	for y := float32(0); y < 2; y++ {
		for z := float32(0); z < 2; z++ {
			fmt.Printf(
				"%0.0f;%0.0f;%0.0f;%0.4f\n",
				x, y, z,
				gen.Eval32(x/10, y/10, z/10),
			)
		}
	}
}
Output:

0;0;0;0.0000
0;0;1;-0.1672
0;1;0;0.0607
0;1;1;-0.1040
1;0;0;-0.0611
1;0;1;-0.2227
1;1;0;0.0003
1;1;1;-0.1585
Example (Three_dimension_perlin_noise_in_float32)
const seed = 100

gen, err := noise.New(noise.Perlin, seed)
if err != nil {
	log.Fatal(err)
}

for x := float32(0); x < 2; x++ {
	for y := float32(0); y < 2; y++ {
		for z := float32(0); z < 2; z++ {
			fmt.Printf("%0.0f;%0.0f;%0.0f;%0.4f\n", x, y, z, gen.Eval32(x/10, y/10, z/10))
		}
	}
}
Output:

0;0;0;0.0000
0;0;1;0.2616
0;1;0;-0.0755
0;1;1;0.2020
1;0;0;-0.2138
1;0;1;0.0616
1;1;0;-0.2208
1;1;1;0.0304
Example (Three_dimension_perlin_noise_in_float64)
const seed = 100

gen, err := noise.New(noise.Perlin, seed)
if err != nil {
	log.Fatal(err)
}

for x := float64(0); x < 2; x++ {
	for y := float64(0); y < 2; y++ {
		for z := float64(0); z < 2; z++ {
			fmt.Printf("%0.0f;%0.0f;%0.0f;%0.4f\n", x, y, z, gen.Eval64(x/10, y/10, z/10))
		}
	}
}
Output:

0;0;0;0.0000
0;0;1;0.2616
0;1;0;-0.0755
0;1;1;0.2020
1;0;0;-0.2138
1;0;1;0.0616
1;1;0;-0.2208
1;1;1;0.0304
Example (Two_dimension_opensimplex_noise_in_float32)
const seed = 100

gen, err := noise.New(noise.OpenSimplex, seed)
if err != nil {
	log.Fatal(err)
}

for x := float32(0); x < 2; x++ {
	for y := float32(0); y < 2; y++ {
		fmt.Printf(
			"%0.0f;%0.0f;%0.4f\n",
			x, y,
			gen.Eval32(x/10, y/10),
		)
	}
}
Output:

0;0;0.0000
0;1;-0.0673
1;0;0.1664
1;1;0.0950
Example (Two_dimension_perlin_noise_in_float32)
const seed = 100

gen, err := noise.New(noise.Perlin, seed)
if err != nil {
	log.Fatal(err)
}

for x := float32(0); x < 2; x++ {
	for y := float32(0); y < 2; y++ {
		fmt.Printf("%0.0f;%0.0f;%0.4f\n", x, y, gen.Eval32(x/10, y/10))
	}
}
Output:

0;0;0.0000
0;1;-0.2002
1;0;-0.3389
1;1;-0.5045
Example (Two_dimension_perlin_noise_in_float64)
const seed = 100

gen, err := noise.New(noise.Perlin, seed)
if err != nil {
	log.Fatal(err)
}

for x := float64(0); x < 2; x++ {
	for y := float64(0); y < 2; y++ {
		fmt.Printf("%0.0f;%0.0f;%0.4f\n", x, y, gen.Eval64(x/10, y/10))
	}
}
Output:

0;0;0.0000
0;1;-0.2002
1;0;-0.3389
1;1;-0.5045

Directories

Path Synopsis
_example
2d
3d
pkg
custom
Package custom provides a noise generator using the user-defined function.
Package custom provides a noise generator using the user-defined function.
perlin
Package perlin is a wrapper of github.com/aquilax/go-perlin.
Package perlin is a wrapper of github.com/aquilax/go-perlin.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL