scene.org File Archive

File download

<root>­/­parties­/­2016­/­tokyodemofest16­/­glsl_graphics_compo/carbon.txt

File size:
5 953 bytes (5.81K)
File date:
2016-02-24 05:45:01
Download count:
all-time: 629

Preview

#ifdef GL_ES
precision mediump float;
#endif

// uniforms
uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;

// debug for camera
uniform bool debugCamera;
uniform vec3 cameraPos;
uniform vec3 cameraDir;

// consts
const float EPS = 0.01;
const float OFFSET = EPS * 100.0;
const float PI = 3.14159;


// globals
const vec3 lightDir = vec3( -0.48666426339228763, 0.8111071056538127, -0.3244428422615251 );
vec3 cPos, cDir;
vec3 sPos;
float sSize;
vec3 illuminationColor;
float tempo;

struct Intersect {
	bool isHit;

	vec3 position;
	float distance;
	vec3 normal;

	int material;
	vec3 color;
};

const int CIRCUIT_MATERIAL = 0;
const int MIRROR_MATERIAL = 1;


// distance functions
vec3 onRep( vec3 p, float interval ) {

	return mod( p, interval ) - 0.5 * interval;

}

float MBoxDist( vec3 p ) {

  const float scale = 2.7;
  const int n = 12;
  vec4 q0 = vec4 (p, 1.);
  vec4 q = q0;

  for ( int i = 0; i < n; i++ ) {

    q.xyz = clamp( q.xyz, -1.0, 1.0 ) * 2.0 - q.xyz;
    q = q * scale / clamp( dot( q.xyz, q.xyz ), 0.5, 1.0 ) + q0;

  }

  return length( q.xyz ) / abs( q.w );

}

float sphereDist( vec3 p, vec3 c, float r ) {

	return length( p - c ) - r;

}

float sceneDist( vec3 p ) {

	return min(
		sphereDist( p, sPos, sSize ),
		MBoxDist( onRep( p, 7.0 ) )
	);

}


// color functions
vec3 hsv2rgb( vec3 c ) {

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

}

vec2 circuitPattern( vec2 p ) {

	p = fract(p);
	float r = 0.123;
	float v = 0.0, g = 0.0;
	r = fract(r * 9184.928);
	float cp, d;
	
	d = p.x;
	g += pow(clamp(1.0 - abs(d), 0.0, 1.0), 1000.0);
	d = p.y;
	g += pow(clamp(1.0 - abs(d), 0.0, 1.0), 1000.0);
	d = p.x - 1.0;
	g += pow(clamp(3.0 - abs(d), 0.0, 1.0), 1000.0);
	d = p.y - 1.0;
	g += pow(clamp(1.0 - abs(d), 0.0, 1.0), 10000.0);
	
	const int iter = 12;
	for(int i = 0; i < iter; i ++)
	{
		cp = 0.5 + (r - 0.5) * 0.9;
		d = p.x - cp;
		g += pow(clamp(1.0 - abs(d), 0.0, 1.0), 200.0);
		if(d > 0.0) {
			r = fract(r * 4829.013);
			p.x = (p.x - cp) / (1.0 - cp);
			v += 1.0;
		}
		else {
			r = fract(r * 1239.528);
			p.x = p.x / cp;
		}
		p = p.yx;
	}
	v /= float(iter);
	return vec2(g, v);

}


Intersect minIntersect( Intersect a, Intersect b ) {

	if ( a.distance < b.distance ) {
		return a;
	} else {
		return b;
	}

}

Intersect sceneIntersect( vec3 p ) {

	Intersect a, b;
	a.distance = sphereDist( p, sPos, sSize );
	a.material = MIRROR_MATERIAL;

	b.distance = MBoxDist( onRep( p, 7.0 ) );
	b.material = CIRCUIT_MATERIAL;

	return minIntersect( a, b );
}

vec3 getNormal( vec3 p ) {

	return normalize(vec3(
		sceneDist(p + vec3( EPS, 0.0, 0.0 ) ) - sceneDist(p + vec3( -EPS, 0.0, 0.0 ) ),
		sceneDist(p + vec3( 0.0, EPS, 0.0 ) ) - sceneDist(p + vec3( 0.0, -EPS, 0.0 ) ),
		sceneDist(p + vec3( 0.0, 0.0, EPS ) ) - sceneDist(p + vec3( 0.0, 0.0, -EPS ) )
	));

}

