1
+ precision highp float ;
2
+
3
+ vec2 clip_coord()
4
+ {
5
+ vec2 aspect = vec2 (cc_ViewSize.x/ cc_ViewSize.y, 1.0 );
6
+ return 2.0 * aspect* gl_FragCoord .xy/ cc_ViewSize.xy - aspect;
7
+ }
8
+
9
+ vec3 eye_ray(vec3 eye, vec3 look_at, vec3 eye_up, float fov){
10
+ // Do as a matrix?
11
+ vec3 forward = normalize (look_at - eye);
12
+ vec3 right = cross (forward, normalize (eye_up));
13
+ vec3 up = cross (right, forward);
14
+
15
+ vec2 clip = clip_coord();
16
+ return normalize (forward + (clip.x* fov)* right + clip.y* up);
17
+ }
18
+
19
+ float d_sphere(vec3 v, vec3 p, float r){
20
+ return length (v - p) - r;
21
+ }
22
+
23
+ float d_cylinder(vec3 v, vec3 p, vec3 n, float r, float l){
24
+ float dvn = dot (v - p, n);
25
+ return max (
26
+ length (v - n* dvn) - r,
27
+ abs (dvn) - l* 0.5
28
+ );
29
+ }
30
+
31
+ float d_box(vec3 v, vec3 p, vec3 b){
32
+ vec3 d = abs (v - p) - b* 0.5 ;
33
+ return max (max (d.x, d.y), d.z);
34
+ }
35
+
36
+ float d_union(float d1, float d2){ return min (d1, d2); }
37
+ float d_subtract(float d1, float d2){ return max (d1, - d2); }
38
+ float d_intersect(float d1, float d2){ return max (d1, d2); }
39
+
40
+ float dist(vec3 v){
41
+ float s = 1.3 ;
42
+ float r = mix (1.6 , 1.8 , 0.5 * sin (2.0 * cc_Time[0 ]) + 0.5 );
43
+
44
+ float d = 1e10 ;
45
+ d = d_union(d, - d_box(v, vec3 (0 ), vec3 (10.0 )));
46
+ d = d_union(d, d_box(v, vec3 (0 ), vec3 (2.0 * s)));
47
+ d = d_subtract(d, d_sphere(v, vec3 (0 ), r));
48
+ d = d_union(d, d_sphere(v, vec3 (0 ), r* 0.75 ));
49
+ d = d_union(d, d_cylinder(v, vec3 (0 ), vec3 (1 ,0 ,0 ), 0.2 , 10.0 ));
50
+ d = d_union(d, d_cylinder(v, vec3 (0 ), vec3 (0 ,1 ,0 ), 0.2 , 10.0 ));
51
+ d = d_union(d, d_cylinder(v, vec3 (0 ), vec3 (0 ,0 ,1 ), 0.2 , 10.0 ));
52
+ return d;
53
+ }
54
+
55
+ const float g_eps = 1e-3 ;
56
+
57
+ vec3 grad(vec3 p){
58
+ return normalize (vec3 (
59
+ dist(p + vec3 (g_eps,0 ,0 )) - dist(p - vec3 (g_eps,0 ,0 )),
60
+ dist(p + vec3 (0 ,g_eps,0 )) - dist(p - vec3 (0 ,g_eps,0 )),
61
+ dist(p + vec3 (0 ,0 ,g_eps)) - dist(p - vec3 (0 ,0 ,g_eps))
62
+ ));
63
+ }
64
+
65
+ const int iterations = 32 ;
66
+ const float threshold = 1e-3 ;
67
+ const float min_step = 1e-4 ;
68
+ const float step_fraction = 0.75 ;
69
+
70
+ struct Hit {
71
+ vec3 p, n;
72
+ float d;
73
+ };
74
+
75
+ Hit raymarch(vec3 eye, vec3 ray){
76
+ float dsum = 0.0 ;
77
+ for (int i= 0 ; i< iterations; i++ ){
78
+ vec3 p = eye + dsum* ray;
79
+ float dmin = dist(p);
80
+ if (dmin < threshold){
81
+ return Hit(p, grad(p), dsum);
82
+ } else {
83
+ dsum += max (min_step, dmin* step_fraction);
84
+ }
85
+ }
86
+
87
+ vec3 p = eye + dsum* ray;
88
+ return Hit(p, vec3 (0 ), dsum);
89
+ }
90
+
91
+ const float ao_samples = 4.0 ;
92
+ const float ao_spacing = 0.3 ;
93
+ const float ao_strength = 4.0 ;
94
+
95
+ float ao(Hit hit){
96
+ float sum = 0.0 ;
97
+ for (float i= 1.0 ; i<= ao_samples; i++ ){
98
+ float d = i* ao_spacing;
99
+ sum += (d - dist(hit.p + hit.n* d))/ pow (2.0 , i);
100
+ }
101
+
102
+ return 1.0 - ao_strength* sum;
103
+ }
104
+
105
+ const int shadow_iterations = 64 ;
106
+
107
+ float shadowmarch(vec3 point, vec3 light){
108
+ vec3 delta = light - point;
109
+ float dmax = length (delta);
110
+ vec3 ray = delta/ dmax;
111
+
112
+ float shadow = 1.0 ;
113
+ float dsum = 0.1 ;
114
+ for (int i= 0 ; i< shadow_iterations; i++ ){
115
+ vec3 p = point + ray* dsum;
116
+ float d = dist(p);
117
+ if (d < 1e-6 ) return 0.0 ;
118
+
119
+ dsum += max (min_step, d* step_fraction);
120
+ shadow = min (shadow, 128.0 * d/ dsum);
121
+ if (dsum > dmax) return shadow;
122
+ }
123
+
124
+ return shadow;
125
+ }
126
+
127
+ void main(void )
128
+ {
129
+ float t = cc_Time[0 ]/ 3.0 ;
130
+ vec3 eye = - 4.0 * normalize (vec3 (- cos (t), cos (0.5 * t), - sin (t)));
131
+ vec3 look_at = vec3 (0 );
132
+ vec3 up = vec3 (0 ,sin (t),cos (t));
133
+
134
+ vec3 ray = eye_ray(eye, look_at, up, 1.0 );
135
+ Hit hit = raymarch(eye, ray);
136
+ vec3 albedo = abs (hit.n);
137
+ float occlusion = ao(hit);
138
+ vec3 color = albedo;
139
+
140
+ vec3 light_pos = - eye.yzx;
141
+ vec3 light_dir = normalize (light_pos - hit.p);
142
+ float diff = clamp (dot (light_dir, hit.n), 0.0 , 1.0 );
143
+
144
+ float spec = pow (clamp (dot (reflect (ray, hit.n), light_dir), 0.0 , 1.0 ), 50.0 );
145
+ float light = 0.5 * diff + 1.0 * spec;
146
+ float shadow = shadowmarch(hit.p, light_pos);
147
+ color *= occlusion* (light* shadow + 0.1 );
148
+
149
+ vec3 fog_color = abs (ray);
150
+ color = mix (color, fog_color, hit.d/ 12.0 );
151
+
152
+ // TODO add a curve to filter out the > 1.0 crustees
153
+ color += 0.5 * albedo* pow (1.0 + dot (hit.n, ray), 4.0 );
154
+
155
+ gl_FragColor = vec4 (color, 0 );
156
+ }
0 commit comments