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);
}