Created
March 21, 2017 06:48
-
-
Save cabbibo/31c536498f35116c42e66808ea5f0cca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Trying to understand the code from | |
// http://lgdv.cs.fau.de/get/2234 | |
const float t_min = .00001; | |
const float t_max = 35.; | |
const int MAX_ITERATIONS = 200; | |
const float infinite = 100000.; | |
const float PI = 3.14159; | |
const float MAX_TRACE_DISTANCE = 40.0; // max trace distance | |
const float INTERSECTION_PRECISION = 0.001; // precision of the intersection | |
const int NUM_OF_TRACE_STEPS = 1000; | |
const bool forceHit = false; | |
float pixelRadius; | |
float cycleTime; | |
vec4 grow = vec4( 1. ); | |
vec3 lightPos = vec3( 0. , 6. , 0.); | |
#define time iGlobalTime | |
vec3 hsv(float h, float s, float v){ | |
return mix( vec3( 1.0 ), clamp( ( abs( fract( | |
h + vec3( 3.0, 2.0, 1.0 ) / 3.0 ) * 6.0 - 3.0 ) - 1.0 ), 0.0, 1.0 ), s ) * v; | |
} | |
//---- | |
// Camera Stuffs | |
//---- | |
mat3 calcLookAtMatrix( in vec3 ro, in vec3 ta, in float roll ){ | |
vec3 ww = normalize( ta - ro ); | |
vec3 uu = normalize( cross(ww,vec3(sin(roll),cos(roll),0.0) ) ); | |
vec3 vv = normalize( cross(uu,ww)); | |
return mat3( uu, vv, ww ); | |
} | |
void doCamera( float radius , out vec3 camPos, out vec3 camTar, in float time, in vec2 mouse ){ | |
float an = 0.3 + 10.0*mouse.x; | |
camPos = vec3(radius*sin(an),2.,radius*cos(an)); | |
camTar = vec3(0.0,1.0,0.0); | |
} | |
float hash( float n ) { return fract(sin(n)*753.5453123); } | |
float noise( in vec3 x ){ | |
vec3 p = floor(x); | |
vec3 f = fract(x); | |
f = f*f*(3.0-2.0*f); | |
float n = p.x + p.y*157.0 + 113.0*p.z; | |
return mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), | |
mix( hash(n+157.0), hash(n+158.0),f.x),f.y), | |
mix(mix( hash(n+113.0), hash(n+114.0),f.x), | |
mix( hash(n+270.0), hash(n+271.0),f.x),f.y),f.z); | |
} | |
float fNoise( vec3 p ){ | |
float n; | |
n += noise( p * 20. ) * .5; | |
n += noise( p * 200. ) * .1; | |
n += noise( p * 60. ) * .3; | |
n += noise( p * 5. ); | |
n /= 2.; | |
return n; | |
} | |
// ROTATION FUNCTIONS TAKEN FROM | |
//https://www.shadertoy.com/view/XsSSzG | |
vec3 xrotate(vec3 pos , float t) { | |
return mat3(1.0, 0.0, 0.0, | |
0.0, cos(t), -sin(t), | |
0.0, sin(t), cos(t)) * pos; | |
} | |
vec3 yrotate(vec3 pos , float t) { | |
return mat3(cos(t), 0.0, -sin(t), | |
0.0, 1.0, 0.0, | |
sin(t), 0.0, cos(t)) * pos; | |
} | |
vec3 zrotate(vec3 pos , float t) { | |
return mat3(cos(t), -sin(t), 0.0, | |
sin(t), cos(t), 0.0, | |
0.0, 0.0, 1.0) * pos; | |
} | |
float sdPlane( vec3 p, vec4 n ){ | |
// n must be normalized | |
return dot(p,n.xyz) + n.w; | |
} | |
float sdCone( vec3 p, vec2 c ){ | |
// c must be normalized | |
float q = length(p.xy); | |
return dot(c,vec2(q,p.z)); | |
} | |
float sdCappedCone( in vec3 p, in vec3 c ){ | |
vec2 q = vec2( length(p.xz), p.y ); | |
vec2 v = vec2( c.z*c.y/c.x, -c.z ); | |
vec2 w = v - q; | |
vec2 vv = vec2( dot(v,v), v.x*v.x ); | |
vec2 qv = vec2( dot(v,w), v.x*w.x ); | |
vec2 d = max(qv,0.0)*qv/vv; | |
return sqrt( dot(w,w) - max(d.x,d.y) )* sign(max(q.y*v.x-q.x*v.y,w.y)); | |
} | |
float sdHexPrism( vec3 p, vec2 h ){ | |
vec3 q = abs(p); | |
return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x); | |
} | |
float sdSphere( vec3 p, float s ){ | |
return length(p)-s; | |
} | |
float sdCappedCylinder( vec3 p, vec2 h ){ | |
vec2 d = abs(vec2(length(p.xz),p.y)) - h; | |
return min(max(d.x,d.y),0.0) + length(max(d,0.0)); | |
} | |
float opS( float d1, float d2 ){ | |
return max(-d1,d2); | |
} | |
vec2 opS( vec2 d1, vec2 d2 ){ | |
return -d1.x > d2.x ? vec2(-d1.x , d1.y) : d2 ; | |
} | |
float opU( float d1, float d2 ){ | |
return d1 < d2 ? d1 : d2 ; | |
} | |
vec2 opU( vec2 d1, vec2 d2 ){ | |
return d1.x < d2.x ? d1 : d2 ; | |
} | |
vec2 smoothU( vec2 d1, vec2 d2, float k){ | |
float a = d1.x; | |
float b = d2.x; | |
float h = clamp(0.5+0.5*(b-a)/k, 0.0, 1.0); | |
return vec2( mix(b, a, h) - k*h*(1.0-h), mix(d2.y, d1.y, pow(h, 2.0))); | |
} | |
float opRepSphere( vec3 p, vec3 c , float r){ | |
vec3 q = mod(p,c)-0.5*c; | |
return sdSphere( q , r ); | |
} | |
float cBase( vec3 pos ){ | |
float c = sdCone( pos , normalize(vec2( 1. , 1. ))); | |
float s = sdPlane( pos , vec4( 0 , 0. , 1. , 1.4 ) ); | |
return opS( s , c ); | |
} | |
// give a base ID to pass out of | |
// first build the fields | |
// than connnect to ID numbers, using by passing through baseID | |
// write out baseID for later use. | |
vec2 body( vec3 pos , out float baseID ){ | |
float c = sdSphere( pos* vec3( 1. , .55 , 1. ) , 1. ); | |
float p = sdPlane( pos * vec3( 1. , .5 , 1. ), vec4( -1. , 0. , 0. , 0. ) ); | |
//baseID += 1.; | |
vec2 torso = opS( vec2( p , baseID + 1. ) , vec2( c , baseID + 1. ) ); | |
//float cb = sdCappedCone( pos - vec3( 1. ) , normalize(vec3( 1. , 1. , 1. ))); | |
vec3 q = xrotate( pos - vec3( -.2 , -.8 , 0. ) , -PI / 2. ); | |
float cb = cBase( q ); | |
vec2 cloakBase = vec2( cb , baseID + 0. ); | |
// head | |
float n = 0.;// abs( noise( pos * 10.1 + time * .5 )); | |
vec2 h = vec2( sdSphere( pos - vec3( 0.2 , 1.2 , 0. ) , .45 - n * .05 ) , baseID + 7. ); | |
vec2 bod = smoothU( cloakBase, torso ,.9); | |
// float n2 = abs( noise( pos * 3. + time * .5 )); | |
//bod.x -= n2 * .06; | |
vec2 fullBod = smoothU( bod , h , .3 ); | |
float b1 = sdSphere( pos - vec3( 0.3 , 1.2 , 0.1 ) , .32); | |
float b2 = sdSphere( pos - vec3( 0.3 , 1.2 , -0.1 ) , .32); | |
float balls= opU( b1, b2 ); | |
vec2 eyes = vec2( balls , baseID + 8.); | |
return opS( eyes ,smoothU( bod , h , .3 )); | |
//return vec2( c , 1. ); | |
} | |
vec3 mapP( vec3 p ) | |
{ | |
p.xyz += .400*sin( 3.*p.yzx )*grow.x; | |
p.xyz += 0.300*sin( 6.0*p.yzx )*grow.y; | |
p.xyz += 0.250*sin( 8.0*p.yzx )*grow.z; | |
p.xyz += 0.100*sin( 20.0*p.yzx )*grow.w; | |
return p; | |
} | |
//-------------------------------- | |
// Modelling | |
//-------------------------------- | |
vec2 map( vec3 pos , float io){ | |
float id = 0.; | |
vec2 res = vec2( 100000. , -1.); | |
vec3 p2 = pos;// - vec3( -4. , 0., 0.); | |
//pos.x = mod( pos.x , 1.5 ); | |
float degree = atan( p2.x , p2.z ); | |
float ogD = degree; | |
///degree += iGlobalTime;// * (1. + lor * .2); | |
float l = length( p2.xz ); | |
degree = mod( degree - 3.14159 / 8. , 3.14159 / 4. ); | |
p2.x = l * sin( degree ); | |
p2.z = l * cos( degree ); | |
//bodys | |
res = body( yrotate( p2 - vec3(3. , 0., 6.) ,-PI/2.) , id ); | |
float n = noise( pos + vec3( 0. , iGlobalTime , 0.) ) + noise( pos * 2. + vec3( 0. , iGlobalTime * 1.4 , 0.) ) ; | |
// Shrine | |
res = smoothU( res , vec2( sdPlane( pos , vec4( 0., 1. , 0. , 2.)) , id + 3. ) , 1. ); | |
res = smoothU( res , vec2( -sdSphere( pos - vec3( 0. , -16. , 0.) , 23. ) , id + 4.) ,1.); | |
//light | |
res = smoothU( res , vec2( (sdSphere( pos - lightPos , 3. ) + n * .8) , id+5.) , 2.5); | |
// res = smoothU( res , vec2( (sdSphere( pos - lightPos - vec3( 0. , 1.5 , 0.) , 1. )) , id+5.) , .0); | |
// Pedestal | |
vec3 q = xrotate( pos - vec3( 0 , -1.2, 0.) , -PI / 2. ); | |
res = smoothU( res , vec2( sdHexPrism(q , vec2( .5 , 1. ) ) , id + 5.) ,.6); | |
//JEWEL | |
q = mapP( pos + vec3( 0. , -1. , 0.) ); | |
//res = opU( res , vec2( (length(q)-(.4 + .6 * -cycleTime) ) * .1, id + 7.) ); | |
res = opU( res , vec2( (length(q)-.4) * .1, id + 7.) ); | |
vec2 eyes = vec2( length(pos + vec3( 0. , -1. , 0.))-(.3 + .15 * -cycleTime) , id + 8. ); | |
eyes.x += noise( pos * 20.) * .04; | |
res = opS( eyes ,res); | |
eyes = vec2( length(pos + vec3( 0. , -1. , 0.))-(.2 + .1 * -cycleTime) , id + 6. ); | |
eyes.x += noise( pos * 20.) * .04; | |
res = opU( eyes ,res); | |
//res = opS(vec2(sdSphere( pos - vec3( 0. , -1. , 0.) , 1.3 ), id + 7. ), res ); | |
// Inside trace function | |
if( io < 0. ){ | |
res = vec2( -(sdSphere( pos - lightPos , 3. ) - n * .8) * .1 , id+5.); | |
} | |
return res; | |
} | |
vec2 calcIntersection( in vec3 ro, in vec3 rd , float io ){ | |
float h = INTERSECTION_PRECISION*2.0; | |
float t = 0.0; | |
float res = -1.0; | |
float id = -1.; | |
for( int i=0; i< NUM_OF_TRACE_STEPS ; i++ ){ | |
if( h < INTERSECTION_PRECISION || t > MAX_TRACE_DISTANCE ) break; | |
vec2 m = map( ro+rd*t , io ); | |
h = m.x; | |
t += h; | |
id = m.y; | |
} | |
if( t < MAX_TRACE_DISTANCE ) res = t; | |
if( t > MAX_TRACE_DISTANCE ) id =-1.0; | |
return vec2( res , id ); | |
} | |
//From | |
//http://lgdv.cs.fau.de/get/2234 | |
vec2 calcIntersection( vec3 ro , vec3 rd , float io , float TAKEMEEOUT){ | |
// o, d : ray origin, direction (normalized) | |
// t_min, t_max: minimum, maximum | |
// pixelRadius: radius of a pixel | |
// forceHit: boolean enforcing to | |
// candidate_t value as result | |
float omega = 1.2; | |
float t = t_min; | |
float candidate_error = infinite; | |
float candidate_t = t_min; | |
float previousRadius = 0.; | |
float stepLength = 0.; | |
float id = -10.; | |
// are we inside or outside the object? | |
// if inside reverse the field! | |
float functionSign = map(ro, io).x < 0. ? -1. : 1.; | |
// functionSign = 1.; | |
for (int i = 0; i < MAX_ITERATIONS; i++ ) { | |
vec2 mapVal = map(rd*t + ro,io); | |
id = mapVal.y; | |
float signedRadius = functionSign * mapVal.x; | |
float radius = abs(signedRadius); | |
bool sorFail = omega > 1. && (radius + previousRadius) < stepLength; | |
if (sorFail) { | |
stepLength -= omega * stepLength; | |
omega = 1.; | |
} else { | |
stepLength = signedRadius * omega; | |
} | |
previousRadius = radius; | |
float error = radius / t; | |
if (!sorFail && error < candidate_error) { | |
candidate_t = t; | |
candidate_error = error; | |
} | |
if (!sorFail && error < pixelRadius || t > t_max) break; | |
t += stepLength; | |
} | |
if ((t > t_max || abs(candidate_error) > pixelRadius) && !forceHit){ | |
// return vec2( infinite , -1. ); | |
} | |
return vec2( candidate_t , id ); | |
} | |
// Calculates the normal by taking a very small distance, | |
// remapping the function, and getting normal for that | |
vec3 calcNormal( in vec3 pos , float io ){ | |
vec3 eps = vec3( 0.001, 0.0, 0.0 ); | |
vec3 nor = vec3( | |
map(pos+eps.xyy,io).x - map(pos-eps.xyy,io).x, | |
map(pos+eps.yxy,io).x - map(pos-eps.yxy,io).x, | |
map(pos+eps.yyx,io).x - map(pos-eps.yyx,io).x ); | |
return normalize(nor); | |
} | |
vec3 doMonkCol( vec3 rd , vec3 p , vec3 n , float match, vec2 res){ | |
vec3 color; | |
float fN = (noise( p * 20. ) * .6 + noise( p * 2. ) * .3 + noise( p * .5) + noise( p * .1) + noise( p * 5. )); | |
vec3 nNorm = n +.3 * normalize(vec3( noise( p * 20. ) , noise( p * 25. ), noise( p * 19. ))); | |
vec3 refl = reflect( rd , nNorm ); | |
vec3 cubeCol = texture( iChannel2 ,refl ).xyz; | |
vec3 buildingCol = cubeCol * vec3( 1. , .6 , .4 ) * 2.;//vec3( match ) * fN * fN *fN * .1 * ; | |
color = mix(cubeCol * vec3( 0.6 , .6 , 1. ) * 2.,buildingCol, p.y * 2. ); | |
float eyeM = dot( rd , n ); | |
vec3 lightDir = p - vec3( 0.,1. ,0.); | |
vec3 refl2 = reflect( normalize( lightDir ) , normalize(nNorm) ); | |
float rMatch = dot( refl2, rd ); | |
color += 2. * vec3( .5 , .2 , .1 ) * max( 0. , pow(rMatch,15.)); | |
color += pow( rMatch , 40. ) * vec3( 1. , .1 , .2 ); | |
vec4 tCol = texture( iChannel0 , vec2( -rMatch,0. ) ); | |
color *= (tCol.x+.2); | |
//color += (1.-tCol.x* 2.) * vec3( .3 , .5 , 1. ); | |
float v = pow((1.+eyeM),5.); | |
color += vec3(1. , .2 , 0.) * v; | |
if( res.y == 2. ){ | |
color = vec3( 1. , 0., 0.); | |
}else if( res.y == 3. ){ | |
//color = n * .5 + .5; | |
} | |
return color;// * (n * .5 + .5); | |
} | |
vec3 doSecondColor(vec2 res, vec3 rd , vec3 p , vec3 n ){ | |
vec3 color; | |
vec3 lightDir = normalize(p - lightPos); | |
float match = dot( -lightDir , n ); | |
// MONKS | |
if( res.y < 2.4 ){ | |
color = doMonkCol( rd, p , n , match, res ); | |
} | |
//Building | |
if( res.y >= 2.4 && res.y < 6. ){ | |
color = vec3(match); | |
float fN = (noise( p * 20. ) * .6 + noise( p * 2. ) * .3 + noise( p * .5) + noise( p * .1) + noise( p * 5. )); | |
vec3 refl = reflect( rd , n ); | |
vec3 cubeCol = texture( iChannel2 ,refl ).xyz; | |
vec3 buildingCol = cubeCol * vec3( 0.2 , .4 , 1. ) * 2.; | |
buildingCol = match * match * fN * fN * vec3( 1. , .4 , .2 );//vec3( match ) * fN * fN *fN * .1 * ; | |
color = buildingCol; | |
} | |
return color; | |
} | |
vec3 doLightCol( vec3 rd , vec3 p , vec3 n ){ | |
vec3 refr = refract( rd , n , .9 ); | |
vec2 res = calcIntersection( p + refr * .1 , refr , -1.); | |
if( res.y > -.5 ){ | |
vec3 p2 = p + refr * ( res.x + .1); | |
vec3 n2 = calcNormal( p2 , -1. ); | |
if( res.y < 5.){ | |
return vec3( 1. ); | |
} | |
vec3 refr2 = refract( refr , n2 , .9 ); | |
vec2 res2 = calcIntersection( p2 + refr2 * .1 , refr2, 1.); | |
if( res2.y >-.5){ | |
vec3 p3 = p2 + refr2 * ( res2.x + .1 ); | |
vec3 n3 = calcNormal( p3 , 1. ); | |
return doSecondColor( res2 , refr2,p3,n3); | |
}else{ | |
return vec3( 1. , 0. , 0.); | |
} | |
}else{ | |
return vec3( 1. ,0., 0.); | |
} | |
} | |
vec3 doColor(vec2 res, vec3 rd , vec3 p , vec3 n , float skip){ | |
vec3 color; | |
vec3 lightDir = normalize(p - lightPos); | |
float match = dot( -lightDir , n ); | |
// MONKS | |
if( res.y < 2.4 ){ | |
color = doMonkCol( rd, p , n , match, res ); | |
} | |
//Building | |
if( res.y >= 2.4 && res.y < 6. ){ | |
color = vec3(match); | |
float fN = noise( p * 2. ) * .4 + noise( p * .5) + noise( p * .1) ; | |
// vec3 buildingCol = vec3(1. - fN * fN * .03 , .5 , .4) * vec3( match ) * fN * fN *fN * .1; | |
n = normalize( n + .3 * vec3( noise( p * 2. + iGlobalTime) , noise( p * 2. + 100. + iGlobalTime) ,noise( p * 2. + 400.+ iGlobalTime ))); | |
vec3 refl = reflect( rd , n ); | |
vec3 cubeCol = texture( iChannel2 ,refl ).xyz; | |
vec3 buildingCol = cubeCol * vec3( 0.2 , .4 , 1. ) * 2.;//vec3( match ) * fN * fN *fN * .1 * ; | |
if( skip == 0. ){ | |
vec3 lightCol = doLightCol( rd, p , n ); | |
float mixVal = clamp( (res.y - 4.4) * 5. , 0. , 1.); | |
if( p.y < 1. ){ mixVal = 0.; } | |
color = mix( buildingCol , lightCol , mixVal ); | |
}else{ | |
color = buildingCol; | |
} | |
vec3 monkCol = doMonkCol( rd, p , n , match, res ); | |
color = mix( monkCol, color , clamp((res.y - 2.4) *.6 , 0., 1.) ); | |
} | |
//Pedestal | |
if( res.y >= 6. && res.y < 7. ){ | |
float fN = noise( p * 2. ) * .4 + noise( p * .5) + noise( p * .1) ; | |
color = vec3(1. - fN * fN * .03 , .5 , .4) * fN * fN *fN * .1; | |
//n = normalize( n + .3 * vec3( noise( p * 20. + iGlobalTime) , noise( p * 20. + 100. + iGlobalTime) ,noise( p * 20. + 400.+ iGlobalTime ))); | |
vec3 refl = reflect( rd , n ); | |
vec3 cubeCol = texture( iChannel2 ,refl ).xyz; | |
color = (cubeCol * dot( -n , rd )) + texture( iChannel2 ,refract(rd, n,.8)).xyz; | |
color *= vec3( 1. , .8 , .3 ); | |
} | |
if( res.y >= 7. && res.y < 8. ){ | |
//float fN = (noise( p * 20. ) * .6 + noise( p * 2. ) * .3 + noise( p * .5) + noise( p * .1) + noise( p * 5. )); | |
//vec3 buildingCol = vec3(1. - fN * fN * .03 , .5 , .4) * vec3( match ) * fN * fN *fN * .1; | |
vec3 nNorm = n;// n +.3 * normalize(vec3( hash( p.x * 100. ) , hash(p.y * 20. ), hash( p.z * 100.))); | |
vec3 refl = reflect( lightDir , normalize(nNorm) ); | |
float m = dot( refl , -rd ); | |
vec3 refr = refract(rd , n,.4 ); | |
vec3 cubeMap = texture( iChannel2 , refl ).xyz; | |
float refrMatch = dot( lightDir , refr ); | |
vec3 aCol = texture( iChannel0 , vec2( abs( match )* .2, 0. )).xyz; | |
// | |
//pow( m , 21. ) * | |
color =cubeMap * hsv( aCol.x * .2 , 1. , 1.);// + max( pow(m , 11. ) ,0.) * vec3( 1. , .5 , 0.) + match * vec3( .6 , .3 , .2 ) ; | |
} | |
if( res.y >= 8. ){ | |
vec3 refl = reflect( lightDir , normalize(n) ); | |
vec3 cubeMap = texture( iChannel2 , refl ).xyz; | |
color = cubeMap * vec3( 1.4 , .2 , 1. ) * 2.; | |
} | |
return color; | |
} | |
void mainImage( out vec4 fragColor, in vec2 fragCoord ){ | |
vec2 p = (-iResolution.xy + 2.0*fragCoord.xy)/iResolution.y; | |
vec2 m = iMouse.xy/iResolution.xy; | |
vec3 ro = vec3( 0., 0., 10.); | |
vec3 ta = vec3( 0. , 0. , 0. ); | |
cycleTime = sin( iGlobalTime * .6 ); | |
grow.x = .1 * (1. - cycleTime); | |
grow.y = .6 * (1. - cycleTime); | |
grow.z = .4 * (1. - cycleTime); | |
grow.w = .6 * (1. - cycleTime); | |
vec2 mPos = vec2( iGlobalTime * .03 , 0.); | |
doCamera( ( cycleTime + 1.3) * 6. , ro , ta , time , mPos ); | |
// camera matrix | |
mat3 camMat = calcLookAtMatrix( ro, ta, 0.0 ); // 0.0 is the camera roll | |
// create view ray | |
vec3 rd = normalize( camMat * vec3(p.xy,2.0) ); // 2.0 is the lens length | |
float pixel = .5 / iResolution.y; | |
vec3 rdu = normalize( camMat * vec3(p.xy + vec2(pixel, 0.) ,2.0) ); | |
vec3 rdd = normalize( camMat * vec3(p.xy - vec2(pixel, 0.),2.0) ); | |
vec3 pu = ro + rdu; | |
vec3 pd = ro + rdd; | |
// Can probably alter this for a speed up too | |
pixelRadius = length( pu - pd ) / 1.; | |
vec2 res = calcIntersection( ro , rd , 1.); | |
vec3 color = vec3( 1. ); | |
if( res.y > -.5 ){ | |
vec3 pos = ro + rd * res.x; | |
vec3 n = calcNormal( pos , 1.); | |
color = doColor( res , rd , pos , n , 0. ); | |
float moreCenter = clamp( 1.0 - (length(pos - vec3( 0. , 1. , 0.)) * (.5 + .5 * -cycleTime)) * .2 , 0. , 1.); | |
color *= moreCenter; | |
} | |
fragColor = vec4(color,1.0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment