PDA

View Full Version : Vertex Shader Perlin-Type Noise?

toneburst
06-03-2009, 01:09 PM
Anyone know of any good Perlin or Simplex Noise-type implementations that will run in the GPU without resorting to vertex texture-fetches? I'm looking for something that will shift mesh vertices along their normals in a pseudo-random way based on their initial object-space positions.

I've found an HLSL version, 'vBomb.fx' in the NVIDIA Shader Library, but I'm having problems getting the 2D and 3D versions to work in GLSL.

a|x
http://machinesdontcare.wordpress.com

toneburst
06-03-2009, 04:34 PM
OK, I have it working! Can't now work out why the original HLSL shader worked, though (but that's another issue)...

http://158.223.20.36/temp/tbNVvBomb01.png
http://158.223.20.36/temp/tbNVvBomb03.png

I wonder if anyone can suggest any GLSL-specific optimisations to the main noise functions. Any advice would be much appreciated:

// This is the smoothstep function f(t) = 3t^2 - 2t^3, without the normalization
vec3 s_curve3(in vec3 t) { return t*t*( vec3(3.0) - vec3(2.0)*t); }

// 3D Version
float nvNoise3(in vec3 v, in vec4 pg[FULLSIZE])
{
v += 10000.0; // Hack to avoid negative numbers

ivec3 i = ivec3(fract(v * NOISEFRAC) * BSIZE); // Index between 0 and BSIZE-1
vec3 f = fract(v); // Fractional position

// Lookup in permutation table
ivec2 p;
p.x = int(pg[i[0]].w);
p.y = int(pg[i[0] + 1].w);
p = p + i[1];

ivec4 b;
b.x = int(pg[p[0]].w);
b.y = int(pg[p[1] ].w);
b.z = int(pg[p[0] + 1].w);
b.w = int(pg[p[1] + 1].w);
b = b + i[2];

// Compute dot products between gradients and vectors
vec4 r;
r[0] = dot(pg[ b[0] ].xyz, f);
r[1] = dot(pg[ b[1] ].xyz, f - vec3(1.0, 0.0, 0.0));
r[2] = dot(pg[ b[2] ].xyz, f - vec3(0.0, 1.0, 0.0));
r[3] = dot(pg[ b[3] ].xyz, f - vec3(1.0, 1.0, 0.0));

vec4 r1;
r1[0] = dot(pg[b[0] + 1].xyz, f - vec3(0.0, 0.0, 1.0));
r1[1] = dot(pg[b[1] + 1].xyz, f - vec3(1.0, 0.0, 1.0));
r1[2] = dot(pg[b[2] + 1].xyz, f - vec3(0.0, 1.0, 1.0));
r1[3] = dot(pg[b[3] + 1].xyz, f - vec3(1.0, 1.0, 1.0));

// interpolate
f = s_curve3(f);
r = mix(r, r1, f[2]);
r = mix(r.xyyy, r.zwww, f[1]);
return mix(r.x, r.y, f[0]);
}

Incidentally, I'm using a large array of vec4s for nTab (66, in fact). Unfortunately I wasn't able to make it a constant array. Anyone know if this is likely to cause problems? It seems to work OK.

Cheers guys,

a|x

overseb
06-04-2009, 07:14 AM
hi
You have code samples in GLSL at nivdia sdk 9.51 homepage