This Perlin Noise Vector Flow-Field visualisation is nice.

## Posts Tagged ‘Perlin Noise

### Flash, But Nice

### OpenCL Perlin Mesh Noise 2D

The normals are incorrect and facetted, but I actually quite like the look.

And a quick video:

Vertex Shader:

/* 2D Perlin-Noise in the vertex shader, based originally on vBomb.fx HLSL vertex noise shader, from the NVIDIA Shader Library. http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#vbomb Original Perlin function substituted for Stefan Gustavson's texture-lookup-based Perlin implementation. Quartz Composer setup toneburst 2009 https://machinesdontcare.wordpress.com */ //////////////////////// // 2D Perlin Noise // //////////////////////// /* 2D Perlin-Noise from example by Stefan Gustavson, found at http://staffwww.itn.liu.se/~stegu/simplexnoise/ */ uniform sampler2D permTexture; // Permutation texture const float permTexUnit = 1.0/256.0; // Perm texture texel-size const float permTexUnitHalf = 0.5/256.0; // Half perm texture texel-size float fade(in float t) { return t*t*t*(t*(t*6.0-15.0)+10.0); } float pnoise2D(in vec2 p) { // Integer part, scaled and offset for texture lookup vec2 pi = permTexUnit*floor(p) + permTexUnitHalf; // Fractional part for interpolation vec2 pf = fract(p); // Noise contribution from lower left corner vec2 grad00 = texture2D(permTexture, pi).rg * 4.0 - 1.0; float n00 = dot(grad00, pf); // Noise contribution from lower right corner vec2 grad10 = texture2D(permTexture, pi + vec2(permTexUnit, 0.0)).rg * 4.0 - 1.0; float n10 = dot(grad10, pf - vec2(1.0, 0.0)); // Noise contribution from upper left corner vec2 grad01 = texture2D(permTexture, pi + vec2(0.0, permTexUnit)).rg * 4.0 - 1.0; float n01 = dot(grad01, pf - vec2(0.0, 1.0)); // Noise contribution from upper right corner vec2 grad11 = texture2D(permTexture, pi + vec2(permTexUnit, permTexUnit)).rg * 4.0 - 1.0; float n11 = dot(grad11, pf - vec2(1.0, 1.0)); // Blend contributions along x vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade(pf.x)); // Blend contributions along y float n_xy = mix(n_x.x, n_x.y, fade(pf.y)); // We're done, return the final noise value. return n_xy; } ///////////////////// // Sphere Function // ///////////////////// const float PI = 3.14159265; const float TWOPI = 6.28318531; uniform float BaseRadius; vec4 sphere(in float u, in float v) { u *= PI; v *= TWOPI; vec4 pSphere; pSphere.x = BaseRadius * cos(v) * sin(u); pSphere.y = BaseRadius * sin(v) * sin(u); pSphere.z = BaseRadius * cos(u); pSphere.w = 1.0; return pSphere; } /////////////////////////// // Apply 2D Perlin Noise // /////////////////////////// uniform vec3 NoiseScale; // Noise scale, 0.01 > 8 uniform float Sharpness; // Displacement 'sharpness', 0.1 > 5 uniform float Displacement; // Displcement amount, 0 > 2 uniform float Speed; // Displacement rate, 0.01 > 1 uniform float Timer; // Feed incrementing value, infinite vec4 perlinSphere(in float u, in float v) { vec4 sPoint = sphere(u, v); // The rest of this function is mainly from vBomb shader from NVIDIA Shader Library vec4 noisePos = vec4(NoiseScale.xyz,1.0) * (sPoint + (Speed * Timer)); float noise = (pnoise2D(noisePos.xy) + 1.0) * 0.5;; float ni = pow(abs(noise),Sharpness) - 0.25; vec4 nn = vec4(normalize(sPoint.xyz),0.0); return (sPoint - (nn * (ni-0.5) * Displacement)); } //////////////////////////////// // Calculate Position, Normal // //////////////////////////////// const float grid = 0.01; // Grid offset for normal-estimation varying vec3 norm; // Normal vec4 posNorm(in float u, in float v) { // Vertex position vec4 vPosition = perlinSphere(u, v); // Estimate normal by 'neighbour' technique // with thanks to tonfilm vec3 tangent = (perlinSphere(u + grid, v) - vPosition).xyz; vec3 bitangent = (perlinSphere(u, v + grid) - vPosition).xyz; norm = gl_NormalMatrix * normalize(cross(tangent, bitangent)); // Return vertex position return vPosition; } ////////////////////////// // Phong Directional VS // ////////////////////////// // -- Lighting varyings (to Fragment Shader) varying vec3 lightDir0, halfVector0; varying vec4 diffuse0, ambient; void phongDir_VS() { // Extract values from gl light parameters // and set varyings for Fragment Shader lightDir0 = normalize(vec3(gl_LightSource[0].position)); halfVector0 = normalize(gl_LightSource[0].halfVector.xyz); diffuse0 = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse; ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient; ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient; } /////////////// // Main Loop // /////////////// uniform vec2 PreScale, PreTranslate; // Mesh pre-transform void main() { vec2 uv = gl_Vertex.xy; // Offset XY mesh coords to 0 > 1 range uv += 0.5; // Pre-scale and transform mesh uv *= PreScale; uv += PreTranslate; // Calculate new vertex position and normal vec4 spherePos = posNorm(uv[0], uv[1]); // Calculate lighting varyings to be passed to fragment shader phongDir_VS(); // Transform new vertex position by modelview and projection matrices gl_Position = gl_ModelViewProjectionMatrix * spherePos; // Forward current texture coordinates after applying texture matrix gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; }

