123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- //
- // FAST32_hash
- // A very fast hashing function. Requires 32bit support.
- // http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
- //
- // The hash formula takes the form....
- // hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
- // We truncate and offset the domain to the most interesting part of the noise.
- // SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
- // 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
- //
- // generates 3 random numbers for each of the 8 cell corners
- // float h = PerlinDerivedJordan(OUT.pos, _Octaves, _Offset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Warp0, _Warp, _Damp0, _Damp, _DampScale);
- void FAST32_hash_3D(float3 gridcell, out float4 lowz_hash_0, out float4 lowz_hash_1, out float4 lowz_hash_2, out float4 highz_hash_0, out float4 highz_hash_1, out float4 highz_hash_2)
- {
- // gridcell is assumed to be an integer coordinate
- // TODO: these constants need tweaked to find the best possible noise.
- // probably requires some kind of brute force computational searching or something....
- const float2 OFFSET = float2(50.0, 161.0);
- const float DOMAIN = 69.0;
- const float3 SOMELARGEFLOATS = float3(635.298681, 682.357502, 668.926525);
- const float3 ZINC = float3(48.500388, 65.294118, 63.934599);
- // truncate the domain
- gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * (1.0 / DOMAIN)) * DOMAIN;
- float3 gridcell_inc1 = step(gridcell, float3(DOMAIN - 1.5, DOMAIN - 1.5, DOMAIN - 1.5)) * (gridcell + 1.0);
- // calculate the noise
- float4 P = float4(gridcell.xy, gridcell_inc1.xy) + OFFSET.xyxy;
- P *= P;
- P = P.xzxz * P.yyww;
- float3 lowz_mod = float3(1.0 / (SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz));
- float3 highz_mod = float3(1.0 / (SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz));
- lowz_hash_0 = frac(P * lowz_mod.xxxx);
- highz_hash_0 = frac(P * highz_mod.xxxx);
- lowz_hash_1 = frac(P * lowz_mod.yyyy);
- highz_hash_1 = frac(P * highz_mod.yyyy);
- lowz_hash_2 = frac(P * lowz_mod.zzzz);
- highz_hash_2 = frac(P * highz_mod.zzzz);
- }
- float4 PerlinSurflet3D_Deriv(float3 P)
- {
- // establish our grid cell and unit position
- float3 Pi = floor(P);
- float3 Pf = P - Pi;
- float3 Pf_min1 = Pf - 1.0;
- // calculate the hash.
- // ( various hashing methods listed in order of speed )
- float4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;
- FAST32_hash_3D(Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1);
- // calculate the gradients
- float4 grad_x0 = hashx0 - 0.49999;
- float4 grad_y0 = hashy0 - 0.49999;
- float4 grad_z0 = hashz0 - 0.49999;
- float4 norm_0 = rsqrt(grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0);
- grad_x0 *= norm_0;
- grad_y0 *= norm_0;
- grad_z0 *= norm_0;
- float4 grad_x1 = hashx1 - 0.49999;
- float4 grad_y1 = hashy1 - 0.49999;
- float4 grad_z1 = hashz1 - 0.49999;
- float4 norm_1 = rsqrt(grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1);
- grad_x1 *= norm_1;
- grad_y1 *= norm_1;
- grad_z1 *= norm_1;
- float4 grad_results_0 = float2(Pf.x, Pf_min1.x).xyxy * grad_x0 + float2(Pf.y, Pf_min1.y).xxyy * grad_y0 + Pf.zzzz * grad_z0;
- float4 grad_results_1 = float2(Pf.x, Pf_min1.x).xyxy * grad_x1 + float2(Pf.y, Pf_min1.y).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1;
- // get lengths in the x+y plane
- float3 Pf_sq = Pf*Pf;
- float3 Pf_min1_sq = Pf_min1*Pf_min1;
- float4 vecs_len_sq = float2(Pf_sq.x, Pf_min1_sq.x).xyxy + float2(Pf_sq.y, Pf_min1_sq.y).xxyy;
- // evaluate the surflet
- float4 m_0 = vecs_len_sq + Pf_sq.zzzz;
- m_0 = max(1.0 - m_0, 0.0);
- float4 m2_0 = m_0*m_0;
- float4 m3_0 = m_0*m2_0;
- float4 m_1 = vecs_len_sq + Pf_min1_sq.zzzz;
- m_1 = max(1.0 - m_1, 0.0);
- float4 m2_1 = m_1*m_1;
- float4 m3_1 = m_1*m2_1;
- // calc the deriv
- float4 temp_0 = -6.0 * m2_0 * grad_results_0;
- float xderiv_0 = dot(temp_0, float2(Pf.x, Pf_min1.x).xyxy) + dot(m3_0, grad_x0);
- float yderiv_0 = dot(temp_0, float2(Pf.y, Pf_min1.y).xxyy) + dot(m3_0, grad_y0);
- float zderiv_0 = dot(temp_0, Pf.zzzz) + dot(m3_0, grad_z0);
- float4 temp_1 = -6.0 * m2_1 * grad_results_1;
- float xderiv_1 = dot(temp_1, float2(Pf.x, Pf_min1.x).xyxy) + dot(m3_1, grad_x1);
- float yderiv_1 = dot(temp_1, float2(Pf.y, Pf_min1.y).xxyy) + dot(m3_1, grad_y1);
- float zderiv_1 = dot(temp_1, Pf_min1.zzzz) + dot(m3_1, grad_z1);
- const float FINAL_NORMALIZATION = 2.3703703703703703703703703703704; // scales the final result to a strict 1.0->-1.0 range
- return float4(dot(m3_0, grad_results_0) + dot(m3_1, grad_results_1), float3(xderiv_0, yderiv_0, zderiv_0) + float3(xderiv_1, yderiv_1, zderiv_1)) * FINAL_NORMALIZATION;
- }
- void FAST32_hash_3D(float3 gridcell, out float4 lowz_hash, out float4 highz_hash) // generates a random number for each of the 8 cell corners
- {
- // gridcell is assumed to be an integer coordinate
- // TODO: these constants need tweaked to find the best possible noise.
- // probably requires some kind of brute force computational searching or something....
- const float2 OFFSET = float2(50.0, 161.0);
- const float DOMAIN = 69.0;
- const float SOMELARGEFLOAT = 635.298681;
- const float ZINC = 48.500388;
- // truncate the domain
- gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * (1.0 / DOMAIN)) * DOMAIN;
- float3 gridcell_inc1 = step(gridcell, float3(DOMAIN - 1.5, DOMAIN - 1.5, DOMAIN - 1.5)) * (gridcell + 1.0);
- // calculate the noise
- float4 P = float4(gridcell.xy, gridcell_inc1.xy) + OFFSET.xyxy;
- P *= P;
- P = P.xzxz * P.yyww;
- highz_hash.xy = float2(1.0 / (SOMELARGEFLOAT + float2(gridcell.z, gridcell_inc1.z) * ZINC));
- lowz_hash = frac(P * highz_hash.xxxx);
- highz_hash = frac(P * highz_hash.yyyy);
- }
- //
- // Interpolation functions
- // ( smoothly increase from 0.0 to 1.0 as x increases linearly from 0.0 to 1.0 )
- // http://briansharpe.wordpress.com/2011/11/14/two-useful-interpolation-functions-for-noise-development/
- //
- float3 Interpolation_C2(float3 x) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }
- float3 Interpolation_C2_Deriv(float3 x) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }
- //
- // Value3D_Deriv
- // Value3D noise with derivatives
- // returns float3( value, xderiv, yderiv, zderiv )
- //
- float4 Value3D_Deriv(float3 P)
- {
- // establish our grid cell and unit position
- float3 Pi = floor(P);
- float3 Pf = P - Pi;
- // calculate the hash.
- // ( various hashing methods listed in order of speed )
- float4 hash_lowz, hash_highz;
- FAST32_hash_3D(Pi, hash_lowz, hash_highz);
- // blend the results and return
- float3 blend = Interpolation_C2(Pf);
- float4 res0 = lerp(hash_lowz, hash_highz, blend.z);
- float4 res1 = lerp(res0.xyxz, res0.zwyw, blend.yyxx);
- float4 res3 = lerp(float4(hash_lowz.xy, hash_highz.xy), float4(hash_lowz.zw, hash_highz.zw), blend.y);
- float2 res4 = lerp(res3.xz, res3.yw, blend.x);
- return float4(res1.x, 0.0, 0.0, 0.0) + (float4(res1.yyw, res4.y) - float4(res1.xxz, res4.x)) * float4(blend.x, Interpolation_C2_Deriv(Pf));
- }
- void FAST32_hash_3D(float3 gridcell, float3 v1_mask, float3 v2_mask, out float4 hash_0, out float4 hash_1, out float4 hash_2) // generates 3 random numbers for each of the 4 3D cell corners. cell corners: v0=0,0,0 v3=1,1,1 the other two are user definable
- {
- // gridcell is assumed to be an integer coordinate
- // TODO: these constants need tweaked to find the best possible noise.
- // probably requires some kind of brute force computational searching or something....
- const float2 OFFSET = float2(50.0, 161.0);
- const float DOMAIN = 69.0;
- const float3 SOMELARGEFLOATS = float3(635.298681, 682.357502, 668.926525);
- const float3 ZINC = float3(48.500388, 65.294118, 63.934599);
- // truncate the domain
- gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * (1.0 / DOMAIN)) * DOMAIN;
- float3 gridcell_inc1 = step(gridcell, float3(DOMAIN - 1.5, DOMAIN - 1.5, DOMAIN - 1.5)) * (gridcell + 1.0);
- // compute x*x*y*y for the 4 corners
- float4 P = float4(gridcell.xy, gridcell_inc1.xy) + OFFSET.xyxy;
- P *= P;
- float4 V1xy_V2xy = lerp(P.xyxy, P.zwzw, float4(v1_mask.xy, v2_mask.xy)); // apply mask for v1 and v2
- P = float4(P.x, V1xy_V2xy.xz, P.z) * float4(P.y, V1xy_V2xy.yw, P.w);
- // get the lowz and highz mods
- float3 lowz_mods = float3(1.0 / (SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz));
- float3 highz_mods = float3(1.0 / (SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz));
- // apply mask for v1 and v2 mod values
- v1_mask = (v1_mask.z < 0.5) ? lowz_mods : highz_mods;
- v2_mask = (v2_mask.z < 0.5) ? lowz_mods : highz_mods;
- // compute the final hash
- hash_0 = frac(P * float4(lowz_mods.x, v1_mask.x, v2_mask.x, highz_mods.x));
- hash_1 = frac(P * float4(lowz_mods.y, v1_mask.y, v2_mask.y, highz_mods.y));
- hash_2 = frac(P * float4(lowz_mods.z, v1_mask.z, v2_mask.z, highz_mods.z));
- }
- //
- // Given an arbitrary 3D point this calculates the 4 vectors from the corners of the simplex pyramid to the point
- // It also returns the integer grid index information for the corners
- //
- void Simplex3D_GetCornerVectors(float3 P, // input point
- out float3 Pi, // integer grid index for the origin
- out float3 Pi_1, // offsets for the 2nd and 3rd corners. ( the 4th = Pi + 1.0 )
- out float3 Pi_2,
- out float4 v1234_x, // vectors from the 4 corners to the intput point
- out float4 v1234_y,
- out float4 v1234_z)
- {
- //
- // Simplex math from Stefan Gustavson's and Ian McEwan's work at...
- // http://github.com/ashima/webgl-noise
- //
- // simplex math constants
- const float SKEWFACTOR = 1.0 / 3.0;
- const float UNSKEWFACTOR = 1.0 / 6.0;
- const float SIMPLEX_CORNER_POS = 0.5;
- const float SIMPLEX_PYRAMID_HEIGHT = 0.70710678118654752440084436210485; // sqrt( 0.5 ) height of simplex pyramid.
- P *= SIMPLEX_PYRAMID_HEIGHT; // scale space so we can have an approx feature size of 1.0 ( optional )
- // Find the vectors to the corners of our simplex pyramid
- Pi = floor(P + dot(P, float3(SKEWFACTOR, SKEWFACTOR, SKEWFACTOR)));
- float3 x0 = P - Pi + dot(Pi, float3(UNSKEWFACTOR, UNSKEWFACTOR, UNSKEWFACTOR));
- float3 g = step(x0.yzx, x0.xyz);
- float3 l = 1.0 - g;
- Pi_1 = min(g.xyz, l.zxy);
- Pi_2 = max(g.xyz, l.zxy);
- float3 x1 = x0 - Pi_1 + UNSKEWFACTOR;
- float3 x2 = x0 - Pi_2 + SKEWFACTOR;
- float3 x3 = x0 - SIMPLEX_CORNER_POS;
- // pack them into a parallel-friendly arrangement
- v1234_x = float4(x0.x, x1.x, x2.x, x3.x);
- v1234_y = float4(x0.y, x1.y, x2.y, x3.y);
- v1234_z = float4(x0.z, x1.z, x2.z, x3.z);
- }
- //
- // SimplexPerlin3D_Deriv
- // SimplexPerlin3D noise with derivatives
- // returns float3( value, xderiv, yderiv, zderiv )
- //
- float4 SimplexPerlin3D_Deriv(float3 P)
- {
- // calculate the simplex vector and index math
- float3 Pi;
- float3 Pi_1;
- float3 Pi_2;
- float4 v1234_x;
- float4 v1234_y;
- float4 v1234_z;
- Simplex3D_GetCornerVectors(P, Pi, Pi_1, Pi_2, v1234_x, v1234_y, v1234_z);
- // generate the random vectors
- // ( various hashing methods listed in order of speed )
- float4 hash_0;
- float4 hash_1;
- float4 hash_2;
- FAST32_hash_3D(Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2);
- hash_0 -= 0.49999;
- hash_1 -= 0.49999;
- hash_2 -= 0.49999;
- // normalize random gradient vectors
- float4 norm = rsqrt(hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2);
- hash_0 *= norm;
- hash_1 *= norm;
- hash_2 *= norm;
- // evaluate gradients
- float4 grad_results = hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z;
- // evaluate the surflet f(x)=(0.5-x*x)^3
- float4 m = v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;
- m = max(0.5 - m, 0.0); // The 0.5 here is SIMPLEX_PYRAMID_HEIGHT^2
- float4 m2 = m*m;
- float4 m3 = m*m2;
- // calc the deriv
- float4 temp = -6.0 * m2 * grad_results;
- float xderiv = dot(temp, v1234_x) + dot(m3, hash_0);
- float yderiv = dot(temp, v1234_y) + dot(m3, hash_1);
- float zderiv = dot(temp, v1234_z) + dot(m3, hash_2);
- const float FINAL_NORMALIZATION = 37.837227241611314102871574478976; // scales the final result to a strict 1.0->-1.0 range
- // sum with the surflet and return
- return float4(dot(m3, grad_results), xderiv, yderiv, zderiv) * FINAL_NORMALIZATION;
- }
- float Perlin3D(float3 P)
- {
- // establish our grid cell and unit position
- float3 Pi = floor(P);
- float3 Pf = P - Pi;
- float3 Pf_min1 = Pf - 1.0;
- //
- // classic noise.
- // requires 3 random values per point. with an efficent hash function will run faster than improved noise
- //
- // calculate the hash.
- // ( various hashing methods listed in order of speed )
- float4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;
- FAST32_hash_3D(Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1);
- // calculate the gradients
- float4 grad_x0 = hashx0 - 0.49999;
- float4 grad_y0 = hashy0 - 0.49999;
- float4 grad_z0 = hashz0 - 0.49999;
- float4 grad_x1 = hashx1 - 0.49999;
- float4 grad_y1 = hashy1 - 0.49999;
- float4 grad_z1 = hashz1 - 0.49999;
- float4 grad_results_0 = rsqrt(grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0) * (float2(Pf.x, Pf_min1.x).xyxy * grad_x0 + float2(Pf.y, Pf_min1.y).xxyy * grad_y0 + Pf.zzzz * grad_z0);
- float4 grad_results_1 = rsqrt(grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1) * (float2(Pf.x, Pf_min1.x).xyxy * grad_x1 + float2(Pf.y, Pf_min1.y).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1);
- // Classic Perlin Interpolation
- float3 blend = Interpolation_C2(Pf);
- float4 res0 = lerp(grad_results_0, grad_results_1, blend.z);
- float2 res1 = lerp(res0.xy, res0.zw, blend.y);
- float final = lerp(res1.x, res1.y, blend.x);
- final *= 1.1547005383792515290182975610039; // (optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)
- return final;
- }
- float4 Simplex3D_GetSurfletWeights(float4 v1234_x, float4 v1234_y, float4 v1234_z)
- {
- // perlins original implementation uses the surlet falloff formula of (0.6-x*x)^4.
- // This is buggy as it can cause discontinuities along simplex faces. (0.5-x*x)^3 solves this and gives an almost identical curve
- // evaluate surflet. f(x)=(0.5-x*x)^3
- float4 surflet_weights = v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;
- surflet_weights = max(0.5 - surflet_weights, 0.0); // 0.5 here represents the closest distance (squared) of any simplex pyramid corner to any of its planes. ie, SIMPLEX_PYRAMID_HEIGHT^2
- return surflet_weights*surflet_weights*surflet_weights;
- }
- float SimplexPerlin3D(float3 P)
- {
- // calculate the simplex vector and index math
- float3 Pi;
- float3 Pi_1;
- float3 Pi_2;
- float4 v1234_x;
- float4 v1234_y;
- float4 v1234_z;
- Simplex3D_GetCornerVectors(P, Pi, Pi_1, Pi_2, v1234_x, v1234_y, v1234_z);
- // generate the random vectors
- // ( various hashing methods listed in order of speed )
- float4 hash_0;
- float4 hash_1;
- float4 hash_2;
- FAST32_hash_3D(Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2);
- hash_0 -= 0.49999;
- hash_1 -= 0.49999;
- hash_2 -= 0.49999;
- // evaluate gradients
- float4 grad_results = rsqrt(hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2) * (hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z);
- // Normalization factor to scale the final result to a strict 1.0->-1.0 range
- // x = sqrt( 0.75 ) * 0.5
- // NF = 1.0 / ( x * ( ( 0.5 ? x*x ) ^ 3 ) * 2.0 )
- // http://briansharpe.wordpress.com/2012/01/13/simplex-noise/#comment-36
- const float FINAL_NORMALIZATION = 37.837227241611314102871574478976;
- // sum with the surflet and return
- return dot(Simplex3D_GetSurfletWeights(v1234_x, v1234_y, v1234_z), grad_results) * FINAL_NORMALIZATION;
- }
- float Value3D(float3 P)
- {
- // establish our grid cell and unit position
- float3 Pi = floor(P);
- float3 Pf = P - Pi;
- // calculate the hash.
- // ( various hashing methods listed in order of speed )
- float4 hash_lowz, hash_highz;
- FAST32_hash_3D(Pi, hash_lowz, hash_highz);
- // blend the results and return
- float3 blend = Interpolation_C2(Pf);
- float4 res0 = lerp(hash_lowz, hash_highz, blend.z);
- float2 res1 = lerp(res0.xy, res0.zw, blend.y);
- return lerp(res1.x, res1.y, blend.x);
- }
- float4 FAST32_hash_3D_Cell(float3 gridcell) // generates 4 different random numbers for the single given cell point
- {
- // gridcell is assumed to be an integer coordinate
- // TODO: these constants need tweaked to find the best possible noise.
- // probably requires some kind of brute force computational searching or something....
- const float2 OFFSET = float2(50.0, 161.0);
- const float DOMAIN = 69.0;
- const float4 SOMELARGEFLOATS = float4(635.298681, 682.357502, 668.926525, 588.255119);
- const float4 ZINC = float4(48.500388, 65.294118, 63.934599, 63.279683);
- // truncate the domain
- gridcell.xyz = gridcell - floor(gridcell * (1.0 / DOMAIN)) * DOMAIN;
- gridcell.xy += OFFSET.xy;
- gridcell.xy *= gridcell.xy;
- return frac((gridcell.x * gridcell.y) * (1.0 / (SOMELARGEFLOATS + gridcell.zzzz * ZINC)));
- }
- static const int MinVal = -1;
- static const int MaxVal = 1;
- float Cellular3D(float3 xyz, int cellType, int distanceFunction)
- {
- int xi = int(floor(xyz.x));
- int yi = int(floor(xyz.y));
- int zi = int(floor(xyz.z));
- float xf = xyz.x - float(xi);
- float yf = xyz.y - float(yi);
- float zf = xyz.z - float(zi);
- float dist1 = 9999999.0;
- float dist2 = 9999999.0;
- float dist3 = 9999999.0;
- float dist4 = 9999999.0;
- float3 cell;
- for (int z = MinVal; z <= MaxVal; z++) {
- for (int y = MinVal; y <= MaxVal; y++) {
- for (int x = MinVal; x <= MaxVal; x++) {
- cell = FAST32_hash_3D_Cell(float3(xi + x, yi + y, zi + z)).xyz;
- cell.x += (float(x) - xf);
- cell.y += (float(y) - yf);
- cell.z += (float(z) - zf);
- float dist = 0.0;
- if (distanceFunction == 1)
- {
- dist = sqrt(dot(cell, cell));
- }
- else if (distanceFunction == 2)
- {
- dist = dot(cell, cell);
- }
- else if (distanceFunction == 3)
- {
- dist = abs(cell.x) + abs(cell.y) + abs(cell.z);
- dist *= 0.5;
- dist *= dist;
- }
- else if (distanceFunction == 4)
- {
- dist = max(abs(cell.x), max(abs(cell.y), abs(cell.z)));
- dist *= dist;
- }
- else if (distanceFunction == 5)
- {
- dist = dot(cell, cell) + cell.x*cell.y + cell.x*cell.z + cell.y*cell.z;
- }
- else if (distanceFunction == 6)
- {
- dist = pow(abs(cell.x*cell.x*cell.x*cell.x + cell.y*cell.y*cell.y*cell.y + cell.z*cell.z*cell.z*cell.z), 0.25);
- }
- else if (distanceFunction == 7)
- {
- dist = sqrt(abs(cell.x)) + sqrt(abs(cell.y)) + sqrt(abs(cell.z));
- dist *= 0.5;
- dist *= dist;
- }
- if (dist < dist1)
- {
- dist4 = dist3;
- dist3 = dist2;
- dist2 = dist1;
- dist1 = dist;
- }
- else if (dist < dist2)
- {
- dist4 = dist3;
- dist3 = dist2;
- dist2 = dist;
- }
- else if (dist < dist3)
- {
- dist4 = dist3;
- dist3 = dist;
- }
- else if (dist < dist4)
- {
- dist4 = dist;
- }
- }
- }
- }
- if (cellType == 1) // F1
- return dist1 / 2; // scale return value from 0.0->1.333333 to 0.0->1.0 (2/3)^2 * 3 == (12/9) == 1.333333
- else if (cellType == 2) // F2
- return dist2 / 2.5;
- else if (cellType == 3) // F3
- return dist3 / 3;
- else if (cellType == 4) // F4
- return dist4 / 4;
- else if (cellType == 5) // F2 - F1
- return dist2 - dist1;
- else if (cellType == 6) // F3 - F2
- return dist3 - dist2;
- else if (cellType == 7) // F1 + F2/2
- return (dist1 + dist2) / 4.0;
- else if (cellType == 8) // F1 * F2
- return (dist1 * dist2) / 2.0;
- else if (cellType == 9) // Crackle
- return max(1.0, 10 * (dist2 - dist1)) * 0.10;
- else return dist1;
- }
- float4 Cellular_weight_samples(float4 samples)
- {
- samples = samples * 2.0 - 1.0;
- //return (1.0 - samples * samples) * sign(samples); // square
- return (samples * samples * samples) - sign(samples); // cubic (even more variance)
- }
- float Cellular3D(float3 P)
- {
- // establish our grid cell and unit position
- float3 Pi = floor(P);
- float3 Pf = P - Pi;
- // calculate the hash.
- // ( various hashing methods listed in order of speed )
- float4 hash_x0, hash_y0, hash_z0, hash_x1, hash_y1, hash_z1;
- FAST32_hash_3D(Pi, hash_x0, hash_y0, hash_z0, hash_x1, hash_y1, hash_z1);
- // generate the 8 random points
- // restrict the random point offset to eliminate artifacts
- // we'll improve the variance of the noise by pushing the points to the extremes of the jitter window
- const float JITTER_WINDOW = 0.166666666; // 0.166666666 will guarentee no artifacts. It is the intersection on x of graphs f(x)=( (0.5 + (0.5-x))^2 + 2*((0.5-x)^2) ) and f(x)=( 2 * (( 0.5 + x )^2) + x * x )
- hash_x0 = Cellular_weight_samples(hash_x0) * JITTER_WINDOW + float4(0.0, 1.0, 0.0, 1.0);
- hash_y0 = Cellular_weight_samples(hash_y0) * JITTER_WINDOW + float4(0.0, 0.0, 1.0, 1.0);
- hash_x1 = Cellular_weight_samples(hash_x1) * JITTER_WINDOW + float4(0.0, 1.0, 0.0, 1.0);
- hash_y1 = Cellular_weight_samples(hash_y1) * JITTER_WINDOW + float4(0.0, 0.0, 1.0, 1.0);
- hash_z0 = Cellular_weight_samples(hash_z0) * JITTER_WINDOW + float4(0.0, 0.0, 0.0, 0.0);
- hash_z1 = Cellular_weight_samples(hash_z1) * JITTER_WINDOW + float4(1.0, 1.0, 1.0, 1.0);
- // return the closest squared distance
- float4 dx1 = Pf.xxxx - hash_x0;
- float4 dy1 = Pf.yyyy - hash_y0;
- float4 dz1 = Pf.zzzz - hash_z0;
- float4 dx2 = Pf.xxxx - hash_x1;
- float4 dy2 = Pf.yyyy - hash_y1;
- float4 dz2 = Pf.zzzz - hash_z1;
- float4 d1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1;
- float4 d2 = dx2 * dx2 + dy2 * dy2 + dz2 * dz2;
- d1 = min(d1, d2);
- d1.xy = min(d1.xy, d1.wz);
- return min(d1.x, d1.y) * (9.0 / 12.0); // scale return value from 0.0->1.333333 to 0.0->1.0 (2/3)^2 * 3 == (12/9) == 1.333333
- }
|