scene.org File Archive

File download

<root>­/­parties­/­2015­/­tokyodemofest15­/­glsl_graphics/shmup.txt.zip

File size:
3 599 bytes (3.51K)
File date:
2015-02-28 12:03:19
Download count:
all-time: 79

Preview

  • shmup.txt 3.63K

file_id.diz

// Shmup Shader
// by Katsuomi Kobayashi (@KatsuomiK)
// http://framesynthesis.com/

#ifdef GL_ES
precision mediump float;
#endif

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;

#define SCREEN_W 0.7
#define SCROLL_SPEED 0.1

#define BLINK_INTERVAL 0.06
float blink = mod(time, BLINK_INTERVAL) / BLINK_INTERVAL;

vec2 p;

vec2 myfighter_pos;

float rand(vec2 co)
{
	return fract(sin(dot(co.xy ,vec2(12.9898, 78.233))) * 43758.5453);
}

float linear_map(float value, float s0, float s1, float d0, float d1)
{
	return d0 + (value - s0) * (d1 - d0) / (s1 - s0);
}

void set_myfighter_pos()
{
	myfighter_pos = mouse.xy - vec2(0.5, 0.5);

	float n = floor(time * 2.0);
	float t = fract(time * 2.0);

	float x0 = linear_map(rand(vec2(n, 0)), 0.0, 1.0, -0.3, 0.3);
	float x1 = linear_map(rand(vec2(n + 1.0, 0)), 0.0, 1.0, -0.3, 0.3);
	float y0 = linear_map(rand(vec2(0, n)), 0.0, 1.0, -0.4, -0.1);
	float y1 = linear_map(rand(vec2(0, n + 1.0)), 0.0, 1.0, -0.4, -0.1);

	float x = linear_map(t, 0.0, 1.0, x0, x1);
	float y = linear_map(t, 0.0, 1.0, y0, y1);

	myfighter_pos.x = x;
	myfighter_pos.y = y;
}

vec3 background()
{
	float interval = 0.1;
	float thick = 0.005;
	vec3 color = vec3(0.0, 0.2, 0.4);

	if (mod(p.y + time * SCROLL_SPEED, interval) < thick || mod(p.x, interval) < thick) {
		return color;
	}
	return vec3(0);
}

vec2 get_boss_pos(float offset)
{
	float x = sin(time - offset) * 0.2;

	return vec2(x, 0.35);
}

vec3 bullet(vec2 v, float t)
{
	vec2 pos = get_boss_pos(t) + v * t;

	if (length(p - pos) < 0.006) {
		return vec3(1);
	}
	if (length(p - pos) < 0.01) {
		return vec3(1, 0.4, 0.3);
	}
	return vec3(0);
}

vec3 myfighter(vec2 pos)
{
	float radius = 0.03;

	float dx = pos.x - p.x;
	float dy = pos.y - p.y;

	int px = int(floor(abs(dx) / 0.02));
	int py = int(floor(dy / 0.02));

	bool pixel = false;

	if (px == 0) {
		if (py >= -1 && py <= 1) {
			pixel = true;
		}
	}
	if (px == 1) {
		if (py >= 1 && py <= 2) {
			pixel = true;
		}
	}

	if (pixel) {
		return vec3(1, 1, 1);
	}
	return vec3(0);
}

float get_laser_hit_y()
{
	if (abs(myfighter_pos.x - get_boss_pos(0.0).x) < 0.09) {
		return 0.3;
	}
	return 2.0;
}

vec3 laser(vec2 pos)
{
	vec2 boss_pos = get_boss_pos(0.0);

	float a = 0.003 + blink * 0.004;

	float d;

	if (p.y > myfighter_pos.y && p.y < get_laser_hit_y()) {
		d = abs(p.x - pos.x);
	} else {
		d = length(p - pos);
	}
	float n = a / (d * 3.0);

	return vec3(2, 2, 5) * n;
}

vec3 laser_hit_effect()
{
	vec2 pos = vec2(myfighter_pos.x, get_laser_hit_y());

	float a = 0.02 + blink * 0.02;

	float d = length(p - pos);
	float n = a / (d * 5.0);

	return vec3(2, 2, 5) * n;
}

vec3 boss()
{
	vec2 pos = get_boss_pos(0.0);

	bool pixel = false;

	float dx = pos.x - p.x;
	float dy = pos.y - p.y;

	int px = int(floor(abs(dx) / 0.02));
	int py = int(floor(dy / 0.02));

	if (px >= -5 && px <= 5) {
		if (py >= -5 && py <= 3) {
			if (rand(vec2(px, py)) > 0.5) {
				pixel = true;
			}
		}
	}

	if (pixel) {
		if (abs(myfighter_pos.x - pos.x) < 0.08 && blink > 0.5) {
			return vec3(1);
		}
		return vec3(1, 0.5, 0);
	}
	return vec3(0);
}

void main(void)
{
	p = (gl_FragCoord.xy - resolution * 0.5) / resolution.y;

	if (abs(p.x) > SCREEN_W / 2.0) {
		discard;
	}

	set_myfighter_pos();

	vec3 c = background();

	c += boss();

	for (int i = -4; i <= 2; i++) {
		float t = fract(time * 0.5 + float(i) * 0.03);
		vec2 v = normalize(vec2(float(i) * 0.1, -1.0));
		c += bullet(v, t);
	}

	for (int i = -2; i <= 4; i++) {
		float t = fract(time * 0.5 + 0.5 + float(i) * -0.03);
		vec2 v = normalize(vec2(float(i) * 0.1, -1.0));
		c += bullet(v, t);
	}

	c += myfighter(myfighter_pos);
	c += laser(myfighter_pos);
	c += laser_hit_effect();

	gl_FragColor = vec4(c, 1);
}