-
Notifications
You must be signed in to change notification settings - Fork 16
/
SimplexPerlin2D_Deriv.glsl
83 lines (72 loc) · 3.54 KB
/
SimplexPerlin2D_Deriv.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
78
79
80
81
82
83
//
// 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 is a modified version of Stefan Gustavson's and Ian McEwan's work at http://github.com/ashima/webgl-noise
// Modifications are...
// - faster random number generation
// - analytical final normalization
// - space scaled can have an approx feature size of 1.0
//
//
// Simplex Perlin Noise 2D Deriv
// Return value range of -1.0->1.0, with format vec3( value, xderiv, yderiv )
//
vec3 SimplexPerlin2D_Deriv( vec2 P )
{
// https://github.com/BrianSharpe/Wombat/blob/master/SimplexPerlin2D_Deriv.glsl
// simplex math constants
const float SKEWFACTOR = 0.36602540378443864676372317075294; // 0.5*(sqrt(3.0)-1.0)
const float UNSKEWFACTOR = 0.21132486540518711774542560974902; // (3.0-sqrt(3.0))/6.0
const float SIMPLEX_TRI_HEIGHT = 0.70710678118654752440084436210485; // sqrt( 0.5 ) height of simplex triangle
const vec3 SIMPLEX_POINTS = vec3( 1.0-UNSKEWFACTOR, -UNSKEWFACTOR, 1.0-2.0*UNSKEWFACTOR ); // simplex triangle geo
// establish our grid cell.
P *= SIMPLEX_TRI_HEIGHT; // scale space so we can have an approx feature size of 1.0
vec2 Pi = floor( P + dot( P, vec2( SKEWFACTOR ) ) );
// calculate the hash
vec4 Pt = vec4( Pi.xy, Pi.xy + 1.0 );
Pt = Pt - floor(Pt * ( 1.0 / 71.0 )) * 71.0;
Pt += vec2( 26.0, 161.0 ).xyxy;
Pt *= Pt;
Pt = Pt.xzxz * Pt.yyww;
vec4 hash_x = fract( Pt * ( 1.0 / 951.135664 ) );
vec4 hash_y = fract( Pt * ( 1.0 / 642.949883 ) );
// establish vectors to the 3 corners of our simplex triangle
vec2 v0 = Pi - dot( Pi, vec2( UNSKEWFACTOR ) ) - P;
vec4 v1pos_v1hash = (v0.x < v0.y) ? vec4(SIMPLEX_POINTS.xy, hash_x.y, hash_y.y) : vec4(SIMPLEX_POINTS.yx, hash_x.z, hash_y.z);
vec4 v12 = vec4( v1pos_v1hash.xy, SIMPLEX_POINTS.zz ) + v0.xyxy;
// calculate the dotproduct of our 3 corner vectors with 3 random normalized vectors
vec3 grad_x = vec3( hash_x.x, v1pos_v1hash.z, hash_x.w ) - 0.49999;
vec3 grad_y = vec3( hash_y.x, v1pos_v1hash.w, hash_y.w ) - 0.49999;
vec3 norm = inversesqrt( grad_x * grad_x + grad_y * grad_y );
grad_x *= norm;
grad_y *= norm;
vec3 grad_results = grad_x * vec3( v0.x, v12.xz ) + grad_y * vec3( v0.y, v12.yw );
// evaluate the kernel
vec3 m = vec3( v0.x, v12.xz ) * vec3( v0.x, v12.xz ) + vec3( v0.y, v12.yw ) * vec3( v0.y, v12.yw );
m = max(0.5 - m, 0.0);
vec3 m2 = m*m;
vec3 m4 = m2*m2;
// calc the derivatives
vec3 temp = 8.0 * m2 * m * grad_results;
float xderiv = dot( temp, vec3( v0.x, v12.xz ) ) - dot( m4, grad_x );
float yderiv = dot( temp, vec3( v0.y, v12.yw ) ) - dot( m4, grad_y );
// Normalization factor to scale the final result to a strict 1.0->-1.0 range
// http://briansharpe.wordpress.com/2012/01/13/simplex-noise/#comment-36
const float FINAL_NORMALIZATION = 99.204334582718712976990005025589;
// sum and return all results as a vec3
return vec3( dot( m4, grad_results ), xderiv, yderiv ) * FINAL_NORMALIZATION;
}