aboutsummaryrefslogtreecommitdiff
path: root/src/main/resources/shaders/play_shader.cs
blob: d3cd4f5806e860c6c30a32783a0cf97e5653c3e7 (plain) (blame)
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.));
}