The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Acme::Noisemaker - Visual noise generator

VERSION

This document is for version 0.006 of Acme::Noisemaker.

SYNOPSIS;

  use Acme::Noisemaker qw| make |;

Make some noise and save it as an image to the specified filename:

  make(
    type => $type,        # white|square|perlin|complex
    out  => $filename,    # "pattern.bmp"

    #
    # Any noise args or post-processing args
    #
  );

A wrapper script, bin/make-noise, is included with this distribution.

  bin/make-noise --type complex --out pattern.bmp

Noise sets are just 2D arrays:

  use Acme::Noisemaker qw| :flavors |;

  my $grid = square(%args);

  #
  # Look up a value, given X and Y coords
  #
  my $value = $grid->[$x]->[$y];

Imager can take care of further post-processing.

  my $grid = perlin(%args);

  my $img = img($grid);

  #
  # Insert image manip methods here!
  #

  $img->write(file => "oot.png");

DESCRIPTION

This module generates various types of two-dimensional grayscale noise. It is not fast, it is not a faithful implementation of any particular algorithm, and it probably never will be.

It is, possibly, a fun and/or educational toy if you are interested in procedural texture generation, or might be useful if you just want a simple module to make a few unique patterns with.

As long as the provided side length is a power of the noise's base frequency, this module will produce seamless tiles. For example, a base frequency of 2 would work fine for an image with a side length of 256 (256x256).

