Seedable shader for classic Perlin and Simplex noise

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
User avatar
0x25a0
Prole
Posts: 36
Joined: Mon Mar 20, 2017 10:08 pm
Contact:

Seedable shader for classic Perlin and Simplex noise

Post by 0x25a0 »

Heya! I thought I'd share my port of Stefan Gustavson's GLSL implementation of classic Perlin and Simplex noise.

https://github.com/25A0/love2d-noise

My only notable contribution is the fact that the noise is seedable; when compiling the shader you can supply a seed that influences the permutation table, which leads to different, but deterministic results for each seed. Seeding the noise by changing the permutation table is not a new idea, but Gustavson's implementation didn't have that feature as far as I'm aware.

The shader allows you to sample 2D, 3D, and 4D Perlin and Simplex noise. Documentation is available on GitHub.

The repository contains a small demo that lets you tinker around with the different noise types.
Image

Currently the precision of the noise is limited to 8 bits, since the shader just produces a grayscale color, which is mapped to a value in [0, 255]. I'm still looking into better ways to extract noise values with higher precision.

Edit: I believe that I found a way to encode the noise value with higher precision, but I'd appreciate second opinions on my approach.

Encoding:

Code: Select all

// Given a noise value in range [0, 1], encode it with 8 bit precision as a greyscale colour
vec4 encode8bit(float n)
{
  return vec4(n, n, n, 1.0);
}

// Given a noise value in range [0, 1], encode it with 16 bit precision in the red and green component
vec4 encode16bit(float n)
{
  float r = int(n * 256) / 256.0;
  return vec4(r, fract(n * 256), 0.0, 1.0);
}

// Given a noise value in range [0, 1], encode it with 24 bit precision in the red, green and blue component
vec4 encode24bit(float n)
{
  float r = int(n * 256) / 256.0;
  float g = int(fract(n * 256) * 256) / 256.0;
  float b = fract(n * 256 * 256);
  return vec4(r, g, b, 1.0);
}
Decoding:

Code: Select all

local div = 1/255
local decoding_functions = {
  [ 8] = function(r      ) return r * div                                 end, -- 8 bit decoding
  [16] = function(r, g   ) return r * div + g * div * div                 end,-- 16 bit decoding
  [24] = function(r, g, b) return r * div + g * div * div + b * div * div end, -- 24 bit decoding
}
Edit: I've added another demo to illustrate how noise data can be used in different shaders without transferring them to main memory.
The demo produces this foggy infinite mountain range:
Image

I also threw in a cheap parallax scrolling effect: https://giphy.com/gifs/3ohhwGFpRk33lDiI3m/html5
Post Reply

Who is online

Users browsing this forum: No registered users and 39 guests