And the Fragment Shader, which just implements a generic Phong Directional lighting model:

/* Generic Fragment Shader with Phong Directional lighting */ ////////////////////////// // Phong Directional FS // ////////////////////////// // -- Lighting varyings (from Vertex Shader) varying vec3 norm, lightDir0, halfVector0; varying vec4 diffuse0, ambient; vec4 phongDir_FS() { vec3 halfV; float NdotL, NdotHV; // The ambient term will always be present vec4 color = ambient; // compute the dot product between normal and ldir NdotL = max(dot(norm, lightDir0),0.0); if (NdotL > 0.0) { color += diffuse0 * NdotL; halfV = normalize(halfVector0); NdotHV = max(dot(norm, halfV), 0.0); color += gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV, gl_FrontMaterial.shininess); } return color; } /////////////// // Main Loop // /////////////// void main() { // Call lighting function and return result gl_FragColor = phongDir_FS(); }

**Setup:**

You’ll need to put a GLSL Grid patch inside the GLSL Shader macro. I’d set the Vertical and Horizontal Resolution of the Grid to a higher value than the default 50. Try to balance resolution (higher the better) against frame-rate. Setting it to 256×256 will give an ultra-smooth mesh, but will potentially slow down the rendering, depending on your system. You could put the GLSL Grid inside a Trackball if you wanted, so you can spin the whole thing around.

You’ll also need to put the whole thing inside a Lighting patch.

The complete setup would be:

*Lighting : GLSL Shader : (optional) Trackball : GLSL Grid*

I’ve tried to organise the code into blocks to make it easier to understand. I’m sure it could be made more efficient and/or elegant by combining some of the functions, but my aim was to make it easier to copy-paste discrete functions into other code, in nice self-contained chunks. It’s probably terrible coding practice, but I’ve placed all the variables for each function with the function definition itself, rather than declaring them all at the top. I found this helped keep the code ‘modular’, and it seems to work, so I guess the compiler can work its way through it OK.

I’ve suggested ranges for the various parameters in the shader code.

You’ll also need this picture, as the permutation texture, connected to the ‘permTex’ input on the shader.

And here’s a couple of examples of the code in action, courtesy of Marcos Prack.

Very smooth, and looks like it’s running faster than it does on my MacBook Pro.

Cheers Marcos!

### 2D/3D Perlin Vertex Noise

Crashes on my laptop, works like a dream on my desktop machine.

More info to come.

The red ones above are from a different version of the effect, that does work on my ageing MacBook Pro (though it’s still slow- 12-14fps at 640 x 360). Note the highlights aren’t as smooth, because I had to drop the resolution of the base mesh to improve the framerates a little on the laptop.

And here’s a clip of the 2D version:

and the 3D one:

and with an environment-map shader (not so successful)

### The Perennial vBomb.fx

I keep coming back to this one (and so do lots of other people, by the looks of it).

It’s a GLSL conversion of the old NVIDIA HLSL vBomb shader, that applies Perlin Noise to vertex positions in much the same way as the Quartz Composer Vertex Noise example.

The idea here though was that I’d try to make a version that would be more likely to be hardware-accelerated. Since the GLSL noise() functions aren’t actually implemented on all graphics hardware. The fact that they seem to generally be pretty slow, at least on my ATI X1600, suggests to me that this is the case with my card, and GLSL noise() is actually forcing software-render-fallback. The vBomb conversion certainly seems pretty fast, though!

Here some examples that don’t take things any further than the original vBomb, in terms of the output. I’m planning to add lighting too, though. Again, absolutely nothing original about that- in fact, Desaxismundi’s beautifully-lit vBomb vvvv shaders (witness here, and, particularly here) were one of my original inspirations for getting into 3D graphics, and particularly GLSL shaders in the first place. I owe Desaxismundi, and the vvvv community generally a huge debt of gratitude for introducing me to this wonderful (if confusing) world.