jax 0.0.0.4 → 0.0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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
+ }