float getShadow( vec3 ro, vec3 rd ) {

	float h = 0.0;
	float c = 0.0;
	float r = 1.0;
	float shadowCoef = 0.5;

	for ( float t = 0.0; t < 50.0; t++ ) {

		h = sceneDist( ro + rd * c );

		if ( h < EPS ) return shadowCoef;

		r = min( r, h * 16.0 / c );
		c += h;

	}

	return 1.0 - shadowCoef + r * shadowCoef;

}

Intersect getRayColor( vec3 origin, vec3 ray ) {

	// marching loop
	float dist;
	float depth = 0.0;
	vec3 p = origin;
	int count = 0;
	Intersect nearest;

	for ( int i = 0; i < 64; i++ ){

		dist = sceneDist( p );
		depth += dist;
		p = origin + depth * ray;

		count = i;
		if ( abs(dist) < EPS ) break;

	}

	if ( abs(dist) < EPS ) {

		nearest = sceneIntersect( p );
		nearest.position = p;
		nearest.normal = getNormal(p);
		float diffuse = clamp( dot( lightDir, nearest.normal ), 0.1, 1.0 );
		float specular = pow( clamp( dot( reflect( lightDir, nearest.normal ), ray ), 0.0, 1.0 ), 10.0 );
		//float shadow = getShadow( p + nearest.normal * OFFSET, lightDir );

		if ( nearest.material == CIRCUIT_MATERIAL ) {

			vec2 uv = p.yz;
			vec2 dg = circuitPattern(uv);

			float glow = max( sin( length( p ) - 1.8 * time ) * 2.5, 0.0 );
			if( dg.x < 1.1 ) glow = 0.0;

			nearest.color = vec3( 0.2, 0.2, 0.2 ) + illuminationColor * glow * diffuse + specular /* * max( 0.5, shadow )*/;

		} else if ( nearest.material == MIRROR_MATERIAL ) {

			nearest.color = ( 0.5 - 0.5 * cos( time * 0.2 ) * illuminationColor * diffuse + specular )/* * max( 0.5, shadow )*/;

		}

		nearest.isHit = true;

	} else {

		nearest.color = vec3(0.1);
		nearest.isHit = false;

	}

	nearest.color += clamp( sin( time * 0.2 - 0.5 * PI ) * 0.2 * depth - 0.005 * float(count), -1.0, 1.0 );
	return nearest;

}

void main(void) {

	// fragment position
	vec2 p = ( gl_FragCoord.xy * 2.0 - resolution ) / min( resolution.x, resolution.y );

	// camera and ray
	if ( debugCamera ) {
		cPos  = cameraPos;
		cDir  = cameraDir;
	} else {
		cPos  = vec3( -0.8185093402862549, 4.509979248046875, time );
		cDir  = normalize( vec3( sin( time * 0.5 ), sin( time * 0.1 ), cos( time * 0.6 ) + 0.5 ) );
	}
	vec3 cSide = normalize( cross( cDir, vec3( 1.0, 1.0 ,0.0 ) ) );
	vec3 cUp   = normalize( cross( cSide, cDir ) );
	float targetDepth = 1.3;
	vec3 ray = normalize( cSide * p.x + cUp * p.y + cDir * targetDepth );

	// music's tempo
	tempo = sin( 4.0 * PI * time );

	// sphere pos
	float d = 0.2 + 0.1 * cos( time * 0.5 );
	sPos = cPos + vec3( 0.0, 0.0, d );
	sSize = 0.03 + 0.005 * tempo;

	// Illumination Color
	illuminationColor = hsv2rgb( vec3( time * 0.02 + 0.6, 1.0, 1.0 ) );

	vec3 color = vec3( 0.0 );
	float alpha = 1.0;
	Intersect nearest;

	for ( int i = 0; i < 3; i++ ) {

		nearest = getRayColor( cPos, ray );

		color += alpha * nearest.color;
		alpha *= 0.99;
		ray = normalize( reflect( ray, nearest.normal ) );
		cPos = nearest.position + nearest.normal * OFFSET;

		if ( !nearest.isHit || nearest.material == CIRCUIT_MATERIAL ) break;

	}

	color += 0.2 * tempo;

	gl_FragColor = vec4(color, 1.0);

}