1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
#version 430
layout(local_size_x = 1, local_size_y = 1) in;
uniform float seconds = 0;
layout(rgba8) uniform writeonly image2D outputImg;
#define MAX_ITERATIONS 500
#define MAX_DISTANCE 100.0
#define SURF_DIST 0.01
float sdfCircle(in vec3 p, in vec3 origin, in float radius) {
return length(p - origin) - radius;
}
float smin(float a, float b, float k) {
float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
return mix(b, a, h) - k * h * (1.0 - h);
}
float scene(in vec3 p) {
float c1 = sdfCircle(p, vec3(0, 1, 2.4), 0.2);
float c2 = sdfCircle(p, vec3(-0.6, 1, 3), 0.3);
return min(c1, c2);
}
float ray_march_scene(in vec3 ray_origin, in vec3 ray_direction) {
float dist = 0.;
for (int i = 0; i < MAX_ITERATIONS && dist < MAX_DISTANCE; i++) {
vec3 p = ray_origin + dist * ray_direction;
float gap = scene(p);
dist += gap;
if (gap <= SURF_DIST)
return dist;
}
return dist;
}
vec3 surface_normal_scene(in vec3 p) {
vec2 inc = vec2(0.01, 0);
return normalize(vec3(scene(p + inc.xyy) - scene(p - inc.xyy),
scene(p + inc.yxy) - scene(p - inc.yxy),
scene(p + inc.yyx) - scene(p - inc.yyx)));
}
void main() {
vec2 resolution = vec2(imageSize(outputImg).xy);
vec3 uv = vec3((gl_GlobalInvocationID.xy - resolution / 2.0) / resolution, 0);
float aspect_ratio = resolution.y / resolution.x;
uv /= vec3(aspect_ratio, 1, 1);
vec3 camera_pos = vec3(0, 1, 0);
vec3 camera_direction = normalize(vec3(uv.x, uv.y, 1.));
vec3 light_pos = vec3(1, 2. * sin(seconds), 1);
float depth = ray_march_scene(camera_pos, camera_direction);
vec3 p = camera_pos + camera_direction * depth;
vec3 normal = surface_normal_scene(p);
vec3 light_vec = normalize(light_pos - p);
float contrast = dot(normal, light_vec);
contrast = clamp(contrast, 0.1, 1.);
vec3 col = vec3(0.15);
if (depth < MAX_DISTANCE) {
float light_ray_dist =
ray_march_scene(p + 10. * normal * SURF_DIST, light_vec);
if (light_ray_dist < length(light_pos - p))
contrast *= 0.3;
col = vec3(0, 1. - (depth / MAX_DISTANCE), 0.4);
col *= contrast;
}
imageStore(outputImg, ivec2(gl_GlobalInvocationID.xy), vec4(col, 1.));
}
|