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///////////////////////////////////////////////////////////////////////////////
106//                                                                           //
107//  GGGG IIIII  AAA  N   N TTTTT     PPPP   AAA   CCCC     M   M  AAA  N   N //
108// G       I   A   A NN  N   T       P   P A   A C         MM MM A   A NN  N //
109// G  GG   I   AAAAA N N N   T       PPPP  AAAAA C     --- M M M AAAAA N N N //
110// G   G   I   A   A N  NN   T       P     A   A C         M   M A   A N  NN //
111//  GGGG IIIII A   A N   N   T       P     A   A  CCCC     M   M A   A N   N //
112//                                                                           //
113///////////////////////////////////////////////////////////////////////////////
114
115// Parameters
116#define VOXEL_RESOLUTION	1.5
117#define VOXEL_LIGHTING
118#define SHADOW
119#define GROUND
120#define GHOST
121//#define MOUSE
122#define HSV2RGB_FAST
123
124#define CAMERA_FOCAL_LENGTH	2.0
125#define DELTA				0.01
126#define RAY_LENGTH_MAX		500.0
127#define RAY_STEP_MAX		100.0
128#define AMBIENT				0.2
129#define SPECULAR_POWER		2.0
130#define SPECULAR_INTENSITY	0.3
131#define SHADOW_LENGTH		150.0
132#define SHADOW_POWER		3.0
133#define FADE_POWER			1.0
134#define BACKGROUND			0.7
135#define GLOW				0.4
136#define GAMMA				0.8
137
138// Math constants
139#define PI		3.14159265359
140#define SQRT3	1.73205080757
141
142// Global variable to handle the glow effect
143float glowCounter;
144
145// PRNG (from https://www.shadertoy.com/view/4djSRW)
146float rand (in vec3 seed) {
147	seed = fract (seed * vec3 (5.3983, 5.4427, 6.9371));
148	seed += dot (seed.yzx, seed.xyz + vec3 (21.5351, 14.3137, 15.3219));
149	return fract (seed.x * seed.y * seed.z * 95.4337);
150}
151
152// Distance to the voxel
153float distVoxel (in vec3 p) {
154
155	// Update the glow counter
156	++glowCounter;
157
158	// Rounded box
159	const float voxelRadius = 0.25;
160	return length (max (abs (p) - 0.5 + voxelRadius, 0.0)) - voxelRadius;
161}
162
163// Distance to the scene and color of the closest point
164vec2 distScene (in vec3 p, out vec3 P) {
165
166	// Update the glow counter
167	++glowCounter;
168
169	// Scaling
170	p *= VOXEL_RESOLUTION;
171
172	// Velocity, period of the waves, spacing of the gums
173	float v = VOXEL_RESOLUTION * floor (iGlobalTime * 100.0 / VOXEL_RESOLUTION);
174	const float k1 = 0.05;
175	const float k2 = 60.0;
176
177	// Giant Pac-Man
178	float body = length (p);
179	body = max (body - 32.0, 27.0 - body);
180	float eyes = 6.0 - length (vec3 (abs (p.x) - 12.5, p.y - 19.5, p.z - 20.0));
181	float mouthAngle = PI * (0.07 + 0.07 * cos (2.0 * v * PI / k2));
182	float mouthTop = dot (p, vec3 (0.0, -cos (mouthAngle), sin (mouthAngle))) - 2.0;
183	mouthAngle *= 2.5;
184	float mouthBottom = dot (p, vec3 (0.0, cos (mouthAngle), sin (mouthAngle)));
185	float pacMan = max (max (body, eyes), min (mouthTop, mouthBottom));
186	vec2 d = vec2 (pacMan, 0.13);
187	P = p;
188
189	// Gums
190	vec3 q = vec3 (p.xy, mod (p.z + v, k2) - k2 * 0.5);
191	float gum = max (length (q) - 6.0, -p.z);
192	if (gum < d.x) {
193		d = vec2 (gum, 0.35);
194		P = q;
195	}
196
197	// Ground
198	#ifdef GROUND
199	q = vec3 (p.xy, p.z + v);
200	float ground = (q.y + 50.0 + 14.0 * cos (q.x * k1) * cos (q.z * k1)) * 0.7;
201	if (ground < d.x) {
202		d = vec2 (ground, 0.55);
203		P = q;
204	}
205	#endif
206
207	// Ghost
208	#ifdef GHOST
209	v = VOXEL_RESOLUTION * floor ((130.0 + 60.0 * cos (iGlobalTime * 3.0)) / VOXEL_RESOLUTION);
210	q = vec3 (p.xy, p.z + v);
211	body = length (vec3 (q.x, max (q.y - 4.0, 0.0), q.z));
212	body = max (body - 28.0, 22.0 - body);
213	eyes = 8.0 - length (vec3 (abs (q.x) - 12.0, q.y - 10.0, q.z - 22.0));
214	float bottom = (q.y + 28.0 + 4.0 * cos (p.x * 0.4) * cos (p.z * 0.4)) * 0.7;
215	float ghost = max (max (body, eyes), -bottom);
216	if (ghost < d.x) {
217		d = vec2 (ghost, 0.76);
218		P = q;
219	}
220	#endif
221
222	// Scaling
223	d.x /= VOXEL_RESOLUTION;
224	return d;
225}
226
227// Distance to the (voxelized?) scene
228vec4 dist (inout vec3 p, in vec3 ray, in float voxelized, in float rayLengthMax) {
229	vec3 P = p;
230	vec2 d = vec2 (0.0, 0.0);
231	float rayLength = 0.0;
232	float rayLengthInVoxel = 0.0;
233	float rayLengthCheckVoxel = 0.0;
234	vec3 raySign = sign (ray);
235	vec3 rayDeltaVoxel = raySign / ray;
236	for (float rayStep = 0.0; rayStep < RAY_STEP_MAX; ++rayStep) {
237		if (rayLength < rayLengthInVoxel) {
238			d.x = distVoxel (fract (p + 0.5) - 0.5);
239			if (d.x < DELTA) {
240				break;
241			}
242		} else if (rayLength < rayLengthCheckVoxel) {
243			vec3 rayDelta = (0.5 - raySign * (fract (p + 0.5) - 0.5)) * rayDeltaVoxel;
244			float dNext = min (rayDelta.x, min (rayDelta.y, rayDelta.z));
245			d = distScene (floor (p + 0.5), P);
246			if (d.x < 0.0) {
247				rayDelta = rayDeltaVoxel - rayDelta;
248				d.x = max (rayLengthInVoxel - rayLength, DELTA - min (rayDelta.x, min (rayDelta.y, rayDelta.z)));
249				rayLengthInVoxel = rayLength + dNext;
250			} else {
251				d.x = DELTA + dNext;
252			}
253		} else {
254			d = distScene (p, P);
255			if (voxelized > 0.5) {
256				if (d.x < SQRT3 * 0.5) {
257					rayLengthCheckVoxel = rayLength + abs (d.x) + SQRT3 * 0.5;
258					d.x = max (rayLengthInVoxel - rayLength + DELTA, d.x - SQRT3 * 0.5);
259				}
260			} else if (d.x < DELTA) {
261				break;
262			}
263		}
264		rayLength += d.x;
265		if (rayLength > rayLengthMax) {
266			break;
267		}
268		p += d.x * ray;
269	}
270	return vec4 (d, rayLength, rand (P));
271}
272
273// Normal at a given point
274vec3 normal (in vec3 p, in float voxelized) {
275	vec2 h = vec2 (DELTA, -DELTA);
276	vec3 n;
277	if (voxelized > 0.5) {
278		p = fract (p + 0.5) - 0.5;
279		n = h.xxx * distVoxel (p + h.xxx) +
280			h.xyy * distVoxel (p + h.xyy) +
281			h.yxy * distVoxel (p + h.yxy) +
282			h.yyx * distVoxel (p + h.yyx);
283	} else {
284		n = h.xxx * distScene (p + h.xxx, n).x +
285			h.xyy * distScene (p + h.xyy, n).x +
286			h.yxy * distScene (p + h.yxy, n).x +
287			h.yyx * distScene (p + h.yyx, n).x;
288	}
289	return normalize (n);
290}
291
292// HSV to RGB
293vec3 hsv2rgb (in vec3 hsv) {
294	#ifdef HSV2RGB_SAFE
295	hsv.yz = clamp (hsv.yz, 0.0, 1.0);
296	#endif
297	#ifdef HSV2RGB_FAST
298	return hsv.z * (1.0 + 0.5 * hsv.y * (cos (2.0 * PI * (hsv.x + vec3 (0.0, 2.0 / 3.0, 1.0 / 3.0))) - 1.0));
299	#else
300	return hsv.z * (1.0 + hsv.y * clamp (abs (fract (hsv.x + vec3 (0.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - 3.0) - 2.0, -1.0, 0.0));
301	#endif
302}
303
304// Main function
305void mainImage (out vec4 fragColor, in vec2 fragCoord) {
306
307	// Get the fragment
308	vec2 frag = (2.0 * fragCoord.xy - iResolution.xy) / iResolution.y;
309
310	// Define the rendering mode
311	float modeTiming = iGlobalTime * 0.234;
312	float modeAngle = PI * cos (iGlobalTime * 0.2);
313	modeAngle = dot (frag - vec2 (cos (iGlobalTime * 2.0), 0.0), vec2 (cos (modeAngle), sin (modeAngle)));
314	float modeVoxel = step (0.5, fract (modeTiming / (4.0 * PI)));
315	modeTiming = cos (modeTiming);
316	float mode3D = smoothstep (0.8, 0.5, modeTiming);
317	float modeSwitch = smoothstep (0.995, 1.0, modeTiming) + smoothstep (0.02, 0.0, abs (modeAngle)) * (1.0 - modeVoxel);
318	modeVoxel += step (0.0, modeAngle) * (1.0 - modeVoxel);
319
320	// Define the ray corresponding to this fragment
321	vec3 ray = normalize (vec3 (frag, mix (8.0, CAMERA_FOCAL_LENGTH, mode3D)));
322
323	// Compute the orientation of the camera
324	float yawAngle = PI * (1.2 + 0.2 * cos (iGlobalTime * 0.5));
325	float pitchAngle = PI * (0.1 * cos (iGlobalTime * 0.3) - 0.05);
326	#ifdef MOUSE
327	yawAngle += 4.0 * PI * iMouse.x / iResolution.x;
328	pitchAngle += PI * 0.3 * (1.0 - iMouse.y / iResolution.y);
329	#endif
330	yawAngle = mix (PI * 1.5, yawAngle, mode3D);
331	pitchAngle *= mode3D;
332
333	float cosYaw = cos (yawAngle);
334	float sinYaw = sin (yawAngle);
335	float cosPitch = cos (pitchAngle);
336	float sinPitch = sin (pitchAngle);
337
338	mat3 cameraOrientation;
339	cameraOrientation [0] = vec3 (cosYaw, 0.0, -sinYaw);
340	cameraOrientation [1] = vec3 (sinYaw * sinPitch, cosPitch, cosYaw * sinPitch);
341	cameraOrientation [2] = vec3 (sinYaw * cosPitch, -sinPitch, cosYaw * cosPitch);
342
343	ray = cameraOrientation * ray;
344
345	// Compute the origin of the ray
346	float cameraDist = mix (300.0, 95.0 + 50.0 * cos (iGlobalTime * 0.8), mode3D);
347	vec3 origin = (vec3 (0.0, 0.0, 40.0 * sin (iGlobalTime * 0.2)) - cameraOrientation [2] * cameraDist) / VOXEL_RESOLUTION;
348
349	// Compute the distance to the scene
350	glowCounter = 0.0;
351	vec4 d = dist (origin, ray, modeVoxel, RAY_LENGTH_MAX / VOXEL_RESOLUTION);
352
353	// Set the background color
354	vec3 finalColor = hsv2rgb (vec3 (0.2 * ray.y + 0.4 * modeVoxel - 0.37, 1.0, mode3D * BACKGROUND));
355	vec3 glowColor = GLOW * vec3 (1.0, 0.3, 0.0) * glowCounter / RAY_STEP_MAX;
356	if (d.x < DELTA) {
357
358		// Set the object color
359		vec3 color = hsv2rgb (vec3 (d.y + 0.1 * d.w * modeVoxel, 0.5 + 0.5 * modeVoxel, 1.0));
360
361		// Lighting
362		vec3 l = normalize (mix (vec3 (1.0, 0.0, 0.0), vec3 (1.25 + cos (iGlobalTime * 0.2), 1.0, 1.0), mode3D));
363		#ifdef VOXEL_LIGHTING
364		if (modeVoxel > 0.5) {
365			vec3 n = normal (floor (origin + 0.5), 0.0);
366			float diffuse = max (0.0, dot (n, l));
367			float specular = pow (max (0.0, dot (reflect (ray, n), l)), SPECULAR_POWER) * SPECULAR_INTENSITY;
368			color = (AMBIENT + diffuse) * color + specular;
369		}
370		#endif
371		vec3 n = normal (origin, modeVoxel);
372		float diffuse = dot (n, l);
373		float specular;
374		if (diffuse < 0.0) {
375			diffuse = 0.0;
376			specular = 0.0;
377		} else {
378			specular = pow (max (0.0, dot (reflect (ray, n), l)), SPECULAR_POWER) * SPECULAR_INTENSITY;
379			#ifdef SHADOW
380			origin += n * DELTA * 2.0;
381			vec4 shadow = dist (origin, l, modeVoxel, SHADOW_LENGTH / VOXEL_RESOLUTION);
382			if (shadow.x < DELTA) {
383				shadow.z = pow (min (1.0, shadow.z * VOXEL_RESOLUTION / SHADOW_LENGTH), SHADOW_POWER);
384				diffuse *= shadow.z;
385				specular *= shadow.z;
386			}
387			#endif
388		}
389		color = (AMBIENT + diffuse) * color + specular;
390
391		// Fading
392		float fade = pow (max (0.0, 1.0 - d.z * VOXEL_RESOLUTION / RAY_LENGTH_MAX), FADE_POWER);
393		finalColor = mix (finalColor, color, fade);
394	}
395
396	// Set the fragment color
397	finalColor = mix (pow (finalColor, vec3 (GAMMA)) + glowColor, vec3 (1.0), modeSwitch);
398	fragColor = vec4 (finalColor, 1.0);
399}
400
401 void main(void)
402{
403  //just some shit to wrap shadertoy's stuff
404  vec2 FragCoord = vTexCoord.xy*OutputSize.xy;
405  mainImage(FragColor,FragCoord);
406}
407#endif
408