scene.org File Archive

File download

<root>­/­parties­/­2021­/­tokyodemofest21­/­glsl/quake.txt

File size:
26 938 bytes (26.31K)
File date:
2021-12-12 11:40:28
Download count:
all-time: 200

Preview

#extension GL_OES_standard_derivatives : enable

precision highp float;

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

/*
Created by soma_arc - 2021
This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported.
*/

// from Syntopia http://blog.hvidtfeldts.net/index.php/2015/01/path-tracing-3d-fractals/
vec2 rand2n(vec2 co, float sampleIndex) {
	vec2 seed = co * (sampleIndex + 1.0);
	seed+=vec2(-1,1);
	// implementation based on: lumina.sourceforge.net/Tutorials/Noise.html
	return vec2(fract(sin(dot(seed.xy ,vec2(12.9898,78.233))) * 43758.5453),
                 fract(cos(dot(seed.xy ,vec2(4.898,7.23))) * 23421.631));
}

struct Plane{
    vec3 p1;
    vec3 p2;
    vec3 p3;
    vec3 normal;
};


const vec3 BLACK = vec3(0);
const vec3 RED = vec3(1, 0, 0);
const vec3 LIGHT_POS = vec3(100, 100, 100);
const vec3 LIGHT_DIR = normalize(LIGHT_POS);
const float AMBIENT_FACTOR = 0.1;

const float EPSILON = 0.001;
const float PI = 3.14159265;
const float PI_2 = 3.14159265 / 2.;
const float RT_3 = sqrt(3.);
const float RT_3_INV = 1.0 / sqrt(3.);

const Plane PL1 = Plane(vec3(0, 5, RT_3_INV),
                vec3(1, 1, 0),
                vec3(2, 2, -RT_3_INV),
                normalize(vec3(RT_3 * 0.5, 0, 1.5)));

const Plane PL2 = Plane(vec3(0, 3, -RT_3_INV),
                        vec3(1, 3, 0),
                        vec3(2, 2, RT_3_INV),
                        normalize(vec3(RT_3 * 0.5, 0, -1.5)));
const Plane PL3 = Plane(
    vec3(-0.5, 0, 1),
    vec3(-0.5, 1, 0),
    vec3(-0.5, 2, 1),
    vec3(-1, 0, 0));

vec4 s2, s4, s6;
vec4 s2A, s4A, s6A;
vec4 s2B, s4B, s6B;
vec4 s2C, s4C, s6C;
vec4 gSpheres0, gSpheres1, gSpheres2, gSpheres3, gSpheres4, gSpheres5;
vec4 inversionSphere;

vec3 vertexes0, vertexes1, vertexes2, vertexes3, vertexes4,vertexes5, vertexes6, vertexes7;
Plane dividePlane;
vec4 convexSphere;

float gInvNum = 0.;
float gBoundingPlaneY = -9999999999.;

const float DISPLAY_GAMMA_COEFF = 1. / 2.2;
vec3 gammaCorrect(vec3 rgb) {
  return vec3((min(pow(rgb.r, DISPLAY_GAMMA_COEFF), 1.)),
              (min(pow(rgb.g, DISPLAY_GAMMA_COEFF), 1.)),
              (min(pow(rgb.b, DISPLAY_GAMMA_COEFF), 1.)));
}

vec3 Hsv2rgb(float h, float s, float v){
    vec3 c = vec3(h, s, v);
    const vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}


void computeCubeSphairahedronA(float zb, float zc) {
    float r2 = 0.5 + (zb * zc) / 3.0;
    float r4 = 0.5 + (zb * zb - zb * zc) / 3.0;
    float r6 = 0.5 + (-zb * zc + zc * zc) / 3.0;
    s2 = s2A = vec4(1. - r2, 0, 0, r2);
    s4 = s4A = vec4(-(1. - r4) * 0.5, zb, sqrt(3.) * (1. - r4) * 0.5, r4);
    s6 = s6A = vec4(-(1. - r6) * 0.5, zc, -sqrt(3.) * (1. - r6) * 0.5, r6);
    inversionSphere = vec4(-s6.x, -s6.y, s6.z, s6.w);
}

