FreeTransform.gdshader 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. shader_type canvas_item;
  2. const float base_line_width = 2.0f;
  3. const float base_square_size = 11.0f;
  4. const float base_center_size = 11.0f;
  5. // 使用数组传递点
  6. uniform vec2 points[4];
  7. uniform vec4 square_color: source_color;
  8. uniform vec4 square_line_color: source_color;
  9. uniform bool editable;
  10. varying vec2 pixel_pos;
  11. varying float line_width;
  12. varying float square_size;
  13. varying float center_size;
  14. int in_square(vec2 center, vec2 m) {
  15. float dx = abs(m.x - center.x);
  16. float dy = abs(m.y - center.y);
  17. bool on_edge = (abs(dx - square_size) <= line_width && dy <= square_size) ||
  18. (abs(dy - square_size) <= line_width && dx <= square_size);
  19. bool inside = dx <= square_size && dy <= square_size;
  20. return on_edge ? 0 : (inside ? 1 : -1);
  21. }
  22. int in_line(vec2 p1, vec2 p2, vec2 m) {
  23. vec2 v = p2 - p1, w = m - p1;
  24. float sq_len = dot(v, v);
  25. if (sq_len < 0.001) return length(w) <= line_width ? 0 : -1;
  26. float t = clamp(dot(w, v) / sq_len, 0.0, 1.0);
  27. return length(m - (p1 + t * v)) <= line_width ? 0 : -1;
  28. }
  29. int in_center(vec2 center, vec2 m)
  30. {
  31. float dis = distance(center, m);
  32. if (dis < line_width * 2.0)
  33. return 0;
  34. if (center_size - line_width < dis && dis < center_size + line_width)
  35. return 0;
  36. return -1;
  37. }
  38. int detect_pixel(vec2 check_points[9], vec2 pos) {
  39. for (int i = 0; i < 8; i++) { // 前8个是正方形检测
  40. int result = in_square(check_points[i], pos);
  41. if (result >= 0)
  42. return result;
  43. }
  44. for (int i = 0; i < 4; i++) { // 边线检测
  45. int result = in_line(points[i], points[(i + 1) % 4], pos);
  46. if (result >= 0)
  47. return result;
  48. }
  49. // 中心区域检测
  50. return in_center(check_points[8], pos);
  51. }
  52. void vertex() {
  53. pixel_pos = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
  54. float scale = length(vec2(CANVAS_MATRIX[0][0], CANVAS_MATRIX[1][1]));
  55. line_width = base_line_width / scale;
  56. square_size = base_square_size / scale;
  57. center_size = base_center_size / scale;
  58. }
  59. void fragment() {
  60. vec2 check_points[9] = {
  61. // 角点
  62. points[0], points[1], points[2], points[3],
  63. // 边中点
  64. (points[0] + points[1]) / 2.0, (points[1] + points[2]) / 2.0,
  65. (points[2] + points[3]) / 2.0, (points[3] + points[0]) / 2.0,
  66. // 中心点
  67. (points[0] + points[2]) / 2.0
  68. };
  69. int point_mode = -1;
  70. if (editable)
  71. point_mode = detect_pixel(check_points, pixel_pos);
  72. else
  73. for (int i = 0; i < 4; i++) { // 边线检测
  74. int result = in_line(check_points[i], check_points[(i + 1) % 4], pixel_pos);
  75. if (result >= 0)
  76. point_mode = 0;
  77. }
  78. if (point_mode == 0)
  79. COLOR = square_line_color;
  80. else if(point_mode == 1)
  81. COLOR = square_color;
  82. else
  83. COLOR = texture(TEXTURE, UV);
  84. }