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// A basic raytracer with help from inigo's article: http://www.iquilezles.org/www/articles/simplegpurt/simplegpurt.htm
106
107const int iterations = 5;
108const float maxDist = 1000.0;
109const vec3 amb = vec3(1.0);
110const float eps = 1e-3;
111
112struct Camera
113{
114	vec3 up, right, forward;
115	vec3 position;
116};
117
118Camera cam;
119vec4 spheres[10];
120vec4 colors[10];
121vec2 materials[10];
122
123void init()
124{
125    // X Y Z Radius
126    spheres[0] = vec4(      0,       0,    -1.5,    0.1);
127    spheres[1] = vec4(      0,    0.25,    -1.5,    0.1);
128    spheres[2] = vec4(      0,    -0.7,    -1.5,    0.3);
129    spheres[3] = vec4(      0,    -0.1,    -1.5,    0.3);
130    spheres[4] = vec4(      0,    -0.1,    -1.5,    0.15);
131    spheres[5] = vec4( 1001.0,       0,       0, 1000.0);
132    spheres[6] = vec4(-1001.0,       0,       0, 1000.0);
133    spheres[7] = vec4(      0,  1001.0,       0, 1000.0);
134    spheres[8] = vec4(      0, -1001.0,       0, 1000.0);
135    spheres[9] = vec4(      0,       0, -1002.0, 1000.0);
136
137    //R G B Diffuse
138    colors[0] = vec4(1.0, 0.8, 0.0,-1.0);
139    colors[1] = vec4(0.0, 0.0, 1.0,-1.0);
140    colors[2] = vec4(1.0, 1.0, 1.0, 1.0);
141    colors[3] = vec4(1.0, 1.0, 1.0, 1.0);
142    colors[4] = vec4(1.0, 0.0, 0.0, 1.0);
143    colors[5] = vec4(0.0, 1.0, 0.0, 0.7);
144    colors[6] = vec4(1.0, 0.0, 0.0, 0.7);
145    colors[7] = vec4(1.0, 1.0, 1.0, 0.7);
146    colors[8] = vec4(1.0, 1.0, 1.0, 0.7);
147    colors[9] = vec4(1.0, 1.0, 1.0, 0.7);
148
149    //Reflection Coeff, Refraction index
150    materials[0] = vec2 (0.0, 0.0);
151    materials[1] = vec2 (0.0, 0.0);
152    materials[2] = vec2 (1.0, 0.0);
153    materials[3] = vec2 (0.1, 0.8);
154    materials[4] = vec2 (0.1, 0.8);
155    materials[5] = vec2 (0.0, 0.0);
156    materials[6] = vec2 (0.0, 0.0);
157    materials[7] = vec2 (0.1, 0.0);
158    materials[8] = vec2 (0.1, 0.0);
159    materials[9] = vec2 (0.1, 0.0);
160
161    cam.up       = vec3(0.0, 1.0, 0.0);
162    cam.right    = vec3(1.0, 0.0, 0.0);
163    cam.forward  = vec3(0.0, 0.0,-1.0);
164    cam.position = vec3(0.0, 0.0,-0.2);
165}
166
167vec3 getRayDir(vec2 fragCoord)
168{
169  vec2 uv = (fragCoord.xy / iResolution.xy )*2.0 - 1.0;
170  uv.x *= iResolution.x/iResolution.y;
171  return normalize(uv.x * cam.right + uv.y * cam.up + cam.forward);
172}
173
174
175// The Intersection funtions and shading funcs are taken from inigo's article:
176// http://www.iquilezles.org/www/articles/simplegpurt/simplegpurt.htm
177
178bool intersectSphere(vec3 ro, vec3 rd, vec4 sp, float tm, out float t)
179{
180    bool r = false;
181	vec3 v = ro - sp.xyz;
182	float b = dot(v,rd);
183	float c = dot(v,v) - sp.w*sp.w;
184	t = b*b-c;
185    if( t > 0.0 )
186    {
187        t = -b-sqrt(t);
188        r = (t > 0.0) && (t < tm);
189    }
190    return r;
191}
192
193float calcInter(vec3 ro, vec3 rd, out vec4 ob, out vec4 col,out vec2 mat)
194{
195	float tm = maxDist;
196	float t;
197
198	if(intersectSphere(ro,rd,spheres[0],tm,t)) { ob = spheres[0]; col = colors[0]; tm = t; mat = materials[0]; }
199	if(intersectSphere(ro,rd,spheres[1],tm,t)) { ob = spheres[1]; col = colors[1]; tm = t; mat = materials[1]; }
200	if(intersectSphere(ro,rd,spheres[2],tm,t)) { ob = spheres[2]; col = colors[2]; tm = t; mat = materials[2]; }
201	if(intersectSphere(ro,rd,spheres[3],tm,t)) { ob = spheres[3]; col = colors[3]; tm = t; mat = materials[3]; }
202	if(intersectSphere(ro,rd,spheres[4],tm,t)) { ob = spheres[4]; col = colors[4]; tm = t; mat = materials[4]; }
203	if(intersectSphere(ro,rd,spheres[5],tm,t)) { ob = spheres[5]; col = colors[5]; tm = t; mat = materials[5]; }
204	if(intersectSphere(ro,rd,spheres[6],tm,t)) { ob = spheres[6]; col = colors[6]; tm = t; mat = materials[6]; }
205	if(intersectSphere(ro,rd,spheres[7],tm,t)) { ob = spheres[7]; col = colors[7]; tm = t; mat = materials[7]; }
206	if(intersectSphere(ro,rd,spheres[8],tm,t)) { ob = spheres[8]; col = colors[8]; tm = t; mat = materials[8]; }
207    if(intersectSphere(ro,rd,spheres[9],tm,t)) { ob = spheres[9]; col = colors[9]; tm = t; mat = materials[9]; }
208
209	return tm;
210}
211
212bool inShadow(vec3 ro,vec3 rd,float d)
213{
214	float t;
215	bool ret = false;
216
217	if(intersectSphere(ro,rd,spheres[2],d,t)){ ret = true; }
218	if(intersectSphere(ro,rd,spheres[3],d,t)){ ret = true; }
219	if(intersectSphere(ro,rd,spheres[4],d,t)){ ret = true; }
220	if(intersectSphere(ro,rd,spheres[5],d,t)){ ret = true; }
221	if(intersectSphere(ro,rd,spheres[6],d,t)){ ret = true; }
222	if(intersectSphere(ro,rd,spheres[7],d,t)){ ret = true; }
223	if(intersectSphere(ro,rd,spheres[8],d,t)){ ret = true; }
224
225	return ret;
226}
227
228vec3 calcShade(vec3 pt, vec4 ob, vec4 col,vec2 mat,vec3 n)
229{
230
231	float dist,diff;
232	vec3 lcol,l;
233
234	vec3 color = vec3(0.0);
235	vec3 ambcol = amb * (1.0-col.w) * col.rgb;
236	vec3 scol = col.w * col.rgb;
237
238	if(col.w > 0.0) //If its not a light
239	{
240		l = spheres[0].xyz - pt;
241		dist = length(l);
242		l = normalize(l);
243		lcol = colors[0].rgb;
244		diff = clamp(dot(n,l),0.0,1.0);
245		color += (ambcol * lcol + lcol * diff * scol) / (1.0+dist*dist);
246		if(inShadow(pt,l,dist))
247			color *= 0.7;
248
249		l = spheres[1].xyz - pt;
250		dist = length(l);
251		l = normalize(l);
252		vec3 lcol = colors[1].rgb;
253		diff = clamp(dot(n,l),0.0,1.0);
254		color += (ambcol * lcol + lcol * diff * scol) / (1.0+dist*dist);
255
256		if(inShadow(pt,l,dist))
257			color *= 0.7;
258	}
259	else
260		color = col.rgb;
261
262	return color;
263}
264
265float getFresnel(vec3 n,vec3 rd,float r0)
266{
267    float ndotv = clamp(dot(n, -rd), 0.0, 1.0);
268	return r0 + (1.0 - r0) * pow(1.0 - ndotv, 5.0);
269}
270
271vec3 getReflection(vec3 ro,vec3 rd)
272{
273	vec3 color = vec3(0);
274	vec4 ob,col;
275    vec2 mat;
276	float tm = calcInter(ro,rd,ob,col,mat);
277	if(tm < maxDist)
278	{
279		vec3 pt = ro + rd*tm;
280		vec3 n = normalize(pt - ob.xyz);
281		color = calcShade(pt,ob,col,mat,n);
282	}
283	return color;
284}
285
286void rotObjects()
287{
288	spheres[0].x += sin(iGlobalTime) * 0.4;
289    spheres[0].z += cos(iGlobalTime) * 0.4;
290
291    spheres[1].x += sin(iGlobalTime) * -0.3;
292    spheres[1].z += cos(iGlobalTime) * -0.3;
293}
294
295
296void mainImage( out vec4 fragColor, in vec2 fragCoord )
297{
298    init();
299	float fresnel,tm;
300	vec4 ob,col;
301    vec2 mat;
302	vec3 pt,refCol,n,refl;
303
304	vec3 mask = vec3(1.0);
305	vec3 color = vec3(0.0);
306	vec3 ro = cam.position;
307	vec3 rd = getRayDir(fragCoord);
308
309    rotObjects();
310
311	for(int i = 0; i < iterations; i++)
312	{
313		tm = calcInter(ro,rd,ob,col,mat);
314		if(tm < maxDist)
315		{
316			pt = ro + rd*tm;
317			n = normalize(pt - ob.xyz);
318			fresnel = getFresnel(n,rd,mat.x);
319			mask *= fresnel;
320
321			if(mat.y > 0.0) // Refractive
322			{
323				ro = pt - n*eps;
324				refl = reflect(rd,n);
325				refCol = getReflection(ro, refl);
326				color += refCol * mask;
327				mask = col.rgb * (1.0 - fresnel) * (mask / fresnel);
328				rd = refract(rd, n, mat.y);
329			}
330			else if(mat.x > 0.0) // Reflective
331			{
332				color += calcShade(pt,ob,col,mat,n) * (1.0 - fresnel) * mask / fresnel;
333				ro = pt + n*eps;
334				rd = reflect(rd, n);
335			}
336			else // Diffuse
337            {
338				color += calcShade(pt,ob,col,mat,n) * mask/fresnel;
339                break;
340            }
341		}
342	}
343	fragColor = vec4(color,1.0);
344}
345
346 void main(void)
347{
348  //just some shit to wrap shadertoy's stuff
349  vec2 FragCoord = vTexCoord.xy*OutputSize.xy;
350  mainImage(FragColor,FragCoord);
351}
352#endif
353