canvas_sdf.glsl 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #[compute]
  2. #version 450
  3. VERSION_DEFINES
  4. layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
  5. layout(r8, set = 0, binding = 1) uniform restrict readonly image2D src_pixels;
  6. layout(r16, set = 0, binding = 2) uniform restrict writeonly image2D dst_sdf;
  7. layout(rg16i, set = 0, binding = 3) uniform restrict readonly iimage2D src_process;
  8. layout(rg16i, set = 0, binding = 4) uniform restrict writeonly iimage2D dst_process;
  9. layout(push_constant, binding = 0, std430) uniform Params {
  10. ivec2 size;
  11. int stride;
  12. int shift;
  13. ivec2 base_size;
  14. uvec2 pad;
  15. }
  16. params;
  17. #define SDF_MAX_LENGTH 16384.0
  18. void main() {
  19. ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
  20. if (any(greaterThanEqual(pos, params.size))) { //too large, do nothing
  21. return;
  22. }
  23. #ifdef MODE_LOAD
  24. bool solid = imageLoad(src_pixels, pos).r > 0.5;
  25. imageStore(dst_process, pos, solid ? ivec4(pos, 0, 0) : ivec4(ivec2(32767), 0, 0));
  26. #endif
  27. #ifdef MODE_LOAD_SHRINK
  28. int s = 1 << params.shift;
  29. ivec2 base = pos << params.shift;
  30. ivec2 center = base + ivec2(params.shift);
  31. ivec2 rel = ivec2(32767);
  32. float d = 1e20;
  33. for (int i = 0; i < s; i++) {
  34. for (int j = 0; j < s; j++) {
  35. ivec2 src_pos = base + ivec2(i, j);
  36. if (any(greaterThanEqual(src_pos, params.base_size))) {
  37. continue;
  38. }
  39. bool solid = imageLoad(src_pixels, src_pos).r > 0.5;
  40. if (solid) {
  41. float dist = length(vec2(src_pos - center));
  42. if (dist < d) {
  43. d = dist;
  44. rel = src_pos;
  45. }
  46. }
  47. }
  48. }
  49. imageStore(dst_process, pos, ivec4(rel, 0, 0));
  50. #endif
  51. #ifdef MODE_PROCESS
  52. ivec2 base = pos << params.shift;
  53. ivec2 center = base + ivec2(params.shift);
  54. ivec2 rel = imageLoad(src_process, pos).xy;
  55. if (center != rel) {
  56. //only process if it does not point to itself
  57. const int ofs_table_size = 8;
  58. const ivec2 ofs_table[ofs_table_size] = ivec2[](
  59. ivec2(-1, -1),
  60. ivec2(0, -1),
  61. ivec2(+1, -1),
  62. ivec2(-1, 0),
  63. ivec2(+1, 0),
  64. ivec2(-1, +1),
  65. ivec2(0, +1),
  66. ivec2(+1, +1));
  67. float dist = length(vec2(rel - center));
  68. for (int i = 0; i < ofs_table_size; i++) {
  69. ivec2 src_pos = pos + ofs_table[i] * params.stride;
  70. if (any(lessThan(src_pos, ivec2(0))) || any(greaterThanEqual(src_pos, params.size))) {
  71. continue;
  72. }
  73. ivec2 src_rel = imageLoad(src_process, src_pos).xy;
  74. float src_dist = length(vec2(src_rel - center));
  75. if (src_dist < dist) {
  76. dist = src_dist;
  77. rel = src_rel;
  78. }
  79. }
  80. }
  81. imageStore(dst_process, pos, ivec4(rel, 0, 0));
  82. #endif
  83. #ifdef MODE_STORE
  84. ivec2 rel = imageLoad(src_process, pos).xy;
  85. float d = length(vec2(rel - pos));
  86. if (d > 0.01) {
  87. d += 1.0; //make it signed
  88. }
  89. d /= SDF_MAX_LENGTH;
  90. d = clamp(d, 0.0, 1.0);
  91. imageStore(dst_sdf, pos, vec4(d));
  92. #endif
  93. #ifdef MODE_STORE_SHRINK
  94. ivec2 base = pos << params.shift;
  95. ivec2 center = base + ivec2(params.shift);
  96. ivec2 rel = imageLoad(src_process, pos).xy;
  97. float d = length(vec2(rel - center));
  98. if (d > 0.01) {
  99. d += 1.0; //make it signed
  100. }
  101. d /= SDF_MAX_LENGTH;
  102. d = clamp(d, 0.0, 1.0);
  103. imageStore(dst_sdf, pos, vec4(d));
  104. #endif
  105. }