ConvolutionShader.shader 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. Shader "Custom/Convolution"
  2. {
  3. Properties
  4. {
  5. _MainTex ("Texture", 2D) = "white" {}
  6. [Enum(kerEdgeDetectionA,1,kerEdgeDetectionB,2,kerEdgeDetectionC,3,kerSharpen,4,kerBoxBlur,5)]
  7. _Kernel("Kernel", Float) = 1
  8. }
  9. SubShader
  10. {
  11. // No culling or depth
  12. Cull Off ZWrite Off ZTest Always
  13. Pass
  14. {
  15. CGPROGRAM
  16. #pragma vertex vert
  17. #pragma fragment frag
  18. #include "UnityCG.cginc"
  19. struct appdata
  20. {
  21. float4 vertex : POSITION;
  22. float2 uv : TEXCOORD0;
  23. };
  24. struct v2f
  25. {
  26. float2 uv : TEXCOORD0;
  27. float4 vertex : SV_POSITION;
  28. };
  29. v2f vert(appdata v)
  30. {
  31. v2f o;
  32. o.vertex = UnityObjectToClipPos(v.vertex);
  33. o.uv = v.uv;
  34. return o;
  35. }
  36. sampler2D _MainTex;
  37. float4 _MainTex_TexelSize;
  38. float3x3 GetData(int channel, sampler2D tex, float2 uv, float4 size)
  39. {
  40. float3x3 mat;
  41. for (int y = -1; y < 2; y++)
  42. {
  43. for (int x = -1; x < 2; x++)
  44. {
  45. mat[x + 1][y + 1] = tex2D(tex, uv + float2(x * size.x, y * size.y))[channel];
  46. }
  47. }
  48. return mat;
  49. }
  50. float3x3 GetMean(float3x3 matr, float3x3 matg, float3x3 matb)
  51. {
  52. float3x3 mat;
  53. for (int y = 0; y < 3; y++)
  54. {
  55. for (int x = 0; x < 3; x++)
  56. {
  57. mat[x][y] = (matr[x][y] + matg[x][y] + matb[x][y]) / 3.0;
  58. }
  59. }
  60. return mat;
  61. }
  62. float Convolve(float3x3 kernel, float3x3 pixels, float denom, float offset)
  63. {
  64. float res = 0.0;
  65. for (int y = 0; y < 3; y++)
  66. {
  67. for (int x = 0; x < 3; x++)
  68. {
  69. res += kernel[2 - x][2 - y] * pixels[x][y];
  70. }
  71. }
  72. return res;
  73. }
  74. float _Kernel;
  75. fixed4 frag(v2f i) : SV_Target
  76. {
  77. float3x3 kerEdgeDetectionA = float3x3(0.0, 0, -1.0,
  78. 1.0, 0, -1.0,
  79. 0.0, 1.0, 0.0);
  80. float3x3 kerEdgeDetectionB = float3x3(0.0, 1.0, 0.0,
  81. 1.0, -4.0, 1.0,
  82. 0.0, 1.0, 0.0);
  83. float3x3 kerEdgeDetectionC = float3x3(-1.0, -1.0, -1.0,
  84. -1.0, 8.0, -1.0,
  85. -1.0, -1.0, -1.0);
  86. float3x3 kerSharpen = float3x3(0.0, -1.0, 0.0,
  87. -1.0, 5.0, -1.0,
  88. 0.0, -1.0, 0.0);
  89. float3x3 kerBoxBlur = (1.0 / 9.0) * float3x3(1.0, 1.0, 1.0,
  90. 1.0, 1.0, 1.0,
  91. 1.0, 1.0, 1.0);
  92. float3x3 kernelSelection;
  93. if (_Kernel == 1)
  94. {
  95. kernelSelection = kerEdgeDetectionA;
  96. }
  97. else if (_Kernel == 2)
  98. {
  99. kernelSelection = kerEdgeDetectionB;
  100. }
  101. else if (_Kernel == 3)
  102. {
  103. kernelSelection = kerEdgeDetectionC;
  104. }
  105. else if (_Kernel == 4)
  106. {
  107. kernelSelection = kerSharpen;
  108. }
  109. else if (_Kernel == 5)
  110. {
  111. kernelSelection = kerBoxBlur;
  112. }
  113. float3x3 matr = GetData(0, _MainTex, i.uv, _MainTex_TexelSize);
  114. float3x3 matg = GetData(1, _MainTex, i.uv, _MainTex_TexelSize);
  115. float3x3 matb = GetData(2, _MainTex, i.uv, _MainTex_TexelSize);
  116. float3x3 mata = GetMean(matr, matg, matb);
  117. // kernel
  118. float4 gl_FragColor = float4(Convolve(kernelSelection, matr, 1.0, 0.0),
  119. Convolve(kernelSelection, matg, 1.0, 0.0),
  120. Convolve(kernelSelection, matb, 1.0, 0.0),
  121. 1.0);
  122. return gl_FragColor;
  123. }
  124. ENDCG
  125. }
  126. }
  127. }