-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathCellular3D.glsl
77 lines (71 loc) · 3.32 KB
/
Cellular3D.glsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//
// Wombat
// An efficient texture-free GLSL procedural noise library
// Source: https://github.com/BrianSharpe/Wombat
// Derived from: https://github.com/BrianSharpe/GPU-Noise-Lib
//
// I'm not one for copyrights. Use the code however you wish.
// All I ask is that credit be given back to the blog or myself when appropriate.
// And also to let me know if you come up with any changes, improvements, thoughts or interesting uses for this stuff. :)
// Thanks!
//
// Brian Sharpe
// brisharpe CIRCLE_A yahoo DOT com
// http://briansharpe.wordpress.com
// https://github.com/BrianSharpe
//
//
// This represents a modified version of Stefan Gustavson's work at http://www.itn.liu.se/~stegu/GLSL-cellular
// The noise is optimized to use a 2x2x2 search window instead of 3x3x3
// Modifications are...
// - faster random number generation
// - analytical final normalization
// - random point offset is restricted to prevent artifacts
//
//
// Cellular Noise 3D
// produces a range of 0.0->1.0
//
float Cellular3D(vec3 P)
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
// clamp the domain
Pi.xyz = Pi.xyz - floor(Pi.xyz * ( 1.0 / 69.0 )) * 69.0;
vec3 Pi_inc1 = step( Pi, vec3( 69.0 - 1.5 ) ) * ( Pi + 1.0 );
// calculate the hash ( over -1.0->1.0 range )
vec4 Pt = vec4( Pi.xy, Pi_inc1.xy ) + vec2( 50.0, 161.0 ).xyxy;
Pt *= Pt;
Pt = Pt.xzxz * Pt.yyww;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS + Pi.zzz * ZINC ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS + Pi_inc1.zzz * ZINC ) );
vec4 hash_x0 = fract( Pt * lowz_mod.xxxx ) * 2.0 - 1.0;
vec4 hash_x1 = fract( Pt * highz_mod.xxxx ) * 2.0 - 1.0;
vec4 hash_y0 = fract( Pt * lowz_mod.yyyy ) * 2.0 - 1.0;
vec4 hash_y1 = fract( Pt * highz_mod.yyyy ) * 2.0 - 1.0;
vec4 hash_z0 = fract( Pt * lowz_mod.zzzz ) * 2.0 - 1.0;
vec4 hash_z1 = fract( Pt * highz_mod.zzzz ) * 2.0 - 1.0;
// generate the 8 point positions
const float JITTER_WINDOW = 0.166666666; // 0.166666666 will guarentee no artifacts.
hash_x0 = ( ( hash_x0 * hash_x0 * hash_x0 ) - sign( hash_x0 ) ) * JITTER_WINDOW + vec4( 0.0, 1.0, 0.0, 1.0 );
hash_y0 = ( ( hash_y0 * hash_y0 * hash_y0 ) - sign( hash_y0 ) ) * JITTER_WINDOW + vec4( 0.0, 0.0, 1.0, 1.0 );
hash_x1 = ( ( hash_x1 * hash_x1 * hash_x1 ) - sign( hash_x1 ) ) * JITTER_WINDOW + vec4( 0.0, 1.0, 0.0, 1.0 );
hash_y1 = ( ( hash_y1 * hash_y1 * hash_y1 ) - sign( hash_y1 ) ) * JITTER_WINDOW + vec4( 0.0, 0.0, 1.0, 1.0 );
hash_z0 = ( ( hash_z0 * hash_z0 * hash_z0 ) - sign( hash_z0 ) ) * JITTER_WINDOW + vec4( 0.0, 0.0, 0.0, 0.0 );
hash_z1 = ( ( hash_z1 * hash_z1 * hash_z1 ) - sign( hash_z1 ) ) * JITTER_WINDOW + vec4( 1.0, 1.0, 1.0, 1.0 );
// return the closest squared distance
vec4 dx1 = Pf.xxxx - hash_x0;
vec4 dy1 = Pf.yyyy - hash_y0;
vec4 dz1 = Pf.zzzz - hash_z0;
vec4 dx2 = Pf.xxxx - hash_x1;
vec4 dy2 = Pf.yyyy - hash_y1;
vec4 dz2 = Pf.zzzz - hash_z1;
vec4 d1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1;
vec4 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 ); // return a value scaled to 0.0->1.0
}