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/*-------------------------------------------------------------------------------------- 106License CC0 - http://creativecommons.org/publicdomain/zero/1.0/ 107To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. 108---------------------------------------------------------------------------------------- 109^ This means do ANYTHING YOU WANT with this code. Because we are programmers, not lawyers. 110-Otavio Good 111*/ 112 113// ---------------- Config ---------------- 114// This is an option that lets you render high quality frames for screenshots. It enables 115// stochastic antialiasing and motion blur automatically for any shader. 116//#define NON_REALTIME_HQ_RENDER 117const float frameToRenderHQ = 15.1; // Time in seconds of frame to render 118const float antialiasingSamples = 16.0; // 16x antialiasing - too much might make the shader compiler angry. 119 120//#define MANUAL_CAMERA 121// Some computers were crashing, so I scaled this down by default. 122//#define HQ_NOISE 123 124// -------------------------------------------------------- 125// These variables are for the non-realtime block renderer. 126float localTime = 0.0; 127float seed = 1.0; 128 129// Animation variables 130float fade = 1.0; 131float exposure = 1.0; 132 133// lighting vars 134vec3 sunDir = normalize(vec3(0.93, 1.0, 1.0)); 135const vec3 sunCol = vec3(250.0, 220.0, 200.0) / 3555.0; 136const vec3 horizonCol = vec3(0.95, 0.95, 0.95)*1.3; 137const vec3 skyCol = vec3(0.03,0.45,0.95); 138const vec3 groundCol = vec3(0.003,0.7,0.75); 139 140// ---- noise functions ---- 141float v31(vec3 a) 142{ 143 return a.x + a.y * 37.0 + a.z * 521.0; 144} 145float v21(vec2 a) 146{ 147 return a.x + a.y * 37.0; 148} 149float Hash11(float a) 150{ 151 return fract(sin(a)*10403.9); 152} 153float Hash21(vec2 uv) 154{ 155 float f = uv.x + uv.y * 37.0; 156 return fract(sin(f)*104003.9); 157} 158vec2 Hash22(vec2 uv) 159{ 160 float f = uv.x + uv.y * 37.0; 161 return fract(cos(f)*vec2(10003.579, 37049.7)); 162} 163vec2 Hash12(float f) 164{ 165 return fract(cos(f)*vec2(10003.579, 37049.7)); 166} 167// noise functions 168float Hash2d(vec2 uv) 169{ 170 float f = uv.x + uv.y * 37.0; 171 return fract(sin(f)*104003.9); 172} 173float Hash3d(vec3 uv) 174{ 175 float f = uv.x + uv.y * 37.0 + uv.z * 521.0; 176 return fract(sin(f)*110003.9); 177} 178float mixP(float f0, float f1, float a) 179{ 180 return mix(f0, f1, a*a*(3.0-2.0*a)); 181} 182const vec2 zeroOne = vec2(0.0, 1.0); 183float noise1d(float uv) 184{ 185 float fr = fract(uv); 186 float fl = floor(uv); 187 float h0 = Hash11(fl); 188 float h1 = Hash11(fl + 1.0); 189 return mixP(h0, h1, fr); 190} 191float noise2d(vec2 uv) 192{ 193 vec2 fr = fract(uv.xy); 194 vec2 fl = floor(uv.xy); 195 float h00 = Hash2d(fl); 196 float h10 = Hash2d(fl + zeroOne.yx); 197 float h01 = Hash2d(fl + zeroOne); 198 float h11 = Hash2d(fl + zeroOne.yy); 199 return mixP(mixP(h00, h10, fr.x), mixP(h01, h11, fr.x), fr.y); 200} 201float noiseValue(vec3 uv) 202{ 203 vec3 fr = fract(uv.xyz); 204 vec3 fl = floor(uv.xyz); 205 float h000 = Hash3d(fl); 206 float h100 = Hash3d(fl + zeroOne.yxx); 207 float h010 = Hash3d(fl + zeroOne.xyx); 208 float h110 = Hash3d(fl + zeroOne.yyx); 209 float h001 = Hash3d(fl + zeroOne.xxy); 210 float h101 = Hash3d(fl + zeroOne.yxy); 211 float h011 = Hash3d(fl + zeroOne.xyy); 212 float h111 = Hash3d(fl + zeroOne.yyy); 213 return mixP( 214 mixP(mixP(h000, h100, fr.x), 215 mixP(h010, h110, fr.x), fr.y), 216 mixP(mixP(h001, h101, fr.x), 217 mixP(h011, h111, fr.x), fr.y) 218 , fr.z); 219} 220 221 222const float PI=3.14159265; 223 224vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); } 225vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); } 226float saturate(float a) { return clamp(a, 0.0, 1.0); } 227 228vec3 RotateX(vec3 v, float rad) 229{ 230 float cos = cos(rad); 231 float sin = sin(rad); 232 return vec3(v.x, cos * v.y + sin * v.z, -sin * v.y + cos * v.z); 233} 234vec3 RotateY(vec3 v, float rad) 235{ 236 float cos = cos(rad); 237 float sin = sin(rad); 238 return vec3(cos * v.x - sin * v.z, v.y, sin * v.x + cos * v.z); 239} 240vec3 RotateZ(vec3 v, float rad) 241{ 242 float cos = cos(rad); 243 float sin = sin(rad); 244 return vec3(cos * v.x + sin * v.y, -sin * v.x + cos * v.y, v.z); 245} 246 247// This function basically is a procedural environment map that makes the sun 248vec3 GetSunColorSmall(vec3 rayDir, vec3 sunDir) 249{ 250 vec3 localRay = normalize(rayDir); 251 float dist = 1.0 - (dot(localRay, sunDir) * 0.5 + 0.5); 252 float sunIntensity = 0.05 / dist; 253 sunIntensity += exp(-dist*150.0)*7000.0; 254 sunIntensity = min(sunIntensity, 40000.0); 255 return sunCol * sunIntensity*0.2; 256} 257 258vec3 GetEnvMap(vec3 rayDir, vec3 sunDir) 259{ 260 // fade the sky color, multiply sunset dimming 261 vec3 finalColor = mix(horizonCol, skyCol, pow(saturate(rayDir.y), 0.47))*0.95; 262 // make clouds - just a horizontal plane with noise 263 float n = noise2d(rayDir.xz/rayDir.y*1.0); 264 n += noise2d(rayDir.xz/rayDir.y*2.0)*0.5; 265 n += noise2d(rayDir.xz/rayDir.y*4.0)*0.25; 266 n += noise2d(rayDir.xz/rayDir.y*8.0)*0.125; 267 n = pow(abs(n), 3.0); 268 n = mix(n * 0.2, n, saturate(abs(rayDir.y * 8.0))); // fade clouds in distance 269 finalColor = mix(finalColor, (vec3(1.0)+sunCol*10.0)*0.75*saturate((rayDir.y+0.2)*5.0), saturate(n*0.125)); 270 271 // add the sun 272 finalColor += GetSunColorSmall(rayDir, sunDir); 273 return finalColor; 274} 275 276// min function that supports materials in the y component 277vec2 matmin(vec2 a, vec2 b) 278{ 279 if (a.x < b.x) return a; 280 else return b; 281} 282 283// ---- shapes defined by distance fields ---- 284// See this site for a reference to more distance functions... 285// http://iquilezles.org/www/articles/distfunctions/distfunctions.htm 286 287// signed box distance field 288float sdBox(vec3 p, vec3 radius) 289{ 290 vec3 dist = abs(p) - radius; 291 return min(max(dist.x, max(dist.y, dist.z)), 0.0) + length(max(dist, 0.0)); 292} 293 294float cyl(vec3 p, float rad) 295{ 296 return length(p.xy) - rad; 297} 298 299float sSphere(vec3 p, float rad) 300{ 301 return length(p) - rad; 302} 303 304// k should be negative. -4.0 works nicely. 305// smooth blending function 306float smin(float a, float b, float k) 307{ 308 return log2(exp2(k*a)+exp2(k*b))/k; 309} 310 311const float sway = 0.015; 312 313// This is the distance function that defines all the scene's geometry. 314// The input is a position in space. 315// The output is the distance to the nearest surface, a material index, 316// and the difference between the iceberg distance and the water distance. 317vec3 DistanceToObject(vec3 p) 318{ 319 float dist = p.y; 320 321 if (abs(dist) < 0.07) // Only calculate noise if we are close. 322 { 323 // Sum up different frequencies of noise to make water waves. 324 float waterNoise = noise2d(p.xz*4.0+localTime)*0.1 + 325 noise2d(p.xz*8.0+localTime)*0.03 + 326 noise2d(p.xz*16.0-localTime)*0.015 + 327 noise2d(p.xz*32.0-localTime)*0.005 + 328 noise2d(p.xz*64.0-localTime)*0.002; 329 // Fade the waves a bit in the distance. 330 dist += waterNoise * 0.2 * saturate(8.0/length(p.xz)); 331 } 332 vec2 water = vec2(dist, 1.0); 333 334 p = RotateZ(p, sin(localTime)*sway); 335 // Sculpt the iceberg. 336 float slant = (p.y + p.x*0.25) / 1.0307; 337 slant -= cos(p.z*2.0)*0.0625; 338 dist = sSphere(p, 2.0) + sin(p.z*4.0)*0.125; 339 dist = smin(dist, sSphere(p + vec3(1.0, 11.85, 0.0), 12.0), -5.0); 340 float chop = cyl(p.xzy + vec3(1.5), 1.5); 341 float chop2 = cyl(p.xyz + vec3(0.0, -0.5, 0.0), 0.6) + sin(p.z*2.0)*0.125; 342 chop2 = min(chop2, -slant + 1.6); 343 chop2 = min(chop2, sdBox(p + vec3(-1.75, -0.74, -2.0), vec3(0.7))); 344 chop = smin(chop, chop2, -10.0); 345 chop = min(chop, chop2); 346 dist = -smin(-dist, chop, -30.0); 347 if (abs(dist) < 0.5) // Only calculate noise if we are close. 348 { 349 //dist += noise1d(slant*4.0+1.333)*0.1 + noise1d(slant*8.0+1.333)*0.05; 350 dist += noiseValue(vec3(slant)*4.0)*0.1 + noiseValue(vec3(slant)*8.0)*0.05; 351 float snowNoise=0.0; 352 snowNoise = noiseValue(p*4.0)*0.5*0.5; 353 snowNoise += noiseValue(p*8.0)*0.125*0.25; 354 // prevent crashing on mac/chrome/nvidia 355#ifdef HQ_NOISE 356 snowNoise += noiseValue(p*16.0)*0.125*0.0625; 357 snowNoise += noiseValue(p*32.0)*0.0625*0.0625; 358#endif 359 //snowNoise -= abs(fract(p.z*0.5-p.y*0.05)-0.5)*2.0; 360 //snowNoise -= 0.95; 361 dist += snowNoise*0.25; 362 } 363 vec2 iceberg = vec2(dist, 0.0); 364 vec2 distAndMat = matmin(water, iceberg); 365 return vec3(distAndMat, water.x - iceberg.x); 366} 367 368vec3 TraceOneRay(vec3 camPos, vec3 rayVec, out vec3 normal, out vec3 distAndMat, out float t) { 369 normal = vec3(0.0); 370 distAndMat = vec3(0.0, -1.0, 1000.0); // Distance and material 371 vec3 finalColor = vec3(0.0); 372 // ----------------------------- Ray march the scene ------------------------------ 373 t = 0.0; 374 const float maxDepth = 32.0; // farthest distance rays will travel 375 vec3 pos = vec3(0.0); 376 const float smallVal = 0.00625; 377 // ray marching time 378 for (int i = 210; i >= 0; i--) // This is the count of the max times the ray actually marches. 379 { 380 // Step along the ray. 381 pos = (camPos + rayVec * t); 382 // This is _the_ function that defines the "distance field". 383 // It's really what makes the scene geometry. The idea is that the 384 // distance field returns the distance to the closest object, and then 385 // we know we are safe to "march" along the ray by that much distance 386 // without hitting anything. We repeat this until we get really close 387 // and then break because we have effectively hit the object. 388 distAndMat = DistanceToObject(pos); 389 390 // move down the ray a safe amount 391 t += distAndMat.x; 392 if (i == 0) t = maxDepth+0.01; 393 // If we are very close to the object, let's call it a hit and exit this loop. 394 if ((t > maxDepth) || (abs(distAndMat.x) < smallVal)) break; 395 } 396 397 // -------------------------------------------------------------------------------- 398 // Now that we have done our ray marching, let's put some color on this geometry. 399 // If a ray actually hit the object, let's light it. 400 if (t <= maxDepth) 401 { 402 float dist = distAndMat.x; 403 // calculate the normal from the distance field. The distance field is a volume, so if you 404 // sample the current point and neighboring points, you can use the difference to get 405 // the normal. 406 vec3 smallVec = vec3(smallVal, 0, 0); 407 vec3 normalU = vec3(dist - DistanceToObject(pos - smallVec.xyy).x, 408 dist - DistanceToObject(pos - smallVec.yxy).x, 409 dist - DistanceToObject(pos - smallVec.yyx).x); 410 normal = normalize(normalU); 411 412 // Giant hack for border between water and snow to look nice. 413 if (abs(distAndMat.z) < smallVal*0.25) normal = vec3(0.0, 0.2, 0.0); 414 415 // calculate 2 ambient occlusion values. One for global stuff and one 416 // for local stuff 417 float ambientS = 1.0; 418 vec3 distAndMatA = DistanceToObject(pos + normal * 0.4); 419 ambientS *= saturate(distAndMatA.x*2.5); 420 distAndMatA = DistanceToObject(pos + normal * 0.8); 421 ambientS *= saturate(distAndMatA.x*1.25); 422 float ambient = ambientS; 423 ambient *= saturate(DistanceToObject(pos + normal * 1.6).x*1.25*0.5); 424 ambient *= saturate(DistanceToObject(pos + normal * 3.2).x*1.25*0.25); 425 //ambient = max(0.05, pow(ambient, 0.5)); // tone down ambient with a pow and min clamp it. 426 ambient = max(0.15, ambient); 427 ambient = saturate(ambient); 428 429 // Trace a ray toward the sun for sun shadows 430 float sunShadow = 1.0; 431 float iter = 0.2; 432 for (int i = 0; i < 10; i++) 433 { 434 float tempDist = DistanceToObject(pos + sunDir * iter).x; 435 sunShadow *= saturate(tempDist*10.0); 436 if (tempDist <= 0.0) break; 437 //iter *= 1.5; // constant is more reliable than distance-based 438 iter += max(0.1, tempDist)*1.2; 439 } 440 sunShadow = saturate(sunShadow); 441 442 // Trace a ray through the solid for sub-surface scattering 443 float scattering = 1.0; 444 iter = 0.05; 445 for (int i = 0; i < 8; i++) 446 { 447 float tempDist = -DistanceToObject(pos - normal * iter).x; 448 scattering *= saturate(tempDist*10.0); 449 if (tempDist <= 0.0) break; 450 //iter *= 1.5; // constant is more reliable than distance-based 451 iter += max(0.001, tempDist);//*0.6; 452 } 453 scattering = saturate(scattering); 454 //scattering = (1.0-sunShadow)*(1.0-length(sunDir * iter)); 455 scattering = saturate(1.0-iter); 456 457 // calculate the reflection vector for highlights 458 vec3 ref = reflect(rayVec, normal); 459 460 // ------ Calculate texture color ------ 461 vec3 texColor = vec3(0.0); 462 // Underwater green glow 463 float fade = 1.0-saturate(abs(distAndMat.z)*3.5); 464 vec3 greenFade = mix(vec3(0.1, 0.995, 0.65)*0.95, vec3(0.75, 1.0, 1.0), fade*fade); 465 texColor += greenFade * fade; 466 texColor *= 0.75; 467 // iceberg 468 if (distAndMat.y == 0.0) { 469 texColor = vec3(1.0); 470 } 471 texColor = saturate(texColor); 472 473 // ------ Calculate lighting color ------ 474 // Start with sun color, standard lighting equation, and shadow 475 vec3 lightColor = vec3(14.0)*sunCol * saturate(dot(sunDir, normal)) * (sunShadow*0.7+0.3); 476 // weighted average the near ambient occlusion with the far for just the right look 477 478 // apply the light to the texture. 479 finalColor = texColor * lightColor; 480 vec3 underwaterGlow = vec3(0.002, 0.6, 0.51); 481 // water 482 if (distAndMat.y == 1.0) { 483 finalColor += underwaterGlow*0.25 * length(normalU)*80.0; 484 finalColor += vec3(0.02, 0.5, 0.71)*0.35 * saturate(1.0-ambient); 485 finalColor += skyCol*0.02 * ambientS; 486 } 487 // iceberg 488 if (distAndMat.y == 0.0) { 489 float fade = saturate(1.0-pos.y); 490 // Add sky color 491 finalColor += (skyCol*0.6 + horizonCol*0.4)*1.5 * saturate(normal.y *0.5+0.5); 492 vec3 rotPos = RotateZ(pos, sin(localTime)*sway); 493 float noiseScatter = noiseValue(rotPos*32.0)*0.25 + 494 noiseValue(rotPos*16.0)*0.5 + 495 noiseValue(rotPos*8.0)*1.0; 496 finalColor += groundCol * 0.5 * max(-normal.y*0.5+0.5, 0.0) * (noiseScatter*0.3+0.6); 497 finalColor += underwaterGlow * 0.35 * saturate(0.5-saturate(abs(pos.y*3.0))); 498 finalColor += vec3(0.01, 0.55, 0.7) * saturate(scattering-sunShadow*0.3)*0.25; 499 finalColor = mix((underwaterGlow + vec3(0.5, 0.9, 0.8))*0.5, finalColor, saturate(distAndMat.z*64.0)*0.75+0.25); 500 finalColor *= 0.7; 501 } 502 503 // visualize length of gradient of distance field to check distance field correctness 504 //finalColor = vec3(0.5) * (length(normalU) / smallVec.x); 505 } 506 else 507 { 508 // Our ray trace hit nothing, so draw background. 509 finalColor = GetEnvMap(rayVec, sunDir); 510 distAndMat.y = -1.0; 511 } 512 return finalColor; 513} 514 515// Input is UV coordinate of pixel to render. 516// Output is RGB color. 517vec3 RayTrace(in vec2 fragCoord ) 518{ 519 fade = 1.0; 520 521 vec3 camPos, camUp, camLookat; 522 // ------------------- Set up the camera rays for ray marching -------------------- 523 // Map uv to [-1.0..1.0] 524 vec2 uv = fragCoord.xy/iResolution.xy * 2.0 - 1.0; 525 uv /= 2.0; // zoom in 526 527#ifdef MANUAL_CAMERA 528 // Camera up vector. 529 camUp=vec3(0,1,0); 530 531 // Camera lookat. 532 camLookat=vec3(0,0,0); 533 534 // debugging camera 535 float mx=-iMouse.x/iResolution.x*PI*2.0; 536 float my=iMouse.y/iResolution.y*3.14*0.95 + PI/2.0; 537 camPos = vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*5.0; 538#else 539 // Do the camera fly-by animation and different scenes. 540 // Time variables for start and end of each scene 541 const float t0 = 0.0; 542 const float t1 = 12.0; 543 const float t2 = 20.0; 544 const float t3 = 38.0; 545 // Repeat the animation after time t3 546 localTime = fract(localTime / t3) * t3; 547 if (localTime < t1) 548 { 549 float time = localTime - t0; 550 float alpha = time / (t1 - t0); 551 fade = saturate(time); 552 fade *= saturate(t1 - localTime); 553 camPos = vec3(0.0, 0.4, -8.0); 554 camPos.x -= smoothstep(0.0, 1.0, alpha) * 2.0; 555 camPos.y += smoothstep(0.0, 1.0, alpha) * 2.0; 556 camPos.z += smoothstep(0.0, 1.0, alpha) * 4.0; 557 camUp=vec3(0,1,0); 558 camLookat=vec3(0,-0.5,0.5); 559 camLookat.y -= smoothstep(0.0, 1.0, alpha) * 0.5; 560 } else if (localTime < t2) 561 { 562 float time = localTime - t1; 563 float alpha = time / (t2 - t1); 564 fade = saturate(time); 565 fade *= saturate(t2 - localTime); 566 camPos = vec3(2.0, 4.3, -0.5); 567 camPos.y -= alpha * 3.5; 568 camPos.x = sin(alpha*1.0) * 9.2; 569 camPos.z = cos(alpha*1.0) * 6.2; 570 camUp=normalize(vec3(0,1,-0.005 + alpha * 0.005)); 571 camLookat=vec3(0,-1.5,0.0); 572 camLookat.y += smoothstep(0.0, 1.0, alpha) * 1.5; 573 } else if (localTime < t3) 574 { 575 float time = localTime - t2; 576 float alpha = time / (t3 - t2); 577 fade = saturate(time); 578 fade *= saturate(t3 - localTime); 579 camPos = vec3(-9.0, 1.3, -10.0); 580 //camPos.y -= alpha * 8.0; 581 camPos.x += alpha * 14.0; 582 camPos.z += alpha * 7.0; 583 camUp=normalize(vec3(0,1,0.0)); 584 camLookat=vec3(0.0,0.0,0.0); 585 } 586#endif 587 588 // Camera setup for ray tracing / marching 589 vec3 camVec=normalize(camLookat - camPos); 590 vec3 sideNorm=normalize(cross(camUp, camVec)); 591 vec3 upNorm=cross(camVec, sideNorm); 592 vec3 worldFacing=(camPos + camVec); 593 vec3 worldPix = worldFacing + uv.x * sideNorm * (iResolution.x/iResolution.y) + uv.y * upNorm; 594 vec3 rayVec = normalize(worldPix - camPos); 595 596 vec3 finalColor = vec3(0.0); 597 598 vec3 normal; 599 vec3 distAndMat; 600 float t; 601 finalColor = TraceOneRay(camPos, rayVec, normal, distAndMat, t); 602 float origDelta = distAndMat.z; 603 if (distAndMat.y == 1.0) { 604 vec3 ref = normalize(reflect(rayVec, normal)); 605 ref.y = abs(ref.y); 606 vec3 newStartPos = (camPos + rayVec * t) + normal * 0.02; // nudge away. 607 float fresnel = saturate(1.0 - dot(-rayVec, normal)); 608 fresnel = fresnel * fresnel * fresnel * fresnel * fresnel * fresnel; 609 fresnel = mix(0.05, 0.9, fresnel); 610 vec3 refColor = TraceOneRay(newStartPos, ref, normal, distAndMat, t); 611 finalColor += refColor * fresnel; 612 } 613 614 // vignette? 615 finalColor *= vec3(1.0) * saturate(1.0 - length(uv/2.5)); 616 finalColor *= exposure; 617 618 // output the final color without gamma correction - will do gamma later. 619 return vec3(clamp(finalColor, 0.0, 1.0));//*saturate(fade)); 620} 621 622#ifdef NON_REALTIME_HQ_RENDER 623// This function breaks the image down into blocks and scans 624// through them, rendering 1 block at a time. It's for non- 625// realtime things that take a long time to render. 626 627// This is the frame rate to render at. Too fast and you will 628// miss some blocks. 629const float blockRate = 20.0; 630void BlockRender(in vec2 fragCoord) 631{ 632 // blockSize is how much it will try to render in 1 frame. 633 // adjust this smaller for more complex scenes, bigger for 634 // faster render times. 635 const float blockSize = 64.0; 636 // Make the block repeatedly scan across the image based on time. 637 float frame = floor(iGlobalTime * blockRate); 638 vec2 blockRes = floor(iResolution.xy / blockSize) + vec2(1.0); 639 // ugly bug with mod. 640 //float blockX = mod(frame, blockRes.x); 641 float blockX = fract(frame / blockRes.x) * blockRes.x; 642 //float blockY = mod(floor(frame / blockRes.x), blockRes.y); 643 float blockY = fract(floor(frame / blockRes.x) / blockRes.y) * blockRes.y; 644 // Don't draw anything outside the current block. 645 if ((fragCoord.x - blockX * blockSize >= blockSize) || 646 (fragCoord.x - (blockX - 1.0) * blockSize < blockSize) || 647 (fragCoord.y - blockY * blockSize >= blockSize) || 648 (fragCoord.y - (blockY - 1.0) * blockSize < blockSize)) 649 { 650 discard; 651 } 652} 653#endif 654 655void mainImage( out vec4 fragColor, in vec2 fragCoord ) 656{ 657#ifdef NON_REALTIME_HQ_RENDER 658 // Optionally render a non-realtime scene with high quality 659 BlockRender(fragCoord); 660#endif 661 662 // Do a multi-pass render 663 vec3 finalColor = vec3(0.0); 664#ifdef NON_REALTIME_HQ_RENDER 665 for (float i = 0.0; i < antialiasingSamples; i++) 666 { 667 const float motionBlurLengthInSeconds = 1.0 / 60.0; 668 // Set this to the time in seconds of the frame to render. 669 localTime = frameToRenderHQ; 670 // This line will motion-blur the renders 671 localTime += Hash11(v21(fragCoord + seed)) * motionBlurLengthInSeconds; 672 // Jitter the pixel position so we get antialiasing when we do multiple passes. 673 vec2 jittered = fragCoord.xy + vec2( 674 Hash21(fragCoord + seed), 675 Hash21(fragCoord*7.234567 + seed) 676 ); 677 // don't antialias if only 1 sample. 678 if (antialiasingSamples == 1.0) jittered = fragCoord; 679 // Accumulate one pass of raytracing into our pixel value 680 finalColor += RayTrace(jittered); 681 // Change the random seed for each pass. 682 seed *= 1.01234567; 683 } 684 // Average all accumulated pixel intensities 685 finalColor /= antialiasingSamples; 686#else 687 // Regular real-time rendering 688 localTime = iGlobalTime; 689 finalColor = RayTrace(fragCoord); 690#endif 691 692 fragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0); 693} 694 695void main(void) 696{ 697 //just some shit to wrap shadertoy's stuff 698 vec2 FragCoord = vTexCoord.xy*OutputSize.xy; 699 mainImage(FragColor,FragCoord); 700} 701#endif 702