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// Rainbow Cavern -  dr2 - 2017-06-01
106// https://www.shadertoy.com/view/XsfBWM
107
108// Underground boat ride (mouseable)
109
110// "Rainbow Cavern" by dr2 - 2017
111// License: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
112
113#define USE_BMAP true
114//#define USE_BMAP false  // for weaker GPUs
115
116float PrSphDf (vec3 p, float r);
117float PrCapsDf (vec3 p, float r, float h);
118float SmoothBump (float lo, float hi, float w, float x);
119vec2 Rot2D (vec2 q, float a);
120float Hashfv3 (vec3 p);
121vec3 Hashv3f (float p);
122vec3 VaryNf (vec3 p, vec3 n, float f);
123
124vec4 vcId;
125vec3 ltPos[2], boatPos[2];
126float boatAng[2], dstFar, tCur, htWat, dstBMap;
127int idObj;
128bool uWat, hitWat;
129const int idBoat = 1, idBLamp = 2, idFLamp = 3;
130const float pi = 3.14159;
131
132float ObjDf (vec3 p)
133{
134  vec3 q;
135  float dMin, d;
136  dMin = dstFar;
137  for (int k = 0; k < 2; k ++) {
138    q = p - boatPos[k];
139    q.xz = Rot2D (q.xz, boatAng[k]);
140    d = max (PrCapsDf (q, 0.11, 0.25),
141       - PrCapsDf (q + vec3 (0., -0.02, 0.), 0.1, 0.24));
142    if (d < dMin) { dMin = d;  idObj = idBoat; }
143    q.y -= 0.1;
144    q.z -= 0.3;
145    d = PrSphDf (q, 0.01);
146    if (d < dMin) { dMin = d;  idObj = idFLamp; }
147    q.z -= -0.6;
148    d = PrSphDf (q, 0.01);
149    if (d < dMin) { dMin = d;  idObj = idBLamp; }
150  }
151  return dMin;
152}
153
154float ObjRay (vec3 ro, vec3 rd)
155{
156  float dHit, d;
157  dHit = 0.;
158  for (int j = 0; j < 100; j ++) {
159    d = ObjDf (ro + dHit * rd);
160    dHit += d;
161    if (d < 0.001 || dHit > dstFar) break;
162  }
163  return dHit;
164}
165
166vec3 ObjNf (vec3 p)
167{
168  vec4 v;
169  vec3 e = vec3 (0.001, -0.001, 0.);
170  v = vec4 (ObjDf (p + e.xxx), ObjDf (p + e.xyy),
171     ObjDf (p + e.yxy), ObjDf (p + e.yyx));
172  return normalize (vec3 (v.x - v.y - v.z - v.w) + 2. * v.yzw);
173}
174
175float VPoly (vec3 p)
176{
177  vec3 ip, fp, g, w, a;
178  ip = floor (p);
179  fp = fract (p);
180  a = vec3 (2.);
181  for (float gz = -1.; gz <= 1.; gz ++) {
182    for (float gy = -1.; gy <= 1.; gy ++) {
183      for (float gx = -1.; gx <= 1.; gx ++) {
184        g = vec3 (gx, gy, gz);
185        w = g + 0.7 * Hashfv3 (ip + g) - fp;
186        a.x = dot (w, w);
187        if (a.x < a.y) {
188          vcId = vec4 (ip + g, a.y - a.x);
189          a = a.zxy;
190        } else a.z = min (a.z, a.x);
191      }
192    }
193  }
194  return a.y;
195}
196
197vec3 TrackPath (float t)
198{
199  return vec3 (4.7 * sin (t * 0.15) + 2.7 * cos (t * 0.19), 0., t);
200}
201
202float CaveDf (vec3 p)
203{
204  vec3 hv;
205  float s, d;
206  s = p.y - htWat;
207  p.xy -= TrackPath (p.z).xy;
208  p += 0.1 * (1. - cos (2. * pi * (p + 0.2 * (1. - cos (2. * pi * p.zxy)))));
209  hv = cos (0.6 * p - 0.5 * sin (1.4 * p.zxy + 0.4 * cos (2.7 * p.yzx)));
210  if (USE_BMAP && dstBMap < 10.) hv *= 1. + 0.01 *
211     (1. - smoothstep (0., 10., dstBMap)) *
212     smoothstep (0.05, 0.4, VPoly (10. * p)) / length (hv);
213  d = 0.9 * (length (hv) - 1.1);
214  if (! uWat) d = min (d, s);
215  return d;
216}
217
218float CaveRay (vec3 ro, vec3 rd)
219{
220  float d, dHit;
221  dHit = 0.;
222  for (int j = 0; j < 200; j ++) {
223    dstBMap = dHit;
224    d = CaveDf (ro + dHit * rd);
225    dHit += d;
226    if (d < 0.001 || dHit > dstFar) break;
227  }
228  return dHit;
229}
230
231vec3 CaveNf (vec3 p)
232{
233  vec4 v;
234  const vec3 e = vec3 (0.001, -0.001, 0.);
235  v = vec4 (CaveDf (p + e.xxx), CaveDf (p + e.xyy),
236     CaveDf (p + e.yxy), CaveDf (p + e.yyx));
237  return normalize (vec3 (v.x - v.y - v.z - v.w) + 2. * v.yzw);
238}
239
240float CaveSShadow (vec3 ro, vec3 rd)
241{
242  float sh, d, h;
243  sh = 1.;
244  d = 0.1;
245  for (int j = 0; j < 16; j ++) {
246    h = CaveDf (ro + rd * d);
247    sh = min (sh, smoothstep (0., 0.05 * d, h));
248    d += max (0.2, 0.1 * d);
249    if (sh < 0.05) break;
250  }
251  return 0.4 + 0.6 * sh;
252}
253
254vec3 CaveCol (vec3 ro, vec3 rd, vec3 ltDir, float atten)
255{
256  vec3 col, vn, q, vno;
257  float glit;
258  VPoly (10. * ro);
259  q = ro;
260  if (! USE_BMAP) q = 0.004 * floor (250. * q);
261  vn = VaryNf (10. * q, CaveNf (q), 1.);
262  col = (vec3 (0.3, 0.1, 0.) + vec3 (0.3, 0.2, 0.1) * Hashv3f (Hashfv3 (vcId.xyz))) *
263     (1.2 - 0.4 * Hashfv3 (100. * ro)) *
264     (0.4 + 0.6 * smoothstep (0.05, 1., sqrt (vcId.w))) *
265     (0.2 + 0.8 * max (dot (vn, ltDir), 0.) +
266     2. * pow (max (dot (normalize (ltDir - rd), vn), 0.), 256.));
267  if (! hitWat) {
268    vno = CaveNf (ro);
269    glit = 20. * pow (max (0., dot (ltDir, reflect (rd, vno))), 4.) *
270       pow (1. - 0.6 * abs (dot (normalize (ltDir - rd),
271       VaryNf (100. * ro, vno, 5.))), 8.);
272    col += vec3 (1., 1., 0.5) * glit;
273  }
274  col *= atten * CaveSShadow (ro, ltDir);
275  return col;
276}
277
278vec3 ObjCol (vec3 ro, vec3 rd, vec3 vn, vec3 ltDir, float atten)
279{
280  vec4 col4;
281  if (idObj == idBoat) col4 = vec4 (0.3, 0.3, 0.6, 0.2);
282  else if (idObj == idFLamp) col4 = vec4 (0., 1., 0., -1.);
283  else if (idObj == idBLamp) col4 = vec4 (1., 0., 0., -1.);
284  if (col4.a >= 0.)
285    col4.rgb = col4.rgb * (0.2 + 0.8 * CaveSShadow (ro, ltDir)) *
286       (0.1 + 0.9 * atten * max (dot (ltDir, vn), 0.)) +
287       col4.a * atten * pow (max (dot (normalize (ltDir - rd), vn), 0.), 64.);
288  return col4.rgb;
289}
290
291vec3 ShowScene (vec3 ro, vec3 rd)
292{
293  vec3 col, colR, bgCol, ltVec, vn, roo, rdo, row, vnw;
294  float dstCave, dstObj, atten, frFac;
295  roo = ro;
296  rdo = rd;
297  bgCol = (abs (rd.y) < 0.5) ? vec3 (0., 0.05, 0.08) : vec3 (0.01);
298  uWat = false;
299  hitWat = false;
300  dstCave = CaveRay (ro, rd);
301  dstObj = ObjRay (ro, rd);
302  if (dstCave < min (dstObj, dstFar) && ro.y + rd.y * dstCave < htWat + 0.001) {
303    hitWat = true;
304    ro += rd * dstCave;
305    row = ro;
306    vnw = VaryNf (1.5 * ro, vec3 (0., 1., 0.), 0.1);
307    rd = reflect (rd, vnw);
308    ro += 0.01 * rd;
309    dstCave = CaveRay (ro, rd);
310    dstObj = ObjRay (ro, rd);
311  }
312  if (min (dstCave, dstObj) < dstFar) {
313    ltVec = roo + ltPos[0] - ro;
314    atten = 1. / (0.1 + dot (ltVec, ltVec));
315    if (hitWat) atten *= 3.;
316    ltVec = normalize (ltVec);
317    ro += min (dstCave, dstObj) * rd;
318    if (dstCave < dstObj) col = mix (CaveCol (ro, rd, ltVec, atten), bgCol,
319       smoothstep (0.45, 0.99, dstCave / dstFar));
320    else col = ObjCol (ro, rd, ObjNf (ro), ltVec, atten);
321  } else col = bgCol;
322  if (hitWat) {
323    frFac = rdo.y * rdo.y;
324    frFac *= frFac;
325    if (frFac > 0.005) {
326      rd = refract (rdo, vnw, 1./1.333);
327      ro = row + 0.01 * rd;
328      uWat = true;
329      dstCave = CaveRay (ro, rd);
330      if (min (dstCave, dstObj) < dstFar) {
331        ltVec = roo + ltPos[1] - ro;
332        atten = 1. / (0.1 + dot (ltVec, ltVec));
333        ltVec = normalize (ltVec);
334        ro += rd * dstCave;
335        hitWat = false;
336        colR = mix (CaveCol (ro, rd, ltVec, atten), bgCol,
337           smoothstep (0.45, 0.99, dstCave / dstFar));
338      } else colR = bgCol;
339      col = mix (col, colR * vec3 (0.4, 1., 0.6) * exp (0.02 * ro.y), frFac);
340    }
341  }
342  return pow (clamp (col, 0., 1.), vec3 (0.8));
343}
344
345void mainImage (out vec4 fragColor, in vec2 fragCoord)
346{
347  mat3 vuMat;
348#ifdef MOUSE
349  vec4 mPtr;
350#endif
351  vec3 ro, rd, fpF, fpB, vd;
352  vec2 canvas, uv, ori, ca, sa;
353  float el, az, t, tt, a;
354  canvas = iResolution.xy;
355  uv = 2. * fragCoord.xy / canvas - 1.;
356  uv.x *= canvas.x / canvas.y;
357  tCur = iGlobalTime;
358#ifdef MOUSE
359  mPtr = iMouse;
360  mPtr.xy = mPtr.xy / canvas - 0.5;
361#endif
362  t = 1. * tCur;
363  az = 0.;
364  el = 0.;
365#ifdef MOUSE
366  if (mPtr.z > 0.) {
367    az = az + 2. * pi * mPtr.x;
368    el = el + 0.95 * pi * mPtr.y;
369  } else {
370    tt = mod (floor (0.05 * tCur), 4.);
371    a = 0.45 * pi * SmoothBump (0.75, 0.95, 0.05, mod (0.05 * tCur, 1.));
372    if (tt < 2.) el = (2. * tt - 1.) * a;
373    else az = (2. * tt - 5.) * a;
374  }
375#else
376    tt = mod (floor (0.05 * tCur), 4.);
377    a = 0.45 * pi * SmoothBump (0.75, 0.95, 0.05, mod (0.05 * tCur, 1.));
378    if (tt < 2.) el = (2. * tt - 1.) * a;
379    else az = (2. * tt - 5.) * a;
380#endif
381  htWat = -0.5;
382  for (int k = 0; k < 2; k ++) {
383    fpF = TrackPath (t + 3. + 3. * float (k) + 0.1);
384    fpB = TrackPath (t + 3. + 3. * float (k) - 0.1);
385    boatPos[k] = 0.5 * (fpF + fpB);
386    boatPos[k].y = htWat + 0.01;
387    vd = fpF - fpB;
388    boatAng[k] = (length (vd.xz) > 0.) ? atan (vd.x, vd.z) : 0.5 * pi;
389  }
390  fpF = TrackPath (t + 0.1);
391  fpB = TrackPath (t - 0.1);
392  ro = 0.5 * (fpF + fpB);
393  vd = fpF - fpB;
394  ori = vec2 (el, az + ((length (vd.xz) > 0.) ? atan (vd.x, vd.z) : 0.5 * pi));
395  ca = cos (ori);
396  sa = sin (ori);
397  vuMat = mat3 (ca.y, 0., - sa.y, 0., 1., 0., sa.y, 0., ca.y) *
398          mat3 (1., 0., 0., 0., ca.x, - sa.x, 0., sa.x, ca.x);
399  rd = vuMat * normalize (vec3 (uv, 2.));
400  ltPos[0] = 0.5 * vuMat * vec3 (0., 1., -1.);
401  ltPos[1] = 0.5 * vuMat * vec3 (0., -1., -1.);
402  dstFar = 50.;
403  fragColor = vec4 (ShowScene (ro, rd) , 1.);
404}
405
406float PrSphDf (vec3 p, float r)
407{
408  return length (p) - r;
409}
410
411float PrCapsDf (vec3 p, float r, float h)
412{
413  return length (p - vec3 (0., 0., clamp (p.z, - h, h))) - r;
414}
415
416float SmoothBump (float lo, float hi, float w, float x)
417{
418  return (1. - smoothstep (hi - w, hi + w, x)) * smoothstep (lo - w, lo + w, x);
419}
420
421vec2 Rot2D (vec2 q, float a)
422{
423  return q * cos (a) + q.yx * sin (a) * vec2 (-1., 1.);
424}
425
426const vec4 cHashA4 = vec4 (0., 1., 57., 58.);
427const vec3 cHashA3 = vec3 (1., 57., 113.);
428const float cHashM = 43758.54;
429
430float Hashfv2 (vec2 p)
431{
432  return fract (sin (dot (p, cHashA3.xy)) * cHashM);
433}
434
435float Hashfv3 (vec3 p)
436{
437  return fract (sin (dot (p, cHashA3)) * cHashM);
438}
439
440vec3 Hashv3f (float p)
441{
442  return fract (sin (vec3 (p, p + 1., p + 2.)) *
443     vec3 (cHashM, cHashM * 0.43, cHashM * 0.37));
444}
445
446vec4 Hashv4f (float p)
447{
448  return fract (sin (p + cHashA4) * cHashM);
449}
450
451float Noisefv2 (vec2 p)
452{
453  vec4 t;
454  vec2 ip, fp;
455  ip = floor (p);
456  fp = fract (p);
457  fp = fp * fp * (3. - 2. * fp);
458  t = Hashv4f (dot (ip, cHashA3.xy));
459  return mix (mix (t.x, t.y, fp.x), mix (t.z, t.w, fp.x), fp.y);
460}
461
462float Fbmn (vec3 p, vec3 n)
463{
464  vec3 s;
465  float a;
466  s = vec3 (0.);
467  a = 1.;
468  for (int i = 0; i < 5; i ++) {
469    s += a * vec3 (Noisefv2 (p.yz), Noisefv2 (p.zx), Noisefv2 (p.xy));
470    a *= 0.5;
471    p *= 2.;
472  }
473  return dot (s, abs (n));
474}
475
476vec3 VaryNf (vec3 p, vec3 n, float f)
477{
478  vec3 g;
479  const vec3 e = vec3 (0.1, 0., 0.);
480  g = vec3 (Fbmn (p + e.xyy, n), Fbmn (p + e.yxy, n), Fbmn (p + e.yyx, n)) -
481     Fbmn (p, n);
482  return normalize (n + f * (g - n * dot (n, g)));
483}
484
485 void main(void)
486{
487  //just some shit to wrap shadertoy's stuff
488  vec2 FragCoord = vTexCoord.xy*OutputSize.xy;
489  mainImage(FragColor,FragCoord);
490}
491#endif
492