1// https://www.shadertoy.com/view/4sl3zn
2
3// Created by inigo quilez - iq/2013
4// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
5
6vec2 disp( in vec3 p )
7{
8	return vec2( pow( 0.5 + 0.5*cos( 1.0*iTime ), 2.0 ),
9                 pow( 0.5 + 0.5*cos( 25.0*p.x  + 1.5*iTime)*
10					            sin( 25.0*p.y  + 2.0*iTime )*
11					            sin( 25.0*p.z  + 1.0*iTime ), 3.0) );
12}
13
14float obj( in vec3 p )
15{
16	vec3 ax = vec3(-2.0,2.0,1.0)/3.0;
17	vec3 ce = vec3(0.0,-0.2,-0.2);
18
19	float d1 = dot(p,ax) - 0.1;
20    float d2 = length(p) - 1.0;
21	float d3 = length( p-ce - ax*dot(p-ce,ax)) - 1.0;
22
23	return max( max( d1, d2 ), -d3 );
24}
25
26vec2 map( in vec3 p )
27{
28	float d1 = obj( p );
29	float d2 = obj( p*vec3(-1.0,-1.0,1.0) );
30
31    vec2        res = vec2( d1, 0.0 );
32	if( d2<d1 ) res = vec2( d2, 1.0 );
33
34	vec2 di = disp( p );
35	res.x -= 0.04*di.x*di.y;
36
37	return res;
38}
39
40vec2 intersect( in vec3 ro, in vec3 rd )
41{
42	float t = 0.0;
43	vec2 h = vec2( -1.0 );
44    for( int i=0; i<32; i++ )
45    {
46        h = map(ro+rd*t);
47		t += h.x;
48	}
49
50	if( h.x<0.1 ) return vec2(t,h.y);
51
52	return vec2(-1.0);
53}
54
55vec3 calcNormal( in vec3 pos )
56{
57    vec3 eps = vec3(0.02,0.0,0.0);
58
59	return normalize( vec3(
60           map(pos+eps.xyy).x - map(pos-eps.xyy).x,
61           map(pos+eps.yxy).x - map(pos-eps.yxy).x,
62           map(pos+eps.yyx).x - map(pos-eps.yyx).x ) );
63}
64
65float softshadow( in vec3 ro, in vec3 rd, float mint, float k )
66{
67    float res = 1.0;
68    float t = mint;
69    for( int i=0; i<16; i++ )
70    {
71        float h = map(ro + rd*t).x;
72        res = min( res, k*h/t );
73        t += h;
74    }
75    return clamp(res,0.0,1.0);
76}
77
78void mainImage( out vec4 fragColor, in vec2 fragCoord )
79{
80    vec2 p = -1.0 + 2.0 * fragCoord.xy / iResolution.xy;
81    p.x *= iResolution.x/iResolution.y;
82
83    vec2 m = iMouse.xy/iResolution.xy;
84	if( iMouse.z<0.0 ) m = vec2(0.0);
85
86    // camera
87	float an = -6.2*m.x + 0.2*sin(0.5*iTime) + 6.5;
88    vec3 ro = 1.5*normalize(vec3(sin(an),-6.0*m.y, cos(an)));
89
90    vec3 ww = normalize( vec3(0.0,0.0,0.0) - ro );
91    vec3 uu = normalize( cross(ww,vec3(0.0,1.0,0.0) ) );
92    vec3 vv = normalize( cross(uu,ww));
93    vec3 rd = normalize( p.x*uu + p.y*vv + 1.0*ww );
94
95    vec3 col = vec3(1.0);
96
97	// raymarch
98    vec2 tmat = intersect(ro,rd);
99    if( tmat.y>-0.5 )
100    {
101        // geometry
102        vec3 pos = ro + tmat.x*rd;
103        vec3 nor = calcNormal(pos);
104        vec3 ref = reflect(rd,nor);
105		vec3 lig = normalize(vec3(-0.6,0.5,0.2));
106		vec2 dis = disp( pos );
107
108        // lights
109        float con = 1.0;
110        float amb = 0.5 + 0.5*nor.y;
111        float dif = max(dot(nor,lig),0.0);
112        float bac = max(0.2 + 0.8*dot(nor,vec3(-lig.x,lig.y,-lig.z)),0.0);
113        float rim = pow(1.0+dot(nor,rd),8.0);
114        float spe = pow(clamp(dot(lig,ref),0.0,1.0),8.0);
115        float occ = mix( 1.0, 0.9 + 3.0*dis.y, dis.x );
116
117		// shadow
118		float sh = softshadow( pos, lig, 0.01, 8.0 );
119		dif *= sh;
120		spe *= sh;
121		rim *= sh;
122
123        col  = 0.10*con*vec3(1.0)*occ;
124        col += 1.00*dif*vec3(1.0,0.8,0.6);
125        col += 0.40*bac*vec3(1.0)*occ;
126        col += 0.25*amb*vec3(0.6,0.8,1.0)*occ;
127
128        // material
129		col *= mix( vec3(0.7,0.1,0.1), vec3(0.0,0.2,1.0), tmat.y );
130
131		// speculars
132        col += 0.50*spe*vec3(1.0);
133		col += 1.00*rim*vec3(1.0);
134
135        // gamma
136        col = sqrt(col);
137    }
138
139
140    fragColor = vec4( col,1.0 );
141}