void computeCubeSphairahedronB(float zb, float zc) {
    float r2 = (3. * RT_3 + 2. * RT_3 * zb * zc) / 9.0;
    float r4 = (3. * zb * zb - 4. * zb * zc + 3.) / 9.0;
    float r6 = (3. * zc * zc - 2. * zb * zc + 6.) / 9.0;
    s2 = s2B = vec4((2. - RT_3 * r2) * 0.5, 0, r2 * 0.5, r2);
    s4 = s4B = vec4(-(1. - r4) * 0.5, zb, RT_3 * (1. - r4) * 0.5, r4);
    s6 = s6B = vec4(-(1. - r6) * 0.5, zc, -RT_3 * (1. - r6) * 0.5, r6);
    inversionSphere = vec4(-s6.x, -s6.y, s6.z, s6.w);
}

void computeCubeSphairahedronC(float zb, float zc) {
    float r2 = (zb * zb + 2. * zb * zc + 6.) / (5. * RT_3);
    float r4 = (3. * zb * zb - 4. * zb * zc + 3.) / (5. * RT_3);
    float r6 = (-zb * zb - 2. * zb * zc + 5. * zc * zc + 9.) / 15.0;
    s2 = s2C = vec4((2. - RT_3 * r2) * 0.5, 0, r2 * 0.5, r2);
    s4 = s4C = vec4(-0.5, zb, RT_3 / 2. - r4, r4);
    s6 = s6C = vec4(-(1. - r6) * 0.5, zc, -RT_3 * (1. - r6) * 0.5, r6);
    inversionSphere = vec4(-s6.x, -s6.y, s6.z, s6.w);
}


float MAX_FLOAT = 1e20;
const float THRESHOLD = 0.001;

bool intersectBoundingPlane(const vec3 n, const vec3 p,
							const vec3 rayOrigin, const vec3 rayDir,
							inout float t0, inout float t1) {
	float d = -dot(p, n);
    float v = dot(n, rayDir);
    float t = -(dot(n, rayOrigin) + d) / v;
    if(THRESHOLD < t){
		if(v < 0.) {
			t0 = max(t, t0);
			t1 = MAX_FLOAT;
		} else {
			t0 = t0;
			t1 = t;
		}
		return true;
    }
    t0 = t0;
    t1 = MAX_FLOAT;
	return (v < 0.);
}

/*
float[12] pivoting(float[12] mat, int n, int k){
    int col = k;
    float maxValue = abs(mat[k*4 + k]);
    for (int i = k + 1; i < n; i++) {
        if (abs(mat[i*4 + k]) > maxValue) {
            col = i;
            maxValue = abs(mat[i*4 + k]);
        }
    }
    if (k != col) {
        float tmp[4];
        tmp[0] = mat[col*4 + 0];
        tmp[1] = mat[col*4 + 1];
        tmp[2] = mat[col*4 + 2];
        tmp[3] = mat[col*4 + 3];
        mat[col*4 + 0] = mat[k*4 + 0];
        mat[col*4 + 1] = mat[k*4 + 1];
        mat[col*4 + 2] = mat[k*4 + 2];
        mat[col*4 + 3] = mat[k*4 + 3];
        mat[k*4 + 0] = tmp[0];
        mat[k*4 + 1] = tmp[1];
        mat[k*4 + 2] = tmp[2];
        mat[k*4 + 3] = tmp[3];
    }
    return mat;
}
*/

