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// Doom 2. Reinder Nijhoff 2013
106// @reindernijhoff
107//
108// https://www.shadertoy.com/view/lsB3zD
109//
110
111#define COL(r,g,b) vec3(r/255.,g/255.,b/255.)
112
113#define time iGlobalTime
114
115//----------------------------------------------------------------------
116// Math functions
117
118float hash( const float n ) {
119    return fract(sin(n*14.1234512)*51231.545341231);
120}
121float hash( const vec2 x ) {
122	float n = dot( x, vec2(14.1432,1131.15532) );
123    return fract(sin(n)*51231.545341231);
124}
125float crossp( const vec2 a, const vec2 b ) { return a.x*b.y - a.y*b.x; }
126vec3 rotate(vec3 r, float v){ return vec3(r.x*cos(v)+r.z*sin(v),r.y,r.z*cos(v)-r.x*sin(v));}
127
128//----------------------------------------------------------------------
129// Intersection functions
130
131bool intersectWall(const vec3 ro, const vec3 rd, const vec2 a, const vec2 b, const float height,
132					  inout float dist, inout vec2 uv ) {
133	vec2 p = ro.xz;	vec2 r = rd.xz;
134	vec2 q = a-p;	vec2 s = b-a;
135	float rCrossS = crossp(r, s);
136
137	if( rCrossS == 0.) {
138		return false;
139	}
140	float d = crossp(q, s) / rCrossS;
141	float u = crossp(q, r) / rCrossS;
142	float he = ro.y+rd.y*d;
143
144	if(0. <= d && d < dist && 0. <= u && u <= 1. && he*sign(height) < height ) {
145		dist = d;
146		uv = vec2( -u*length(s), height-he );
147		return true;
148	}
149	return false;
150}
151bool intersectFloor(const vec3 ro, const vec3 rd, const float height,
152					inout float dist, inout vec2 uv ) {
153	if (rd.y==0.0) {
154		return false;
155	}
156
157	float d = -(ro.y - height)/rd.y;
158	d = min(100000.0, d);
159	if( d > 0. && d < dist) {
160		dist = d;
161		uv = ro.xz+dist*rd.xz;
162		return true;
163	}
164	return false;
165}
166
167//----------------------------------------------------------------------
168// Material helper functions
169
170float sat( const float a ) { return clamp(a,0.,1.); }
171float onCircleAA( const vec2 c, const vec2 centre, const float radius, const float aa ) {
172	return sat( aa*(radius - distance(c,centre)) );
173}
174float onLineX( const vec2 c, const float x ) {
175	return step(x,c.x)*step(c.x,x);
176}
177float onLineY( const vec2 c, const float y ) {
178	return step(y,c.y)*step(c.y,y);
179}
180float onBand( const float c, const float mi, const float ma ) {
181	return step(mi,c)*step(c,ma);
182}
183float onRect( const vec2 c, const vec2 lt, const vec2 rb ) {
184	return onBand( c.x, lt.x, rb.x )*onBand( c.y, lt.y, rb.y );
185}
186vec3 addKnobAA( const vec2 c, const vec2 centre, const float radius, const float strength, const vec3 col ) {
187	vec2 lv = normalize( centre-c );
188	return mix( col, col*(1.0+strength*dot(lv,vec2(-0.7071,0.7071))), onCircleAA(c, centre, radius, 4. ) );
189}
190float onBandAA( const float c, const float mi, const float ma ) {
191	return sat( (ma-c+1.) )*sat( (c-mi+1.) );
192}
193float onRectAA( const vec2 c, const vec2 lt, const vec2 rb ) {
194	return onBandAA( c.x, lt.x, rb.x )*onBandAA( c.y, lt.y, rb.y );
195}
196vec3 addBevel( const vec2 c, const vec2 lt, const vec2 rb, const float size, const float strength, const float lil, const float lit, const vec3 col ) {
197	float xl = sat( (c.x-lt.x)/size);
198	float xr = sat( (rb.x-c.x)/size);
199	float yt = sat( (c.y-lt.y)/size);
200	float yb = sat( (rb.y-c.y)/size);
201	return mix( col, col*clamp(1.0+strength*(lil*(xl-xr)+lit*(yb-yt)), 0., 2.), onRectAA( c, lt, rb ) );
202}
203
204//----------------------------------------------------------------------
205// Generate materials!
206
207void getMaterialColor( const int material, in vec2 uv, out vec3 col ) {
208	uv = floor( uv );
209	float huv = hash(uv), huvx = hash(uv.x);
210
211	if( material == 0 ) { // ceiling GRNLITE1
212		uv = mod(uv, vec2(64.)); vec2 centre = mod(uv,vec2(32.,16.));
213		col = mix( COL(90.,98.,69.),COL(152.,149.,125.),(0.75*huv+0.25*mod(uv.x,2.)) );
214		col = mix( col, mix(vec3(243./255.),vec3(169./255.), distance(centre,vec2(16.,8.))/6.5), onCircleAA(centre, vec2(16.,8.), 6.25, 0.75) );
215	}
216	else if( material == 1 ) { // ceiling FLOOR_1
217		uv = mod(uv, vec2(64.)); vec2 uv8 = mod(uv, vec2(32.,7.7));
218		float h = huv*huvx;
219		col = mix( COL(136.,114.,95.), COL(143.,122.,92.), sat(4.*h) );
220		col = mix( col, COL(175.,126.,89.), sat( 2.*(hash(floor(uv*0.125))+huv-1.35) ) );
221		col = mix( col, COL(121.,103.,83.), sat( onLineX(uv,0.)+onLineY(uv,63.)) );
222		col = mix( col, COL(121.,103.,83.), onLineX(uv,31.)*huv );
223		uv8.x = abs(16.-uv8.x);
224		float d = min( max( uv8.x-8.,abs(uv8.y-4.) ), abs(distance(uv8,vec2(11.,4.))) )+huv;
225		vec3 fgcol = mix( col, col*sat(((16.-uv8.y)/12.)), step(d,3.) );
226		col = mix( mix( fgcol, COL(114.,94.,78.), sat(d*(3.5-d)/4.)*step(2.,d) ), col, onRect(uv, vec2(32.,23),vec2(63.,39.) ) );
227	}
228	else if( material == 2 ) { // wall TEKGREN2 & TEKGREN5
229		uv = mod(uv, vec2(128.,128)); vec2 uv64 = mod(uv, vec2(64.,65.) ); vec2 uv24 = mod(uv64, vec2(64.,24.) );
230		float h = huv*huvx;
231		col = mix( vec3(114./255.), vec3(98./255.), sat(2.*h) );
232		col = mix( col, mix( COL(111.,114.,87.), COL(90.,98.,69.), sat(2.*h) ), sat( 100.*(hash(uv+vec2(523.,53.))*hash(150.-uv.x)-0.15)) );
233		col = addKnobAA( mod( uv24, vec2(3.,32.) ), vec2(0.,4.5), 1.1, 0.4, col );
234		col = mix( col, COL(137.,141.,115.), 0.7*sat( onLineX(uv64,1.)+onLineY(uv,1.)+onLineY(uv24,0.)+onLineY(uv24,19.)+onLineY(uv64,59.) ) );
235		col = mix( col, COL(73.,81.,55.), sat( onLineX(uv64,0.)+onLineX(uv64,62.) ) );
236		col = mix( col, mix(COL(73.,81.,55.),vec3(38./255.),uv24.y-22.), onBand(uv24.y,22.,23.) );
237		col = mix( col, mix(COL(73.,81.,55.),vec3(38./255.),uv64.y-63.), onBand(uv64.y,63.,64.) );
238		col = mix( col, vec3(38./255.), sat( onLineY(uv,0.)+onLineX(uv64,63.) ) );
239		col = mix( col, COL(137.,141.,115.), onRect(uv,vec2(3.),vec2(60.,12.)) );
240		col = mix( col, mix( vec3(1.), COL(255.,253.,110.), sat( abs(uv.x-32.)/20.)-0.25*mod(uv.x,2.)), onRect(uv,vec2(4.),vec2(59.,11.)) );
241	}
242	else if( material == 3 ) { // wall BRONZE2
243		uv = mod(uv, vec2(64.,128)); float s = sin(31.15926*uv.x/64.);
244		col = mix( vec3(75./255.), vec3(64./255.), huv );
245		col = mix( col, COL(106.,86.,51.),  sat( 5.*(huv+(s+1.2)*(1.-(uv.y+44.)/64.))) * onBand(uv.y, 0., 30. ) );
246		col = mix( col, COL(123.,105.,85.), sat( 2.*(0.5*huvx+huv+(s+1.7)*(1.-(uv.y+44.)/64.)-0.5) ) * onBand(uv.y, 0., 30. ) );
247		col = mix( col, COL(106.,86.,51.),  sat( 5.*(huv+(s+0.7)*(1.-(uv.y+14.)/64.))) * onBand(uv.y, 30., 98. ) );
248		col = mix( col, COL(123.,105.,85.), sat( 2.*(1.1*huvx+(s+1.7)*(1.-(uv.y+14.)/64.)-0.5) ) * onBand(uv.y, 30., 98. ) );
249		col = mix( col, COL(7.,59.,20.), sat( huv*uv.y/96.-0.5) );
250		col = mix( col, COL(106.,86.,51.),  sat( 5.*(huv+(s+1.2)*(1.-(uv.y-40.)/64.))) * onBand(uv.y, 98., 128. ) );
251		col = mix( col, COL(123.,105.,85.), sat( 2.*(huvx+(s+1.7)*(1.-(uv.y-40.)/64.)-0.5) ) * onBand(uv.y, 98., 128. ) );
252		col = mix( col, mix(COL(110.,89.,70.),COL(130.,112.,92.),sat((uv.y-3.)/18.)), onRectAA(mod(uv,vec2(16.,128.)),vec2(6.5,1.5),vec2(12.5,21.5)) );
253		col = addBevel( mod(uv,vec2(16.,128.)),vec2(5.5,-2.5),vec2(12.5,21.5), 2.3, 1., 0.1, 0.7, col );
254		col = mix( col, addBevel( abs(mod(uv+vec2(0.,-85.),vec2(64.))-vec2(32.,0.)), vec2(15.5,0.5), vec2(34.5,52.5), 1.2, 1., 0.5, -0.7, col ), onBand(uv.y, 30.,97.));
255		col = mix( col, 0.7*col, sat( onLineY(uv,127.)+onLineX(uv,0.)+onBand(uv.y, 97.,98.)+onBand(uv.y, 29.,30.)) );
256		col = mix( col, 1.2*col, sat( onBand(uv.y, 98.,99.)+onBand(uv.y, 0.,1.)+onLineX(uv, 63.)) );
257		col = mix( col, 0.75*col*uv.x, onBand(uv.x, 0., 1.)*onBand(uv.y, 30.,97.) );
258		col *= 1.0-0.1*huv;
259	}
260	else if( material == 4 ) { // wall STEP2
261		uv = mod(uv, vec2(64.,16.));
262		col = mix( COL(182.,133.,93.), COL(132.,98.,66.), sat(huv-0.5) );
263		col = mix( col, COL(129.,111.,79.), sat(1.-(uv.y-4.)/8.) );
264		col = mix( col, COL(102.,82.,50.), sat((huv+1.)*onRectAA(mod(uv,vec2(32.,16.)), vec2(1.5,9.7), vec2(29.5,13.5))) );
265		col = mix( col, COL(102.,82.,50.), 0.6*sat((huv+1.)*onRectAA(mod(uv,vec2(8.,16.)), vec2(2.5,3.5), vec2(5.5,6.2))) );
266		col = mix( col, COL(143.,122.,92.), onLineY(uv,0.) );
267		col = mix( col, COL(106.,86.,61.), onLineY(uv,2.) );
268		col *= 1.-0.2*onLineY(uv,3.);
269	}
270	else if( material == 5 ) { // wall PIPE4
271		uv = mod(uv, vec2(128.,64.)); float huv2 = hash( uv*5312. );
272		col = mix( mix(COL(184.,165.,144.),COL(136.,102.,67.),uv.x/128.),
273				   mix(COL(142.,122.,104.),COL(93.,77.,50.),uv.x/128.), sat(huv+huvx) );
274		col *= 1.+0.5*sat(hash(uv.y)-0.7);
275		col *= 1.-0.2*sat(hash(uv.y-1.)-0.7);
276		col = mix( col, COL(102.,82.,50.), sat(0.2*huv2+3.*(huvx-0.7)) );
277		col = mix( col, COL(165.,122.,85.), (0.75+0.5*huv2)*sat( onBandAA(uv.x,122.5,123.5)+onBandAA(uv.x,117.5,118.5)+onBandAA(uv.x,108.5,109.5) ) );
278		col = mix( col, mix(  (1.-sat(0.2*abs(2.8-mod(uv.x,6.))))*mix(COL(175.,126.,89.),COL(143.,107.,71.),0.4*distance( mod(uv,vec2(6.)), vec2 (1.5))), COL(77.,68.,40.), onBandAA(mod(uv.x+1.,6.),0.,1.5)),
279								   (0.75+0.5*huv2)*sat( onBandAA(uv.x,6.5,11.5)+onBandAA(uv.x,54.5,59.5)+onBandAA(uv.x,66.5,70.5)+onBandAA(uv.x,72.5,78.5) ) );
280		col = mix( col, mix( COL(82.,90.,64.), 1.2*COL(118.,125.,99.), huv*(sat(abs(uv.x-14.)-huv)+sat(abs(uv.x-62.)-huv)) ), onBandAA(uv.x,12.8,13.8) + onBandAA(uv.x,60.8,61.8));
281		col = mix( col, vec3(0.), 0.3*(onBandAA(uv.y,18.8,21.8)*onBandAA(uv.x,40.8,52.8) + onBandAA(uv.x,0.1,3.7) + onBandAA(uv.x,41.3,44.2) + onBandAA(uv.x,48.9,51.8)+0.6*onBandAA(uv.x,80.1,81.6)));
282		col = mix( col, mix( 1.2*COL(205.,186.,167.), COL(143.,122.,92.), 0.3*(sat(abs(uv.x-2.)+huv)+sat(abs(uv.x-43.)+huv)+sat(abs(uv.x-51.)+huv)) ), onBandAA(uv.x,0.8,2.8) + onBandAA(uv.x,42.1,43.3) + onBandAA(uv.x,49.8,51.2)+0.6*onBandAA(uv.x,80.8,81.5));
283		col = mix( col, mix( 1.2*COL(205.,186.,167.), COL(154.,133.,105.), (sat(abs(uv.y-20.5)+huv)) ), onBandAA(uv.y,19.3,21.2)*onBandAA(uv.x,40.8,52.1));
284		float d = min( min( min( min( min( min( distance(uv,vec2(6.,39.)), 0.8*distance(uv,vec2(23.,45.)) ), 1.2*distance(uv,vec2(39.,30.)) )
285					  , 1.5*distance(uv,vec2(48.,42.)) ), distance(uv,vec2(90.,32.)) ), 0.8*distance(uv,vec2(98.,50.)) ), 1.15*distance(uv,vec2(120.,44.)) );;
286		d *= (1.-0.8*(sat(hash(uv.x+uv.y)-0.6)+sat(huvx-0.6)));
287		col = mix( col,COL(93.,77.,50.), sat((7.-d)/8.) );
288		col = mix( col, vec3(0.), pow(sat((5.-d)/6.),1.5) );
289	}
290	else if( material == 6 ) { // floor FLOOR_3_3
291		uv = mod(uv, vec2(64.));
292		col = mix( COL(147.,126.,108.), COL(175.,152.,134.), sat( 1.5*(huv+hash(uv.x-uv.y)-0.95-uv.y/128.)) );
293		col = mix( col, COL(175.,152.,134.), sat( 1.5*(huv+hash(uv.x-uv.y*1.1+5.)-1.8+uv.y/64.)) );
294		col = mix( col, COL(130.,133.,108.), sat( 10.*(huv+hash(uv.x*1.1-uv.y+3.)-1.25)) );
295		col = mix( col, mix( COL(118.,125.,99.), COL(130.,133.,108.), 1.-huv), sat(5.*(huv-1.5+uv.y/64.)) );
296		col = mix( col, COL(129.,111.,91.), sat( onLineX(uv,0.)+onLineY(uv,63.) ) );
297		col *= sat(0.92+huv);
298	}
299	else if( material == 7 ) { // floor FLOOR_0_1
300		uv = mod(uv, vec2(64.));
301		float h = hash(3.*uv.x+uv.y);
302		col = mix( COL(136.,114.,95.), COL(143.,122.,104.), sat(4.*h*huv) );
303		col = mix( col, COL(129.,111.,91.), sat(h-0.5) );
304		col *= 1.+0.05*sat( 0.3+mod(uv.x,2.)*cos(uv.y*0.2)*huv );
305		col = mix( col, COL(175.,126.,89.), sat( 2.*(hash(floor(uv*0.125))+huv-1.5) ) );
306		vec3 ncol = mix( col, COL(114.,94.,78.), sat(
307			(0.4*huv+0.4)*onRectAA( mod(uv+vec2(0.,33.),vec2(64.)), vec2(6.5,0.5), vec2(36.5,58.5) )
308						 -onRectAA( mod(uv+vec2(0.,33.),vec2(64.)), vec2(9.5,3.5), vec2(33.5,55.5) ) ));
309		ncol = mix( ncol, COL(114.,94.,78.), sat( (0.6*huv+0.3)*onRectAA( mod(uv+vec2(0.,5.),vec2(64.)), vec2(33.5,0.5), vec2(59.5,60.5) ) ));
310		ncol = mix( ncol, col, sat(               0.8*onRectAA( mod(uv+vec2(0.,5.),vec2(64.)), vec2(35.5,2.5), vec2(57.5,58.5) ) ));
311		ncol = mix( ncol, COL(121.,103.,81.), sat( (0.8*huv+0.9)*onRectAA( mod(uv+vec2(0.,53.),vec2(64.)), vec2(18.5,0.5), vec2(41.5,22.5) ) ));
312		ncol = mix( ncol, col, sat(               onRectAA( mod(uv+vec2(0.,53.),vec2(64.)), vec2(19.5,1.5), vec2(40.5,21.5) ) ));
313		ncol = mix( ncol, COL(114.,94.,78. ), sat( (0.8*huv+0.6)*onRectAA( mod(uv+vec2(8.,46.),vec2(64.)), vec2(0.5,0.5), vec2(20.5,36.5) ) ));
314		col  = mix( ncol, col, sat(               onRectAA( mod(uv+vec2(8.,46.),vec2(64.)), vec2(1.5,1.5), vec2(19.5,35.5) ) ));
315	} else  {
316		col = vec3(0.5);
317	}
318}
319
320//----------------------------------------------------------------------
321// Render MAP functions
322
323struct lineDef { vec2 a, b; float h; float l; int m; };
324
325vec3 castRay( const vec3 ro, const vec3 rd ) {
326	lineDef ldfs[14];
327	ldfs[0]  = lineDef(vec2(192.,-448.), vec2(320.,-320.), 264., 128., 5 );
328	ldfs[1]  = lineDef(vec2(320.,-320.), vec2(256.,0.),    264., 128., 5 );
329	ldfs[2]  = lineDef(vec2(256.,0.),    vec2(64.,0.),     264., 128., 5 );
330	ldfs[4]  = lineDef(vec2(64.,0.),     vec2(0.,0.),       56., 208., 4 );
331	ldfs[3]  = lineDef(vec2(0.,448.),    vec2(320.,448.),  128., 224., 2 );
332	ldfs[5]  = lineDef(vec2(64.,0.),     vec2(-64.,0.),   -128., 208., 5 );
333	ldfs[6]  = lineDef(vec2(192.,-320.), vec2(128.,-320.), 264., 128., 3 );
334	ldfs[7]  = lineDef(vec2(128.,-320.), vec2(128.,-256.), 264., 128., 3 );
335	ldfs[8]  = lineDef(vec2(192.,0.),    vec2(0.,-320.),    16., 144., 4 );
336	ldfs[9]  = lineDef(vec2(160.,0.),    vec2(0.,-256.),    24., 160., 4 );
337	ldfs[10] = lineDef(vec2(128.,0.),    vec2(0.,-192.),    32., 176., 4 );
338	ldfs[11] = lineDef(vec2(96.,0.),     vec2(0.,-128.),    40., 192., 4 );
339	ldfs[12] = lineDef(vec2(64.,0.),     vec2(0.,-64.),     48., 208., 4 );
340	ldfs[13] = lineDef(vec2(64.,0.),     vec2(64.,320.),   128., 224., 2 );
341
342	float dist = 999999., curdist; vec2 uv, curuv;
343	vec3 col = vec3( 0. ); float lightning = 128.; int mat = 0;
344
345	// check walls
346	for( int i=0; i<14; i++ ) {
347		vec2 a = ldfs[i].a, b = ldfs[i].b; float h=ldfs[i].h;
348		if( intersectWall(ro, rd, a, b, h, dist, uv) ||
349			intersectWall(ro, rd, b*vec2(-1.,1.), a*vec2(-1.,1.), h, dist, uv) ) {
350			mat = ldfs[i].m;
351			lightning = ldfs[i].l * (1.-0.2*abs( normalize( (a-b).yx ).y ));
352		}
353	}
354	if( mat == 5 ) { // fix large texture on wall above portal
355		vec3 intersection = ro + rd*dist;
356		if( intersection.z > -0.1 ) {
357			uv = -intersection.xy+vec2(64.,0.);
358			lightning = 0.8*max(128., min(208., 248.-20.*floor(abs(intersection.x)/32.)));
359		}
360		uv *= 0.5;
361	}
362
363	// check floor and ceiling
364	if( intersectFloor(ro, rd, 264., dist, uv ) ) {
365		mat = 1;
366		lightning =128.;
367		float c1=320., c2=196.;
368		for( int i=4; i>=0; i-- ) {
369			if( abs(uv.x)*(c1/c2)-uv.y < c1 ) {
370				lightning = float(208-i*16);
371			}
372			c1-=64.; c2-=32.;
373		}
374	}
375	if( intersectFloor(ro, rd, 8., dist, uv ) ) {
376		mat = 7;
377		lightning =128.;
378	}
379	float c1=64., c2=64., c3=48.;
380	for( int i=0; i<5; i++ ) {
381		curdist = dist;
382		if( intersectFloor(ro, rd, c3, curdist, curuv ) && abs(curuv.x)*(c1/c2)-curuv.y < c1 ) {
383			uv = curuv;
384			mat = 7;
385			dist = curdist;
386			lightning = float(208-i*16);
387		}
388		c3-=8.; c1+=64.; c2+=32.;
389	}
390	// and hall
391	curdist = dist;
392	if( (intersectFloor(ro, rd, 56., curdist, curuv ) || intersectFloor(ro, rd, 128., curdist, curuv ) ) && curuv.y > 0. ) {
393		dist = curdist;
394		uv = curuv;
395		mat = rd.y>0.?0:6;
396		lightning = 224.;
397	}
398
399	getMaterialColor( mat, uv, col );
400
401	col *= 0.3*pow(2.*lightning/255., 2.5)*sat( 1.-curdist/2000. );
402	// fake 8-bit pallete
403	col = floor((col)*64.+vec3(0.5))/64.;
404	return col;
405}
406
407//----------------------------------------------------------------------
408// Camera path
409
410float getPathHeight( const float z, const float t ) {
411	return max( 0.+step(0.,z)*56.+step(z,-448.)*56.+
412		mix(56.,8.,(448.+z)/32.)*step(-448.,z)*step(z,-416.)+
413		mix(8.,56.,(320.+z)/320.)*step(z,0.)*step(-320.,z), 8.) + 56.;
414}
415vec2 path( const float t ) {
416	return vec2(32.*sin(t*0.21), -200.-249.*cos( max(0.,mod(t,30.)-10.)*(3.1415936/10.) ) );
417}
418
419
420//----------------------------------------------------------------------
421// Main
422
423void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
424	vec2 q = fragCoord.xy/iResolution.xy;
425	vec2 p = -1.0 + 2.0*q;
426    p.x *= iResolution.x/ iResolution.y;
427
428	vec3 ro; ro.xz = path(time);
429	vec3 ta; ta.xz = path(time+0.1) + vec2(0.,20.);
430	ta.y = ro.y = getPathHeight(ro.z, time);
431
432    vec3 rdcenter =  rotate( normalize(ta - ro), 0.5*cos(time*0.5) );
433    vec3 uu = normalize(cross( vec3(0.,1.,0.), rdcenter ));
434    vec3 vv = normalize(cross(rdcenter,uu));
435    vec3 rd = normalize( p.x*uu + p.y*vv + 1.25*rdcenter );
436
437	vec3 col = castRay( ro, rd );
438
439	fragColor = vec4( col, 1.0 );
440}
441
442 void main(void)
443{
444  //just some shit to wrap shadertoy's stuff
445  vec2 FragCoord = vTexCoord.xy*OutputSize.xy;
446  mainImage(FragColor,FragCoord);
447}
448#endif
449