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