vec4 sphereFromPoints(vec3 p0, vec3 p1, vec3 p2, vec3 p3){
    /*
    float coefficient[12];
    for (int i = 0; i < 3; i++) {
        coefficient[i * 4 + 0] = 2. * (p[i + 1].x - p[i].x);
        coefficient[i * 4 + 1] = 2. * (p[i + 1].y - p[i].y);
        coefficient[i * 4 + 2] = 2. * (p[i + 1].z - p[i].z);
        coefficient[i * 4 + 3] = -(pow(p[i].x, 2.) + pow(p[i].y, 2.) + pow(p[i].z, 2.)) +
                pow(p[i + 1].x, 2.) + pow(p[i + 1].y, 2.) + pow(p[i + 1].z, 2.);
    }
    */
    float coefficient0, coefficient1, coefficient2, coefficient3, coefficient4;
    float coefficient5, coefficient6, coefficient7, coefficient8, coefficient9;
    float coefficient10, coefficient11;
    coefficient0 = 2. * (p1.x - p0.x);
    coefficient1 = 2. * (p1.y - p0.y);
    coefficient2 = 2. * (p1.z - p0.z);
    coefficient3 = -(pow(p0.x, 2.) + pow(p0.y, 2.) + pow(p0.z, 2.)) +
                     pow(p1.x, 2.) + pow(p1.y, 2.) + pow(p1.z, 2.);
    coefficient4 = 2. * (p2.x - p1.x);
    coefficient5 = 2. * (p2.y - p1.y);
    coefficient6 = 2. * (p2.z - p1.z);
    coefficient7 = -(pow(p1.x, 2.) + pow(p1.y, 2.) + pow(p1.z, 2.)) +
                     pow(p2.x, 2.) + pow(p2.y, 2.) + pow(p2.z, 2.);
    coefficient8 = 2. * (p3.x - p2.x);
    coefficient9 = 2. * (p3.y - p2.y);
    coefficient10 = 2. * (p3.z - p2.z);
    coefficient11 = -(pow(p2.x, 2.) + pow(p2.y, 2.) + pow(p2.z, 2.)) +
                      pow(p3.x, 2.) + pow(p3.y, 2.) + pow(p3.z, 2.);
    
    /*
    const int n = 3;
    for (int k = 0; k < n - 1; k++) {
        coefficient = pivoting(coefficient, n, k);

        float vkk = coefficient[k * 4 + k];
        for (int i = k + 1; i < n; i++) {
            float vik = coefficient[i * 4 + k];
            for (int j = k; j < n + 1; ++j) {
                coefficient[i * 4 + j] = coefficient[i*4 + j] - vik * (coefficient[k * 4 + j] / vkk);
            }
        }
    }
    
    coefficient[(n - 1) * 4 + n] = coefficient[(n - 1) * 4 + n] / coefficient[(n - 1) * 4 + n - 1];
    for (int i = n - 2; i >= 0; i--) {
        float acc = 0.0;
        for (int j = i + 1; j < n; j++) {
            acc += coefficient[i * 4 + j] * coefficient[j * 4 + n];
        }
        coefficient[i * 4 + n] = (coefficient[i * 4 + n] - acc) / coefficient[i * 4 + i];
    }
    */
        //coefficient = pivoting(coefficient, 3, 0);
    int col = 0;
    float maxValue = abs(coefficient0);
    if (abs(coefficient4) > maxValue) {
        col = 1;
        maxValue = abs(coefficient4);
    }
    if (abs(coefficient8) > maxValue) {
        col = 2;
        maxValue = abs(coefficient8);
    }
    
    if (col == 1) {
        float tmp0 = coefficient4;
        float tmp1 = coefficient5;
        float tmp2 = coefficient6;
        float tmp3 = coefficient7;
        coefficient4 = coefficient0;
        coefficient5 = coefficient1;
        coefficient6 = coefficient2;
        coefficient7 = coefficient3;
        coefficient0 = tmp0;
        coefficient1 = tmp1;
        coefficient2 = tmp2;
        coefficient3 = tmp3;
    }
    
    if (col == 2) {
        float tmp0 = coefficient8;
        float tmp1 = coefficient9;
        float tmp2 = coefficient10;
        float tmp3 = coefficient11;
        coefficient8 = coefficient0;
        coefficient9 = coefficient1;
        coefficient10 = coefficient2;
        coefficient11 = coefficient3;
        coefficient0 = tmp0;
        coefficient1 = tmp1;
        coefficient2 = tmp2;
        coefficient3 = tmp3;
    }

    
        float vkk = coefficient0;
        float vik = coefficient4;    
        coefficient4 = coefficient4 - vik * (coefficient0 / vkk);
        coefficient5 = coefficient5 - vik * (coefficient1 / vkk);
        coefficient6 = coefficient6 - vik * (coefficient2 / vkk);
        coefficient7 = coefficient7 - vik * (coefficient3 / vkk);
    
        vik = coefficient8;            
        coefficient8 = coefficient8 - vik * (coefficient0 / vkk);
        coefficient9 = coefficient9 - vik * (coefficient1 / vkk);
        coefficient10 = coefficient10 - vik * (coefficient2 / vkk);
        coefficient11 = coefficient11 - vik * (coefficient3 / vkk);

        
        //coefficient = pivoting(coefficient, 3, 1);
    col = 1;
    maxValue = abs(coefficient5);
    
        if (abs(coefficient9) > maxValue) {
            col = 2;
            maxValue = abs(coefficient9);
        }
    
    if (col == 2) {
        float tmp0 = coefficient8;
        float tmp1 = coefficient9;
        float tmp2 = coefficient10;
        float tmp3 = coefficient11;
        coefficient8 = coefficient4;
        coefficient9 = coefficient5;
        coefficient10 = coefficient6;
        coefficient11 = coefficient7;
        coefficient4 = tmp0;
        coefficient5 = tmp1;
        coefficient6 = tmp2;
        coefficient7 = tmp3;
    }

        vkk = coefficient5;
        vik = coefficient9;
            
        coefficient9 = coefficient9 - vik * (coefficient5 / vkk);
        coefficient10 = coefficient10 - vik * (coefficient6 / vkk);
        coefficient11 = coefficient11 - vik * (coefficient7 / vkk);


    
    coefficient11 = coefficient11 / coefficient10;

    float acc = 0.0;
    acc += coefficient6 * coefficient11;
        
    coefficient7 = (coefficient7 - acc) / coefficient5;
        
    acc = 0.0;
    acc += coefficient1 * coefficient7;
    acc += coefficient2 * coefficient11;

    coefficient3 = (coefficient3 - acc) / coefficient0;
    
    //vec3 center = vec3(coefficient[0 * 4 + 3], coefficient[1 * 4 + 3], coefficient[2 * 4 + 3]);
    vec3 center = vec3(coefficient3, coefficient7, coefficient11);
    float r = length(center - p0);
    return vec4(center, r);
}

vec3 invertOnPoint(vec4 sphere, vec3 p) {
    vec3 d = p - sphere.xyz;
    float len = length(d);
    return d * (sphere.r * sphere.r / (len * len)) + sphere.xyz;
}

vec4 invertOnSphere(vec4 invSphere, vec4 s) {
    float r = s.w;
    float coeffR = r * RT_3 / 3.;
    vec3 p1 = invertOnPoint(invSphere, s.xyz + vec3(coeffR, coeffR, coeffR));
    vec3 p2 = invertOnPoint(invSphere, s.xyz + vec3(-coeffR, -coeffR, -coeffR));
    vec3 p3 = invertOnPoint(invSphere, s.xyz + vec3(coeffR, -coeffR, -coeffR));
    vec3 p4 = invertOnPoint(invSphere, s.xyz + vec3(coeffR, coeffR, -coeffR));
    return sphereFromPoints(p1, p2, p3, p4);
}

vec4 invertOnPlane(vec4 invSphere, Plane p) {
    return sphereFromPoints(invertOnPoint(invSphere, p.p1),
                            invertOnPoint(invSphere, p.p2),
                            invertOnPoint(invSphere, p.p3),
                            invSphere.xyz);
}

void computeGSpheres(){
    gSpheres0 = invertOnPlane(inversionSphere, PL1);
    gSpheres1 = invertOnSphere(inversionSphere, s2);
    gSpheres2 = invertOnPlane(inversionSphere, PL2);
    gSpheres3 = invertOnSphere(inversionSphere, s4);
    gSpheres4 = invertOnPlane(inversionSphere, PL3);
    gSpheres5 = invertOnSphere(inversionSphere, s6);
    
}

vec3 computeVertex(vec4 a, vec4 b, vec4 c) {
    float AB = (dot(a.xyz, a.xyz) - dot(b.xyz, b.xyz) - a.w * a.w + b.w * b.w) * 0.5 -
               dot(a.xyz, a.xyz) + dot(a.xyz, b.xyz);
    float AC = (dot(a.xyz, a.xyz) - dot(c.xyz, c.xyz) - a.w * a.w + c.w * c.w) * 0.5 -
               dot(a.xyz, a.xyz) + dot(a.xyz, c.xyz);
    float x = -dot(a.xyz, a.xyz) - dot(b.xyz, b.xyz) + 2. * dot(a.xyz, b.xyz);
    float y = -dot(a.xyz, a.xyz) - dot(c.xyz, c.xyz) + 2. * dot(a.xyz, c.xyz);
    float z = -dot(a.xyz, a.xyz) + dot(a.xyz, b.xyz) +
               dot(a.xyz, c.xyz) - dot(b.xyz, c.xyz);
    float s = (AB * y - AC * z) / (x * y - z * z);
    float t = (AC * x - AB * z) / (x * y - z * z);
    return a.xyz + (b.xyz - a.xyz) * s + (c.xyz - a.xyz) * t;
}


