Created
November 28, 2017 11:48
-
-
Save haotian-liu/846da8d05dff217bad7764f1b790aec1 to your computer and use it in GitHub Desktop.
Shader-based animation forked from https://www.shadertoy.com/view/XsBSRG
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
//#define CARS | |
#define I_MAX 70 | |
float rand(vec2 n) { | |
return fract(sin((n.x*1e2+n.y*1e4+1475.4526)*1e-4)*1e6); | |
} | |
float noise(vec2 p) | |
{ | |
p = floor(p*200.0); | |
return rand(p); | |
} | |
vec3 polygonXY(float z,vec2 vert1, vec2 vert2, vec3 camPos,vec3 rayDir){ | |
float t = -(camPos.z-z)/rayDir.z; | |
vec2 cross = camPos.xy + rayDir.xy*t; | |
if (cross.x>min(vert1.x,vert2.x) && | |
cross.x<max(vert1.x,vert2.x) && | |
cross.y>min(vert1.y,vert2.y) && | |
cross.y<max(vert1.y,vert2.y) && | |
dot(rayDir,vec3(cross,z)-camPos)>0.0){ | |
float dist = length(camPos-vec3(cross,z)); | |
return vec3(dist, cross.x-min(vert1.x,vert2.x),cross.y-min(vert1.y,vert2.y)); | |
} | |
return vec3(101.0,0.0,0.0); | |
} | |
vec3 polygonYZ(float x,vec2 vert1, vec2 vert2, vec3 camPos,vec3 rayDir){ | |
float t = -(camPos.x-x)/rayDir.x; | |
vec2 cross1 = camPos.yz + rayDir.yz*t; | |
if (cross1.x>min(vert1.x,vert2.x) && | |
cross1.x<max(vert1.x,vert2.x) && | |
cross1.y>min(vert1.y,vert2.y) && | |
cross1.y<max(vert1.y,vert2.y)&& | |
dot(rayDir,vec3(x,cross1)-camPos)>0.0){ | |
float dist = length(camPos-vec3(x,cross1)); | |
return vec3(dist, cross1.x-min(vert1.x,vert2.x),cross1.y-min(vert1.y,vert2.y)); | |
} | |
return vec3(101.0,0.0,0.0); | |
} | |
vec3 polygonXZ(float y,vec2 vert1, vec2 vert2, vec3 camPos,vec3 rayDir){ | |
float t = -(camPos.y-y)/rayDir.y; | |
vec2 cross1 = camPos.xz + rayDir.xz*t; | |
if (cross1.x>min(vert1.x,vert2.x) && | |
cross1.x<max(vert1.x,vert2.x) && | |
cross1.y>min(vert1.y,vert2.y) && | |
cross1.y<max(vert1.y,vert2.y)&& | |
dot(rayDir,vec3(cross1.x,y,cross1.y)-camPos)>0.0){ | |
float dist = length(camPos-vec3(cross1.x,y,cross1.y)); | |
return vec3(dist, cross1.x-min(vert1.x,vert2.x),cross1.y-min(vert1.y,vert2.y)); | |
} | |
return vec3(101.0,0.0,0.0); | |
} | |
vec3 textureWall(vec2 pos, vec2 maxPos, vec2 squarer,float s,float height,float dist,vec3 rayDir,vec3 norm){ | |
float randB = rand(squarer*2.0); | |
vec3 windowColor =(-0.4+randB*0.8)*vec3(0.3,0.3,0.0)+(-0.4+fract(randB*10.0)*0.8)*vec3(0.0,0.0,0.3)+(-0.4+fract(randB*10000.0)*0.8)*vec3(0.3,0.0,0.0); | |
float floorFactor = 1.0; | |
vec2 windowSize = vec2(0.65,0.35); | |
vec3 wallColor = s*(0.3+1.4*fract(randB*100.0))*vec3(0.1,0.1,0.1)+(-0.7+1.4*fract(randB*1000.0))*vec3(0.02,0.,0.); | |
wallColor*=1.3; | |
vec3 color = vec3(0.0); | |
vec3 conturColor = wallColor/1.5; | |
if (height<0.51){ | |
windowColor += vec3(0.3,0.3,0.0); | |
windowSize = vec2(0.4,0.4); | |
floorFactor = 0.0; | |
} | |
if (height<0.6){floorFactor = 0.0;} | |
if (height>0.75){ | |
windowColor += vec3(0.0,0.0,0.3); | |
} | |
windowColor*=1.5; | |
float wsize = 0.02; | |
wsize+=-0.007+0.014*fract(randB*75389.9365); | |
windowSize+= vec2(0.34*fract(randB*45696.9365),0.50*fract(randB*853993.5783)); | |
vec2 contur=vec2(0.0)+(fract(maxPos/2.0/wsize))*wsize; | |
if (contur.x<wsize){contur.x+=wsize;} | |
if (contur.y<wsize){contur.y+=wsize;} | |
vec2 winPos = (pos-contur)/wsize/2.0-floor((pos-contur)/wsize/2.0); | |
float numWin = floor((maxPos-contur)/wsize/2.0).x; | |
if ( (maxPos.x>0.5&&maxPos.x<0.6) && ( ((pos-contur).x>wsize*2.0*floor(numWin/2.0)) && ((pos-contur).x<wsize*2.0+wsize*2.0*floor(numWin/2.0)) )){ | |
return (0.9+0.2*noise(pos))*conturColor; | |
} | |
if ( (maxPos.x>0.6&&maxPos.x<0.7) &&( ( ((pos-contur).x>wsize*2.0*floor(numWin/3.0)) && ((pos-contur).x<wsize*2.0+wsize*2.0*floor(numWin/3.0)) )|| | |
( ((pos-contur).x>wsize*2.0*floor(numWin*2.0/3.0)) && ((pos-contur).x<wsize*2.0+wsize*2.0*floor(numWin*2.0/3.0)) )) ){ | |
return (0.9+0.2*noise(pos))*conturColor; | |
} | |
if ( (maxPos.x>0.7) &&( ( ((pos-contur).x>wsize*2.0*floor(numWin/4.0)) && ((pos-contur).x<wsize*2.0+wsize*2.0*floor(numWin/4.0)) )|| | |
( ((pos-contur).x>wsize*2.0*floor(numWin*2.0/4.0)) && ((pos-contur).x<wsize*2.0+wsize*2.0*floor(numWin*2.0/4.0)) )|| | |
( ((pos-contur).x>wsize*2.0*floor(numWin*3.0/4.0)) && ((pos-contur).x<wsize*2.0+wsize*2.0*floor(numWin*3.0/4.0)) )) ){ | |
return (0.9+0.2*noise(pos))*conturColor; | |
} | |
if ((maxPos.x-pos.x<contur.x)||(maxPos.y-pos.y<contur.y+2.0*wsize)||(pos.x<contur.x)||(pos.y<contur.y)){ | |
return (0.9+0.2*noise(pos))*conturColor; | |
} | |
if (maxPos.x<0.14) { | |
return (0.9+0.2*noise(pos))*wallColor; | |
} | |
vec2 window = floor((pos-contur)/wsize/2.0); | |
float random = rand(squarer*s*maxPos.y+window); | |
float randomZ = rand(squarer*s*maxPos.y+floor(vec2((pos-contur).y,(pos-contur).y)/wsize/2.0)); | |
float windows = floorFactor*sin(randomZ*5342.475379+(fract(975.568*randomZ)*0.15+0.05)*window.x); | |
float blH = 0.06*dist*600.0/iResolution.x/abs(dot(normalize(rayDir.xy),normalize(norm.xy))); | |
float blV = 0.06*dist*600.0/iResolution.x/sqrt(abs(1.0-pow(abs(rayDir.z),2.0))); | |
windowColor +=vec3(1.0,1.0,1.0); | |
windowColor *= smoothstep(0.5-windowSize.x/2.0-blH,0.5-windowSize.x/2.0+blH,winPos.x); | |
windowColor *= smoothstep(0.5+windowSize.x/2.0+blH,0.5+windowSize.x/2.0-blH,winPos.x); | |
windowColor *= smoothstep(0.5-windowSize.y/2.0-blV,0.5-windowSize.y/2.0+blV,winPos.y); | |
windowColor *= smoothstep(0.5+windowSize.y/2.0+blV,0.5+windowSize.y/2.0-blV,winPos.y); | |
if ((random <0.05*(3.5-2.5*floorFactor))||(windows>0.65)){ | |
if (winPos.y<0.5) {windowColor*=(1.0-0.4*fract(random*100.0));} | |
if ((winPos.y>0.5)&&(winPos.x<0.5)) {windowColor*=(1.0-0.4*fract(random*10.0));} | |
return (0.9+0.2*noise(pos))*wallColor+(0.9+0.2*noise(pos))*windowColor; | |
} | |
else{ | |
windowColor*=0.08*fract(10.0*random); | |
} | |
return (0.9+0.2*noise(pos))*wallColor+windowColor; | |
} | |
vec3 textureRoof(vec2 pos, vec2 maxPos,vec2 squarer){ | |
float wsize = 0.025; | |
float randB = rand(squarer*2.0); | |
vec3 wallColor = (0.3+1.4*fract(randB*100.0))*vec3(0.1,0.1,0.1)+(-0.7+1.4*fract(randB*1000.0))*vec3(0.02,0.,0.); | |
vec3 conturColor = wallColor*1.5/2.5; | |
vec2 contur = vec2(0.02); | |
if ((maxPos.x-pos.x<contur.x)||(maxPos.y-pos.y<contur.y)||(pos.x<contur.x)||(pos.y<contur.y)){ | |
return (0.9+0.2*noise(pos))*conturColor; | |
} | |
float step1 = 0.06+0.12*fract(randB*562526.2865); | |
pos -=step1; | |
maxPos -=step1*2.0; | |
if ((pos.x>0.0&&pos.y>0.0&&pos.x<maxPos.x&&pos.y<maxPos.y)&&((abs(maxPos.x-pos.x)<contur.x)||(abs(maxPos.y-pos.y)<contur.y)||(abs(pos.x)<contur.x)||(abs(pos.y)<contur.y))){ | |
return (0.9+0.2*noise(pos))*conturColor; | |
} | |
pos -=step1; | |
maxPos -=step1*2.0; | |
if ((pos.x>0.0&&pos.y>0.0&&pos.x<maxPos.x&&pos.y<maxPos.y)&&((abs(maxPos.x-pos.x)<contur.x)||(abs(maxPos.y-pos.y)<contur.y)||(abs(pos.x)<contur.x)||(abs(pos.y)<contur.y))){ | |
return (0.9+0.2*noise(pos))*conturColor; | |
} | |
pos -=step1; | |
maxPos -=step1*2.0; | |
if ((pos.x>0.0&&pos.y>0.0&&pos.x<maxPos.x&&pos.y<maxPos.y)&&((abs(maxPos.x-pos.x)<contur.x)||(abs(maxPos.y-pos.y)<contur.y)||(abs(pos.x)<contur.x)||(abs(pos.y)<contur.y))){ | |
return (0.9+0.2*noise(pos))*conturColor; | |
} | |
return (0.9+0.2*noise(pos))*wallColor; | |
} | |
vec3 cars(vec2 squarer, vec2 pos, float dist,float level){ | |
vec3 color = vec3(0.0); | |
float carInten = 3.5/sqrt(dist); | |
float carRadis = 0.01; | |
if (dist>2.0) {carRadis *= sqrt(dist/2.0);} | |
vec3 car1 = vec3(0.5,0.5,1.0); | |
vec3 car2 = vec3(1.0,0.1,0.1); | |
float carNumber = 0.5; | |
float random = noise((level+1.0)*squarer*1.24435824); | |
for (int j=0;j<10; j++){ | |
float i = 0.03+float(j)*0.094; | |
if(fract(random*5.0/i)>carNumber){color += car1*carInten*smoothstep(carRadis,0.0,length(pos - vec2(fract(i+iTime/4.0),0.025)));} | |
if(fract(random*10.0/i)>carNumber){color += car2*carInten*smoothstep(carRadis,0.0,length(pos - vec2(fract(i-iTime/4.0),0.975)));} | |
if(color.x>0.0) break; | |
} | |
for (int j=0;j<10; j++){ | |
float i= 0.03+float(j)*0.094; | |
if(fract(random*5.0/i)>carNumber){color += car2*carInten*smoothstep(carRadis,0.0,length(pos - vec2(0.025,fract(i+iTime/4.0))));} | |
if(fract(random*10.0/i)>carNumber){color += car1*carInten*smoothstep(carRadis,0.0,length(pos - vec2(0.975,fract(i-iTime/4.0))));} | |
if(color.x>0.0) break; | |
} | |
for (int j=0;j<10; j++){ | |
float i = 0.03+0.047+float(j)*0.094; | |
if(fract(random*100.0/i)>carNumber){color += car1*carInten*smoothstep(carRadis,0.0,length(pos - vec2(fract(i+iTime/4.0),0.045)));} | |
if(fract(random*1000.0/i)>carNumber){color += car2*carInten*smoothstep(carRadis,0.0,length(pos - vec2(fract(i-iTime/4.0),0.955)));} | |
if(color.x>0.0) break; | |
} | |
for (int j=0;j<10; j++){ | |
float i = 0.03+0.047+float(j)*0.094; | |
if(fract(random*100.0/i)>carNumber){color += car2*carInten*smoothstep(carRadis,0.0,length(pos - vec2(0.045,fract(i+iTime/4.0))));} | |
if(fract(random*1000.0/i)>carNumber){color += car1*carInten*smoothstep(carRadis,0.0,length(pos - vec2(0.955,fract(i-iTime/4.0))));} | |
if(color.x>0.0) break; | |
} | |
return color; | |
} | |
vec3 textureGround(vec2 squarer, vec2 pos,vec2 vert1,vec2 vert2,float dist){ | |
vec3 color = (0.9+0.2*noise(pos))*vec3(0.1,0.15,0.1); | |
float randB = rand(squarer*2.0); | |
vec3 wallColor = (0.3+1.4*fract(randB*100.0))*vec3(0.1,0.1,0.1)+(-0.7+1.4*fract(randB*1000.0))*vec3(0.02,0.,0.); | |
float fund = 0.03; | |
float bl = 0.01; | |
float f = smoothstep(vert1.x-fund-bl,vert1.x-fund,pos.x); | |
f *= smoothstep(vert1.y-fund-bl,vert1.y-fund,pos.y); | |
f *= smoothstep(vert2.y+fund+bl,vert2.y+fund,pos.y); | |
f *= smoothstep(vert2.x+fund+bl,vert2.x+fund,pos.x); | |
pos -= 0.0; | |
vec2 maxPos = vec2(1.,1.); | |
vec2 contur = vec2(0.06,0.06); | |
if ((pos.x>0.0&&pos.y>0.0&&pos.x<maxPos.x&&pos.y<maxPos.y)&&((abs(maxPos.x-pos.x)<contur.x)||(abs(maxPos.y-pos.y)<contur.y)||(abs(pos.x)<contur.x)||(abs(pos.y)<contur.y))){ | |
color = vec3(0.1,0.1,0.1)*(0.9+0.2*noise(pos)); | |
} | |
pos -= 0.06; | |
maxPos = vec2(.88,0.88); | |
contur = vec2(0.01,0.01); | |
if ((pos.x>0.0&&pos.y>0.0&&pos.x<maxPos.x&&pos.y<maxPos.y)&&((abs(maxPos.x-pos.x)<contur.x)||(abs(maxPos.y-pos.y)<contur.y)||(abs(pos.x)<contur.x)||(abs(pos.y)<contur.y))){ | |
color = vec3(0.,0.,0.); | |
} | |
color = mix(color,(0.9+0.2*noise(pos))*wallColor*1.5/2.5,f); | |
pos+=0.06; | |
#ifdef CARS | |
if (pos.x<0.07||pos.x>0.93||pos.y<0.07||pos.y>0.93){ | |
color+=cars(squarer,pos,dist,0.0); | |
} | |
#endif | |
return color; | |
} | |
void mainImage( out vec4 fragColor, in vec2 fragCoord ) { | |
vec2 pos = (fragCoord.xy*2.0 - iResolution.xy) / iResolution.y; | |
float t = -iTime; | |
float tt = -iTime-0.5; | |
vec3 camPos = vec3(5.0+12.0*sin(t*0.05),5.0+ 7.0*cos(t*0.05), 1.9); | |
vec3 camTarget = vec3(5.0+0.0,5.0+7.0*sin(t*0.05), 0.0); | |
if (fract(t/12.0)<0.25){ | |
camPos = vec3(5.*t,3.1*t,2.1); | |
camTarget = vec3(5.*tt,3.1*tt,1.7); | |
} | |
if (fract(t/12.0)>0.75){ | |
camPos = vec3(35.,3.1,1.); | |
camTarget = vec3(35.+sin(t/10.0),3.1+cos(t/10.0),0.7); | |
} | |
vec3 camDir = normalize(camTarget-camPos); | |
vec3 camUp = normalize(vec3(0.0, 0.0, -1.0)); | |
vec3 camSide = cross(camDir, camUp); | |
camUp = cross(camDir, camSide); | |
vec3 rayDir = normalize(camSide*pos.x + camUp*pos.y + camDir*1.6); | |
float angle = 0.03*pow(abs(acos(rayDir.x)),4.0); | |
//angle = min(0.0,angle); | |
vec3 color = vec3(0.0); | |
vec2 square = floor(camPos.xy); | |
square.x += 0.5-0.5*sign(rayDir.x); | |
square.y += 0.5-0.5*sign(rayDir.y); | |
float mind = 100.0; | |
int k = 0; | |
vec3 pol; | |
vec2 maxPos; | |
vec2 crossG; | |
float tSky = -(camPos.z-3.9)/rayDir.z; | |
vec2 crossSky = floor(camPos.xy + rayDir.xy*tSky); | |
for (int i=1; i<I_MAX; i++){ | |
vec2 squarer = square-vec2(0.5,0.5)+0.5*sign(rayDir.xy); | |
if (crossSky == squarer&&crossSky!=floor(camPos.xy)) | |
{ | |
color += vec3(vec2(0.5,0.15)*abs(angle)*exp(-rayDir.z*rayDir.z*30.0),0.2); | |
break; | |
} | |
float t; | |
float random = rand(squarer); | |
float height = 0.0; | |
float quartalR = rand(floor(squarer/10.0)); | |
if (floor(squarer/10.0) == vec2(0.0,0.0)) quartalR = 0.399; | |
if (quartalR<0.4) { | |
height = -0.15+0.4*random+smoothstep(12.0,7.0,length(fract(squarer/10.0)*10.0-vec2(5.0,5.0)))*0.8*random+0.9*smoothstep(10.0,0.0,length(fract(squarer/10.0)*10.0-vec2(5.0,5.0))); | |
height*=quartalR/0.4; | |
} | |
float maxJ=2.0; | |
float roof = 1.0; | |
if (height<0.3){ | |
height = 0.3*(0.7+1.8*fract(random*100.543264));maxJ = 2.0; | |
if (fract(height*1000.0)<0.04) height*=1.3; | |
} | |
if (height>0.5) {maxJ=3.0;} | |
if (height>0.85){maxJ = 4.0;} | |
if (fract(height*100.0)<0.15){height = pow(maxJ-1.0,0.3)*height; maxJ = 2.0; roof = 0.0;} | |
float maxheight = 1.5*pow((maxJ-1.0),0.3)*height+roof*0.07; | |
if (camPos.z+rayDir.z*(length(camPos.xy - square) +0.71 - sign(rayDir.z)*0.71)/length(rayDir.xy)<maxheight){ | |
vec2 vert1r; | |
vec2 vert2r; | |
float zz = 0.0; | |
float prevZZ = 0.0; | |
for(int nf=1;nf<8;nf++){ | |
float j = float(nf); | |
if(j>maxJ){break;} | |
prevZZ = zz; | |
zz = 1.5*pow(j,0.3)*height; | |
//prevZZ = zz-0.8; | |
float dia = 1.0/pow(j,0.3); | |
if(j==maxJ){ | |
if (roof == 0.0) {break;} | |
zz = 1.5*pow((j-1.0),0.3)*height+0.03+0.04*fract(random*1535.347); | |
dia = 1.0/pow((j-1.0),0.3)-0.2-0.2*fract(random*10000.0); | |
} | |
vec2 v1 = vec2(0.0);//vec2(random*10.0,random*1.0); | |
vec2 v2 = vec2(0.0);//vec2(random*1000.0,random*100.0); | |
float randomF = fract(random*10.0); | |
if (randomF<0.25){ v1 = vec2(fract(random*1000.0),fract(random*100.0));} | |
if (randomF>0.25&&randomF<0.5){ v1 = vec2(fract(random*100.0),0.0);v2 = vec2(0.0,fract(random*1000.0));} | |
if (randomF>0.5&&randomF<0.75){ v2 = vec2(fract(random*1000.0),fract(random*100.0));} | |
if (randomF>0.75){ v1 = vec2(0.0,fract(random*1000.0)); v2 = vec2(fract(random*100.0),0.0);} | |
if (rayDir.y<0.0){ | |
float y = v1.y; | |
v1.y = v2.y; | |
v2.y = y; | |
} | |
if (rayDir.x<0.0){ | |
float x = v1.x; | |
v1.x = v2.x; | |
v2.x = x; | |
} | |
vec2 vert1 = square+sign(rayDir.xy)*(0.5-0.37*(dia*1.0-1.0*v1)); | |
vec2 vert2 = square+sign(rayDir.xy)*(0.5+0.37*(dia*1.0-1.0*v2)); | |
if (j==1.0){ | |
vert1r = vec2(min(vert1.x, vert2.x),min(vert1.y,vert2.y)); | |
vert2r = vec2(max(vert1.x, vert2.x),max(vert1.y,vert2.y)); | |
} | |
vec3 pxy = polygonXY(zz,vert1,vert2,camPos,rayDir); | |
if (pxy.x<mind){mind = pxy.x; pol = pxy; k=1;maxPos = vec2(abs(vert1.x-vert2.x),abs(vert1.y-vert2.y));} | |
vec3 pyz = polygonYZ(vert1.x,vec2(vert1.y,prevZZ),vec2(vert2.y,zz),camPos,rayDir); | |
if (pyz.x<mind){mind = pyz.x; pol = pyz; k=2;maxPos = vec2(abs(vert1.y-vert2.y),zz-prevZZ);} | |
vec3 pxz = polygonXZ(vert1.y,vec2(vert1.x,prevZZ),vec2(vert2.x,zz),camPos,rayDir); | |
if (pxz.x<mind){mind = pxz.x; pol = pxz; k=3;maxPos = vec2(abs(vert1.x-vert2.x),zz-prevZZ);} | |
} | |
if ((mind<100.0)&&(k==1)){ | |
color += textureRoof(vec2(pol.y,pol.z),maxPos,squarer); | |
if (mind>3.0){color*=sqrt(3.0/mind);} | |
break; | |
} | |
if ((mind<100.0)&&(k==2)){ | |
color += textureWall(vec2(pol.y,pol.z),maxPos,squarer,1.2075624928,height,mind,rayDir,vec3(1.0,0.0,0.0)); | |
if (mind>3.0){color*=sqrt(3.0/mind);} | |
break; | |
} | |
if ((mind<100.0)&&(k==3)){ | |
color += textureWall(vec2(pol.y,pol.z),maxPos,squarer,0.8093856205,height,mind,rayDir,vec3(0.0,1.0,0.0)); | |
if (mind>3.0){color*=sqrt(3.0/mind);} | |
break; | |
} | |
t = -camPos.z/rayDir.z; | |
crossG = camPos.xy + rayDir.xy*t; | |
if (floor(crossG) == squarer) | |
{ | |
mind = length(vec3(crossG,0.0)-camPos); | |
color += textureGround(squarer,fract(crossG),fract(vert1r),fract(vert2r),mind); | |
if (mind>3.0){color*=sqrt(3.0/mind);} | |
break; | |
} | |
} | |
if ((square.x+sign(rayDir.x)-camPos.x)/rayDir.x<(square.y+sign(rayDir.y)-camPos.y)/rayDir.y) { | |
square.x += sign(rayDir.x)*1.0; | |
} else { | |
square.y += sign(rayDir.y)*1.0; | |
} | |
if(i==I_MAX-1&&rayDir.z>-0.1) {color += vec3(vec2(0.5,0.15)*abs(angle)*exp(-rayDir.z*rayDir.z*30.0),0.2);} | |
} | |
fragColor = vec4( color, 1.0);; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment