canvas_sdf.glsl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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_snorm, 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, 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(ivec2(-32767), 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. int found = 0;
  34. int solid_found = 0;
  35. for (int i = 0; i < s; i++) {
  36. for (int j = 0; j < s; j++) {
  37. ivec2 src_pos = base + ivec2(i, j);
  38. if (any(greaterThanEqual(src_pos, params.base_size))) {
  39. continue;
  40. }
  41. bool solid = imageLoad(src_pixels, src_pos).r > 0.5;
  42. if (solid) {
  43. float dist = length(vec2(src_pos - center));
  44. if (dist < d) {
  45. d = dist;
  46. rel = src_pos;
  47. }
  48. solid_found++;
  49. }
  50. found++;
  51. }
  52. }
  53. if (solid_found == found) {
  54. //mark solid only if all are solid
  55. rel = ivec2(-32767);
  56. }
  57. imageStore(dst_process, pos, ivec4(rel, 0, 0));
  58. #endif
  59. #ifdef MODE_PROCESS
  60. ivec2 base = pos << params.shift;
  61. ivec2 center = base + ivec2(params.shift);
  62. ivec2 rel = imageLoad(src_process, pos).xy;
  63. bool solid = rel.x < 0;
  64. if (solid) {
  65. rel = -rel - ivec2(1);
  66. }
  67. if (center != rel) {
  68. //only process if it does not point to itself
  69. const int ofs_table_size = 8;
  70. const ivec2 ofs_table[ofs_table_size] = ivec2[](
  71. ivec2(-1, -1),
  72. ivec2(0, -1),
  73. ivec2(+1, -1),
  74. ivec2(-1, 0),
  75. ivec2(+1, 0),
  76. ivec2(-1, +1),
  77. ivec2(0, +1),
  78. ivec2(+1, +1));
  79. float dist = length(vec2(rel - center));
  80. for (int i = 0; i < ofs_table_size; i++) {
  81. ivec2 src_pos = pos + ofs_table[i] * params.stride;
  82. if (any(lessThan(src_pos, ivec2(0))) || any(greaterThanEqual(src_pos, params.size))) {
  83. continue;
  84. }
  85. ivec2 src_rel = imageLoad(src_process, src_pos).xy;
  86. bool src_solid = src_rel.x < 0;
  87. if (src_solid) {
  88. src_rel = -src_rel - ivec2(1);
  89. }
  90. if (src_solid != solid) {
  91. src_rel = ivec2(src_pos << params.shift); //point to itself if of different type
  92. }
  93. float src_dist = length(vec2(src_rel - center));
  94. if (src_dist < dist) {
  95. dist = src_dist;
  96. rel = src_rel;
  97. }
  98. }
  99. }
  100. if (solid) {
  101. rel = -rel - ivec2(1);
  102. }
  103. imageStore(dst_process, pos, ivec4(rel, 0, 0));
  104. #endif
  105. #ifdef MODE_STORE
  106. ivec2 rel = imageLoad(src_process, pos).xy;
  107. bool solid = rel.x < 0;
  108. if (solid) {
  109. rel = -rel - ivec2(1);
  110. }
  111. float d = length(vec2(rel - pos));
  112. if (solid) {
  113. d = -d;
  114. }
  115. d /= SDF_MAX_LENGTH;
  116. d = clamp(d, -1.0, 1.0);
  117. imageStore(dst_sdf, pos, vec4(d));
  118. #endif
  119. #ifdef MODE_STORE_SHRINK
  120. ivec2 base = pos << params.shift;
  121. ivec2 center = base + ivec2(params.shift);
  122. ivec2 rel = imageLoad(src_process, pos).xy;
  123. bool solid = rel.x < 0;
  124. if (solid) {
  125. rel = -rel - ivec2(1);
  126. }
  127. float d = length(vec2(rel - center));
  128. if (solid) {
  129. d = -d;
  130. }
  131. d /= SDF_MAX_LENGTH;
  132. d = clamp(d, -1.0, 1.0);
  133. imageStore(dst_sdf, pos, vec4(d));
  134. #endif
  135. }