/*
0, 1, 2, 
0, 3, 4, 
2, 4, 5,
0, 1, 3,
3, 4, 5,
1, 2, 5,
1, 3, 5,
0, 2, 4
*/
void computeVertexes(){
    vertexes0 = computeVertex(gSpheres0,
                                gSpheres1,
                                gSpheres2);
    vertexes1 = computeVertex(gSpheres0,
                                gSpheres3,
                                gSpheres4);
    vertexes2 = computeVertex(gSpheres2,
                                gSpheres4,
                                gSpheres5);
    vertexes3 = computeVertex(gSpheres0,
                                gSpheres1,
                                gSpheres3);
    vertexes4 = computeVertex(gSpheres3,
                                gSpheres4,
                                gSpheres5);
    vertexes5 = computeVertex(gSpheres1,
                                gSpheres2,
                                gSpheres5);
    vertexes6 = computeVertex(gSpheres1,
                                gSpheres3,
                                gSpheres5);
    vertexes7 = computeVertex(gSpheres0,
                                gSpheres2,
                                gSpheres4);
    /*
    for(int i = 0; i < 8; i++) {
        vertexes[i] = computeVertex(gSpheres[index[i*3 + 0]],
                                    gSpheres[index[i*3 + 1]],
                                    gSpheres[index[i*3 + 2]]);
    }
    */
}

Plane computePlane() {
        vec3 p1 = invertOnPoint(inversionSphere, vertexes0);
        vec3 p2 = invertOnPoint(inversionSphere, vertexes1);
        vec3 p3 = invertOnPoint(inversionSphere, vertexes2);

        vec3 v1 = p2 - p1;
        vec3 v2 = p3 - p1;
        vec3 normal = normalize(cross(v1, v2));
        if (normal.y < 0.) {
            normal = normal * -1.;
        }
        Plane p = Plane(p1, p2, p3, normal);
        
        return p;
}

vec4 computeConvexSphere(){
    return invertOnPlane(inversionSphere, dividePlane);
}

// p: center of the plane
// n: normal of the plane
bool intersectPlane(vec3 p, vec3 n, 
                    vec3 rayOrigin, vec3 rayDir,
                     inout float minDist,
                    inout vec3 intersection, inout vec3 normal){
    float d = -dot(p, n);
    float v = dot(n, rayDir);
    float t = -(dot(n, rayOrigin) + d) / v;
    if(EPSILON < t && t < minDist){
		intersection = rayOrigin + t * rayDir;
        normal = n;
        minDist = t;
        return true;
    }
    return false;
}

vec2 opUnion(vec2 d1, vec2 d2) {
	return (d1.x < d2.x) ? d1 : d2;
}

float distSphere(vec3 p, vec4 sphere){
	return distance(p, sphere.xyz) - sphere.w;
}

float distPlane(vec3 pos, vec3 p, vec3 n) {
    return dot(pos - p, n);
}

float distPrism(const vec3 pos) {
    float d = -1.;
	d = max(distPlane(pos, PL1.p1,
					  PL1.normal),
			d);
    d = max(distPlane(pos, PL2.p1,
					  PL2.normal),
			d);
    d = max(distPlane(pos, PL3.p1,
					  PL3.normal),
			d);
    return d;
}

float distInfSphairahedra(const vec3 pos) {
    float d = distPrism(pos);
    d = max(distPlane(pos, dividePlane.p1,
                           dividePlane.normal),
            d);
	d = max(-distSphere(pos, s2),
			d);
    d = max(-distSphere(pos, s4),
			d);
    d = max(-distSphere(pos, s6),
			d);
    return d;
}

void SphereInvert(inout vec3 pos, inout float dr, vec4 s) {
    vec3 diff = pos - s.xyz;
    float lenSq = dot(diff, diff);
    float k = (s.w * s.w) / lenSq;
    dr *= k; // (r * r) / lenSq
    pos = (diff * k) + s.xyz;
}

float distLimitSetTerrain(vec3 pos, out float invNum) {
    float dr = 1.;
    invNum = 0.;

    float d;
    for(int i = 0; i < 200; i++) {
        if(25 <= i) break;
        bool inFund = true;
		if(distance(pos, s2.xyz) < s2.w) {
            invNum ++;
			SphereInvert(pos, dr, s2);
			inFund = false;
		}
        if(distance(pos, s4.xyz) < s4.w) {
            invNum ++;
			SphereInvert(pos, dr, s4);
			inFund = false;
		}
        if(distance(pos, s6.xyz) < s6.w) {
            invNum ++;
			SphereInvert(pos, dr, s6);
			inFund = false;
		}

		pos -= PL1.p1;
		d = dot(pos, PL1.normal);
		if(d > 0.) {
            //invNum += 1.;
			pos -= 2. * d * PL1.normal;
			inFund = false;
		}
		pos += PL1.p1;
        
        pos -= PL2.p1;
		d = dot(pos, PL2.normal);
		if(d > 0.) {
            //invNum += 1.;
			pos -= 2. * d * PL2.normal;
			inFund = false;
		}
		pos += PL2.p1;
        
        pos -= PL3.p1;
		d = dot(pos, PL3.normal);
		if(d > 0.) {
            //invNum += 1.;
			pos -= 2. * d * PL3.normal;
			inFund = false;
		}
		pos += PL3.p1;

        if(inFund) break;
    }
    return distInfSphairahedra(pos) / abs(dr) * 0.1;
}

vec2 distFunc(vec3 p) {
	vec2 d = vec2(distLimitSetTerrain(p, gInvNum), 1);
    return d;
}

const vec2 NORMAL_COEFF = vec2(0.001, 0.);
vec3 computeNormal(const vec3 p){
  return normalize(vec3(distFunc(p + NORMAL_COEFF.xyy).x - distFunc(p - NORMAL_COEFF.xyy).x,
                        distFunc(p + NORMAL_COEFF.yxy).x - distFunc(p - NORMAL_COEFF.yxy).x,
                        distFunc(p + NORMAL_COEFF.yyx).x - distFunc(p - NORMAL_COEFF.yyx).x));
}

const int MAX_MARCH = 300;
int march (vec3 rayOrg, vec3 rayDir, inout float minDist,
           inout vec3 intersection, inout vec3 normal) {
    vec2 dist = vec2(-1);
    float rayLength = minDist;
    vec3 rayPos = rayOrg + rayDir * rayLength;

    for(int i = 0 ; i < MAX_MARCH ; i++){
        dist = distFunc(rayPos);
        rayLength += dist.x;
        rayPos = rayOrg + rayDir * rayLength;
        if(dist.x < EPSILON){
            int objId = int(dist.y);
            intersection = rayPos;
            normal = computeNormal(intersection);
            minDist = rayLength;
            return objId;
        }
    }
    return -1;
}

vec3 calcRay (const vec3 eye, const vec3 target, const vec3 up, const float fov,
              const float width, const float height, const vec2 coord){
  float imagePlane = (height * .5) / tan(fov * .5);
  vec3 v = normalize(target - eye);
  vec3 xaxis = normalize(cross(v, up));
  vec3 yaxis =  normalize(cross(v, xaxis));
  vec3 center = v * imagePlane;
  vec3 origin = center - (xaxis * (width  *.5)) - (yaxis * (height * .5));
  return normalize(origin + (xaxis * coord.x) + (yaxis * (height - coord.y)));
}

const vec4 K = vec4(1.0, .666666, .333333, 3.0);
vec3 hsv2rgb(const vec3 c){
  vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
  return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}


vec3 getMatColor(int objId, vec3 normal, vec3 intersection, float t){
    if(objId == 1){
        vec3 col = Hsv2rgb((1., -0.01 + (gInvNum) * 0.02), 1., 1.);;
        return col; 
    }
	return BLACK;
}

vec3 sky(vec3 rayDir){
	return clamp(vec3(.7, .8, 1.) + exp(dot(rayDir, LIGHT_DIR))*0.1, 0.0, 1.0);
}

float computeShadowFactor (vec3 rayOrg, vec3 rayDir,
                           float mint, float maxt, float k) {
    float shadowFactor = 1.0;
    float t = mint;
    for(int n = 0; n < 1000; n++){
        if(t > maxt) break;
        float d = distFunc(rayOrg + rayDir * t).x;
        if(d < 0.0001) return 0.;

        shadowFactor = min(shadowFactor, k * d / t);
        t += d;
    }
    return clamp(shadowFactor, 0.0, 1.0);
}


float specular(vec3 n,vec3 l,vec3 e,float s) {    
    return pow(clamp(dot(reflect(e,n),l),0.0, 1.),s);
}

const float FOG_START = 5.;
const float FOG_END = 100.;
const float FOG_END_START_RECIPROCAL = 1. / (FOG_END - FOG_START);
const vec3 FOG_F = vec3(1.);
vec3 calcColor(float time, vec3 eye, vec3 ray){
  	vec3 l = BLACK;

    float tmin = 0.;
    float t = 9999999.;
    const int maxLoop = 10;
    	vec3 intersection, normal;
    	bool isect;
    	int objId = -1;
        
        
    bool hit = intersectBoundingPlane(vec3(0, 1, 0), vec3(0, gBoundingPlaneY, 0),
                                 eye, ray,
                                 tmin, t);
    if(hit && tmin < 30.) {
        objId = march(eye, ray, tmin,
                      intersection, normal);
        if(objId != -1){
            vec3 matColor = getMatColor(objId, normal, intersection, t);
            float k = computeShadowFactor(intersection + 0.0001 * normal,
                                         LIGHT_DIR,
                                         0.001, 5., 100.);
            vec3 diffuse =  clamp(dot(normal, LIGHT_DIR), 0., 1.) * matColor;
            vec3 ambient = matColor * AMBIENT_FACTOR;
    		l += k * diffuse + ambient;
            
            l = mix(FOG_F, l, clamp((FOG_END - tmin) * FOG_END_START_RECIPROCAL, 0.1, 1.0));
        }
                      
    } else {
        l = mix( sky(ray), l, exp( -0.000000009*t * t ) );
    }
    
  	return l;
}

//w: start time
//s: duration
float scene(in float t, in float w, in float s){
    return clamp(t - w, 0.0, s) / s;
}

float expEasingIn(float t){
    return pow( 2., 13. * (t - 1.) );
}

float circEasingIn(float t){
	return -  (sqrt(1. - t*t) - 1.);
}

float circEasingOut(float t){
    return sqrt(1. - pow(t - 1., 2.));
}

float circEasingInOut(float t){
	t /= .5;
	if (t < 1.) return -.5 * (sqrt(1. - t*t) - 1.);
	t -= 2.;
	return .5 * (sqrt(1. - t*t) + 1.);
}

const vec3 target = vec3(0, 0, 0);
vec3 up = vec3(0, 1, 0);
float fov = radians(60.);

