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