jax 0.0.0.4 → 0.0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. data/CHANGELOG +14 -0
  2. data/Rakefile +4 -0
  3. data/builtin/shaders/depthmap/fragment.ejs +4 -2
  4. data/builtin/shaders/depthmap/material.js +5 -0
  5. data/builtin/shaders/depthmap/vertex.ejs +4 -1
  6. data/builtin/shaders/functions/noise.ejs +523 -0
  7. data/builtin/shaders/lighting/common.ejs +1 -1
  8. data/builtin/shaders/normal_map/common.ejs +1 -1
  9. data/builtin/shaders/{paraboloid-depthmap → paraboloid}/common.ejs +2 -2
  10. data/builtin/shaders/{paraboloid-depthmap → paraboloid}/fragment.ejs +3 -3
  11. data/builtin/shaders/paraboloid/manifest.yml +5 -0
  12. data/builtin/shaders/{paraboloid-depthmap → paraboloid}/material.js +4 -4
  13. data/builtin/shaders/{paraboloid-depthmap → paraboloid}/vertex.ejs +1 -0
  14. data/builtin/shaders/shadow_map/common.ejs +1 -1
  15. data/builtin/shaders/shadow_map/fragment.ejs +1 -1
  16. data/lib/jax.rb +4 -0
  17. data/lib/jax/application.rb +4 -5
  18. data/lib/jax/generators/app/templates/public/javascripts/jax.js +190 -6
  19. data/lib/jax/generators/material/USAGE +1 -1
  20. data/lib/jax/generators/shader/templates/common.ejs.tt +1 -1
  21. data/lib/jax/generators/shader/templates/spec.js.tt +4 -0
  22. data/lib/jax/packager/sprockets_template.rb +4 -0
  23. data/lib/jax/resource_compiler.rb +1 -1
  24. data/lib/jax/shader.rb +19 -7
  25. data/lib/jax/version.rb +1 -1
  26. data/spec/example_app/app/controllers/noise_controller.js +18 -0
  27. data/spec/example_app/app/helpers/noise_helper.js +3 -0
  28. data/spec/example_app/app/resources/materials/blob.yml +28 -0
  29. data/spec/example_app/app/shaders/blob/common.ejs +18 -0
  30. data/spec/example_app/app/shaders/blob/fragment.ejs +8 -0
  31. data/spec/example_app/app/shaders/blob/manifest.yml +15 -0
  32. data/spec/example_app/app/shaders/blob/material.js +48 -0
  33. data/spec/example_app/app/shaders/blob/vertex.ejs +13 -0
  34. data/spec/example_app/app/views/noise/index.js +4 -0
  35. data/spec/example_app/config/routes.rb +1 -0
  36. data/spec/example_app/spec/javascripts/controllers/noise_controller_spec.js +11 -0
  37. data/spec/example_app/spec/javascripts/helpers/noise_helper_spec.js +12 -0
  38. data/spec/example_app/spec/javascripts/shaders/blob_spec.js +30 -0
  39. data/spec/example_app/spec/javascripts/support/spec_layout.html.erb +2 -1
  40. data/spec/javascripts/shaders/core_materials_spec.js +1 -0
  41. data/spec/javascripts/shaders/{dual_paraboloid_spec.js → paraboloid_spec.js} +2 -2
  42. data/src/constants.yml +1 -0
  43. data/src/constants.yml.erb +1 -0
  44. data/src/jax.js +14 -1
  45. data/src/jax/noise.js +193 -0
  46. data/src/jax/webgl/material.js +3 -2
  47. data/src/jax/webgl/scene/light_source.js +3 -2
  48. metadata +41 -12
  49. data/spec/javascripts/Player.js +0 -58
data/CHANGELOG ADDED
@@ -0,0 +1,14 @@
1
+ * 0.0.0.5 *
2
+
3
+ * Jax now checks JS version against gem version and reports on mismatches
4
+
5
+ * Perlin noise functions added -- just do this in your shader:
6
+ //= require "functions/noise"
7
+
8
+ * Split 'paraboloid-depthmap' shader into 2 separate shaders: 'paraboloid' and 'depthmap'
9
+ This makes it possible to reuse paraboloids for environment mapping.
10
+
11
+ * Shader dependencies are now loaded via Jax.shader_load_paths, which can be multiple
12
+ different directories (e.g. Jax builtin + app/shaders)
13
+
14
+ * Added CHANGELOG. :)
data/Rakefile CHANGED
@@ -49,6 +49,10 @@ end
49
49
 
50
50
  desc "compile Jax"
51
51
  task :compile do
