Skip to content

Instantly share code, notes, and snippets.

@anissen
Created November 18, 2013 20:56
Show Gist options
  • Save anissen/7535140 to your computer and use it in GitHub Desktop.
Save anissen/7535140 to your computer and use it in GitHub Desktop.
Temp. fork of Fractal Cartoon on ShaderToy
// "Fractal Cartoon" - former "DE edge detection" by Kali
// Cartoon-like effect using eiffies's edge detection found here:
// https://www.shadertoy.com/view/4ss3WB
// I used my own method previously but was too complicated and not compiling everywhere.
// Thanks to the suggestion by WouterVanNifterick.
// There are no lights and no AO, only color by normals and dark edges.
//#define WAVES
#define RAY_STEPS 150
#define BRIGHTNESS 1.2
#define GAMMA 1.4
#define SATURATION .65
#define detail .001
#define t iGlobalTime*.1
const vec3 origin = vec3(-1.0,0.7,0.0);
float det = 0.0;
// 2D rotation function
mat2 rot(float a) {
return mat2(cos(a),sin(a),-sin(a),cos(a));
}
// "Amazing Surface" fractal
vec4 formula(vec4 p) {
p.xz = abs(p.xz + 1.0) - abs(p.xz - 1.0) - p.xz;
p.y -= 0.35;
p.xy *= rot(radians(45.0+sin(iGlobalTime)*10.0));
p = p * 2.0 / clamp(dot(p.xyz, p.xyz), 0.3, 0.9);
return p;
}
// Distance function
float de(vec3 pos) {
#ifdef WAVES
pos.y+=sin(pos.z-t*6.)*.15; //waves!
#endif
float hid=0.;
vec3 tpos=pos;
tpos.z=abs(3.-mod(tpos.z,6.));
vec4 p=vec4(tpos,1.);
for (int i=0; i<4; i++) {p=formula(p);}
float fr=(length(max(vec2(0.),p.yz-1.5))-1.)/p.w;
float ro=max(abs(pos.x+1.)-.3,pos.y-.35);
ro=max(ro,-max(abs(pos.x+1.)-.1,pos.y-.5));
pos.z=abs(.25-mod(pos.z,.5));
ro=max(ro,-max(abs(pos.z)-.2,pos.y-.3));
ro=max(ro,-max(abs(pos.z)-.01,-pos.y+.32));
float d=min(fr,ro);
return d;
}
// Camera path
vec3 path(float ti) {
ti*=1.5;
vec3 p=vec3(sin(ti),(1.-sin(ti))*.5,-ti*5.)*.5;
return p;
}
// Calc normals, and here is edge detection, set to variable "edge"
float edge=0.0;
vec3 normal(vec3 p) {
vec3 e = vec3(0.0,det*5.,0.0);
float d1=de(p-e.yxx),d2=de(p+e.yxx);
float d3=de(p-e.xyx),d4=de(p+e.xyx);
float d5=de(p-e.xxy),d6=de(p+e.xxy);
float d=de(p);
edge=abs(d-0.5*(d2+d1))+abs(d-0.5*(d4+d3))+abs(d-0.5*(d6+d5));//edge finder
edge=min(1.,pow(edge,.5)*15.);
return normalize(vec3(d1-d2,d3-d4,d5-d6));
}
// Raymarching and 2D graphics
vec3 raymarch(in vec3 from, in vec3 dir){
edge=0.;
vec3 p, norm;
float d=100.;
float totdist=0.;
for (int i=0; i<RAY_STEPS; i++) {
if (d > det && totdist < 25.0) {
p = from + totdist * dir;
d = de(p);
det = detail*exp(.13*totdist);
totdist += d;
}
}
vec3 col=vec3(0.);
p-=(det-d)*dir;
norm=normal(p);
col=(1.-abs(norm))*max(0.,1.-edge*.8); // set normal as color with dark edges
totdist=clamp(totdist,0.,26.);
dir.y-=.02;
// set up background with sky and sun
vec3 backg=vec3(0.2,0.,0.4);
if (totdist>25.) col=backg; // hit background
col=pow(col,vec3(GAMMA))*BRIGHTNESS;
col=mix(vec3(length(col)),col,SATURATION);
col*=vec3(1.,.9,.85);
return col;
}
// get camera position
vec3 move(inout vec3 dir) {
vec3 go=path(t);
vec3 adv=path(t+.7);
float hd=de(adv);
vec3 advec=normalize(adv-go);
float an=adv.x-go.x; an*=min(1.,abs(adv.z-go.z))*sign(adv.z-go.z)*.7;
dir.xy*=mat2(cos(an),sin(an),-sin(an),cos(an));
an=advec.y*1.7;
dir.yz*=mat2(cos(an),sin(an),-sin(an),cos(an));
an=atan(advec.x,advec.z);
dir.xz*=mat2(cos(an),sin(an),-sin(an),cos(an));
return go;
}
void main(void) {
vec2 uv = gl_FragCoord.xy / iResolution.xy*2.-1.;
vec2 oriuv=uv;
uv.y*=iResolution.y/iResolution.x;
vec2 mouse=(iMouse.xy/iResolution.xy-.5)*3.;
if (iMouse.z<1.) mouse=vec2(0.,-0.05);
float fov=.9-max(0.,.7-iGlobalTime*.3);
vec3 dir=normalize(vec3(uv*fov,1.));
dir.yz*=rot(mouse.y);
dir.xz*=rot(mouse.x);
vec3 from=origin+move(dir);
vec3 color=raymarch(from,dir);
gl_FragColor = vec4(color,1.);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment