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.

141 lines
3.2 KiB

  1. #version 330 core
  2. #define FOV 24
  3. #define EPSILON 0.01
  4. #define MAX_STEPS 128
  5. #define NEAR_D 0.1
  6. #define FAR_D 120.
  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 "hg_sdf.glsl"
  14. #include "utils.glsl"
  15. #include "march_prolog.glsl"
  16. #include "colormap_cool.glsl"
  17. #define MAT_NORMALS 1.
  18. vec3 ray_dir(float fov, vec2 uv) {
  19. float z = 1./tan(radians(fov)/2.);
  20. return normalize(vec3(uv, z));
  21. }
  22. SceneResult scene_f(vec3 p) {
  23. SceneResult ball = SceneResult(length(p-vec3(0, 2, 0)) - 2, 3.);
  24. SceneResult ball2 = SceneResult(length(p-vec3(2*sin(u_Time), 2-2*cos(u_Time), 0)) - 1, 3.);
  25. SceneResult plane = SceneResult(p.y+5, 2.);
  26. // SceneResult box = SceneResult(
  27. // fOpUnionRound(fBox(p, vec3(1)), fSphere(p-vec3(.8), 1.), .2), 0.);
  28. //SceneResult res = SceneResult(
  29. // mix(fBox(p, vec3(1.)), fSphere(p, 1.),
  30. // pow(sin(.5*TAU*u_Time), 0.8)),
  31. // 1.);
  32. // SceneResult res = SceneResult(-p.z, 1.);
  33. // SceneResult res = SceneResult(
  34. // fBox(p, vec3(1)),
  35. // 1.);
  36. SceneResult res = min_sr(min_sr(ball, ball2), plane);
  37. return res;
  38. }
  39. vec3 estimate_scene_normal(vec3 p) {
  40. vec3 dx = vec3(GRAD_EPSILON, 0, 0);
  41. vec3 dy = vec3(0, GRAD_EPSILON, 0);
  42. vec3 dz = vec3(0, 0, GRAD_EPSILON);
  43. return normalize(vec3(
  44. scene_f(p + dx).d - scene_f(p - dx).d,
  45. scene_f(p + dy).d - scene_f(p - dy).d,
  46. scene_f(p + dz).d - scene_f(p - dz).d
  47. ));
  48. }
  49. vec3 raymarch(vec3 o, vec3 d, float start, float end) {
  50. float t = start;
  51. for (int i = 0; i < MAX_STEPS; i++) {
  52. SceneResult sr = scene_f(o + d*t);
  53. if (sr.d < EPSILON || t > end)
  54. return vec3(t, sr.mat_idx, i);
  55. t += sr.d;
  56. }
  57. return vec3(end, N_HIT_FAR_PLANE, MAX_STEPS);
  58. }
  59. float checker(vec2 uv) {
  60. return sign(mod(floor(uv.x) + floor(uv.y), 2.0));
  61. }
  62. vec4 shade_material(vec3 p, vec3 norm, float mat_idx) {
  63. if (mat_idx <= 0.0) {
  64. return vec4(0);
  65. }
  66. if (mat_idx <= 1.0) {
  67. // return colormap((mod(p.x, 3.) + 1)/2.5);
  68. return vec4(norm, 1.0);
  69. }
  70. if (mat_idx <= 2.0) {
  71. return vec4(vec3(mix(0.8, 1.0, checker(p.xz))), 1);
  72. }
  73. if (mat_idx <= 3.0) {
  74. return vec4(mix(vec3(0), vec3(0.05, 0, 0.1), dot(vec3(3, 3, 3), norm)), 1);
  75. }
  76. return vec4(1, 0, 0, 1);
  77. //return
  78. }
  79. vec4 shade(vec3 p, float mat_idx) {
  80. vec3 norm = estimate_scene_normal(p);
  81. vec4 color_mat = shade_material(p, norm, mat_idx);
  82. return color_mat;
  83. }
  84. void main() {
  85. vec2 mouse_uv = u_Mouse.xy * 2.0 / u_Resolution.xy - 1.0;
  86. vec2 uv = gl_FragCoord.xy * 2.0 / u_Resolution.xy - 1.0;
  87. uv.x *= u_Resolution.x/u_Resolution.y;
  88. float an = 0.;
  89. float d = 5.;
  90. vec3 eye = vec3(3. * sin(an), 3., 3. * cos(an)) * d;
  91. vec3 target = vec3(0., 2., 0.);
  92. mat3 lookAt = look_mat(eye, target, 0);
  93. vec3 dir = normalize(lookAt * ray_dir(FOV, uv));
  94. color = vec4(0.);
  95. vec3 result = raymarch(eye, dir, NEAR_D, FAR_D);
  96. float depth = result.x;
  97. float mat_idx = result.y;
  98. float iters = result.z;
  99. if (depth >= FAR_D) {
  100. // color = vec4(.1, .3, .9, 1.);
  101. return;
  102. }
  103. //color = colormap(iters/MAX_STEPS+0.5);
  104. vec3 p = eye + dir * depth; // recast the ray
  105. color = shade(p, mat_idx);
  106. //color = vec4(vec3(depth/FAR_D), 1);
  107. // gamma
  108. color = vec4(pow(clamp(color.xyz, 0.0, 1.0), vec3(0.4545)), 1.0);
  109. }