1#version 130
2
3// Meta CRT - @P_Malin
4// https://www.shadertoy.com/view/4dlyWX#
5
6#pragma parameter posx "TV Angle X" -0.25 -1.0 1.0 0.05
7#pragma parameter posy "TV Angle Y" 0.2 -1.0 1.0 0.05
8#pragma parameter targetx "Cam Pos X" 0.0 -1.0 1.0 0.05
9#pragma parameter targety "Cam Pos Y" 0.10 -1.0 1.0 0.05
10#pragma parameter zoom "Cam Zoom" -0.6 -10.0 10.0 0.1
11#pragma parameter showSphere "Show Sphere" 0.0 0.0 1.0 1.0
12#pragma parameter sphereX "Sphere X Pos" 0.2 -10.0 10.0 0.05
13#pragma parameter sphereY "Sphere Y Pos" 0.075 -10.0 10.0 0.05
14#pragma parameter sphereZ "Sphere Z Pos" -0.1 -10.0 10.0 0.01
15#pragma parameter sphereMaterial "Sphere Material" 4.0 -1.0 4.0 1.0
16#pragma parameter cam_index "Cam Pos Preset" 2.0 0.0 9.0 1.0
17#pragma parameter snow "Snow Toggle" 0.0 0.0 1.0 1.0
18
19#if defined(VERTEX)
20
21#if __VERSION__ >= 130
22#define COMPAT_VARYING out
23#define COMPAT_ATTRIBUTE in
24#define COMPAT_TEXTURE texture
25#else
26#define COMPAT_VARYING varying
27#define COMPAT_ATTRIBUTE attribute
28#define COMPAT_TEXTURE texture2D
29#endif
30
31#ifdef GL_ES
32#define COMPAT_PRECISION mediump
33#else
34#define COMPAT_PRECISION
35#endif
36
37COMPAT_ATTRIBUTE vec4 VertexCoord;
38COMPAT_ATTRIBUTE vec4 COLOR;
39COMPAT_ATTRIBUTE vec4 TexCoord;
40COMPAT_VARYING vec4 COL0;
41COMPAT_VARYING vec4 TEX0;
42
43vec4 _oPosition1;
44uniform mat4 MVPMatrix;
45uniform COMPAT_PRECISION int FrameDirection;
46uniform COMPAT_PRECISION int FrameCount;
47uniform COMPAT_PRECISION vec2 OutputSize;
48uniform COMPAT_PRECISION vec2 TextureSize;
49uniform COMPAT_PRECISION vec2 InputSize;
50
51// compatibility #defines
52#define vTexCoord TEX0.xy
53#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
54#define OutSize vec4(OutputSize, 1.0 / OutputSize)
55
56void main()
57{
58    gl_Position = MVPMatrix * VertexCoord;
59    TEX0.xy = TexCoord.xy;
60}
61
62#elif defined(FRAGMENT)
63
64#ifdef GL_ES
65#ifdef GL_FRAGMENT_PRECISION_HIGH
66precision highp float;
67#else
68precision mediump float;
69precision mediump int;
70#endif
71#define COMPAT_PRECISION mediump
72#else
73#define COMPAT_PRECISION
74#endif
75
76#if __VERSION__ >= 130
77#define COMPAT_VARYING in
78#define COMPAT_TEXTURE texture
79out COMPAT_PRECISION vec4 FragColor;
80#else
81#define COMPAT_VARYING varying
82#define FragColor gl_FragColor
83#define COMPAT_TEXTURE texture2D
84#endif
85
86uniform COMPAT_PRECISION int FrameDirection;
87uniform COMPAT_PRECISION int FrameCount;
88uniform COMPAT_PRECISION vec2 OutputSize;
89uniform COMPAT_PRECISION vec2 TextureSize;
90uniform COMPAT_PRECISION vec2 InputSize;
91uniform sampler2D Texture;
92uniform sampler2D cubeMap;
93uniform sampler2D table;
94COMPAT_VARYING vec4 TEX0;
95
96// compatibility #defines
97#define Source Texture
98#define vTexCoord TEX0.xy
99
100#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
101#define OutSize vec4(OutputSize, 1.0 / OutputSize)
102
103#ifdef PARAMETER_UNIFORM
104uniform COMPAT_PRECISION float posx;
105uniform COMPAT_PRECISION float posy;
106uniform COMPAT_PRECISION float targetx;
107uniform COMPAT_PRECISION float targety;
108uniform COMPAT_PRECISION float zoom;
109uniform COMPAT_PRECISION float showSphere;
110uniform COMPAT_PRECISION float sphereX;
111uniform COMPAT_PRECISION float sphereY;
112uniform COMPAT_PRECISION float sphereZ;
113uniform COMPAT_PRECISION float sphereMaterial;
114uniform COMPAT_PRECISION float cam_index;
115uniform COMPAT_PRECISION float snow;
116#else
117#define posx -0.4
118#define posy 0.2
119#define targetx 0.15
120#define targety 0.28
121#define zoom -1.3
122#define showSphere 0.0
123#define sphereX 0.2
124#define sphereY 0.075
125#define sphereZ -0.1
126#define sphereMaterial 4.0
127#define cam_index 2.0
128#define snow 0.0
129#endif
130
131// Scene Rendering
132
133#define ENABLE_TAA_JITTER
134
135#define kMaxTraceDist 1000.0
136#define kFarDist 1100.0
137
138#define MAT_FG_BEGIN 	10
139
140#define PI 3.141592654
141
142///////////////////////////
143// Hash Functions
144///////////////////////////
145
146// From: Hash without Sine by Dave Hoskins
147// https://www.shadertoy.com/view/4djSRW
148
149// *** Use this for integer stepped ranges, ie Value-Noise/Perlin noise functions.
150//#define HASHSCALE1 .1031
151//#define HASHSCALE3 vec3(.1031, .1030, .0973)
152//#define HASHSCALE4 vec4(1031, .1030, .0973, .1099)
153
154// For smaller input rangers like audio tick or 0-1 UVs use these...
155#define HASHSCALE1 443.8975
156#define HASHSCALE3 vec3(443.897, 441.423, 437.195)
157#define HASHSCALE4 vec3(443.897, 441.423, 437.195, 444.129)
158
159
160//----------------------------------------------------------------------------------------
161//  1 out, 1 in...
162float hash11(float p)
163{
164	vec3 p3  = fract(vec3(p) * HASHSCALE1);
165    p3 += dot(p3, p3.yzx + 19.19);
166    return fract((p3.x + p3.y) * p3.z);
167}
168
169//  2 out, 1 in...
170vec2 hash21(float p)
171{
172	vec3 p3 = fract(vec3(p) * HASHSCALE3);
173	p3 += dot(p3, p3.yzx + 19.19);
174    return fract((p3.xx+p3.yz)*p3.zy);
175
176}
177
178///  2 out, 3 in...
179vec2 hash23(vec3 p3)
180{
181	p3 = fract(p3 * HASHSCALE3);
182    p3 += dot(p3, p3.yzx+19.19);
183    return fract((p3.xx+p3.yz)*p3.zy);
184}
185
186//  1 out, 3 in...
187float hash13(vec3 p3)
188{
189	p3  = fract(p3 * HASHSCALE1);
190    p3 += dot(p3, p3.yzx + 19.19);
191    return fract((p3.x + p3.y) * p3.z);
192}
193
194
195///////////////////////////
196// Data Storage
197///////////////////////////
198
199vec4 LoadVec4( sampler2D sampler, in ivec2 vAddr )
200{
201    return texelFetch( sampler, vAddr, 0 );
202}
203
204vec3 LoadVec3( sampler2D sampler, in ivec2 vAddr )
205{
206    return LoadVec4( sampler, vAddr ).xyz;
207}
208
209bool AtAddress( ivec2 p, ivec2 c ) { return all( equal( p, c ) ); }
210
211void StoreVec4( in ivec2 vAddr, in vec4 vValue, inout vec4 fragColor, in ivec2 fragCoord )
212{
213    fragColor = AtAddress( fragCoord, vAddr ) ? vValue : fragColor;
214}
215
216void StoreVec3( in ivec2 vAddr, in vec3 vValue, inout vec4 fragColor, in ivec2 fragCoord )
217{
218    StoreVec4( vAddr, vec4( vValue, 0.0 ), fragColor, fragCoord);
219}
220
221///////////////////////////
222// Camera
223///////////////////////////
224
225struct CameraState
226{
227    vec3 vPos;
228    vec3 vTarget;
229    float fFov;
230    vec2 vJitter;
231    float fPlaneInFocus;
232};
233
234void Cam_LoadState( out CameraState cam, sampler2D sampler, ivec2 addr )
235{
236    vec4 vPos = LoadVec4( sampler, addr + ivec2(0,0) );
237    cam.vPos = vPos.xyz;
238    vec4 targetFov = LoadVec4( sampler, addr + ivec2(1,0) );
239    cam.vTarget = targetFov.xyz;
240    cam.fFov = targetFov.w;
241    vec4 jitterDof = LoadVec4( sampler, addr + ivec2(2,0) );
242    cam.vJitter = jitterDof.xy;
243    cam.fPlaneInFocus = jitterDof.z;
244}
245
246void Cam_StoreState( ivec2 addr, const in CameraState cam, inout vec4 fragColor, in ivec2 fragCoord )
247{
248    StoreVec4( addr + ivec2(0,0), vec4( cam.vPos, 0 ), fragColor, fragCoord );
249    StoreVec4( addr + ivec2(1,0), vec4( cam.vTarget, cam.fFov ), fragColor, fragCoord );
250    StoreVec4( addr + ivec2(2,0), vec4( cam.vJitter, cam.fPlaneInFocus, 0 ), fragColor, fragCoord );
251}
252
253mat3 Cam_GetWorldToCameraRotMatrix( const CameraState cameraState )
254{
255    vec3 vForward = normalize( cameraState.vTarget - cameraState.vPos );
256	vec3 vRight = normalize( cross(vec3(0, 1, 0), vForward) );
257	vec3 vUp = normalize( cross(vForward, vRight) );
258
259    return mat3( vRight, vUp, vForward );
260}
261
262vec2 Cam_GetViewCoordFromUV( const in vec2 vUV )
263{
264	vec2 vWindow = vUV * 2.0 - 1.0;
265	vWindow.x *= SourceSize.x / SourceSize.y;
266
267	return vWindow;
268}
269
270void Cam_GetCameraRay( const vec2 vUV, const CameraState cam, out vec3 vRayOrigin, out vec3 vRayDir )
271{
272    vec2 vView = Cam_GetViewCoordFromUV( vUV );
273    vRayOrigin = cam.vPos;
274    float fPerspDist = 1.0 / tan( radians( cam.fFov ) );
275    vRayDir = normalize( Cam_GetWorldToCameraRotMatrix( cam ) * vec3( vView, fPerspDist ) );
276}
277
278vec2 Cam_GetUVFromWindowCoord( const in vec2 vWindow )
279{
280    vec2 vScaledWindow = vWindow;
281    vScaledWindow.x *= SourceSize.y / SourceSize.x;
282
283    return (vScaledWindow * 0.5 + 0.5);
284}
285
286vec2 Cam_WorldToWindowCoord(const in vec3 vWorldPos, const in CameraState cameraState )
287{
288    vec3 vOffset = vWorldPos - cameraState.vPos;
289    vec3 vCameraLocal;
290
291    vCameraLocal = vOffset * Cam_GetWorldToCameraRotMatrix( cameraState );
292
293    vec2 vWindowPos = vCameraLocal.xy / (vCameraLocal.z * tan( radians( cameraState.fFov ) ));
294
295    return vWindowPos;
296}
297
298float EncodeDepthAndObject( float depth, int objectId )
299{
300    //depth = max( 0.0, depth );
301    //objectId = max( 0, objectId + 1 );
302    //return exp2(-depth) + float(objectId);
303    return depth;
304}
305
306float DecodeDepthAndObjectId( float value, out int objectId )
307{
308    objectId = 0;
309    return max(0.0, value);
310    //objectId = int( floor( value ) ) - 1;
311    //return abs( -log2(fract(value)) );
312}
313
314///////////////////////////////
315
316///////////////////////////
317// Scene
318///////////////////////////
319
320struct SceneResult
321{
322	float fDist;
323	int iObjectId;
324    vec3 vUVW;
325};
326
327void Scene_Union( inout SceneResult a, in SceneResult b )
328{
329    if ( b.fDist < a.fDist )
330    {
331        a = b;
332    }
333}
334
335
336void Scene_Subtract( inout SceneResult a, in SceneResult b )
337{
338    if ( a.fDist < -b.fDist )
339    {
340        a.fDist = -b.fDist;
341        a.iObjectId = b.iObjectId;
342        a.vUVW = b.vUVW;
343    }
344}
345
346SceneResult Scene_GetDistance( vec3 vPos );
347
348vec3 Scene_GetNormal(const in vec3 vPos)
349{
350    const float fDelta = 0.0001;
351    vec2 e = vec2( -1, 1 );
352
353    vec3 vNormal =
354        Scene_GetDistance( e.yxx * fDelta + vPos ).fDist * e.yxx +
355        Scene_GetDistance( e.xxy * fDelta + vPos ).fDist * e.xxy +
356        Scene_GetDistance( e.xyx * fDelta + vPos ).fDist * e.xyx +
357        Scene_GetDistance( e.yyy * fDelta + vPos ).fDist * e.yyy;
358
359    return normalize( vNormal );
360}
361
362SceneResult Scene_Trace( const in vec3 vRayOrigin, const in vec3 vRayDir, float minDist, float maxDist )
363{
364    SceneResult result;
365    result.fDist = 0.0;
366    result.vUVW = vec3(0.0);
367    result.iObjectId = -1;
368
369	float t = minDist;
370	const int kRaymarchMaxIter = 128;
371	for(int i=0; i<kRaymarchMaxIter; i++)
372	{
373        float epsilon = 0.0001 * t;
374		result = Scene_GetDistance( vRayOrigin + vRayDir * t );
375        if ( result.fDist < epsilon )
376		{
377			break;
378		}
379
380        if ( t > maxDist )
381        {
382            result.iObjectId = -1;
383	        t = maxDist;
384            break;
385        }
386
387        if ( result.fDist > 1.0 )
388        {
389            result.iObjectId = -1;
390        }
391
392        t += result.fDist;
393	}
394
395    result.fDist = t;
396
397
398    return result;
399}
400
401float Scene_TraceShadow( const in vec3 vRayOrigin, const in vec3 vRayDir, const in float fMinDist, const in float fLightDist )
402{
403    //return 1.0;
404    //return ( Scene_Trace( vRayOrigin, vRayDir, 0.1, fLightDist ).fDist < fLightDist ? 0.0 : 1.0;
405
406	float res = 1.0;
407    float t = fMinDist;
408    for( int i=0; i<5; i++ )
409    {
410		float h = Scene_GetDistance( vRayOrigin + vRayDir * t ).fDist;
411        res = min( res, 8.0*h/t );
412        t += clamp( h, 0.02, 0.10 );
413        if( h<0.0001 || t>fLightDist ) break;
414    }
415    return clamp( res, 0.0, 1.0 );
416}
417
418float Scene_GetAmbientOcclusion( const in vec3 vPos, const in vec3 vDir )
419{
420    float fOcclusion = 0.0;
421    float fScale = 1.0;
422    for( int i=0; i<5; i++ )
423    {
424        float fOffsetDist = 0.001 + 0.1*float(i)/4.0;
425        vec3 vAOPos = vDir * fOffsetDist + vPos;
426        float fDist = Scene_GetDistance( vAOPos ).fDist;
427        fOcclusion += (fOffsetDist - fDist) * fScale;
428        fScale *= 0.4;
429    }
430
431    return clamp( 1.0 - 30.0*fOcclusion, 0.0, 1.0 );
432}
433
434///////////////////////////
435// Lighting
436///////////////////////////
437
438struct SurfaceInfo
439{
440    vec3 vPos;
441    vec3 vNormal;
442    vec3 vBumpNormal;
443    vec3 vAlbedo;
444    vec3 vR0;
445    float fSmoothness;
446    vec3 vEmissive;
447};
448
449SurfaceInfo Scene_GetSurfaceInfo( const in vec3 vRayOrigin,  const in vec3 vRayDir, SceneResult traceResult );
450
451struct SurfaceLighting
452{
453    vec3 vDiffuse;
454    vec3 vSpecular;
455};
456
457SurfaceLighting Scene_GetSurfaceLighting( const in vec3 vRayDir, in SurfaceInfo surfaceInfo );
458
459float Light_GIV( float dotNV, float k)
460{
461	return 1.0 / ((dotNV + 0.0001) * (1.0 - k)+k);
462}
463
464void Light_Add(inout SurfaceLighting lighting, SurfaceInfo surface, const in vec3 vViewDir, const in vec3 vLightDir, const in vec3 vLightColour)
465{
466	float fNDotL = clamp(dot(vLightDir, surface.vBumpNormal), 0.0, 1.0);
467
468	lighting.vDiffuse += vLightColour * fNDotL;
469
470	vec3 vH = normalize( -vViewDir + vLightDir );
471	float fNdotV = clamp(dot(-vViewDir, surface.vBumpNormal), 0.0, 1.0);
472	float fNdotH = clamp(dot(surface.vBumpNormal, vH), 0.0, 1.0);
473
474	float alpha = 1.0 - surface.fSmoothness;
475	// D
476
477	float alphaSqr = alpha * alpha;
478	float denom = fNdotH * fNdotH * (alphaSqr - 1.0) + 1.0;
479	float d = alphaSqr / (PI * denom * denom);
480
481	float k = alpha / 2.0;
482	float vis = Light_GIV(fNDotL, k) * Light_GIV(fNdotV, k);
483
484	float fSpecularIntensity = d * vis * fNDotL;
485	lighting.vSpecular += vLightColour * fSpecularIntensity;
486}
487
488void Light_AddPoint(inout SurfaceLighting lighting, SurfaceInfo surface, const in vec3 vViewDir, const in vec3 vLightPos, const in vec3 vLightColour)
489{
490    vec3 vPos = surface.vPos;
491	vec3 vToLight = vLightPos - vPos;
492
493	vec3 vLightDir = normalize(vToLight);
494	float fDistance2 = dot(vToLight, vToLight);
495	float fAttenuation = 10.0 / (fDistance2);
496
497	float fShadowFactor = Scene_TraceShadow( surface.vPos, vLightDir, 0.1, length(vToLight) );
498
499	Light_Add( lighting, surface, vViewDir, vLightDir, vLightColour * fShadowFactor * fAttenuation);
500}
501
502void Light_AddDirectional(inout SurfaceLighting lighting, SurfaceInfo surface, const in vec3 vViewDir, const in vec3 vLightDir, const in vec3 vLightColour)
503{
504	float fAttenuation = 0.1;
505	float fShadowFactor = Scene_TraceShadow( surface.vPos, vLightDir, 0.1, 10.0 );
506
507	Light_Add( lighting, surface, vViewDir, vLightDir, vLightColour * fShadowFactor * fAttenuation);
508}
509
510vec3 Light_GetFresnel( vec3 vView, vec3 vNormal, vec3 vR0, float fGloss )
511{
512    float NdotV = max( 0.0, dot( vView, vNormal ) );
513
514    return vR0 + (vec3(0.5) - vR0) * pow( 1.0 - NdotV, 1.5 ) * pow( fGloss, 20.0 );
515}
516
517void Env_AddPointLightFlare(inout vec3 vEmissiveGlow, const in vec3 vRayOrigin, const in vec3 vRayDir, const in float fIntersectDistance, const in vec3 vLightPos, const in vec3 vLightColour)
518{
519    vec3 vToLight = vLightPos - vRayOrigin;
520    float fPointDot = dot(vToLight, vRayDir);
521    fPointDot = clamp(fPointDot, 0.0, fIntersectDistance);
522
523    vec3 vClosestPoint = vRayOrigin + vRayDir * fPointDot;
524    float fDist = length(vClosestPoint - vLightPos);
525	vEmissiveGlow += sqrt(vLightColour * 0.05 / (fDist * fDist));
526}
527
528void Env_AddDirectionalLightFlareToFog(inout vec3 vFogColour, const in vec3 vRayDir, const in vec3 vLightDir, const in vec3 vLightColour)
529{
530	float fDirDot = clamp(dot(vLightDir, vRayDir) * 0.5 + 0.5, 0.0, 1.0);
531	float kSpreadPower = 2.0;
532	vFogColour += vLightColour * pow(fDirDot, kSpreadPower) * 0.25;
533}
534
535
536///////////////////////////
537// Rendering
538///////////////////////////
539
540vec4 Env_GetSkyColor( const vec3 vViewPos, const vec3 vViewDir );
541vec3 Env_ApplyAtmosphere( const in vec3 vColor, const in vec3 vRayOrigin,  const in vec3 vRayDir, const in float fDist );
542vec3 FX_Apply( in vec3 vColor, const in vec3 vRayOrigin,  const in vec3 vRayDir, const in float fDist);
543
544vec4 Scene_GetColorAndDepth( vec3 vRayOrigin, vec3 vRayDir )
545{
546	vec3 vResultColor = vec3(0.0);
547
548	SceneResult firstTraceResult;
549
550    float fStartDist = 0.0;
551    float fMaxDist = 10.0;
552
553    vec3 vRemaining = vec3(0.5);
554
555	for( int iPassIndex=0; iPassIndex < 1; iPassIndex++ )
556    {
557    	SceneResult traceResult = Scene_Trace( vRayOrigin, vRayDir, fStartDist, fMaxDist );
558
559        if ( iPassIndex == 0 )
560        {
561            firstTraceResult = traceResult;
562        }
563
564        vec3 vColor = vec3(0);
565        vec3 vReflectAmount = vec3(0);
566
567		if( traceResult.iObjectId < 0 )
568		{
569            vColor = Env_GetSkyColor( vRayOrigin, vRayDir ).rgb;
570        }
571        else
572        {
573
574            SurfaceInfo surfaceInfo = Scene_GetSurfaceInfo( vRayOrigin, vRayDir, traceResult );
575            SurfaceLighting surfaceLighting = Scene_GetSurfaceLighting( vRayDir, surfaceInfo );
576
577            // calculate reflectance (Fresnel)
578			vReflectAmount = Light_GetFresnel( -vRayDir, surfaceInfo.vBumpNormal, surfaceInfo.vR0, surfaceInfo.fSmoothness );
579
580			vColor = (surfaceInfo.vAlbedo * surfaceLighting.vDiffuse + surfaceInfo.vEmissive) * (vec3(1.0) - vReflectAmount);
581
582            vec3 vReflectRayOrigin = surfaceInfo.vPos;
583            vec3 vReflectRayDir = normalize( reflect( vRayDir, surfaceInfo.vBumpNormal ) );
584            fStartDist = 0.001 / max(0.0000001,abs(dot( vReflectRayDir, surfaceInfo.vNormal )));
585
586            vColor += surfaceLighting.vSpecular * vReflectAmount;
587
588			vColor = Env_ApplyAtmosphere( vColor, vRayOrigin, vRayDir, traceResult.fDist );
589			vColor = FX_Apply( vColor, vRayOrigin, vRayDir, traceResult.fDist );
590
591            vRayOrigin = vReflectRayOrigin;
592            vRayDir = vReflectRayDir;
593        }
594
595        vResultColor += vColor * vRemaining;
596        vRemaining *= vReflectAmount;
597    }
598
599    return vec4( vResultColor, EncodeDepthAndObject( firstTraceResult.fDist, firstTraceResult.iObjectId ) );
600}
601
602/////////////////////////////////////////////////////////////////////////////////////////////////////////
603
604/////////////////////////
605// Scene Description
606/////////////////////////
607
608// Materials
609
610#define MAT_SKY		 	-1
611#define MAT_DEFAULT 	 0
612#define MAT_SCREEN		 1
613#define MAT_TV_CASING    2
614#define MAT_TV_TRIM      3
615#define MAT_CHROME       4
616
617
618vec3 PulseIntegral( vec3 x, float s1, float s2 )
619{
620    // Integral of function where result is 1.0 between s1 and s2 and 0 otherwise
621
622    // V1
623    //if ( x > s2 ) return s2 - s1;
624	//else if ( x > s1 ) return x - s1;
625	//return 0.0f;
626
627    // V2
628    //return clamp( (x - s1), 0.0f, s2 - s1);
629    //return t;
630
631    return clamp( (x - s1), vec3(0.0), vec3(s2 - s1));
632}
633
634float PulseIntegral( float x, float s1, float s2 )
635{
636    // Integral of function where result is 1.0 between s1 and s2 and 0 otherwise
637
638    // V1
639    //if ( x > s2 ) return s2 - s1;
640	//else if ( x > s1 ) return x - s1;
641	//return 0.0f;
642
643    // V2
644    //return clamp( (x - s1), 0.0, s2 - s1);
645    //return t;
646
647    return clamp( (x - s1), (0.0), (s2 - s1));
648}
649
650vec3 Bayer( vec2 vUV, vec2 vBlur )
651{
652    vec3 x = vec3(vUV.x);
653    vec3 y = vec3(vUV.y);
654
655    x += vec3(0.66, 0.33, 0.0);
656    y += 0.5 * step( fract( x * 0.5 ), vec3(0.5) );
657
658    //x -= 0.5f;
659    //y -= 0.5f;
660
661    x = fract( x );
662    y = fract( y );
663
664    // cell centered at 0.5
665
666    vec2 vSize = vec2(0.16, 0.75);
667
668    vec2 vMin = 0.5 - vSize * 0.5;
669    vec2 vMax = 0.5 + vSize * 0.5;
670
671    vec3 vResult= vec3(0.0);
672
673    vec3 vResultX = (PulseIntegral( x + vBlur.x, vMin.x, vMax.x) - PulseIntegral( x - vBlur.x, vMin.x, vMax.x)) / min( vBlur.x, 1.0);
674    vec3 vResultY = (PulseIntegral(y + vBlur.y, vMin.y, vMax.y) - PulseIntegral(y - vBlur.y, vMin.y, vMax.y))  / min( vBlur.y, 1.0);
675
676    vResult = min(vResultX,vResultY)  * 5.0;
677
678    //vResult = vec3(1.0);
679
680    return vResult;
681}
682
683vec3 GetPixelMatrix( vec2 vUV )
684{
685#if 1
686    vec2 dx = dFdx( vUV );
687    vec2 dy = dFdy( vUV );
688    float dU = length( vec2( dx.x, dy.x ) );
689    float dV = length( vec2( dx.y, dy.y ) );
690    if (dU <= 0.0 || dV <= 0.0 ) return vec3(1.0);
691    return Bayer( vUV, vec2(dU, dV) * 1.0);
692#else
693    return vec3(1.0);
694#endif
695}
696
697float Scanline( float y, float fBlur )
698{
699    float fResult = sin( y * 10.0 ) * 0.45 + 0.55;
700    return mix( fResult, 1.0, min( 1.0, fBlur ) );
701}
702
703
704float GetScanline( vec2 vUV )
705{
706#if 1
707    vUV.y *= 0.25;
708    vec2 dx = dFdx( vUV );
709    vec2 dy = dFdy( vUV );
710    float dV = length( vec2( dx.y, dy.y ) );
711    if (dV <= 0.0 ) return 1.0;
712    return Scanline( vUV.y, dV * 1.3 );
713#else
714    return 0.5;
715#endif
716}
717
718
719vec2 kScreenRsolution = vec2(480.0, 576.0);
720
721struct Interference
722{
723    float noise;
724    float scanLineRandom;
725};
726
727float InterferenceHash(float p)
728{
729    float hashScale = 0.1031;
730
731    vec3 p3  = fract(vec3(p, p, p) * hashScale);
732    p3 += dot(p3, p3.yzx + 19.19);
733    return fract((p3.x + p3.y) * p3.z);
734}
735
736
737float InterferenceSmoothNoise1D( float x )
738{
739    float f0 = floor(x);
740    float fr = fract(x);
741
742    float h0 = InterferenceHash( f0 );
743    float h1 = InterferenceHash( f0 + 1.0 );
744
745    return h1 * fr + h0 * (1.0 - fr);
746}
747
748
749float InterferenceNoise( vec2 uv )
750{
751	float displayVerticalLines = 483.0;
752    float scanLine = floor(uv.y * displayVerticalLines);
753    float scanPos = scanLine + uv.x;
754	float timeSeed = fract( float(FrameCount) * 123.78 );
755
756    return InterferenceSmoothNoise1D( scanPos * 234.5 + timeSeed * 12345.6 );
757}
758
759Interference GetInterference( vec2 vUV )
760{
761    Interference interference;
762
763    interference.noise = InterferenceNoise( vUV );
764    interference.scanLineRandom = InterferenceHash(vUV.y * 100.0 + fract(float(FrameCount) * 1234.0) * 12345.0);
765
766    return interference;
767}
768
769vec3 SampleScreen( vec3 vUVW )
770{
771    vec3 vAmbientEmissive = vec3(0.1);
772    vec3 vBlackEmissive = vec3(0.02);
773    float fBrightness = 1.75;
774    vec2 vResolution = SourceSize.xy;
775    vec2 vPixelCoord = vUVW.xy * vResolution;
776
777    vec3 vPixelMatrix = GetPixelMatrix( vPixelCoord );
778    float fScanline = GetScanline( vPixelCoord );
779
780    vec2 vTextureUV = vUVW.xy;
781    //vec2 vTextureUV = vPixelCoord;
782//    vTextureUV = floor(vTextureUV * vResolution * 2.0) / (vResolution * 2.0);
783
784    Interference interference = GetInterference( vTextureUV );
785
786    float noiseIntensity = 0.1;
787
788    //vTextureUV.x += (interference.scanLineRandom * 2.0 - 1.0) * 0.025 * noiseIntensity;
789
790
791    vec3 vPixelEmissive = textureLod( Source, (vTextureUV.xy * vec2(1.0, -1.0) + vec2(0.0, 1.)) * vec2(InputSize.xy / TextureSize.xy), 1.0 ).rgb;
792
793    if (snow > 0.5) vPixelEmissive = clamp( vPixelEmissive + (interference.noise - 0.5) * 2.0 * noiseIntensity, 0.0, 1.0 );
794
795	vec3 vResult = (vPixelEmissive * vPixelEmissive * fBrightness + vBlackEmissive) * vPixelMatrix * fScanline + vAmbientEmissive;
796
797    // TODO: feather edge?
798    if( any( greaterThanEqual( vUVW.xy, vec2(1.0) ) ) || any ( lessThan( vUVW.xy, vec2(0.0) ) ) || ( vUVW.z > 0.0 ) )
799    {
800        return vec3(0.0);
801    }
802
803    return vResult;
804
805}
806
807SurfaceInfo Scene_GetSurfaceInfo( const in vec3 vRayOrigin,  const in vec3 vRayDir, SceneResult traceResult )
808{
809    SurfaceInfo surfaceInfo;
810
811    surfaceInfo.vPos = vRayOrigin + vRayDir * (traceResult.fDist);
812
813    surfaceInfo.vNormal = Scene_GetNormal( surfaceInfo.vPos );
814    surfaceInfo.vBumpNormal = surfaceInfo.vNormal;
815    surfaceInfo.vAlbedo = textureLod( cubeMap, traceResult.vUVW.xz * -1.0, 0.0 ).rgb;
816    surfaceInfo.vR0 = vec3( 0.02 );
817    surfaceInfo.fSmoothness = 1.0;
818    surfaceInfo.vEmissive = vec3( 0.2 );
819    //return surfaceInfo;
820
821    if ( traceResult.iObjectId == MAT_DEFAULT )
822    {
823    	surfaceInfo.vR0 = vec3( 0.02 );
824	    surfaceInfo.vAlbedo = textureLod( table, traceResult.vUVW.xz * 2.0, 0.0 ).rgb;
825        surfaceInfo.vAlbedo = surfaceInfo.vAlbedo * surfaceInfo.vAlbedo;
826
827    	surfaceInfo.fSmoothness = clamp( 1.0 - surfaceInfo.vAlbedo.r * surfaceInfo.vAlbedo.r * 2.0, 0.0, 1.0);
828
829    }
830
831    if ( traceResult.iObjectId == MAT_SCREEN )
832    {
833        surfaceInfo.vAlbedo = vec3(0.02);
834        surfaceInfo.vEmissive = SampleScreen( traceResult.vUVW );
835    }
836
837    if ( traceResult.iObjectId == MAT_TV_CASING )
838    {
839        surfaceInfo.vAlbedo = vec3(0.5, 0.4, 0.3);
840	    surfaceInfo.fSmoothness = 0.4;
841    }
842
843    if ( traceResult.iObjectId == MAT_TV_TRIM )
844    {
845        surfaceInfo.vAlbedo = vec3(0.03, 0.03, 0.05);
846	    surfaceInfo.fSmoothness = 0.5;
847    }
848
849    if ( traceResult.iObjectId == MAT_CHROME )
850    {
851        surfaceInfo.vAlbedo = vec3(0.1, 0.1, 0.1);
852	    surfaceInfo.fSmoothness = 0.9;
853    	surfaceInfo.vR0 = vec3( 0.8 );
854    }
855
856    return surfaceInfo;
857}
858
859// Scene Description
860
861float SmoothMin( float a, float b, float k )
862{
863	//return min(a,b);
864
865
866    //float k = 0.06;
867	float h = clamp( 0.5 + 0.5*(b-a)/k, 0.0, 1.0 );
868	return mix( b, a, h ) - k*h*(1.0-h);
869}
870
871float UdRoundBox( vec3 p, vec3 b, float r )
872{
873    //vec3 vToFace = abs(p) - b;
874    //vec3 vConstrained = max( vToFace, 0.0 );
875    //return length( vConstrained ) - r;
876    return length(max(abs(p)-b,0.0))-r;
877}
878
879SceneResult Scene_GetCRT( vec3 vScreenDomain, vec2 vScreenWH, float fScreenCurveRadius, float fBevel, float fDepth )
880{
881    SceneResult resultScreen;
882#if 1
883    vec3 vScreenClosest;
884    vScreenClosest.xy = max(abs(vScreenDomain.xy)-vScreenWH,0.0);
885    vec2 vCurveScreenDomain = vScreenDomain.xy;
886    vCurveScreenDomain = clamp( vCurveScreenDomain, -vScreenWH, vScreenWH );
887    float fCurveScreenProjection2 = fScreenCurveRadius * fScreenCurveRadius - vCurveScreenDomain.x * vCurveScreenDomain.x - vCurveScreenDomain.y * vCurveScreenDomain.y;
888    float fCurveScreenProjection = sqrt( fCurveScreenProjection2 ) - fScreenCurveRadius;
889    vScreenClosest.z = vScreenDomain.z - clamp( vScreenDomain.z, -fCurveScreenProjection, fDepth );
890    resultScreen.vUVW.z = vScreenDomain.z + fCurveScreenProjection;
891    resultScreen.fDist = (length( vScreenClosest ) - fBevel) * 0.95;
892    //resultScreen.fDist = (length( vScreenDomain - vec3(0,0,fScreenCurveRadius)) - fScreenCurveRadius - fBevel);
893#endif
894
895#if 0
896    vec3 vScreenClosest;
897    vScreenClosest.xyz = max(abs(vScreenDomain.xyz)-vec3(vScreenWH, fDepth),0.0);
898    float fRoundDist = length( vScreenClosest.xyz ) - fBevel;
899    float fSphereDist = length( vScreenDomain - vec3(0,0,fScreenCurveRadius) ) - (fScreenCurveRadius + fBevel);
900    resultScreen.fDist = max(fRoundDist, fSphereDist);
901#endif
902
903    resultScreen.vUVW.xy = (vScreenDomain.xy / vScreenWH) * 0.5 + 0.5;
904	resultScreen.iObjectId = MAT_SCREEN;
905    return resultScreen;
906}
907
908SceneResult Scene_GetComputer( vec3 vPos )
909{
910    SceneResult resultComputer;
911    resultComputer.vUVW = vPos.xzy;
912
913    float fXSectionStart = -0.2;
914    float fXSectionLength = 0.15;
915    float fXSectionT = clamp( (vPos.z - fXSectionStart) / fXSectionLength, 0.0, 1.0);
916    float fXSectionR1 = 0.03;
917    float fXSectionR2 = 0.05;
918    float fXSectionR = mix( fXSectionR1, fXSectionR2, fXSectionT );
919    float fXSectionZ = fXSectionStart + fXSectionT * fXSectionLength;
920
921    vec2 vXSectionCentre = vec2(fXSectionR, fXSectionZ );
922    vec2 vToPos = vPos.yz - vXSectionCentre;
923    float l = length( vToPos );
924    if ( l > fXSectionR ) l = fXSectionR;
925    vec2 vXSectionClosest = vXSectionCentre + normalize(vToPos) * l;
926    //float fXSectionDist = length( vXSectionClosest ) - fXSectionR;
927
928    float x = max( abs( vPos.x ) - 0.2, 0.0 );
929
930    resultComputer.fDist = length( vec3(x, vXSectionClosest - vPos.yz) )-0.01;
931    //resultComputer.fDist = x;
932
933    resultComputer.iObjectId = MAT_TV_CASING;
934/*
935    vec3 vKeyPos = vPos.xyz - vec3(0,0.125,0);
936    vKeyPos.y -= vKeyPos.z * (fXSectionR2 - fXSectionR1) * 2.0 / fXSectionLength;
937    float fDomainRepeatScale = 0.02;
938    if ( fract(vKeyPos.z * 0.5 / fDomainRepeatScale + 0.25) > 0.5) vKeyPos.x += fDomainRepeatScale * 0.5;
939    vec2 vKeyIndex = round(vKeyPos.xz / fDomainRepeatScale);
940    vKeyIndex.x = clamp( vKeyIndex.x, -8.0, 8.0 );
941    vKeyIndex.y = clamp( vKeyIndex.y, -10.0, -5.0 );
942    //vKeyPos.xz = (fract( vKeyPos.xz / fDomainRepeatScale ) - 0.5) * fDomainRepeatScale;
943    vKeyPos.xz = (vKeyPos.xz - (vKeyIndex) * fDomainRepeatScale);
944    vKeyPos.xz /= 0.7 + vKeyPos.y;
945    SceneResult resultKey;
946    resultKey.vUVW = vPos.xzy;
947    resultKey.fDist = UdRoundBox( vKeyPos, vec3(0.01), 0.001 );
948    resultKey.iObjectId = MAT_TV_TRIM;
949    Scene_Union( resultComputer, resultKey );
950*/
951    return resultComputer;
952}
953
954SceneResult Scene_GetDistance( vec3 vPos )
955{
956    SceneResult result;
957
958	//result.fDist = vPos.y;
959    float fBenchBevel = 0.01;
960    result.fDist = UdRoundBox( vPos - vec3(0,-0.02-fBenchBevel,0.0), vec3(2.0, 0.02, 1.0), fBenchBevel );
961    result.vUVW = vPos;
962	result.iObjectId = MAT_DEFAULT;
963
964    vec3 vSetPos = vec3(0.0, 0.0, 0.0);
965    vec3 vScreenPos = vSetPos + vec3(0.0, 0.25, 0.00);
966
967//    vPos.x = fract( vPos.x ) - 0.5;
968
969    vec2 vScreenWH = vec2(4.0, 3.0) / 25.0;
970
971    SceneResult resultSet;
972    resultSet.vUVW = vPos.xzy;
973	resultSet.fDist = UdRoundBox( vPos - vScreenPos - vec3(0.0,-0.01,0.2), vec3(.21, 0.175, 0.18), 0.01 );
974    resultSet.iObjectId = MAT_TV_CASING;
975    Scene_Union( result, resultSet );
976
977    SceneResult resultSetRecess;
978    resultSetRecess.vUVW = vPos.xzy;
979    resultSetRecess.fDist = UdRoundBox( vPos - vScreenPos - vec3(0.0,-0.0, -0.05), vec3(vScreenWH + 0.01, 0.05) + 0.005, 0.015 );
980    resultSetRecess.iObjectId = MAT_TV_TRIM;
981	Scene_Subtract( result, resultSetRecess );
982
983    SceneResult resultSetBase;
984    resultSetBase.vUVW = vPos.xzy;
985    float fBaseBevel = 0.03;
986	resultSetBase.fDist = UdRoundBox( vPos - vSetPos - vec3(0.0,0.04,0.22), vec3(0.2, 0.04, 0.17) - fBaseBevel, fBaseBevel );
987    resultSetBase.iObjectId = MAT_TV_CASING;
988    Scene_Union( result, resultSetBase );
989
990	SceneResult resultScreen = Scene_GetCRT( vPos - vScreenPos, vScreenWH, 0.75, 0.02, 0.1 );
991    Scene_Union( result, resultScreen );
992
993    //SceneResult resultComputer = Scene_GetComputer( vPos - vec3(0.0, 0.0, -0.1) );
994    //Scene_Union( result, resultComputer );
995
996//    SceneResult resultSphere;
997if (showSphere > 0.5){
998    resultSet.vUVW = vPos.xzy;
999    resultSet.fDist = length(vPos - vec3(sphereX,sphereY,sphereZ)) - 0.075;
1000    resultSet.iObjectId = int(sphereMaterial);//MAT_CHROME;
1001    Scene_Union( result, resultSet );
1002}
1003
1004    return result;
1005}
1006
1007// Scene Lighting
1008
1009vec3 g_vSunDir = normalize(vec3(0.3, 0.4, -0.5));
1010vec3 g_vSunColor = vec3(1, 0.95, 0.8) * 3.0;
1011vec3 g_vAmbientColor = vec3(0.8, 0.8, 0.8) * 1.0;
1012
1013SurfaceLighting Scene_GetSurfaceLighting( const in vec3 vViewDir, in SurfaceInfo surfaceInfo )
1014{
1015    SurfaceLighting surfaceLighting;
1016
1017    surfaceLighting.vDiffuse = vec3(0.0);
1018    surfaceLighting.vSpecular = vec3(0.0);
1019
1020    Light_AddDirectional( surfaceLighting, surfaceInfo, vViewDir, g_vSunDir, g_vSunColor );
1021
1022    Light_AddPoint( surfaceLighting, surfaceInfo, vViewDir, vec3(1.4, 2.0, 0.8), vec3(1,1,1) * 0.2 );
1023
1024    float fAO = Scene_GetAmbientOcclusion( surfaceInfo.vPos, surfaceInfo.vNormal );
1025    // AO
1026    surfaceLighting.vDiffuse += fAO * (surfaceInfo.vBumpNormal.y * 0.5 + 0.5) * g_vAmbientColor;
1027
1028    return surfaceLighting;
1029}
1030
1031// Environment
1032
1033vec4 Env_GetSkyColor( const vec3 vViewPos, const vec3 vViewDir )
1034{
1035	vec4 vResult = vec4( 0.0, 0.0, 0.0, kFarDist );
1036
1037#if 1
1038    vec3 vEnvMap = textureLod( cubeMap, vViewDir.zy, 1.0 ).rgb;
1039    vEnvMap = vEnvMap * vEnvMap;
1040    float kEnvmapExposure = 0.999;
1041    vResult.rgb = -log2(1.0 - vEnvMap * kEnvmapExposure);
1042
1043#endif
1044
1045    // Sun
1046    float NdotV = dot( g_vSunDir, vViewDir );
1047    vResult.rgb += smoothstep( cos(radians(.7)), cos(radians(.5)), NdotV ) * g_vSunColor * 5000.0;
1048
1049    return vResult;
1050}
1051
1052float Env_GetFogFactor(const in vec3 vRayOrigin,  const in vec3 vRayDir, const in float fDist )
1053{
1054	float kFogDensity = 0.00001;
1055	return exp(fDist * -kFogDensity);
1056}
1057
1058vec3 Env_GetFogColor(const in vec3 vDir)
1059{
1060	return vec3(0.2, 0.5, 0.6) * 2.0;
1061}
1062
1063vec3 Env_ApplyAtmosphere( const in vec3 vColor, const in vec3 vRayOrigin,  const in vec3 vRayDir, const in float fDist )
1064{
1065    //return vColor;
1066    vec3 vResult = vColor;
1067
1068
1069	float fFogFactor = Env_GetFogFactor( vRayOrigin, vRayDir, fDist );
1070	vec3 vFogColor = Env_GetFogColor( vRayDir );
1071	//Env_AddDirectionalLightFlareToFog( vFogColor, vRayDir, g_vSunDir, g_vSunColor * 3.0);
1072    vResult = mix( vFogColor, vResult, fFogFactor );
1073
1074    return vResult;
1075}
1076
1077
1078vec3 FX_Apply( in vec3 vColor, const in vec3 vRayOrigin,  const in vec3 vRayDir, const in float fDist)
1079{
1080    return vColor;
1081}
1082
1083
1084vec4 MainCommon( vec3 vRayOrigin, vec3 vRayDir )
1085{
1086	vec4 vColorLinAndDepth = Scene_GetColorAndDepth( vRayOrigin, vRayDir );
1087    vColorLinAndDepth.rgb = max( vColorLinAndDepth.rgb, vec3(0.0) );
1088
1089    vec4 FragColor = vColorLinAndDepth;
1090
1091    float fExposure = 2.0;
1092
1093    FragColor.rgb *= fExposure;
1094
1095    FragColor.a = vColorLinAndDepth.w;
1096
1097    return FragColor;
1098}
1099
1100CameraState GetCameraPosition( int whatever )
1101{
1102    CameraState cam;
1103
1104	int index = int(cam_index);
1105
1106    vec3 vFocus = vec3(0,0.25,-0.012);
1107
1108//    if ( index > 9 )
1109//    {
1110//    	index = int(hash11(float(index) / 10.234) * 100.0);
1111//    	index = index % 10;
1112//    }
1113
1114    if ( index == 0 )
1115    {
1116        cam.vPos = vec3(-0.1,0.2,-0.08);
1117        cam.vTarget = vec3(0,0.25,0.1);
1118        cam.fFov = 10.0;
1119    }
1120    if ( index == 1 )
1121    {
1122        cam.vPos = vec3(0.01,0.334,-0.03);
1123        cam.vTarget = vec3(0,0.3,0.1);
1124        cam.fFov = 10.0;
1125    }
1126    if ( index == 2 )
1127    {
1128        cam.vPos = vec3(posx,posy,zoom);
1129        cam.vTarget = vec3(targetx,targety,0.5);
1130        cam.fFov = 4.5;
1131    }
1132    if ( index == 3 )
1133    {
1134        cam.vPos = vec3(-0.8,1.0,-1.5);
1135        cam.vTarget = vec3(0.2,0.0,0.5);
1136        cam.fFov = 10.0;
1137    }
1138    if ( index == 4 )
1139    {
1140        cam.vPos = vec3(-0.8,0.3,-1.0);
1141        cam.vTarget = vec3(0.4,0.18,0.5);
1142        cam.fFov = 20.0;
1143    }
1144    if ( index == 5 )
1145    {
1146        cam.vPos = vec3(-0.244,0.334,-0.0928);
1147        cam.vTarget = vec3(0,0.25,0.1);
1148        cam.fFov = 20.0;
1149    }
1150    if ( index == 6 )
1151    {
1152        cam.vPos = vec3(0.0,0.1,-0.5);
1153        cam.vTarget = vec3(0.2,0.075,-0.1);
1154        vFocus = cam.vTarget;
1155        cam.fFov = 15.0;
1156    }
1157    if ( index == 7 )
1158    {
1159        cam.vPos = vec3(-0.01,0.01,-0.25);
1160        cam.vTarget = vec3(0.01,0.27,0.1);
1161        vFocus = cam.vTarget;
1162        cam.fFov = 23.0;
1163    }
1164    if ( index == 8 )
1165    {
1166        cam.vPos = vec3(-0.23,0.3,-0.05);
1167        cam.vTarget = vec3(0.1,0.2,0.1);
1168        cam.fFov = 15.0;
1169    }
1170    if ( index == 9 )
1171    {
1172        cam.vPos = vec3(0.4,0.2,-0.2);
1173        cam.vTarget = vec3(-0.1,0.25,0.1);
1174        cam.fFov = 12.0;
1175    }
1176
1177    cam.fPlaneInFocus = length( vFocus - cam.vPos);
1178    cam.vJitter = vec2(0.0);
1179
1180    return cam;
1181}
1182
1183void main()
1184{
1185    vec2 vUV = (gl_FragCoord.xy / SourceSize.xy) * (TextureSize.xy / InputSize.xy);
1186
1187    CameraState cam;
1188
1189    {
1190    	CameraState camA;
1191    	CameraState camB;
1192
1193        float fSeqTime = mod(float(FrameCount) / 50.0, 300.0);
1194        float fSequenceSegLength = 5.0;
1195        float fSeqIndex = 1.0;//floor(fSeqTime / fSequenceSegLength);
1196        float fSeqPos = 1.0;//fract(fSeqTime / fSequenceSegLength);
1197        int iIndex = int(fSeqIndex);
1198		int iIndexNext = int(fSeqIndex) + 1;
1199        camA = GetCameraPosition(iIndex);
1200        camB = GetCameraPosition(iIndexNext);
1201
1202        float t = smoothstep(0.3, 1.0, fSeqPos);
1203        cam.vPos = mix(camA.vPos, camB.vPos, t );
1204        cam.vTarget = mix(camA.vTarget, camB.vTarget, t );
1205        cam.fFov = mix(camA.fFov, camB.fFov, t );
1206        cam.fPlaneInFocus = mix(camA.fPlaneInFocus, camB.fPlaneInFocus, t );
1207    }
1208/*
1209    if ( iMouse.z > 0.0 )
1210    {
1211        float fDist = 0.01 + 3.0 * (iMouse.y / SourceSize.y);
1212
1213        float fAngle = (iMouse.x / SourceSize.x) * radians(360.0);
1214    	//float fElevation = (iMouse.y / SourceSize.y) * radians(90.0);
1215    	float fElevation = 0.15 * radians(90.0);
1216
1217        cam.vPos = vec3(sin(fAngle) * fDist * cos(fElevation),sin(fElevation) * fDist,cos(fAngle) * fDist * cos(fElevation));
1218        cam.vTarget = vec3(0,0.25,0.1);
1219        cam.vPos +=cam.vTarget;
1220        cam.fFov = 20.0 / (1.0 + fDist * 0.5);
1221    	vec3 vFocus = vec3(0,0.25,-0.012);
1222	    cam.fPlaneInFocus = length( vFocus - cam.vPos );
1223    }
1224*/
1225#ifdef ENABLE_TAA_JITTER
1226    cam.vJitter = hash21( fract( float(FrameCount) ) ) - 0.5;
1227#endif
1228
1229
1230    vec3 vRayOrigin, vRayDir;
1231    vec2 vJitterUV = vUV + cam.vJitter;// / SourceSize.xy;
1232    Cam_GetCameraRay( vJitterUV, cam, vRayOrigin, vRayDir );
1233
1234    float fHitDist = 0.0;
1235    FragColor = MainCommon( vRayOrigin, vRayDir );
1236
1237
1238	Cam_StoreState( ivec2(0), cam, FragColor, ivec2(gl_FragCoord.xy) );
1239}
1240#endif
1241