FUNCTIONS

  • make(type => $type, out => $filename, %ARGS)

      my ( $grid, $img ) = make(
        type => "perlin",
        out  => "perlin.bmp",
    
        #
        # Any noise args or post-processing args
        #
      );
      

    Creates the specified noise type (white, square, perlin, or complex), writing the resulting image to the received filename.

    Returns the resulting dataset, as well as the Imager object which was created from it.

    See POST-PROCESSING FUNCTIONS for additional fun-ctionality.

    make-noise, included with this distribution, provides a CLI for this function.

  • img($grid)

      my $grid = perlin();
    
      my $img = img($grid);
    
      #
      # Insert Imager image manip stuff here!
      #
    
      $img->write(file => "oot.png");

    Returns an Imager object from the received two-dimensional grid.

  • clamp($value)

      my $clamped = clamp($num);

    Limits the received value to between 0 and 255. If the received value is less than 0, returns 0; more than 255, returns 255; otherwise returns the same value which was received.

  • noise($grid, $x, $y)

    The so-called "noise function" required to generate coherent noise. Returns the same "random" value each time it is called with the same arguments (makes it more like a key hashing function a la memcached doesn't it? Not very random, if you ask me).

    Acme::Noisemaker diverges from most Perlin implementations in that its noise function simply utilizes a lookup table. The lookup table contains pre-populated random values. Turns out, this works fine.

  • lerp($a, $b, $x)

    Linear interpolate from $a to $b, by $x percent. $x is between 0 and 1. Not currently used, but it's there.

    http://en.wikipedia.org/wiki/Linear_interpolation

  • coslerp($a, $b, $x)

    Cosine interpolate from $a to $b, by $x percent. $x is between 0 and 1.

POST-PROCESSING FUNCTIONS

  • smooth($grid)

      #
      # Unsmoothed noise source
      #
      my $grid = white(smooth => 0);
    
      my $smooth = smooth($grid);

    Perform smoothing of the values contained in the received two-dimensional grid. Returns a new grid.

    Smoothing is on by default.

  • spheremap($grid, %args)

    Generates a fake (but convincing) spheremap from the received 2D noise grid, by embellishing the polar regions.

    Re-maps the pixel values along the north and south edges of the source image using polar coordinates, slowly blending back into original pixel values towards the middle.

    Returns a new 2D grid of pixel values.

      my $grid = perlin(%args);
    
      my $spheremap = spheremap($grid);

    sphere may also be passed as an arg to to make.

      my $grid = make(
        type => "perlin",
        sphere => 1,
      );
  • refract($grid)

    Return a new grid, replacing the color values in the received grid with one-dimensional indexed noise values from itself. This can enhance the "fractal" appearance of noise.

      my $grid = perlin(%args);
    
      my $refracted = refract($grid);

    refract may also be passed as an arg to make.

      my $grid = make(
        type => "perlin",
        refract => 1,
      );

GENERATORS

Each noise function returns a two-dimentional array containing grayscale values.

All function args are optional-- the built-in defaults should be reasonable to get started with. Each noise function accepts the following args in hash key form:

  amp     - Amplitude, or max variance from the bias value
  freq    - Frequency, or "density" of the noise produced
  len     - Side length of the output images, which are always square
  bias    - "Baseline" value for all pixels, .5 = 50%
  smooth  - Enable/disable noise smoothing. 1 is recommended.

For the purposes of this module, amplitude actually means semi-amplitude (peak-to-peak amp/2), and frequency represents the edge length of the starting white noise grid.

...in addition, Perlin and Complex noise accept:

  oct     - Octave count, increases the complexity of Perlin noise

...and Complex noise has several more possible args:

  feather - Edge falloff amount for Complex noise. 0-255
  layers  - Number of noise sources to use for Complex noise
  • White

      my $grid = white(
        amp     => <num>,
        freq    => <num>,
        len     => <int>,
        bias    => <num>,
        smooth  => <0|1>
      );

    Example of white noise

    White noise, for the purposes of this module, is probably what most people think of as noise. It looks like television static-- every pixel contains a pseudo-random value.

  • Diamond-Square

      my $grid = square(
        amp     => <num>,
        freq    => <num>,
        len     => <int>,
        bias    => <num>,
        smooth  => <0|1>
      );

    Example of square noise

    Sometimes called "cloud" or "plasma" noise. Often suffers from diamond- and square-shaped artifacts, but there are ways of dealing with them.

    This module seeds the initial values with White noise.

  • Perlin

      my $grid = perlin(
        amp     => <num>,
        freq    => <num>,
        len     => <int>,
        oct     => <int>,
        bias    => <num>,
        smooth  => <0|1>
      )

    Example of Perlin noise

    Perlin noise (not related to Perl) combines multiple noise sources to produce very turbulent-looking noise.

    This module generates its Perlin slices from Diamond-Square noise.

  • Complex Perlin

      my $grid = complex(
        amp     => <num>,
        freq    => <num>,
        len     => <int>,
        oct     => <int>,
        bias    => <num>,
        feather => <num>,
        layers  => <int>,
        smooth  => <0|1>
      )

    Example of complex noise

    Complex Perlin noise combines multiple Perlin noise sources. This is not a real name for any noise type beyond this module, as far as I can tell, but the methodology used to combine the noise is heavily inspired by the way libnoise allows the daisy-chaining of different noise modules.

SEE ALSO

Acme::Noisemaker is on github: http://github.com/aayars/noisemaker

  • Wikipedia

    As usual, Wikipedia is there for us.

    Diamond-Square algorithm: http://en.wikipedia.org/wiki/Diamond-square_algorithm

    Perlin Noise: http://en.wikipedia.org/wiki/Perlin_noise

    White Noise: http://en.wikipedia.org/wiki/White_noise

    Interpolation: http://en.wikipedia.org/wiki/Interpolation

  • Generating Random Fractal Terrain - http://gameprogrammer.com/fractal.html

    This page has a good intro to Diamond-Square noise. It taught me how to make clouds.

  • Perlin Noise - http://freespace.virgin.net/hugo.elias/models/m_perlin.htm

    Acme::Noisemaker heavily pilfers the pseudo-code for interpolation and smoothing functions which I found at the above site.

  • libnoise - http://libnoise.sourceforge.net/

    "A portable, open-source, coherent noise-generating library for C++"

    Though it does not use it, Acme::Noisemaker is inspired by libnoise, which is what you should really be using if you're serious about this sort of thing. It is very cool stuff. The developer has provided many examples which let you write C++ without actually knowing it (cue Sorcerer's Apprentice music...)

  • pynoise - http://home.gna.org/pynoise/

    Python bindings to libnoise via swig. I would like to make a package like this for Perl one day, unless someone else wants to first.

AUTHOR

  Alex Ayars <pause@nodekit.org>

COPYRIGHT

  File: Acme/Noisemaker.pm
 
  Copyright (c) 2009 Alex Ayars
 
  All rights reserved. This program and the accompanying materials
  are made available under the terms of the Common Public License v1.0
  which accompanies this distribution, and is available at
  http://opensource.org/licenses/cpl1.0.txt