diff --git a/glm/gtx/noise.inl b/glm/gtx/noise.inl index 7ff9bba8..6e926133 100644 --- a/glm/gtx/noise.inl +++ b/glm/gtx/noise.inl @@ -17,11 +17,17 @@ namespace glm { - template - inline detail::tvec3 permute(detail::tvec3 const & x) + template class vecType> + inline vecType permute(vecType const & x) { return mod(((x * T(34)) + T(1)) * x, T(289)); } + + template class vecType> + inline vecType taylorInvSqrt(vecType const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } namespace gtx{ namespace noise @@ -54,34 +60,123 @@ namespace noise detail::tvec3 p = permute( permute(i.y + detail::tvec3(T(0), i1.y, T(1))) + i.x + detail::tvec3(T(0), i1.x, T(1))); -/* + detail::tvec3 m = max(T(0.5) - detail::tvec3( dot(x0, x0), dot(detail::tvec2(x12.x, x12.y), detail::tvec2(x12.x, x12.y)), - dot(detail::tvec2(x12.z, x12.w), detail::tvec2(x12.z, x12.w)), T(0.0)); + dot(detail::tvec2(x12.z, x12.w), detail::tvec2(x12.z, x12.w))), T(0)); m = m * m ; m = m * m ; // 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) - detail::tvec3 x = 2.0 * fract(p * C.w) - 1.0; - detail::tvec3 h = abs(x) - 0.5; - detail::tvec3 ox = floor(x + 0.5); + detail::tvec3 x = T(2) * fract(p * C.w) - T(1); + detail::tvec3 h = abs(x) - T(0.5); + detail::tvec3 ox = floor(x + T(0.5)); detail::tvec3 a0 = x - ox; // Normalise gradients implicitly by scaling m // 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 detail::tvec3 g; g.x = a0.x * x0.x + h.x * x0.y; - g.yz = a0.yz * x12.xz + h.yz * x12.yw; - return 130.0 * dot(m, g); -*/ + //g.yz = a0.yz * x12.xz + h.yz * x12.yw; + 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 + inline T snoise(glm::detail::tvec3 const & v) + { + detail::tvec2 const C = detail::tvec2(1.0 / 6.0, 1.0 / 3.0); + detail::tvec4 const D = detail::tvec4(0.0, 0.5, 1.0, 2.0); + + // First corner + detail::tvec3 i = floor(v + dot(v, C.y)); + detail::tvec3 x0 = v - i + dot(i, C.x); + + // Other corners + detail::tvec3 g = step(x0.yzx, x0.xyz); + detail::tvec3 l = 1.0 - g; + detail::tvec3 i1 = min( g.xyz, l.zxy ); + detail::tvec3 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 x1 = x0 - i1 + C.x; + detail::tvec3 x2 = x0 - i2 + C.y; // 2.0*C.x = 1/3 = C.y + detail::tvec3 x3 = x0 - D.y; // -1.0+3.0*C.x = -0.5 = -D.y + + // Permutations + i = mod(i, T(289)); + detail::tvec4 p = permute(permute(permute( + i.z + detail::tvec4(0.0, i1.z, i2.z, 1.0)) + + i.y + detail::tvec4(0.0, i1.y, i2.y, 1.0)) + + i.x + detail::tvec4(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 ns = n_ * D.wyz - D.xzx; + + detail::tvec4 j = p - T(49) * floor(p * ns.z * ns.z); // mod(p,7*7) + + detail::tvec4 x_ = floor(j * ns.z); + detail::tvec4 y_ = floor(j - T(7) * x_ ); // mod(j,N) + + detail::tvec4 x = x_ * ns.x + ns; + detail::tvec4 y = y_ * ns.x + ns; + detail::tvec4 h = T(1) - abs(x) - abs(y); + + detail::tvec4 b0 = detail::tvec4(x.xy, y.xy); + detail::tvec4 b1 = detail::tvec4(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 s0 = floor(b0) * T(2) + T(1); + detail::tvec4 s1 = floor(b1) * T(2) + T(1); + detail::tvec4 sh = -step(h, detail::tvec4(0)); + + detail::tvec4 a0 = b0 + s0 * sh.xxyy; + detail::tvec4 a1 = b1 + s1 * sh.zzww; + + detail::tvec3 p0 = vec3(a0.xy, h.x); + detail::tvec3 p1 = vec3(a0.zw, h.y); + detail::tvec3 p2 = vec3(a1.xy, h.z); + detail::tvec3 p3 = vec3(a1.zw, h.w); + + //Normalise gradients + detail::tvec4 norm = taylorInvSqrt(detail::tvec4( + 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( + 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( + dot(p0, x0), + dot(p1, x1), + dot(p2, x2), + dot(p3, x3))); + } + + }//namespace noise }//namespace gtx }//namespace glm