A little toolkit for single-quad fragment shader demos
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
1.8 KiB

  1. #version 330 core
  2. #define FOV 60
  3. #define EPSILON 0.01
  4. #define MAX_STEPS 64
  5. #define NEAR_D 0.
  6. #define FAR_D 10.
  7. #define GRAD_EPSILON 0.0001
  8. #define saturate(x) clamp(x, 0, 1)
  9. uniform vec2 u_Resolution;
  10. uniform vec4 u_Mouse;
  11. uniform float u_Time;
  12. out vec4 color;
  13. #include "utils.glsl"
  14. #include "hg_sdf.glsl"
  15. #include "colormap_cool.glsl"
  16. vec3 ray_dir(float fov, vec2 uv) {
  17. float z = 1./tan(radians(fov)/2.);
  18. return normalize(vec3(uv, z));
  19. }
  20. float scene_f(vec3 p) {
  21. float b1 = fBox(p, vec3(1));
  22. float s2 = fSphere(p + vec3(1), 1.0);
  23. return fOpUnionRound(b1, s2, 0.5);
  24. }
  25. vec3 estimate_scene_normal(vec3 p) {
  26. vec3 dx = vec3(GRAD_EPSILON, 0, 0);
  27. vec3 dy = vec3(0, GRAD_EPSILON, 0);
  28. vec3 dz = vec3(0, 0, GRAD_EPSILON);
  29. return normalize(vec3(
  30. scene_f(p + dx) - scene_f(p - dx),
  31. scene_f(p + dy) - scene_f(p - dy),
  32. scene_f(p + dz) - scene_f(p - dz)
  33. ));
  34. }
  35. vec3 raymarch(vec3 o, vec3 d, float start, float end) {
  36. float t = start;
  37. for (int i = 0; i < MAX_STEPS; i++) {
  38. float dist = scene_f(o + d*t);
  39. if (dist < EPSILON || t > end)
  40. return vec3(t, i, 0.);
  41. t += dist;
  42. }
  43. return vec3(end, MAX_STEPS, 0.);
  44. }
  45. vec4 shade(vec3 p) {
  46. vec3 normal = estimate_scene_normal(p);
  47. return vec4((normal + vec3(1.0))/2.0, 1.0);
  48. }
  49. void main() {
  50. vec2 mouse_uv = u_Mouse.xy * 2.0 / u_Resolution.xy - 1.0;
  51. vec2 uv = gl_FragCoord.xy * 2.0 / u_Resolution.xy - 1.0;
  52. uv.x *= u_Resolution.x/u_Resolution.y;
  53. vec3 eye = vec3(0., 0., -5.);
  54. mat3 lookAt = calcLookAtMatrix(eye, vec3(0., 0., 0.), u_Time);
  55. vec3 dir = normalize(lookAt * ray_dir(FOV, uv));
  56. color = vec4(0.);
  57. vec3 result = raymarch(eye, dir, NEAR_D, FAR_D);
  58. float depth = result.x;
  59. float iters = result.y;
  60. if (depth >= FAR_D) {
  61. color = vec4(1.0, 0.5, 1.0, 1.0);
  62. return;
  63. }
  64. color = colormap(iters/MAX_STEPS+0.5);
  65. vec3 p = eye + dir * depth;
  66. color = shade(p);
  67. }