Updated simplex noise 3D

This commit is contained in:
Christophe Riccio 2011-04-21 18:19:06 +01:00
parent 477382f798
commit 082d9151d8

View File

@ -17,11 +17,17 @@
namespace glm namespace glm
{ {
template <typename T> template <typename T, template<typename> class vecType>
inline detail::tvec3<T> permute(detail::tvec3<T> const & x) inline vecType<T> permute(vecType<T> const & x)
{ {
return mod(((x * T(34)) + T(1)) * x, T(289)); return mod(((x * T(34)) + T(1)) * x, T(289));
} }
template <typename T, template<typename> class vecType>
inline vecType<T> taylorInvSqrt(vecType<T> const & r)
{
return T(1.79284291400159) - T(0.85373472095314) * r;
}
namespace gtx{ namespace gtx{
namespace noise namespace noise
@ -54,34 +60,123 @@ namespace noise
detail::tvec3<T> p = permute( detail::tvec3<T> p = permute(
permute(i.y + detail::tvec3<T>(T(0), i1.y, T(1))) permute(i.y + detail::tvec3<T>(T(0), i1.y, T(1)))
+ i.x + detail::tvec3<T>(T(0), i1.x, T(1))); + i.x + detail::tvec3<T>(T(0), i1.x, T(1)));
/*
detail::tvec3<T> m = max(T(0.5) - detail::tvec3<T>( detail::tvec3<T> m = max(T(0.5) - detail::tvec3<T>(
dot(x0, x0), dot(x0, x0),
dot(detail::tvec2<T>(x12.x, x12.y), detail::tvec2<T>(x12.x, x12.y)), dot(detail::tvec2<T>(x12.x, x12.y), detail::tvec2<T>(x12.x, x12.y)),
dot(detail::tvec2<T>(x12.z, x12.w), detail::tvec2<T>(x12.z, x12.w)), T(0.0)); dot(detail::tvec2<T>(x12.z, x12.w), detail::tvec2<T>(x12.z, x12.w))), T(0));
m = m * m ; m = m * m ;
m = m * m ; m = m * m ;
// Gradients: 41 points uniformly over a line, mapped onto a diamond. // Gradients: 41 points uniformly over a line, mapped onto a diamond.
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
detail::tvec3<T> x = 2.0 * fract(p * C.w) - 1.0; detail::tvec3<T> x = T(2) * fract(p * C.w) - T(1);
detail::tvec3<T> h = abs(x) - 0.5; detail::tvec3<T> h = abs(x) - T(0.5);
detail::tvec3<T> ox = floor(x + 0.5); detail::tvec3<T> ox = floor(x + T(0.5));
detail::tvec3<T> a0 = x - ox; detail::tvec3<T> a0 = x - ox;
// Normalise gradients implicitly by scaling m // Normalise gradients implicitly by scaling m
// Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h ); // Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h );
m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h); m *= T(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h);
// Compute final noise value at P // Compute final noise value at P
detail::tvec3<T> g; detail::tvec3<T> g;
g.x = a0.x * x0.x + h.x * x0.y; g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw; //g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g); g.y = a0.y * x12.x + h.y * x12.y;
*/ g.z = a0.z * x12.z + h.z * x12.w;
return T(130) * dot(m, g);
} }
template <typename T>
inline T snoise(glm::detail::tvec3<T> const & v)
{
detail::tvec2<T> const C = detail::tvec2<T>(1.0 / 6.0, 1.0 / 3.0);
detail::tvec4<T> const D = detail::tvec4<T>(0.0, 0.5, 1.0, 2.0);
// First corner
detail::tvec3<T> i = floor(v + dot(v, C.y));
detail::tvec3<T> x0 = v - i + dot(i, C.x);
// Other corners
detail::tvec3<T> g = step(x0.yzx, x0.xyz);
detail::tvec3<T> l = 1.0 - g;
detail::tvec3<T> i1 = min( g.xyz, l.zxy );
detail::tvec3<T> 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;
detail::tvec3<T> x1 = x0 - i1 + C.x;
detail::tvec3<T> x2 = x0 - i2 + C.y; // 2.0*C.x = 1/3 = C.y
detail::tvec3<T> x3 = x0 - D.y; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
i = mod(i, T(289));
detail::tvec4<T> p = permute(permute(permute(
i.z + detail::tvec4<T>(0.0, i1.z, i2.z, 1.0)) +
i.y + detail::tvec4<T>(0.0, i1.y, i2.y, 1.0)) +
i.x + detail::tvec4<T>(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)
T n_ = T(0.142857142857); // 1.0/7.0
detail::tvec3<T> ns = n_ * D.wyz - D.xzx;
detail::tvec4<T> j = p - T(49) * floor(p * ns.z * ns.z); // mod(p,7*7)
detail::tvec4<T> x_ = floor(j * ns.z);
detail::tvec4<T> y_ = floor(j - T(7) * x_ ); // mod(j,N)
detail::tvec4<T> x = x_ * ns.x + ns;
detail::tvec4<T> y = y_ * ns.x + ns;
detail::tvec4<T> h = T(1) - abs(x) - abs(y);
detail::tvec4<T> b0 = detail::tvec4<T>(x.xy, y.xy);
detail::tvec4<T> b1 = detail::tvec4<T>(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;
detail::tvec4<T> s0 = floor(b0) * T(2) + T(1);
detail::tvec4<T> s1 = floor(b1) * T(2) + T(1);
detail::tvec4<T> sh = -step(h, detail::tvec4<T>(0));
detail::tvec4<T> a0 = b0 + s0 * sh.xxyy;
detail::tvec4<T> a1 = b1 + s1 * sh.zzww;
detail::tvec3<T> p0 = vec3(a0.xy, h.x);
detail::tvec3<T> p1 = vec3(a0.zw, h.y);
detail::tvec3<T> p2 = vec3(a1.xy, h.z);
detail::tvec3<T> p3 = vec3(a1.zw, h.w);
//Normalise gradients
detail::tvec4<T> norm = taylorInvSqrt(detail::tvec4<T>(
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(T(0.6) - detail::tvec4<T>(
dot(x0, x0),
dot(x1, x1),
dot(x2, x2),
dot(x3, x3)), T(0));
m = m * m;
return T(42) * dot(m * m, detail::tvec4<T>(
dot(p0, x0),
dot(p1, x1),
dot(p2, x2),
dot(p3, x3)));
}
}//namespace noise }//namespace noise
}//namespace gtx }//namespace gtx
}//namespace glm }//namespace glm