52
+ # generate constants file
53
+ erb = ERB.new(File.read(File.join(File.dirname(__FILE__), "src/constants.yml.erb")))
54
+ File.open(File.join(File.dirname(__FILE__), "src/constants.yml"), "w") { |f| f.puts erb.result(binding) }
55
+
52
56
  secretary = Sprockets::Secretary.new(
53
57
  :root => File.dirname(__FILE__),
54
58
  :asset_root => "public",
@@ -1,5 +1,7 @@
1
- //= require "../functions/depth_map"
1
+ //= require "functions/depth_map"
2
2
 
3
3
  void main(void) {
4
- gl_FragColor = pack_depth(gl_FragCoord.z);
4
+ vec4 pos = gl_FragCoord;
5
+ import(exPos, pos = exPos);
6
+ gl_FragColor = pack_depth(pos.z);
5
7
  }
@@ -0,0 +1,5 @@
1
+ Jax.Material.Depthmap = Jax.Class.create(Jax.Material, {
2
+ initialize: function($super) {
3
+ $super({shader:"depthmap"});
4
+ }
5
+ });
@@ -3,5 +3,8 @@ shared attribute vec4 VERTEX_POSITION;
3
3
  shared uniform mat4 mvMatrix;
4
4
 
5
5
  void main(void) {
6
- gl_Position = pMatrix * mvMatrix * VERTEX_POSITION;
6
+ vec4 pos = pMatrix * mvMatrix * VERTEX_POSITION;
7
+ import(Position, pos = Position);
8
+
9
+ gl_Position = pos;
7
10
  }
@@ -0,0 +1,523 @@
1
+ /*
2
+ * 2D, 3D and 4D Perlin noise, classic and simplex, in a GLSL fragment shader.
3
+ *
4
+ * Classic noise is implemented by the functions:
5
+ * float noise(vec2 P)
6
+ * float noise(vec3 P)
7
+ * float noise(vec4 P)
8
+ *
9
+ * Simplex noise is implemented by the functions:
10
+ * float snoise(vec2 P)
11
+ * float snoise(vec3 P)
12
+ * float snoise(vec4 P)
13
+ *
14
+ * Author: Stefan Gustavson ITN-LiTH (stegu@itn.liu.se) 2004-12-05
15
+ * You may use, modify and redistribute this code free of charge,
16
+ * provided that my name and this notice appears intact.
17
+ */
18
+
19
+ /*
20
+ * NOTE: there is a formal problem with the dependent texture lookups.
21
+ * A texture coordinate of exactly 1.0 will wrap to 0.0, so strictly speaking,
22
+ * an error occurs every 256 units of the texture domain, and the same gradient
23
+ * is used for two adjacent noise cells. One solution is to set the texture
24
+ * wrap mode to "CLAMP" and do the wrapping explicitly in GLSL with the "mod"
25
+ * operator. This could also give you noise with repetition intervals other
26
+ * than 256 without any extra cost.
27
+ * This error is not even noticeable to the eye even if you isolate the exact
28
+ * position in the domain where it occurs and know exactly what to look for.
29
+ * The noise pattern is still visually correct, so I left the bug in there.
30
+ *
31
+ * The value of classic 4D noise goes above 1.0 and below -1.0 at some
32
+ * points. Not much and only very sparsely, but it happens.
33
+ */
34
+
35
+
36
+ /*
37
+ * "permTexture" is a 256x256 texture that is used for both the permutations
38
+ * and the 2D and 3D gradient lookup. For details, see the main C program.
39
+ * "simplexTexture" is a small look-up table to determine a simplex traversal
40
+ * order for 3D and 4D simplex noise. Details are in the C program.
41
+ * "gradTexture" is a 256x256 texture with 4D gradients, similar to
42
+ * "permTexture" but with the permutation index in the alpha component
43
+ * replaced by the w component of the 4D gradient.
44
+ * 2D classic noise uses only permTexture.
45
+ * 2D simplex noise uses permTexture and simplexTexture.
46
+ * 3D classic noise uses only permTexture.
47
+ * 3D simplex noise uses permTexture and simplexTexture.
48
+ * 4D classic noise uses permTexture and gradTexture.
49
+ * 4D simplex noise uses all three textures.
50
+ */
51
+ uniform sampler2D permTexture;
52
+ // sampler1D not supported in WebGL
53
+ //uniform sampler1D simplexTexture;
54
+ uniform sampler2D simplexTexture;
55
+ uniform sampler2D gradTexture;
56
+ uniform float time; // Used for texture animation
57
+
58
+ /*
59
+ * Both 2D and 3D texture coordinates are defined, for testing purposes.
60
+ */
61
+ //varying vec2 v_texCoord2D;
62
+ //varying vec3 v_texCoord3D;
63
+ //varying vec4 v_color;
64
+
65
+ /*
66
+ * To create offsets of one texel and one half texel in the
67
+ * texture lookup, we need to know the texture image size.
68
+ */
69
+ #define ONE 0.00390625
70
+ #define ONEHALF 0.001953125
71
+ // The numbers above are 1/256 and 0.5/256, change accordingly
72
+ // if you change the code to use another texture size.
73
+
74
+
75
+ /*
76
+ * The interpolation function. This could be a 1D texture lookup
77
+ * to get some more speed, but it's not the main part of the algorithm.
78
+ */
79
+ float fade(float t) {
80
+ // return t*t*(3.0-2.0*t); // Old fade, yields discontinuous second derivative
81
+ return t*t*t*(t*(t*6.0-15.0)+10.0); // Improved fade, yields C2-continuous noise
82
+ }
83
+
84
+
85
+ /*
86
+ * 2D classic Perlin noise. Fast, but less useful than 3D noise.
87
+ */
88
+ float noise(vec2 P)
89
+ {
90
+ vec2 Pi = ONE*floor(P)+ONEHALF; // Integer part, scaled and offset for texture lookup
91
+ vec2 Pf = fract(P); // Fractional part for interpolation
92
+
93
+ // Noise contribution from lower left corner
94
+ vec2 grad00 = texture2D(permTexture, Pi).rg * 4.0 - 1.0;
95
+ float n00 = dot(grad00, Pf);
96
+
97
+ // Noise contribution from lower right corner
98
+ vec2 grad10 = texture2D(permTexture, Pi + vec2(ONE, 0.0)).rg * 4.0 - 1.0;
99
+ float n10 = dot(grad10, Pf - vec2(1.0, 0.0));
100
+
101
+ // Noise contribution from upper left corner
102
+ vec2 grad01 = texture2D(permTexture, Pi + vec2(0.0, ONE)).rg * 4.0 - 1.0;
103
+ float n01 = dot(grad01, Pf - vec2(0.0, 1.0));
104
+
105
+ // Noise contribution from upper right corner
106
+ vec2 grad11 = texture2D(permTexture, Pi + vec2(ONE, ONE)).rg * 4.0 - 1.0;
107
+ float n11 = dot(grad11, Pf - vec2(1.0, 1.0));
108
+
109
+ // Blend contributions along x
110
+ vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade(Pf.x));
111
+
112
+ // Blend contributions along y
113
+ float n_xy = mix(n_x.x, n_x.y, fade(Pf.y));
114
+
115
+ // We're done, return the final noise value.
116
+ return n_xy;
117
+ }
118
+
119
+
120
+ /*
121
+ * 3D classic noise. Slower, but a lot more useful than 2D noise.
122
+ */
123
+ float noise(vec3 P)
124
+ {
125
+ vec3 Pi = ONE*floor(P)+ONEHALF; // Integer part, scaled so +1 moves one texel
126
+ // and offset 1/2 texel to sample texel centers
127
+ vec3 Pf = fract(P); // Fractional part for interpolation
128
+
129
+ // Noise contributions from (x=0, y=0), z=0 and z=1
130
+ float perm00 = texture2D(permTexture, Pi.xy).a ;
131
+ vec3 grad000 = texture2D(permTexture, vec2(perm00, Pi.z)).rgb * 4.0 - 1.0;
132
+ float n000 = dot(grad000, Pf);
133
+ vec3 grad001 = texture2D(permTexture, vec2(perm00, Pi.z + ONE)).rgb * 4.0 - 1.0;
134
+ float n001 = dot(grad001, Pf - vec3(0.0, 0.0, 1.0));
135
+
136
+ // Noise contributions from (x=0, y=1), z=0 and z=1
137
+ float perm01 = texture2D(permTexture, Pi.xy + vec2(0.0, ONE)).a ;
138
+ vec3 grad010 = texture2D(permTexture, vec2(perm01, Pi.z)).rgb * 4.0 - 1.0;
139
+ float n010 = dot(grad010, Pf - vec3(0.0, 1.0, 0.0));
140
+ vec3 grad011 = texture2D(permTexture, vec2(perm01, Pi.z + ONE)).rgb * 4.0 - 1.0;
141
+ float n011 = dot(grad011, Pf - vec3(0.0, 1.0, 1.0));
142
+
143
+ // Noise contributions from (x=1, y=0), z=0 and z=1
144
+ float perm10 = texture2D(permTexture, Pi.xy + vec2(ONE, 0.0)).a ;
145
+ vec3 grad100 = texture2D(permTexture, vec2(perm10, Pi.z)).rgb * 4.0 - 1.0;
146
+ float n100 = dot(grad100, Pf - vec3(1.0, 0.0, 0.0));
147
+ vec3 grad101 = texture2D(permTexture, vec2(perm10, Pi.z + ONE)).rgb * 4.0 - 1.0;
148
+ float n101 = dot(grad101, Pf - vec3(1.0, 0.0, 1.0));
149
+
150
+ // Noise contributions from (x=1, y=1), z=0 and z=1
151
+ float perm11 = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a ;
152
+ vec3 grad110 = texture2D(permTexture, vec2(perm11, Pi.z)).rgb * 4.0 - 1.0;
153
+ float n110 = dot(grad110, Pf - vec3(1.0, 1.0, 0.0));
154
+ vec3 grad111 = texture2D(permTexture, vec2(perm11, Pi.z + ONE)).rgb * 4.0 - 1.0;
155
+ float n111 = dot(grad111, Pf - vec3(1.0, 1.0, 1.0));
156
+
157
+ // Blend contributions along x
158
+ vec4 n_x = mix(vec4(n000, n001, n010, n011),
159
+ vec4(n100, n101, n110, n111), fade(Pf.x));
160
+
161
+ // Blend contributions along y
162
+ vec2 n_xy = mix(n_x.xy, n_x.zw, fade(Pf.y));
163
+
164
+ // Blend contributions along z
165
+ float n_xyz = mix(n_xy.x, n_xy.y, fade(Pf.z));
166
+
167
+ // We're done, return the final noise value.
168
+ return n_xyz;
169
+ }
170
+
171
+
172
+ /*
173
+ * 4D classic noise. Slow, but very useful. 4D simplex noise is a lot faster.
174
+ *
175
+ * This function performs 8 texture lookups and 16 dependent texture lookups,
176
+ * 16 dot products, 4 mix operations and a lot of additions and multiplications.
177
+ * Needless to say, it's not super fast. But it's not dead slow either.
178
+ */
179
+ float noise(vec4 P)
180
+ {
181
+ vec4 Pi = ONE*floor(P)+ONEHALF; // Integer part, scaled so +1 moves one texel
182
+ // and offset 1/2 texel to sample texel centers
183
+ vec4 Pf = fract(P); // Fractional part for interpolation
184
+
185
+ // "n0000" is the noise contribution from (x=0, y=0, z=0, w=0), and so on
186
+ float perm00xy = texture2D(permTexture, Pi.xy).a ;
187
+ float perm00zw = texture2D(permTexture, Pi.zw).a ;
188
+ vec4 grad0000 = texture2D(gradTexture, vec2(perm00xy, perm00zw)).rgba * 4.0 -1.0;
189
+ float n0000 = dot(grad0000, Pf);
190
+
191
+ float perm01zw = texture2D(permTexture, Pi.zw + vec2(0.0, ONE)).a ;
192
+ vec4 grad0001 = texture2D(gradTexture, vec2(perm00xy, perm01zw)).rgba * 4.0 - 1.0;
193
+ float n0001 = dot(grad0001, Pf - vec4(0.0, 0.0, 0.0, 1.0));
194
+
195
+ float perm10zw = texture2D(permTexture, Pi.zw + vec2(ONE, 0.0)).a ;
196
+ vec4 grad0010 = texture2D(gradTexture, vec2(perm00xy, perm10zw)).rgba * 4.0 - 1.0;
197
+ float n0010 = dot(grad0010, Pf - vec4(0.0, 0.0, 1.0, 0.0));
198
+
199
+ float perm11zw = texture2D(permTexture, Pi.zw + vec2(ONE, ONE)).a ;
200
+ vec4 grad0011 = texture2D(gradTexture, vec2(perm00xy, perm11zw)).rgba * 4.0 - 1.0;
201
+ float n0011 = dot(grad0011, Pf - vec4(0.0, 0.0, 1.0, 1.0));
202
+
203
+ float perm01xy = texture2D(permTexture, Pi.xy + vec2(0.0, ONE)).a ;
204
+ vec4 grad0100 = texture2D(gradTexture, vec2(perm01xy, perm00zw)).rgba * 4.0 - 1.0;
205
+ float n0100 = dot(grad0100, Pf - vec4(0.0, 1.0, 0.0, 0.0));
206
+
207
+ vec4 grad0101 = texture2D(gradTexture, vec2(perm01xy, perm01zw)).rgba * 4.0 - 1.0;
208
+ float n0101 = dot(grad0101, Pf - vec4(0.0, 1.0, 0.0, 1.0));
209
+
210
+ vec4 grad0110 = texture2D(gradTexture, vec2(perm01xy, perm10zw)).rgba * 4.0 - 1.0;
211
+ float n0110 = dot(grad0110, Pf - vec4(0.0, 1.0, 1.0, 0.0));
212
+
213
+ vec4 grad0111 = texture2D(gradTexture, vec2(perm01xy, perm11zw)).rgba * 4.0 - 1.0;
214
+ float n0111 = dot(grad0111, Pf - vec4(0.0, 1.0, 1.0, 1.0));
215
+
216
+ float perm10xy = texture2D(permTexture, Pi.xy + vec2(ONE, 0.0)).a ;
217
+ vec4 grad1000 = texture2D(gradTexture, vec2(perm10xy, perm00zw)).rgba * 4.0 - 1.0;
218
+ float n1000 = dot(grad1000, Pf - vec4(1.0, 0.0, 0.0, 0.0));
219
+
220
+ vec4 grad1001 = texture2D(gradTexture, vec2(perm10xy, perm01zw)).rgba * 4.0 - 1.0;
221
+ float n1001 = dot(grad1001, Pf - vec4(1.0, 0.0, 0.0, 1.0));
222
+
223
+ vec4 grad1010 = texture2D(gradTexture, vec2(perm10xy, perm10zw)).rgba * 4.0 - 1.0;
224
+ float n1010 = dot(grad1010, Pf - vec4(1.0, 0.0, 1.0, 0.0));
225
+
226
+ vec4 grad1011 = texture2D(gradTexture, vec2(perm10xy, perm11zw)).rgba * 4.0 - 1.0;
227
+ float n1011 = dot(grad1011, Pf - vec4(1.0, 0.0, 1.0, 1.0));
228
+
229
+ float perm11xy = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a ;
230
+ vec4 grad1100 = texture2D(gradTexture, vec2(perm11xy, perm00zw)).rgba * 4.0 - 1.0;
231
+ float n1100 = dot(grad1100, Pf - vec4(1.0, 1.0, 0.0, 0.0));
232
+
233
+ vec4 grad1101 = texture2D(gradTexture, vec2(perm11xy, perm01zw)).rgba * 4.0 - 1.0;
234
+ float n1101 = dot(grad1101, Pf - vec4(1.0, 1.0, 0.0, 1.0));
235
+
236
+ vec4 grad1110 = texture2D(gradTexture, vec2(perm11xy, perm10zw)).rgba * 4.0 - 1.0;
237
+ float n1110 = dot(grad1110, Pf - vec4(1.0, 1.0, 1.0, 0.0));
238
+
239
+ vec4 grad1111 = texture2D(gradTexture, vec2(perm11xy, perm11zw)).rgba * 4.0 - 1.0;
240
+ float n1111 = dot(grad1111, Pf - vec4(1.0, 1.0, 1.0, 1.0));
241
+
242
+ // Blend contributions along x
243
+ float fadex = fade(Pf.x);
244
+ vec4 n_x0 = mix(vec4(n0000, n0001, n0010, n0011),
245
+ vec4(n1000, n1001, n1010, n1011), fadex);
246
+ vec4 n_x1 = mix(vec4(n0100, n0101, n0110, n0111),
247
+ vec4(n1100, n1101, n1110, n1111), fadex);
248
+
249
+ // Blend contributions along y
250
+ vec4 n_xy = mix(n_x0, n_x1, fade(Pf.y));
251
+
252
+ // Blend contributions along z
253
+ vec2 n_xyz = mix(n_xy.xy, n_xy.zw, fade(Pf.z));
254
+
255
+ // Blend contributions along w
256
+ float n_xyzw = mix(n_xyz.x, n_xyz.y, fade(Pf.w));
257
+
258
+ // We're done, return the final noise value.
259
+ return n_xyzw;
260
+ }
261
+
262
+
263
+ /*
264
+ * 2D simplex noise. Somewhat slower but much better looking than classic noise.
265
+ */
266
+ float snoise(vec2 P) {
267
+
268
+ // Skew and unskew factors are a bit hairy for 2D, so define them as constants
269
+ // This is (sqrt(3.0)-1.0)/2.0
270
+ #define F2 0.366025403784
271
+ // This is (3.0-sqrt(3.0))/6.0
272
+ #define G2 0.211324865405
273
+
274
+ // Skew the (x,y) space to determine which cell of 2 simplices we're in
275
+ float s = (P.x + P.y) * F2; // Hairy factor for 2D skewing
276
+ vec2 Pi = floor(P + s);
277
+ float t = (Pi.x + Pi.y) * G2; // Hairy factor for unskewing
278
+ vec2 P0 = Pi - t; // Unskew the cell origin back to (x,y) space
279
+ Pi = Pi * ONE + ONEHALF; // Integer part, scaled and offset for texture lookup
280
+
281
+ vec2 Pf0 = P - P0; // The x,y distances from the cell origin
282
+
283
+ // For the 2D case, the simplex shape is an equilateral triangle.
284
+ // Find out whether we are above or below the x=y diagonal to
285
+ // determine which of the two triangles we're in.
286
+ vec2 o1;
287
+ if(Pf0.x > Pf0.y) o1 = vec2(1.0, 0.0); // +x, +y traversal order
288
+ else o1 = vec2(0.0, 1.0); // +y, +x traversal order
289
+
290
+ // Noise contribution from simplex origin
291
+ vec2 grad0 = texture2D(permTexture, Pi).rg * 4.0 - 1.0;
292
+ float t0 = 0.5 - dot(Pf0, Pf0);
293
+ float n0;
294
+ if (t0 < 0.0) n0 = 0.0;
295
+ else {
296
+ t0 *= t0;
297
+ n0 = t0 * t0 * dot(grad0, Pf0);
298
+ }
299
+
300
+ // Noise contribution from middle corner
301
+ vec2 Pf1 = Pf0 - o1 + G2;
302
+ vec2 grad1 = texture2D(permTexture, Pi + o1*ONE).rg * 4.0 - 1.0;
303
+ float t1 = 0.5 - dot(Pf1, Pf1);
304
+ float n1;
305
+ if (t1 < 0.0) n1 = 0.0;
306
+ else {
307
+ t1 *= t1;
308
+ n1 = t1 * t1 * dot(grad1, Pf1);
309
+ }
310
+
311
+ // Noise contribution from last corner
312
+ vec2 Pf2 = Pf0 - vec2(1.0-2.0*G2);
313
+ vec2 grad2 = texture2D(permTexture, Pi + vec2(ONE, ONE)).rg * 4.0 - 1.0;
314
+ float t2 = 0.5 - dot(Pf2, Pf2);
315
+ float n2;
316
+ if(t2 < 0.0) n2 = 0.0;
317
+ else {
318
+ t2 *= t2;
319
+ n2 = t2 * t2 * dot(grad2, Pf2);
320
+ }
321
+
322
+ // Sum up and scale the result to cover the range [-1,1]
323
+ return 70.0 * (n0 + n1 + n2);
324
+ }
325
+
326
+
327
+ /*
328
+ * 3D simplex noise. Comparable in speed to classic noise, better looking.
329
+ */
330
+ float snoise(vec3 P) {
331
+
332
+ // The skewing and unskewing factors are much simpler for the 3D case
333
+ #define F3 0.333333333333
334
+ #define G3 0.166666666667
335
+
336
+ // Skew the (x,y,z) space to determine which cell of 6 simplices we're in
337
+ float s = (P.x + P.y + P.z) * F3; // Factor for 3D skewing
338
+ vec3 Pi = floor(P + s);
339
+ float t = (Pi.x + Pi.y + Pi.z) * G3;
340
+ vec3 P0 = Pi - t; // Unskew the cell origin back to (x,y,z) space
341
+ Pi = Pi * ONE + ONEHALF; // Integer part, scaled and offset for texture lookup
342
+
343
+ vec3 Pf0 = P - P0; // The x,y distances from the cell origin
344
+
345
+ // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
346
+ // To find out which of the six possible tetrahedra we're in, we need to
347
+ // determine the magnitude ordering of x, y and z components of Pf0.
348
+ // The method below is explained briefly in the C code. It uses a small
349
+ // 1D texture as a lookup table. The table is designed to work for both
350
+ // 3D and 4D noise, so only 8 (only 6, actually) of the 64 indices are
351
+ // used here.
352
+ float c1 = (Pf0.x > Pf0.y) ? 0.5078125 : 0.0078125; // 1/2 + 1/128
353
+ float c2 = (Pf0.x > Pf0.z) ? 0.25 : 0.0;
354
+ float c3 = (Pf0.y > Pf0.z) ? 0.125 : 0.0;
355
+ float sindex = c1 + c2 + c3;
356
+ vec3 offsets = texture2D(simplexTexture, vec2(sindex, 0.0)).rgb;
357
+ // vec3 offsets = texture1D(simplexTexture, sindex).rgb;
358
+ vec3 o1 = step(0.375, offsets);
359
+ vec3 o2 = step(0.125, offsets);
360
+
361
+ // Noise contribution from simplex origin
362
+ float perm0 = texture2D(permTexture, Pi.xy).a;
363
+ vec3 grad0 = texture2D(permTexture, vec2(perm0, Pi.z)).rgb * 4.0 - 1.0;
364
+ float t0 = 0.6 - dot(Pf0, Pf0);
365
+ float n0;
366
+ if (t0 < 0.0) n0 = 0.0;
367
+ else {
368
+ t0 *= t0;
369
+ n0 = t0 * t0 * dot(grad0, Pf0);
370
+ }
371
+
372
+ // Noise contribution from second corner
373
+ vec3 Pf1 = Pf0 - o1 + G3;
374
+ float perm1 = texture2D(permTexture, Pi.xy + o1.xy*ONE).a;
375
+ vec3 grad1 = texture2D(permTexture, vec2(perm1, Pi.z + o1.z*ONE)).rgb * 4.0 - 1.0;
376
+ float t1 = 0.6 - dot(Pf1, Pf1);
377
+ float n1;
378
+ if (t1 < 0.0) n1 = 0.0;
379
+ else {
380
+ t1 *= t1;
381
+ n1 = t1 * t1 * dot(grad1, Pf1);
382
+ }
383
+
384
+ // Noise contribution from third corner
385
+ vec3 Pf2 = Pf0 - o2 + 2.0 * G3;
386
+ float perm2 = texture2D(permTexture, Pi.xy + o2.xy*ONE).a;
387
+ vec3 grad2 = texture2D(permTexture, vec2(perm2, Pi.z + o2.z*ONE)).rgb * 4.0 - 1.0;
388
+ float t2 = 0.6 - dot(Pf2, Pf2);
389
+ float n2;
390
+ if (t2 < 0.0) n2 = 0.0;
391
+ else {
392
+ t2 *= t2;
393
+ n2 = t2 * t2 * dot(grad2, Pf2);
394
+ }
395
+
396
+ // Noise contribution from last corner
397
+ vec3 Pf3 = Pf0 - vec3(1.0-3.0*G3);
398
+ float perm3 = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a;
399
+ vec3 grad3 = texture2D(permTexture, vec2(perm3, Pi.z + ONE)).rgb * 4.0 - 1.0;
400
+ float t3 = 0.6 - dot(Pf3, Pf3);
401
+ float n3;
402
+ if(t3 < 0.0) n3 = 0.0;
403
+ else {
404
+ t3 *= t3;
405
+ n3 = t3 * t3 * dot(grad3, Pf3);
406
+ }
407
+
408
+ // Sum up and scale the result to cover the range [-1,1]
409
+ return 32.0 * (n0 + n1 + n2 + n3);
410
+ }
411
+
412
+
413
+ /*
414
+ * 4D simplex noise. A lot faster than classic 4D noise, and better looking.
415
+ */
416
+
417
+ float snoise(vec4 P) {
418
+
419
+ // The skewing and unskewing factors are hairy again for the 4D case
420
+ // This is (sqrt(5.0)-1.0)/4.0
421
+ #define F4 0.309016994375
422
+ // This is (5.0-sqrt(5.0))/20.0
423
+ #define G4 0.138196601125
424
+
425
+ // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
426
+ float s = (P.x + P.y + P.z + P.w) * F4; // Factor for 4D skewing
427
+ vec4 Pi = floor(P + s);
428
+ float t = (Pi.x + Pi.y + Pi.z + Pi.w) * G4;
429
+ vec4 P0 = Pi - t; // Unskew the cell origin back to (x,y,z,w) space
430
+ Pi = Pi * ONE + ONEHALF; // Integer part, scaled and offset for texture lookup
431
+
432
+ vec4 Pf0 = P - P0; // The x,y distances from the cell origin
433
+
434
+ // For the 4D case, the simplex is a 4D shape I won't even try to describe.
435
+ // To find out which of the 24 possible simplices we're in, we need to
436
+ // determine the magnitude ordering of x, y, z and w components of Pf0.
437
+ // The method below is presented without explanation. It uses a small 1D
438
+ // texture as a lookup table. The table is designed to work for both
439
+ // 3D and 4D noise and contains 64 indices, of which only 24 are actually
440
+ // used. An extension to 5D would require a larger texture here.
441
+ float c1 = (Pf0.x > Pf0.y) ? 0.5078125 : 0.0078125; // 1/2 + 1/128
442
+ float c2 = (Pf0.x > Pf0.z) ? 0.25 : 0.0;
443
+ float c3 = (Pf0.y > Pf0.z) ? 0.125 : 0.0;
444
+ float c4 = (Pf0.x > Pf0.w) ? 0.0625 : 0.0;
445
+ float c5 = (Pf0.y > Pf0.w) ? 0.03125 : 0.0;
446
+ float c6 = (Pf0.z > Pf0.w) ? 0.015625 : 0.0;
447
+ float sindex = c1 + c2 + c3 + c4 + c5 + c6;
448
+ vec4 offsets = texture2D(simplexTexture, vec2(sindex, 0.0)).rgba;
449
+ // vec4 offsets = texture1D(simplexTexture, sindex).rgba;
450
+ vec4 o1 = step(0.625, offsets);
451
+ vec4 o2 = step(0.375, offsets);
452
+ vec4 o3 = step(0.125, offsets);
453
+
454
+ // Noise contribution from simplex origin
455
+ float perm0xy = texture2D(permTexture, Pi.xy).a;
456
+ float perm0zw = texture2D(permTexture, Pi.zw).a;
457
+ vec4 grad0 = texture2D(gradTexture, vec2(perm0xy, perm0zw)).rgba * 4.0 - 1.0;
458
+ float t0 = 0.6 - dot(Pf0, Pf0);
459
+ float n0;
460
+ if (t0 < 0.0) n0 = 0.0;
461
+ else {
462
+ t0 *= t0;
463
+ n0 = t0 * t0 * dot(grad0, Pf0);
464
+ }
465
+
466
+ // Noise contribution from second corner
467
+ vec4 Pf1 = Pf0 - o1 + G4;
468
+ o1 = o1 * ONE;
469
+ float perm1xy = texture2D(permTexture, Pi.xy + o1.xy).a;
470
+ float perm1zw = texture2D(permTexture, Pi.zw + o1.zw).a;
471
+ vec4 grad1 = texture2D(gradTexture, vec2(perm1xy, perm1zw)).rgba * 4.0 - 1.0;
472
+ float t1 = 0.6 - dot(Pf1, Pf1);
473
+ float n1;
474
+ if (t1 < 0.0) n1 = 0.0;
475
+ else {
476
+ t1 *= t1;
477
+ n1 = t1 * t1 * dot(grad1, Pf1);
478
+ }
479
+
480
+ // Noise contribution from third corner
481
+ vec4 Pf2 = Pf0 - o2 + 2.0 * G4;
482
+ o2 = o2 * ONE;
483
+ float perm2xy = texture2D(permTexture, Pi.xy + o2.xy).a;
484
+ float perm2zw = texture2D(permTexture, Pi.zw + o2.zw).a;
485
+ vec4 grad2 = texture2D(gradTexture, vec2(perm2xy, perm2zw)).rgba * 4.0 - 1.0;
486
+ float t2 = 0.6 - dot(Pf2, Pf2);
487
+ float n2;
488
+ if (t2 < 0.0) n2 = 0.0;
489
+ else {
490
+ t2 *= t2;
491
+ n2 = t2 * t2 * dot(grad2, Pf2);
492
+ }
493
+
494
+ // Noise contribution from fourth corner
495
+ vec4 Pf3 = Pf0 - o3 + 3.0 * G4;
496
+ o3 = o3 * ONE;
497
+ float perm3xy = texture2D(permTexture, Pi.xy + o3.xy).a;
498
+ float perm3zw = texture2D(permTexture, Pi.zw + o3.zw).a;
499
+ vec4 grad3 = texture2D(gradTexture, vec2(perm3xy, perm3zw)).rgba * 4.0 - 1.0;
500
+ float t3 = 0.6 - dot(Pf3, Pf3);
501
+ float n3;
502
+ if (t3 < 0.0) n3 = 0.0;
503
+ else {
504
+ t3 *= t3;
505
+ n3 = t3 * t3 * dot(grad3, Pf3);
506
+ }
507
+
508
+ // Noise contribution from last corner
509
+ vec4 Pf4 = Pf0 - vec4(1.0-4.0*G4);
510
+ float perm4xy = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a;
511
+ float perm4zw = texture2D(permTexture, Pi.zw + vec2(ONE, ONE)).a;
512
+ vec4 grad4 = texture2D(gradTexture, vec2(perm4xy, perm4zw)).rgba * 4.0 - 1.0;
513
+ float t4 = 0.6 - dot(Pf4, Pf4);
514
+ float n4;
515
+ if(t4 < 0.0) n4 = 0.0;
516
+ else {
517
+ t4 *= t4;
518
+ n4 = t4 * t4 * dot(grad4, Pf4);
519
+ }
520
+
521
+ // Sum up and scale the result to cover the range [-1,1]
522
+ return 27.0 * (n0 + n1 + n2 + n3 + n4);
523
+ }