builtin-sprite.effect 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
  2. CCEffect %{
  3. techniques:
  4. - passes:
  5. - vert: sprite-vs:vert
  6. frag: sprite-fs:frag
  7. depthStencilState:
  8. depthTest: false
  9. depthWrite: false
  10. blendState:
  11. targets:
  12. - blend: true
  13. blendSrc: src_alpha
  14. blendDst: one_minus_src_alpha
  15. blendDstAlpha: one_minus_src_alpha
  16. rasterizerState:
  17. cullMode: none
  18. properties:
  19. edgeColor: { value: [1.0, 1.0, 1.0, 1.0] }
  20. textureSize: { value: [512.0, 512.0] }
  21. edgeWidth: { value: 2.0 }
  22. alphaThreshold: { value: 0.5 }
  23. }%
  24. CCProgram sprite-vs %{
  25. precision highp float;
  26. #include <builtin/uniforms/cc-global>
  27. #if USE_LOCAL
  28. #include <builtin/uniforms/cc-local>
  29. #endif
  30. #if SAMPLE_FROM_RT
  31. #include <common/common-define>
  32. #endif
  33. in vec3 a_position;
  34. in vec2 a_texCoord;
  35. in vec4 a_color;
  36. out vec4 color;
  37. out vec2 uv0;
  38. vec4 vert () {
  39. vec4 pos = vec4(a_position, 1);
  40. #if USE_LOCAL
  41. pos = cc_matWorld * pos;
  42. #endif
  43. #if USE_PIXEL_ALIGNMENT
  44. pos = cc_matView * pos;
  45. pos.xyz = floor(pos.xyz);
  46. pos = cc_matProj * pos;
  47. #else
  48. pos = cc_matViewProj * pos;
  49. #endif
  50. uv0 = a_texCoord;
  51. #if SAMPLE_FROM_RT
  52. CC_HANDLE_RT_SAMPLE_FLIP(uv0);
  53. #endif
  54. color = a_color;
  55. return pos;
  56. }
  57. }%
  58. CCProgram sprite-fs %{
  59. precision highp float;
  60. #include <builtin/internal/embedded-alpha>
  61. #include <builtin/internal/alpha-test>
  62. #define MAX_EDGE_WIDTH 10.0 // 最大边缘宽度(可根据需求调整)
  63. in vec4 color;
  64. #if USE_TEXTURE
  65. in vec2 uv0;
  66. #pragma builtin(local)
  67. layout(set = 2, binding = 12) uniform sampler2D cc_spriteTexture;
  68. #endif
  69. uniform EdgeUniforms {
  70. vec4 edgeColor;
  71. vec2 textureSize;
  72. float edgeWidth;
  73. };
  74. vec4 frag () {
  75. vec4 o = vec4(1, 1, 1, 1);
  76. #if USE_TEXTURE
  77. o *= CCSampleWithAlphaSeparated(cc_spriteTexture, uv0);
  78. // Edge detection based on alpha channel
  79. vec2 texelSize = 1.0 / textureSize;
  80. float currentAlpha = o.a;
  81. // Sample surrounding pixels to detect edge
  82. float edgeDetected = 0.0;
  83. if (currentAlpha > 0.01) {
  84. // Check if we're at the edge by sampling neighboring pixels
  85. for (float x = -MAX_EDGE_WIDTH; x <= MAX_EDGE_WIDTH; x += 1.0) {
  86. for (float y = -MAX_EDGE_WIDTH; y <= MAX_EDGE_WIDTH; y += 1.0) {
  87. if (x == 0.0 && y == 0.0) continue;
  88. vec2 sampleUV = uv0 + vec2(x, y) * texelSize;
  89. float sampleAlpha = CCSampleWithAlphaSeparated(cc_spriteTexture, sampleUV).a;
  90. // If we find a transparent pixel nearby, we're at an edge
  91. if (sampleAlpha < 0.01) {
  92. float distance = length(vec2(x, y));
  93. if (distance <= edgeWidth) {
  94. float edgeStrength = 1.0 - (distance / edgeWidth);
  95. edgeDetected = max(edgeDetected, edgeStrength);
  96. }
  97. }
  98. }
  99. }
  100. }
  101. // Apply edge effect
  102. if (edgeDetected > 0.0) {
  103. o.rgb = mix(o.rgb, edgeColor.rgb, edgeDetected * edgeColor.a);
  104. }
  105. #if IS_GRAY
  106. float gray = 0.2126 * o.r + 0.7152 * o.g + 0.0722 * o.b;
  107. o.r = o.g = o.b = gray;
  108. #endif
  109. #endif
  110. o *= color;
  111. ALPHA_TEST(o);
  112. return o;
  113. }
  114. }%