1// Compatibility #ifdefs needed for parameters
2#ifdef GL_ES
3#define COMPAT_PRECISION mediump
4#else
5#define COMPAT_PRECISION
6#endif
7
8// Parameter lines go here:
9#pragma parameter RETRO_PIXEL_SIZE "Retro Pixel Size" 0.84 0.0 1.0 0.01
10#ifdef PARAMETER_UNIFORM
11// All parameter floats need to have COMPAT_PRECISION in front of them
12uniform COMPAT_PRECISION float RETRO_PIXEL_SIZE;
13#else
14#define RETRO_PIXEL_SIZE 0.84
15#endif
16
17#if defined(VERTEX)
18
19#if __VERSION__ >= 130
20#define COMPAT_VARYING out
21#define COMPAT_ATTRIBUTE in
22#define COMPAT_TEXTURE texture
23#else
24#define COMPAT_VARYING varying
25#define COMPAT_ATTRIBUTE attribute
26#define COMPAT_TEXTURE texture2D
27#endif
28
29#ifdef GL_ES
30#define COMPAT_PRECISION mediump
31#else
32#define COMPAT_PRECISION
33#endif
34
35COMPAT_ATTRIBUTE vec4 VertexCoord;
36COMPAT_ATTRIBUTE vec4 COLOR;
37COMPAT_ATTRIBUTE vec4 TexCoord;
38COMPAT_VARYING vec4 COL0;
39COMPAT_VARYING vec4 TEX0;
40// out variables go here as COMPAT_VARYING whatever
41
42vec4 _oPosition1;
43uniform mat4 MVPMatrix;
44uniform COMPAT_PRECISION int FrameDirection;
45uniform COMPAT_PRECISION int FrameCount;
46uniform COMPAT_PRECISION vec2 OutputSize;
47uniform COMPAT_PRECISION vec2 TextureSize;
48uniform COMPAT_PRECISION vec2 InputSize;
49
50// compatibility #defines
51#define vTexCoord TEX0.xy
52#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
53#define OutSize vec4(OutputSize, 1.0 / OutputSize)
54
55void main()
56{
57    gl_Position = MVPMatrix * VertexCoord;
58    TEX0.xy = VertexCoord.xy;
59// Paste vertex contents here:
60}
61
62#elif defined(FRAGMENT)
63
64#if __VERSION__ >= 130
65#define COMPAT_VARYING in
66#define COMPAT_TEXTURE texture
67out vec4 FragColor;
68#else
69#define COMPAT_VARYING varying
70#define FragColor gl_FragColor
71#define COMPAT_TEXTURE texture2D
72#endif
73
74#ifdef GL_ES
75#ifdef GL_FRAGMENT_PRECISION_HIGH
76precision highp float;
77#else
78precision mediump float;
79#endif
80#define COMPAT_PRECISION mediump
81#else
82#define COMPAT_PRECISION
83#endif
84
85uniform COMPAT_PRECISION int FrameDirection;
86uniform COMPAT_PRECISION int FrameCount;
87uniform COMPAT_PRECISION vec2 OutputSize;
88uniform COMPAT_PRECISION vec2 TextureSize;
89uniform COMPAT_PRECISION vec2 InputSize;
90uniform sampler2D Texture;
91COMPAT_VARYING vec4 TEX0;
92// in variables go here as COMPAT_VARYING whatever
93
94// compatibility #defines
95#define Source Texture
96#define vTexCoord TEX0.xy
97
98#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
99#define OutSize vec4(OutputSize, 1.0 / OutputSize)
100
101// delete all 'params.' or 'registers.' or whatever in the fragment
102float iGlobalTime = float(FrameCount)*0.025;
103vec2 iResolution = OutputSize.xy;
104
105// White Folly -  dr2 - 2017-11-07
106// https://www.shadertoy.com/view/ll2cDG
107
108// Folly (architectural) with spiral stairways (in a pond filled with Voronoi stones); mouse enabled
109
110// "White Folly" by dr2 - 2017
111// License: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
112
113float PrBoxDf (vec3 p, vec3 b);
114float PrBox2Df (vec2 p, vec2 b);
115float PrCylDf (vec3 p, float r, float h);
116float PrCylAnDf (vec3 p, float r, float w, float h);
117void HexVorInit ();
118vec4 HexVor (vec2 p);
119float SmoothMin (float a, float b, float r);
120float SmoothBump (float lo, float hi, float w, float x);
121vec2 Rot2D (vec2 q, float a);
122vec3 HsvToRgb (vec3 c);
123float Hashfv2 (vec2 p);
124vec2 Hashv2v2 (vec2 p);
125float Noisefv2 (vec2 p);
126float Fbm2 (vec2 p);
127vec3 VaryNf (vec3 p, vec3 n, float f);
128
129const float pi = 3.14159;
130
131vec3 sunDir, qHit;
132float dstFar, tCur, tWav;
133int idObj;
134bool inWat;
135const int idStr = 1, idBal = 2, idPlat = 3, idBalc = 4, idPil = 5, idWl = 6, idFlr = 7;
136
137float ObjDfS (vec3 p, float dMin)
138{
139  vec3 q;
140  float d, db, s, a;
141  q = p;
142  q.xz = abs (Rot2D (q.xz, pi)) - 6.5;
143  db = PrBox2Df (q.xz, vec2 (4.));
144  q.xz += 6.5;
145  q.xz = Rot2D (q.xz, 0.75 * pi);
146  q.x += 4.;
147  a = (length (q.xz) > 0.) ? atan (q.z, - q.x) / (2. * pi) : 0.;
148  q.xz = vec2 (24. * a, length (q.xz) - 6.);
149  q.xy = Rot2D (q.xy, -0.25 * pi);
150  s = mod (q.x, sqrt (0.5));
151  d = max (0.3 * max (q.y - min (s, sqrt (0.5) - s), max (-0.1 - q.y, abs (q.z) - 1.5)),
152     abs (p.y) - 3.5);
153  d = max (d, db);
154  if (d < dMin) { dMin = d;  idObj = idStr; }
155  q.xy -= vec2 (1.5, 1.4);
156  q.z = abs (q.z) - 1.43;
157  d = PrBoxDf (q, vec3 (4.7, 0.07, 0.07));
158  q.x = 0.5 * mod (96. * a + 0.5, 1.) - 0.35;
159  q.y += 0.7;
160  d = min (d,  PrCylDf (q.xzy, 0.05, 0.7));
161  d = max (0.3 * d, db);
162  if (d < dMin) { dMin = d;  idObj = idBal; }
163  return dMin;
164}
165
166/*
167  This function is called twice, for the two orientations of the horizontal
168  walkway. Could be replaced by a single call, with orientation dependent on
169  position along ray path; this is faster (good) but there are visual artifacts for
170  certain view directions (bad). Artifacts can be removed by using cells in the
171  vertical direction (good), but this is slower (bad).
172*/
173
174float ObjDfB (vec3 p, float dMin)
175{
176  vec3 q;
177  float d;
178  q = p;
179  d = max (PrBoxDf (q, vec3 (10.35, 0.26, 2.85)),
180    - max (length (vec2 (mod (q.x + 2., 4.) - 2., q.z)) - 1.5, 0.3 - abs (q.z)));
181  if (d < dMin) { dMin = d;  idObj = idPlat;  qHit = q; }
182  q = p;  q.y -= 2.05;  q.z = abs (q.z) - 2.45;
183  d = PrBoxDf (q, vec3 (7.45, 0.08, 0.07));
184  q.x = mod (q.x + 0.25, 0.5) - 0.25;
185  q.y += 0.95;
186  d = min (d, max (PrCylDf (q.xzy, 0.06, 0.9), abs (p.x) - 7.45));
187  q = p;  q.y -= 1.06;  q.x = abs (q.x) - 10.23;  q.y -= 0.95;
188  d = min (d, PrBoxDf (q, vec3 (0.07, 0.08, 2.5)));
189  q.y += 0.95;  q.z = mod (q.z + 0.25, 0.5) - 0.25;
190  d = min (d, max (PrCylDf (q.xzy, 0.06, 0.9), abs (p.z) - 2.45));
191  if (d < dMin) { dMin = d;  idObj = idBalc; }
192  q = p;  q.xz = abs (q.xz) - vec2 (8.8, 2.4);  q.x = abs (q.x) - 1.45;  q.y -= 1.3;
193  d = PrCylDf (q.xzy, 0.2, 1.05);
194  if (d < dMin) { dMin = d;  idObj = idPil;  qHit = q; }
195  return dMin;
196}
197
198float ObjDf (vec3 p)
199{
200  vec3 q;
201  float dMin, d;
202  dMin = dstFar;
203  p.y -= 3.;
204  if (! inWat) {
205    dMin = ObjDfS (p, dMin);
206    q = p;  q.y -= 3.25;
207    dMin = ObjDfB (q, dMin);
208    q = p;  q.y -= -3.25;  q.xz = vec2 (- q.z, q.x);
209    dMin = ObjDfB (q, dMin);
210    q = p;  q.y -= 9.;
211    d = max (PrBoxDf (q, vec3 (2.5, 0.15, 2.5)),
212       - max (length (q.xz) - 1., max (0.1 - abs (q.x), 0.1 - abs (q.z))));
213    if (d < dMin) { dMin = d;  idObj = idPlat;  qHit = q; }
214  }
215  q = p;  q.xz = abs (q.xz) - 1.8;  q.y -= 1.;
216  d = PrCylDf (q.xzy, 0.2, 8.);
217  if (d < dMin) { dMin = d;  idObj = idPil;  qHit = q; }
218  q = p;  q.y -= -5.2;
219  d = PrCylAnDf (q.xzy, 20., 0.3, 2.3);
220  if (d < dMin) { dMin = d;  idObj = idWl; }
221  q = p;  q.y -= -7.4;
222  d = PrCylDf (q.xzy, 20., 0.01);
223  if (d < dMin) { dMin = d;  idObj = idFlr; }
224  return dMin;
225}
226
227float ObjRay (vec3 ro, vec3 rd)
228{
229  float dHit, d, eps;
230  eps = 0.001;
231  dHit = 0.;
232  for (int j = 0; j < 160; j ++) {
233    d = ObjDf (ro + dHit * rd);
234    dHit += d;
235    if (d < eps || dHit > dstFar) break;
236  }
237  return dHit;
238}
239
240vec3 ObjNf (vec3 p)
241{
242  vec4 v;
243  vec3 e = vec3 (0.001, -0.001, 0.);
244  v = vec4 (ObjDf (p + e.xxx), ObjDf (p + e.xyy), ObjDf (p + e.yxy), ObjDf (p + e.yyx));
245  return normalize (vec3 (v.x - v.y - v.z - v.w) + 2. * v.yzw);
246}
247
248float ObjSShadow (vec3 ro, vec3 rd)
249{
250  float sh, d, h;
251  sh = 1.;
252  d = 0.05;
253  for (int j = 0; j < 40; j ++) {
254    h = ObjDf (ro + rd * d);
255    sh = min (sh, smoothstep (0., 0.05 * d, h));
256    d += h;
257    if (sh < 0.05) break;
258  }
259  return sh;
260}
261
262vec3 BgCol (vec3 ro, vec3 rd)
263{
264  vec3 col;
265  if (rd.y >= 0.) col = mix (vec3 (0.1, 0.2, 0.4), vec3 (1.), 0.1 + 0.8 * rd.y);
266  else {
267    ro -= ((ro.y + 0.5) / rd.y) * rd;
268    col = mix (0.7 * mix (vec3 (0.3, 0.4, 0.1), vec3 (0.4, 0.5, 0.2), Fbm2 (ro.xz)) *
269         (1. - 0.15 * Noisefv2 (330. * ro.xz)), vec3 (0.18, 0.28, 0.48), pow (1. + rd.y, 5.));
270  }
271  return col;
272}
273
274float WaveHt (vec2 p)
275{
276  mat2 qRot = mat2 (0.8, -0.6, 0.6, 0.8);
277  vec4 t4, v4;
278  vec2 t;
279  float wFreq, wAmp, ht;
280  wFreq = 1.;
281  wAmp = 1.;
282  ht = 0.;
283  for (int j = 0; j < 3; j ++) {
284    p *= qRot;
285    t = tWav * vec2 (1., -1.);
286    t4 = (p.xyxy + t.xxyy) * wFreq;
287    t = vec2 (Noisefv2 (t4.xy), Noisefv2 (t4.zw));
288    t4 += 2. * t.xxyy - 1.;
289    v4 = (1. - abs (sin (t4))) * (abs (sin (t4)) + abs (cos (t4)));
290    ht += wAmp * dot (pow (1. - sqrt (v4.xz * v4.yw), vec2 (8.)), vec2 (1.));
291    wFreq *= 2.;
292    wAmp *= 0.5;
293  }
294  return ht;
295}
296
297vec3 WaveNf (vec3 p, float d)
298{
299  vec3 vn;
300  vec2 e;
301  e = vec2 (max (0.01, 0.005 * d * d), 0.);
302  p *= 0.5;
303  vn.xz = 3. * (WaveHt (p.xz) - vec2 (WaveHt (p.xz + e.xy),  WaveHt (p.xz + e.yx)));
304  vn.y = e.x;
305  return normalize (vn);
306}
307
308vec3 ShowScene (vec3 ro, vec3 rd)
309{
310  vec4 vc;
311  vec3 vn, vnw, row, rdw, col;
312  float dstObj, dstWat, s, a, sh;
313  bool isRefl;
314  HexVorInit ();
315  inWat = false;
316  isRefl = false;
317  tWav = 0.3 * tCur;
318  dstObj = ObjRay (ro, rd);
319  dstWat = - (ro.y + 0.6) / rd.y;
320  if (dstWat < min (dstObj, dstFar) && length ((ro + dstWat * rd).xz) < 20.) {
321    ro += dstWat * rd;
322    row = ro;
323    rdw = rd;
324    vnw = WaveNf (1.5 * ro, dstWat);;
325    rd = refract (rd, vnw, 1./1.333);
326    ro += 0.01 * rd;
327    inWat = true;
328    dstObj = ObjRay (ro, rd);
329    inWat = false;
330    isRefl = true;
331  }
332  if (dstObj < dstFar) {
333    ro += rd * dstObj;
334    if (ro.y < -0.5 && length (ro.xz) > 20.3) col = BgCol (ro, rd);
335    else {
336      vn = ObjNf (ro);
337      if (idObj == idStr) {
338        col = vec3 (0.95, 0.95, 1.);
339      } else if (idObj == idBal || idObj == idBalc) {
340        col = vec3 (0.8, 0.8, 1.);
341      } else if (idObj == idPlat) {
342        col = vec3 (1.);
343        if (vn.y > 0.99) {
344          if (ro.y > 7.5) s = mod (3. * length (qHit.xz), 1.);
345          else s = mod (3. * qHit.x, 1.);
346          col *= 0.8 + 0.2 * SmoothBump (0.1, 0.9, 0.03, s);
347        } else if (abs (vn.y) < 0.01) {
348          s = mod (8. * ro.y, 1.);
349          col *= 0.8 + 0.2 * SmoothBump (0.1, 0.9, 0.03, s);
350        }
351        vn = VaryNf (100. * ro, vn, 0.2);
352      } else if (idObj == idPil) {
353        if (abs (vn.y) < 0.01) {
354          a = (length (qHit.xz) > 0.) ? atan (qHit.z, - qHit.x) / pi : 0.;
355          s = mod (3. * qHit.y + a, 1.);
356          vn.y = 0.2 * (1. - SmoothBump (0.2, 0.8, 0.1, s)) * sign (s - 0.5);
357          vn.xz *= sqrt (1. - vn.y * vn.y);
358        }
359        col = vec3 (0.9, 0.9, 0.3);
360      } else if (idObj == idWl) {
361        a = (length (ro.xz) > 0.) ? atan (ro.z, - ro.x) / pi : 0.;
362        col = vec3 (0.6, 0.4, 0.3) * (0.5 +
363           0.5 * SmoothBump (0.05, 0.95, 0.02, mod (64. * a, 1.))) *
364           (0.5 + 0.5 * SmoothBump (0.03, 0.97, 0.01, mod (ro.y + 0.5, 1.)));
365        vn = VaryNf (20. * ro, vn, 1.);
366      } else if (idObj == idFlr) {
367        vc = HexVor (ro.xz);
368        vn.xz = - 0.7 * vc.yz;
369        vn = normalize (vn);
370        s = mod (10. * vc.w, 1.);
371        col = HsvToRgb (vec3 (0.1 + 0.3 * step (2. * s, 1.) + 0.1 * mod (5. * s, 1.),
372           0.5 + 0.5 * mod (17. * s, 1.), 0.7 + 0.3 * mod (12. * s, 1.))) *
373           (0.6 + 0.4 * smoothstep (0., 0.2, vc.x)) * (1. - 0.2 * Noisefv2 (128. * ro.xz));
374      }
375      sh = 0.4 + 0.6 * ObjSShadow (ro, sunDir);
376      col = col * (0.2 + sh * max (dot (sunDir, vn), 0.) +
377         0.1 * max (dot (- sunDir.xz, vn.xz), 0.)) +
378         0.1 * sh * pow (max (dot (normalize (sunDir - rd), vn), 0.), 64.);
379    }
380  } else {
381    if (isRefl) sh = ObjSShadow (row, sunDir);
382    col = BgCol (ro, rd);
383  }
384  if (isRefl) {
385    col = mix (0.9 * col, vec3 (1., 1., 0.9), sh *
386       pow (max (0., dot (sunDir, reflect (rdw, vnw))), 64.));
387  }
388  return clamp (col, 0., 1.);
389}
390
391void mainImage (out vec4 fragColor, in vec2 fragCoord)
392{
393  mat3 vuMat;
394#ifdef MOUSE
395  vec4 mPtr;
396#endif
397  vec3 ro, rd;
398  vec2 canvas, uv, ori, ca, sa;
399  float el, az, zmFac;
400  canvas = iResolution.xy;
401  uv = 2. * fragCoord.xy / canvas - 1.;
402  uv.x *= canvas.x / canvas.y;
403  tCur = iGlobalTime;
404#ifdef MOUSE
405  mPtr = iMouse;
406  mPtr.xy = mPtr.xy / canvas - 0.5;
407#endif
408  dstFar = 120.;
409  az = 0.;
410  el = -0.2 * pi;
411#ifdef MOUSE
412  if (mPtr.z > 0.) {
413    az += 3. * pi * mPtr.x;
414    el += 1. * pi * mPtr.y;
415  } else {
416    az -= 0.1 * tCur;
417    el -= 0.1 * pi * cos (0.03 * pi * tCur);
418  }
419#else
420  az -= 0.1 * tCur;
421  el -= 0.1 * pi * cos (0.03 * pi * tCur);
422#endif
423  el = clamp (el, -0.4 * pi, -0.05 * pi);
424  ori = vec2 (el, az);
425  ca = cos (ori);
426  sa = sin (ori);
427  vuMat = mat3 (ca.y, 0., - sa.y, 0., 1., 0., sa.y, 0., ca.y) *
428          mat3 (1., 0., 0., 0., ca.x, - sa.x, 0., sa.x, ca.x);
429  zmFac = 7. - 2. * cos (az);
430  rd = vuMat * normalize (vec3 (uv, zmFac));
431  ro = vuMat * vec3 (0., 1., -70.);
432  sunDir = vuMat * normalize (vec3 (1., 1., -1.));
433  fragColor = vec4 (ShowScene (ro, rd), 1.);
434}
435
436float PrBoxDf (vec3 p, vec3 b)
437{
438  vec3 d;
439  d = abs (p) - b;
440  return min (max (d.x, max (d.y, d.z)), 0.) + length (max (d, 0.));
441}
442
443float PrBox2Df (vec2 p, vec2 b)
444{
445  vec2 d;
446  d = abs (p) - b;
447  return min (max (d.x, d.y), 0.) + length (max (d, 0.));
448}
449
450float PrCylDf (vec3 p, float r, float h)
451{
452  return max (length (p.xy) - r, abs (p.z) - h);
453}
454
455float PrCylAnDf (vec3 p, float r, float w, float h)
456{
457  return max (abs (length (p.xy) - r) - w, abs (p.z) - h);
458}
459
460vec2 gVec[7], hVec[7];
461#define SQRT3 1.7320508
462
463vec2 PixToHex (vec2 p)
464{
465  vec3 c, r, dr;
466  c.xz = vec2 ((1./SQRT3) * p.x - (1./3.) * p.y, (2./3.) * p.y);
467  c.y = - c.x - c.z;
468  r = floor (c + 0.5);
469  dr = abs (r - c);
470  r -= step (dr.yzx, dr) * step (dr.zxy, dr) * dot (r, vec3 (1.));
471  return r.xz;
472}
473
474vec2 HexToPix (vec2 h)
475{
476  return vec2 (SQRT3 * (h.x + 0.5 * h.y), (3./2.) * h.y);
477}
478
479void HexVorInit ()
480{
481  vec3 e = vec3 (1., 0., -1.);
482  gVec[0] = e.yy;
483  gVec[1] = e.xy;
484  gVec[2] = e.yx;
485  gVec[3] = e.xz;
486  gVec[4] = e.zy;
487  gVec[5] = e.yz;
488  gVec[6] = e.zx;
489  for (int k = 0; k < 7; k ++) hVec[k] = HexToPix (gVec[k]);
490}
491
492vec4 HexVor (vec2 p)
493{
494  vec4 sd, udm;
495  vec2 ip, fp, d, u;
496  float amp, a;
497  amp = 0.7;
498  ip = PixToHex (p);
499  fp = p - HexToPix (ip);
500  sd = vec4 (4.);
501  udm = vec4 (4.);
502  for (int k = 0; k < 7; k ++) {
503    u = Hashv2v2 (ip + gVec[k]);
504    a = 2. * pi * (u.y - 0.5);
505    d = hVec[k] + amp * (0.4 + 0.6 * u.x) * vec2 (cos (a), sin (a)) - fp;
506    sd.w = dot (d, d);
507    if (sd.w < sd.x) {
508      sd = sd.wxyw;
509      udm = vec4 (d, u);
510    } else sd = (sd.w < sd.y) ? sd.xwyw : ((sd.w < sd.z) ? sd.xyww : sd);
511  }
512  sd.xyz = sqrt (sd.xyz);
513  return vec4 (SmoothMin (sd.y, sd.z, 0.3) - sd.x, udm.xy, Hashfv2 (udm.zw));
514}
515
516float SmoothMin (float a, float b, float r)
517{
518  float h;
519  h = clamp (0.5 + 0.5 * (b - a) / r, 0., 1.);
520  return mix (b, a, h) - r * h * (1. - h);
521}
522
523float SmoothBump (float lo, float hi, float w, float x)
524{
525  return (1. - smoothstep (hi - w, hi + w, x)) * smoothstep (lo - w, lo + w, x);
526}
527
528vec2 Rot2D (vec2 q, float a)
529{
530  return q * cos (a) + q.yx * sin (a) * vec2 (-1., 1.);
531}
532
533vec3 HsvToRgb (vec3 c)
534{
535  vec3 p;
536  p = abs (fract (c.xxx + vec3 (1., 2./3., 1./3.)) * 6. - 3.);
537  return c.z * mix (vec3 (1.), clamp (p - 1., 0., 1.), c.y);
538}
539
540const float cHashM = 43758.54;
541
542float Hashfv2 (vec2 p)
543{
544  return fract (sin (dot (p, vec2 (37., 39.))) * cHashM);
545}
546
547vec2 Hashv2v2 (vec2 p)
548{
549  vec2 cHashVA2 = vec2 (37., 39.);
550  return fract (sin (vec2 (dot (p, cHashVA2), dot (p + vec2 (1., 0.), cHashVA2))) * cHashM);
551}
552
553float Noisefv2 (vec2 p)
554{
555  vec2 t, ip, fp;
556  ip = floor (p);
557  fp = fract (p);
558  fp = fp * fp * (3. - 2. * fp);
559  t = mix (Hashv2v2 (ip), Hashv2v2 (ip + vec2 (0., 1.)), fp.y);
560  return mix (t.x, t.y, fp.x);
561}
562
563float Fbm2 (vec2 p)
564{
565  float f, a;
566  f = 0.;
567  a = 1.;
568  for (int i = 0; i < 5; i ++) {
569    f += a * Noisefv2 (p);
570    a *= 0.5;
571    p *= 2.;
572  }
573  return f * (1. / 1.9375);
574}
575
576float Fbmn (vec3 p, vec3 n)
577{
578  vec3 s;
579  float a;
580  s = vec3 (0.);
581  a = 1.;
582  for (int i = 0; i < 5; i ++) {
583    s += a * vec3 (Noisefv2 (p.yz), Noisefv2 (p.zx), Noisefv2 (p.xy));
584    a *= 0.5;
585    p *= 2.;
586  }
587  return dot (s, abs (n));
588}
589
590vec3 VaryNf (vec3 p, vec3 n, float f)
591{
592  vec3 g;
593  vec2 e = vec2 (0.1, 0.);
594  g = vec3 (Fbmn (p + e.xyy, n), Fbmn (p + e.yxy, n), Fbmn (p + e.yyx, n)) - Fbmn (p, n);
595  return normalize (n + f * (g - n * dot (n, g)));
596}
597
598 void main(void)
599{
600  //just some shit to wrap shadertoy's stuff
601  vec2 FragCoord = vTexCoord.xy*OutputSize.xy;
602  mainImage(FragColor,FragCoord);
603}
604#endif
605