Scalable noise Perlin or not

Hello,

I’m looking for a scalable noise affect, where one can really “zoom” inside (up to 64x). I did look on this forum and people talk about Perlin Noise, which should be scalable. I’ve found an add-on ofxMSAPerlin, but it doesn’t come with examples and I’m a bit lost on how to use it. Didn’t find any other add-ons with scalable noise. I’m sure it does exist. Can you please point me to a right direction ?

Thanks
M

Hey @SFR75, maybe have a look at ofNoise. Its a perlin- or maybe simplex-type noise. You can see it in action and play around with it a bit in the threadedObject.h file of the threadExample. You could also implement a function either in OF or in a shader.

Here are a few online resources for noise-related stuff (not ofxAddons though):

  1. Patricio Gonzalez Vivo
  2. the ashima arts functions
  3. Inigo Quilez: see the articles on Procedural Noises

There is also a technique of summing values of noise in a loop, maybe called FBM, or Brownian motion noise. Inigo Quilez has a nice article about how to use it.

A shader is a very fast and efficient way to calculate multiple values of noise (say for each pixel in an ofFbo).

Hello,

Thanks for an answer! I looked at the links that you’ve provided. It seems somewhat above my level of understanding. I was honestly hoping for a nice scalable noise implemented as shader ) … And shader is not something I know how to write. Especially for this application it serves mostly as background, but it needs to be scalable. Oh well… Maybe I need to think of some other solution if noises are not possible :frowning:

Thanks
M

Hey you can always learn how to write shaders. ofBook has an awesome chapter on them, how to write them (.vert and .frag files), and how to use them in OF with ofShader. The projects in /examples/shader/ go along with that chapter.

In the links above, the noise functions are in the fragment shader. The vertex shader pass some texture coordinates (as vTexcoord) for the fragment shader to use. The scaling happens sort of like a frequency, where higher values provide faster oscillations of noise values.

A vertex shader might be something like:

#version 330
uniform mat4 modelViewProjectionMatrix;
in vec4 position;
in vec2 texcoord;

out vec2 vTexCoord;

void main() {
    gl_Position = modelViewProjectionMatrix * position;
    vTexCoord = texcoord;
}

a fragment shader (with noise from ashima) could be something like:

#version 330

uniform vec2 resolution; // from OF: used to normalize vTexcoord
uniform float time; // also from OF: time
uniform float freqNoise; // also from OF: the frequency or scale
in vec2 vTexCoord; // from the vertex shader

out vec4 fragColor;

// some function declarations for the noise; functions definitions follow main():
vec3 mod289(vec3 x);
vec4 mod289(vec4 x);
vec4 permute(vec4 x);
vec4 taylorInvSqrt(vec4 r);
float snoise(vec3 v);

// use the texture coordinate (in vTexcoord) in the noise function to set the red channel of the output color
void main() {
    vec2 tc = vTexCoord / resolution; // normalize
    float noise01 = snoise(freqNoise * vec3(tc, time)); // -1.0 - 1.0
    noise01 = noise01 * 0.5 + 0.5; // shift to 0.0 - 1.0
    noise01 *= 0.5; //
    
    float noise02 = snoise(freqNoise * vec3(tc, time * 2.0)); // higher frequency noise
    noise02 = noise02 * 0.5 + 0.5; // again shift to 0.0 - 1.0
    noise02 *= 0.5;
    
    float red = noise01 + noise02; // combine the two noise calls
    if(red > 1.0) {
        red = red - 1.0;
    }
    vec3 color = vec3(red, 0.0, 0.0);
    fragColor = vec4(color, 1.0);
}

// the following are the noise functions from ashima arts:
// Description : Array and textureless GLSL 2D/3D/4D simplex
//               noise functions.
//      Author : Ian McEwan, Ashima Arts.
//  Maintainer : stegu
//     Lastmod : 20201014 (stegu)
//     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
//               Distributed under the MIT License. See LICENSE file.
//               https://github.com/ashima/webgl-noise
//               https://github.com/stegu/webgl-noise

vec3 mod289(vec3 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 mod289(vec4 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 permute(vec4 x) {
     return mod289(((x*34.0)+10.0)*x);
}

vec4 taylorInvSqrt(vec4 r)
{
  return 1.79284291400159 - 0.85373472095314 * r;
}

float snoise(vec3 v)
  {
  const vec2  C = vec2(1.0/6.0, 1.0/3.0) ;
  const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);

// First corner
  vec3 i  = floor(v + dot(v, C.yyy) );
  vec3 x0 =   v - i + dot(i, C.xxx) ;

// Other corners
  vec3 g = step(x0.yzx, x0.xyz);
  vec3 l = 1.0 - g;
  vec3 i1 = min( g.xyz, l.zxy );
  vec3 i2 = max( g.xyz, l.zxy );

  //   x0 = x0 - 0.0 + 0.0 * C.xxx;
  //   x1 = x0 - i1  + 1.0 * C.xxx;
  //   x2 = x0 - i2  + 2.0 * C.xxx;
  //   x3 = x0 - 1.0 + 3.0 * C.xxx;
  vec3 x1 = x0 - i1 + C.xxx;
  vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
  vec3 x3 = x0 - D.yyy;      // -1.0+3.0*C.x = -0.5 = -D.y

// Permutations
  i = mod289(i);
  vec4 p = permute( permute( permute(
             i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
           + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
           + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));

// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
  float n_ = 0.142857142857; // 1.0/7.0
  vec3  ns = n_ * D.wyz - D.xzx;

  vec4 j = p - 49.0 * floor(p * ns.z * ns.z);  //  mod(p,7*7)

  vec4 x_ = floor(j * ns.z);
  vec4 y_ = floor(j - 7.0 * x_ );    // mod(j,N)

  vec4 x = x_ *ns.x + ns.yyyy;
  vec4 y = y_ *ns.x + ns.yyyy;
  vec4 h = 1.0 - abs(x) - abs(y);

  vec4 b0 = vec4( x.xy, y.xy );
  vec4 b1 = vec4( x.zw, y.zw );

  //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
  //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
  vec4 s0 = floor(b0)*2.0 + 1.0;
  vec4 s1 = floor(b1)*2.0 + 1.0;
  vec4 sh = -step(h, vec4(0.0));

  vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
  vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;

  vec3 p0 = vec3(a0.xy,h.x);
  vec3 p1 = vec3(a0.zw,h.y);
  vec3 p2 = vec3(a1.xy,h.z);
  vec3 p3 = vec3(a1.zw,h.w);

//Normalise gradients
  vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
  p0 *= norm.x;
  p1 *= norm.y;
  p2 *= norm.z;
  p3 *= norm.w;

// Mix final noise value
  vec4 m = max(0.5 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
  m = m * m;
  return 105.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
                                dot(p2,x2), dot(p3,x3) ) );
  }

Thanks !)

I have seen this cool ofApp:
(not sure how much related, but just in case could be useful as reference.)

+

1 Like