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.007 of Acme::Noisemaker.

SYNOPSIS

  use Acme::Noisemaker qw| :all |;

  make;

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

  make-noise --help

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,%args);

  #
  # Insert image manip methods here!
  #

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

DESCRIPTION

Acme::Noisemaker provides a simple functional interface for generating various types of 2D noise.

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).

FUNCTION

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

      #
      # Just make some noise:
      #
      make();
    
      #
      # Care slightly more:
      #
      my ( $grid, $img, $filename ) = make(
        #
        # Any MAKE ARGS or noise args here!
        #
      );

Creates the specified noise type (see NOISE TYPES), writing the resulting image to the received filename.

Unless seriously tinkering, make may be the only function you need. make-noise, included with this distribution, provides a CLI for this function.

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

In addition to any argument appropriate to the type of noise being generated, make accepts the following arguments:

  • type => $noiseType

    The type of noise to generate, defaults to Perlin. Specify any type.

      make(type => 'gel');
  • sphere => $bool

    Generate a pseudo-spheremap from the resulting noise.

    This feature is a work in progress.

      make(sphere => 1);
  • refract => $bool

    "Refracted" pixel values. Can be used to enhance the fractal appearance of the resulting noise. Often makes it look dirty.

      make(refract => 1);
  • clut => $filename

    Use an input image as a color lookup table

    This feature is a work in progress.

      make(clut => $filename);
  • clutdir => <0|1|2>

    0: Hypotenuse lookup (corner to corner, so it doesn't matter if the input table is oriented horizontally or vertically). This is the default.

    1: Vertical lookup, good for generating maps which have ice caps at the poles and tropical looking colors at the equator.

    2: Fractal lookup, uses the same methodology as refract

    This feature is a work in progress.

      make(clut => $filename, clutdir => 1);
  • limit => <0|1>

    0: Scale the pixel values of the noise set to image-friendly levels

    1: Clamp pixel values outside of a representable range

      make(limit => 1);
  • quiet => <0|1>

    Don't spam console

      make(quiet => 1);
  • out => $filename

    Output image filename. Defaults to the name of the noise type being generated.

      make(out => "oot.bmp");

SIMPLE NOISE

Simple noise types are generated from a single noise source.

  • white(%args)

    Each non-smoothed pixel contains a pseudo-random value

  • square(%args)

    Diamond-Square

  • gel(%args)

    Low-frequency smooth white noise with XY offset; see GEL TYPES

  • sgel(%args)

    Diamond-Square noise with XY offset; see GEL TYPES

  • stars(%args)

    White noise generated with extreme gappiness

Simple noise types accept the following arguments in hash key form:

  • amp => $num

    Amplitude, or max variance from the bias value.

    For the purposes of this module, amplitude actually means semi- amplitude (peak-to-peak amp/2).

      make(amp => 1);
  • freq => $num

    Frequency, or "density" of the noise produced.

    For the purposes of this module, frequency represents the edge length of the starting noise grid.

      make(freq => 8);
  • len => $int

    Side length of the output images, which are always square.

      make(len => 512);
  • bias => $num

    "Baseline" value for all pixels, .5 = 50%

      make(bias => .25);
  • smooth => $bool

    Enable/disable noise smoothing. 1 is default/recommended

      make(smooth => 0);

PERLIN TYPES

Perlin noise combines the values from multiple 2D slices (octaves), which are generated using successively higher frequencies and lower amplitudes.

The slice type used for generating Perlin noise may be controlled with the stype argument. Any simple type may be specified.

The default slice type is smoothed white noise.

  • perlin(%args)

    Perlin

  • ridged(%args)

    Ridged multifractal

  • block(%args)

    Unsmoothed Perlin

  • pgel(%args)

    Perlin noise with an XY offset; see GEL TYPES

  • rgel(%args)

    Ridged multifractal noise with an XY offset; see GEL TYPES

In addition to any of the args which may be used for simple noise types, Perlin noise types accept the following arguments in hash key form:

  • octaves => $int

    e.g. 1..8

    Octave (slice) count, increases the complexity of Perlin noise. Higher generally looks nicer.

      my $blurry = make(octaves => 3);
    
      my $sharp = make(octaves => 8);
  • stype => $simpleType

    Perlin slice type, defaults to white. Any simple type may be specified.

      my $grid = make(stype => 'gel');

COMPLEX NOISE

  • complex

    Complex layered noise

    Complex noise is a homebrew noise recipe inspired by (but not using) libnoise.

    This function generates a noise base and multiple noise layers. Each pixel in the resulting noise is blended towards the value in the noise layer which corresponds to the reference value in the noise base. Finally, the noise base itself is very slightly superimposed over the combined layers.

      my $grid = complex();

    Presets for hundreds of noise variants (many of them quite interesting visually) may be generated through this function, by combining different base types, layer types, and slice types.

      my $grid = complex(
        lbase => <any noise type but complex>,
        ltype => <any noise type but complex>,
        stype => <any simple type>,
        # ...
      );

In addition to all simple and Perlin args, complex noise accepts the following additional args in hash key form:

  • feather => $num

    e.g. 0..255

    Amount of blending between different regions of the noise.

      make(type => 'complex', feather => 50);
  • layers => $int

    Number of complex layers to generate

      make(type => 'complex', layers => 4);
  • lbase => $noiseType

    Complex layer base - defaults to "perlin". Any type except for complex may be used.

      make(type => 'complex', lbase => 'gel');
  • ltype => $noiseType

    Complex layer type - defaults to "perlin". Any type except for complex may be used.

      make(type => 'complex', ltype => 'gel');

GEL TYPES

The simple and Perlin "gel" types - gel, sgel, pgel and rgel, accept the following additional arguments:

  • offset => $float

    Amount of self-displacement to apply to gel noise

      make(type => 'gel', offset => .125);

MORE FUNCTIONS

  • img($grid,%args)

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

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

  • clamp($value)

    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.

      my $clamped = clamp($num);
  • 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.

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

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

  • smooth($grid, %args)

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

    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,%args);

    See MAKE ARGS

  • refract($grid,%args)

    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);

    See MAKE ARGS

  • offset($grid,%args)

    Return a new grid containing XY offset values from the original, by a factor of the received offset argument.

    See GEL TYPES

SEE ALSO

Imager, Math::Trig

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

Acme::Noisemaker uses adapted pseudocode from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm and http://gameprogrammer.com/fractal.html

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