SpineEffectOutline.fx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. float4x4 World;
  2. float4x4 View;
  3. float4x4 Projection;
  4. sampler TextureSampler : register(s0);
  5. float _OutlineWidth = 3;
  6. float4 _OutlineColor = float4(1, 1, 0, 1);
  7. float _ThresholdEnd = 0.25;
  8. float _OutlineSmoothness = 1.0;
  9. float _OutlineMipLevel = 0;
  10. // TODO: add effect parameters here.
  11. struct VertexShaderInput
  12. {
  13. float4 Position : POSITION0;
  14. float4 Color : COLOR0;
  15. float4 TextureCoordinate : TEXCOORD0;
  16. float4 Color2 : COLOR1;
  17. };
  18. struct VertexShaderOutput
  19. {
  20. float4 Position : POSITION0;
  21. float4 Color : COLOR0;
  22. float4 TextureCoordinate : TEXCOORD0;
  23. float4 Color2 : COLOR1;
  24. };
  25. VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
  26. {
  27. VertexShaderOutput output;
  28. float4 worldPosition = mul(input.Position, World);
  29. float4 viewPosition = mul(worldPosition, View);
  30. output.Position = mul(viewPosition, Projection);
  31. output.TextureCoordinate = input.TextureCoordinate;
  32. output.Color = input.Color;
  33. output.Color2 = input.Color2;
  34. return output;
  35. }
  36. float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
  37. {
  38. float4 texColor = tex2D(TextureSampler, input.TextureCoordinate);
  39. float alpha = texColor.a * input.Color.a;
  40. float4 output;
  41. output.a = alpha;
  42. output.rgb = ((texColor.a - 1.0) * input.Color2.a + 1.0 - texColor.rgb) * input.Color2.rgb + texColor.rgb * input.Color.rgb;
  43. return output;
  44. }
  45. // Outline pass
  46. #define _USE8NEIGHBOURHOOD_ON
  47. float4 PixelShaderFunctionOutline(VertexShaderOutput i) : COLOR0
  48. {
  49. float4 texColor = float4(0,0,0,0);
  50. float uvDeltaPerPixel = max(ddx(i.TextureCoordinate), ddy(i.TextureCoordinate));
  51. float outlineWidthCompensated = _OutlineWidth * uvDeltaPerPixel;
  52. float xOffset = outlineWidthCompensated;
  53. float yOffset = outlineWidthCompensated;
  54. float xOffsetDiagonal = outlineWidthCompensated * 0.7;
  55. float yOffsetDiagonal = outlineWidthCompensated * 0.7;
  56. float pixelCenter = tex2D(TextureSampler, i.TextureCoordinate).a;
  57. float4 uvCenterWithLod = float4(i.TextureCoordinate.xy, 0, _OutlineMipLevel);
  58. float pixelTop = tex2Dlod(TextureSampler, uvCenterWithLod + float4(0, yOffset, 0, 0)).a;
  59. float pixelBottom = tex2Dlod(TextureSampler, uvCenterWithLod + float4(0, -yOffset, 0, 0)).a;
  60. float pixelLeft = tex2Dlod(TextureSampler, uvCenterWithLod + float4(-xOffset, 0, 0, 0)).a;
  61. float pixelRight = tex2Dlod(TextureSampler, uvCenterWithLod + float4(xOffset, 0, 0, 0)).a;
  62. #ifdef _USE8NEIGHBOURHOOD_ON
  63. float numSamples = 8;
  64. float pixelTopLeft = tex2Dlod(TextureSampler, uvCenterWithLod + float4(-xOffsetDiagonal, yOffsetDiagonal, 0, 0)).a;
  65. float pixelTopRight = tex2Dlod(TextureSampler, uvCenterWithLod + float4(xOffsetDiagonal, yOffsetDiagonal, 0, 0)).a;
  66. float pixelBottomLeft = tex2Dlod(TextureSampler, uvCenterWithLod + float4(-xOffsetDiagonal, -yOffsetDiagonal, 0, 0)).a;
  67. float pixelBottomRight = tex2Dlod(TextureSampler, uvCenterWithLod + float4(xOffsetDiagonal, -yOffsetDiagonal, 0, 0)).a;
  68. float average = (pixelTop + pixelBottom + pixelLeft + pixelRight +
  69. pixelTopLeft + pixelTopRight + pixelBottomLeft + pixelBottomRight)
  70. * i.Color.a / numSamples;
  71. #else // 4 neighbourhood
  72. float numSamples = 1;
  73. float average = (pixelTop + pixelBottom + pixelLeft + pixelRight) * i.Color.a / numSamples;
  74. #endif
  75. float thresholdStart = _ThresholdEnd * (1.0 - _OutlineSmoothness);
  76. float outlineAlpha = saturate((average - thresholdStart) / (_ThresholdEnd - thresholdStart)) - pixelCenter;
  77. texColor.rgba = lerp(texColor, _OutlineColor, outlineAlpha);
  78. return texColor;
  79. }
  80. technique Technique1
  81. {
  82. pass OutlinePass
  83. {
  84. // TODO: set renderstates here.
  85. VertexShader = compile vs_3_0 VertexShaderFunction();
  86. PixelShader = compile ps_3_0 PixelShaderFunctionOutline();
  87. }
  88. pass Pass2
  89. {
  90. // TODO: set renderstates here.
  91. VertexShader = compile vs_2_0 VertexShaderFunction();
  92. PixelShader = compile ps_2_0 PixelShaderFunction();
  93. }
  94. }