const float SAMPLE_NUM = 2.;
void main(  ){
    float t = mod(time, 31.);
    
    float rad = mix(0.0001, 1.0, circEasingInOut(scene(t, 1.0, 15.)));
    float rotationT = mix(0., 50., (scene(t, 0., 15.)));
    if(t < 21.) {
        
        float tb = rad * cos(rotationT);
        float tc = rad * sin(rotationT);
        tb = mix(tb, 0., circEasingInOut(scene(t, 15., 1.)));
        tc = mix(tc, 0., circEasingInOut(scene(t, 15., 1.)));
        
        tb = mix(tb, 1.2224464245160123, circEasingInOut(scene(t, 16., 1.)));
        tc = mix(tc, 0.612090457867328, circEasingInOut(scene(t, 16., 1.)));
        
        tb = mix(tb, -0.8661174154839888, circEasingInOut(scene(t, 17., 1.)));
        tc = mix(tc, 0., circEasingInOut(scene(t, 17., 1.)));
        
        tb = mix(tb, 0.61096041060052, circEasingInOut(scene(t, 18., 1.)));
        tc = mix(tc, -0.6110480831254523, circEasingInOut(scene(t, 18., 1.)));
        
        tb = mix(tb, -0.6144427845492827, circEasingInOut(scene(t, 19., 1.)));
        tc = mix(tc, 0.6155169219301033, circEasingInOut(scene(t, 19., 1.)));
        
        tb = mix(tb, -0.6492253932449349, circEasingInOut(scene(t, 20., 1.)));
        tc = mix(tc, -1.1670917737220714, circEasingInOut(scene(t, 20., 1.)));
        
        computeCubeSphairahedronA(tb, tc);
    } else if(t < 22.) {
        computeCubeSphairahedronA(-0.6492253932449349, -1.1670917737220714);
        computeCubeSphairahedronB(-1.4263771231354925, -0.4114778978502866);
        s2 = mix(s2A, s2B, circEasingInOut(scene(t, 21., 1.)));
        s4 = mix(s4A, s4B, circEasingInOut(scene(t, 21., 1.)));
        s6 = mix(s6A, s6B, circEasingInOut(scene(t, 21., 1.)));
        inversionSphere = vec4(-s6.x, -s6.y, s6.z, s6.w);
    } else if(t < 26.){
        float tb = -1.4263771231354925;
        float tc = -0.4114778978502866;
        tb = mix(tb, 0.9480876782578194, circEasingInOut(scene(t, 22., 1.)));
        tc = mix(tc, -0.27487295833102093, circEasingInOut(scene(t, 22., 1.)));
        
        tb = mix(tb, -0.7341647058410344, circEasingInOut(scene(t, 23., 1.)));
        tc = mix(tc, -0.8016177852310659, circEasingInOut(scene(t, 23., 1.)));
        
        tb = mix(tb, -1.1021579831206387, circEasingInOut(scene(t, 24., 1.)));
        tc = mix(tc, 0., circEasingInOut(scene(t, 24., 1.)));
        
        tb = mix(tb, 0.7341944231647511, circEasingInOut(scene(t, 25., 1.)));
        tc = mix(tc, 0.8010951070853616, circEasingInOut(scene(t, 25., 1.)));
        computeCubeSphairahedronB(tb, tc);
    } else if(t < 27.){
        computeCubeSphairahedronB(0.7341944231647511, 0.8010951070853616);
        computeCubeSphairahedronC(0.80897179163727, -0.6172090398213005);
        s2 = mix(s2B, s2C, circEasingInOut(scene(t, 26., 1.)));
        s4 = mix(s4B, s4C, circEasingInOut(scene(t, 26., 1.)));
        s6 = mix(s6B, s6C, circEasingInOut(scene(t, 26., 1.)));
        inversionSphere = vec4(-s6.x, -s6.y, s6.z, s6.w);

    } else if(t < 30.){
        float tb = 0.80897179163727;
        float tc = -0.6172090398213005;
        tb = mix(tb, -1.0724597039839807, circEasingInOut(scene(t, 27., 1.)));
        tc = mix(tc, 0.10239062161550339, circEasingInOut(scene(t, 27., 1.)));
        
        tb = mix(tb, -0.4626628191468804, circEasingInOut(scene(t, 28., 1.)));
        tc = mix(tc, -0.7985798919860417, circEasingInOut(scene(t, 28., 1.)));
        
        tb = mix(tb, 1.0842163989231046, circEasingInOut(scene(t, 29., 1.)));
        tc = mix(tc, -0.09944669059450531, circEasingInOut(scene(t, 29., 1.)));
        
        computeCubeSphairahedronC(tb, tc);
    } else {
        computeCubeSphairahedronC(1.0842163989231046, -0.09944669059450531);
        computeCubeSphairahedronA(0., 0.);
        s2 = mix(s2C, s2A, circEasingInOut(scene(t, 30., 1.)));
        s4 = mix(s4C, s4A, circEasingInOut(scene(t, 30., 1.)));
        s6 = mix(s6C, s6A, circEasingInOut(scene(t, 30., 1.)));
        inversionSphere = vec4(-s6.x, -s6.y, s6.z, s6.w);
    }

    computeGSpheres();
    computeVertexes();
    dividePlane = computePlane();
    convexSphere = computeConvexSphere();
    gBoundingPlaneY = max(gBoundingPlaneY, s2.y + .01);
    gBoundingPlaneY = max(gBoundingPlaneY, s4.y + .01);
    gBoundingPlaneY = max(gBoundingPlaneY, s6.y + .01);
    vec3 eye = vec3(2. , 2., 2. );
    eye = mix(eye, vec3(-2, 2, 2), circEasingInOut(scene(t, 15.0, 1.)));
    eye = mix(eye, vec3(-2, 2, -2), circEasingInOut(scene(t, 20.0, 1.)));
    eye = mix(eye, vec3(2, 2, -2), circEasingInOut(scene(t, 25.0, 1.)));
    eye = mix(eye, vec3(2, 2, 2), circEasingInOut(scene(t, 30.0, 1.)));
    
    vec3 sum = vec3(0);
  	for(float i = 0. ; i < SAMPLE_NUM ; i++){
    	vec2 coordOffset = rand2n(gl_FragCoord.xy, i);
          
    	vec3 ray = calcRay(eye, target, up, fov,
        	               resolution.x, resolution.y,
            	           gl_FragCoord.xy + coordOffset);
        
    	sum += calcColor(t, eye, ray);
  	}
 	vec3 col = (sum/SAMPLE_NUM);
  
    
  	gl_FragColor = vec4(gammaCorrect(col), 1.);
}