|
| 1 | +//Some shader code is based on Dan Moran's Shader case study of Pokemon Battle Transition YouTube video |
| 2 | +//and Acerola's post processing github |
| 3 | +//The only change is the removal of the distort calculation and parameters and modifications to the gaussian blur |
| 4 | +//code to be more oriented in blurring the edges of the keyhole mask. |
| 5 | +Shader "Hidden/KeyholeOverlay" |
| 6 | +{ |
| 7 | + Properties |
| 8 | + { |
| 9 | + _MainTex("Texture", 2D) = "white" {} |
| 10 | + _KeyholeTex("Keyhole Texture", 2D) = "white" {} |
| 11 | + _Color("Screen Color", Color) = (1,1,1,1) |
| 12 | + _Cutoff("Cutoff", Range(0, 1)) = 0 |
| 13 | + _Fade("Fade", Range(0, 1)) = 0 |
| 14 | + _Scale("Scale", Range(0,3)) = 1 |
| 15 | + _BlurAmount("Blur Amount", Float) = 1.0 |
| 16 | + _BlurEdgeThreshold("Blur Amount", Float) = 0.01 |
| 17 | + _BlurEdgeRefine("Blur Edge Refine", Float) = 0.45 |
| 18 | + } |
| 19 | + |
| 20 | + SubShader |
| 21 | + { |
| 22 | + // No culling or depth |
| 23 | + Cull Off ZWrite Off ZTest Always |
| 24 | + |
| 25 | + CGINCLUDE |
| 26 | + |
| 27 | + #include "UnityCG.cginc" |
| 28 | + |
| 29 | + //all the structs needed for the passes |
| 30 | + struct appdata |
| 31 | + { |
| 32 | + float4 vertex : POSITION; |
| 33 | + float2 uv : TEXCOORD0; |
| 34 | + }; |
| 35 | + |
| 36 | + struct v2f |
| 37 | + { |
| 38 | + float2 uv : TEXCOORD0; |
| 39 | + float2 uv1 : TEXCOORD1; |
| 40 | + float4 vertex : SV_POSITION; |
| 41 | + }; |
| 42 | + |
| 43 | + //variables relating to textures |
| 44 | + sampler2D _MainTex; |
| 45 | + float4 _MainTex_TexelSize; |
| 46 | + sampler2D _KeyholeTex; |
| 47 | + |
| 48 | + //other variables |
| 49 | + float4 _Color; |
| 50 | + float _Scale; |
| 51 | + float _Fade; |
| 52 | + float _Cutoff; |
| 53 | + float _BlurAmount; |
| 54 | + float _BlurEdgeThreshold; |
| 55 | + float _BlurEdgeRefine; |
| 56 | + |
| 57 | + //vert function for first pass (index 0) |
| 58 | + v2f vert(appdata v) |
| 59 | + { |
| 60 | + v2f o; |
| 61 | + o.vertex = UnityObjectToClipPos(v.vertex); |
| 62 | + |
| 63 | + o.uv = v.uv; |
| 64 | + o.uv1 = v.uv; |
| 65 | + |
| 66 | + #if UNITY_UV_STARTS_AT_TOP |
| 67 | + if (_MainTex_TexelSize.y < 0) |
| 68 | + o.uv1.y = 1 - o.uv1.y; |
| 69 | + #endif |
| 70 | + |
| 71 | + return o; |
| 72 | + } |
| 73 | + |
| 74 | + //vert function for second and third pass (index 1 & 2) |
| 75 | + v2f vp(appdata v) { |
| 76 | + v2f o; |
| 77 | + o.vertex = UnityObjectToClipPos(v.vertex); |
| 78 | + o.uv = v.uv; |
| 79 | + o.uv1 = v.uv; |
| 80 | + return o; |
| 81 | + } |
| 82 | + |
| 83 | + #define PI 3.14159265358979323846f |
| 84 | + |
| 85 | + // Helper function to calculate gaussian needed for the blur effect |
| 86 | + // Normally supposed to use a 3x3 matrix of pre determined weights of each pixel in a 3x3 grid |
| 87 | + // But I am using a line from Acerola's open source code from his post processing github repo to run a equation that does the |
| 88 | + // calculation itself that results a very close aproximation of the values similar to the ones in the pre determined weight matrix |
| 89 | + float gaussian(float sigma, float pos) { |
| 90 | + return (1.0f / sqrt(2.0f * PI * sigma * sigma)) * exp(-(pos * pos) / (2.0f * sigma * sigma)); |
| 91 | + } |
| 92 | + |
| 93 | + // Helper function to determine if we're at the edge |
| 94 | + float isEdge(float maskValue, float cutoff) { |
| 95 | + fixed edgeWidth = _BlurEdgeThreshold; |
| 96 | + fixed distFromCutoff = abs(maskValue - cutoff); |
| 97 | + return 1.0 - saturate(distFromCutoff / edgeWidth); |
| 98 | + } |
| 99 | + ENDCG |
| 100 | + |
| 101 | + //keyhole hole cutout mask pass (index 0) |
| 102 | + Pass |
| 103 | + { |
| 104 | + CGPROGRAM |
| 105 | + #pragma vertex vert |
| 106 | + #pragma fragment frag |
| 107 | + |
| 108 | + fixed4 frag(v2f i) : SV_Target |
| 109 | + { |
| 110 | + //Scale the uv to desired center position |
| 111 | + fixed2 uv = i.uv1; |
| 112 | + uv -= 0.5; |
| 113 | + uv /= _Scale; |
| 114 | + uv += 0.5; |
| 115 | + |
| 116 | + fixed4 transit = tex2D(_KeyholeTex, uv); |
| 117 | + |
| 118 | + fixed2 direction = float2(0,0); |
| 119 | + |
| 120 | + //getting the screen colour with cutoff values and mask in place |
| 121 | + fixed4 col = tex2D(_MainTex, i.uv + _Cutoff * direction); |
| 122 | + |
| 123 | + //overlay our results onto the screen to mask it off |
| 124 | + if (transit.b < _Cutoff){ |
| 125 | + col = lerp(col, _Color, _Fade); |
| 126 | + } |
| 127 | + |
| 128 | + return col; |
| 129 | + } |
| 130 | + ENDCG |
| 131 | + } |
| 132 | + |
| 133 | + // Gaussian Blur First Pass (index 1) |
| 134 | + Pass { |
| 135 | + CGPROGRAM |
| 136 | + #pragma vertex vp |
| 137 | + #pragma fragment fp |
| 138 | + |
| 139 | + //where all the rendering work is at |
| 140 | + fixed4 fp(v2f i) : SV_Target { |
| 141 | + //Scale the uv to desired center position |
| 142 | + fixed2 uv = i.uv1; |
| 143 | + uv -= 0.5; |
| 144 | + uv.x /= _Scale; //- 0.06f; |
| 145 | + uv.y /= _Scale; //- 0.02f; |
| 146 | + //uv /= _Scale; |
| 147 | + uv += 0.5; |
| 148 | + |
| 149 | + fixed4 transit = tex2D(_KeyholeTex, uv); |
| 150 | + |
| 151 | + fixed maskValue = transit.b; |
| 152 | + //get the edge factor and apply the gaussian blur on it |
| 153 | + fixed edgeFactor = isEdge(maskValue, _Cutoff); |
| 154 | + if (edgeFactor > 0.0) { |
| 155 | + fixed4 output = 0; |
| 156 | + fixed sum = 0; |
| 157 | + //gaussian blur stuff |
| 158 | + for (int x = -9; x <= 9; ++x) { |
| 159 | + fixed2 offset = float2(x, 0) * _MainTex_TexelSize.xy; |
| 160 | + fixed4 c = tex2D(_MainTex, i.uv + offset); |
| 161 | + fixed gauss = gaussian(_BlurAmount, x); |
| 162 | + |
| 163 | + output += c * gauss; |
| 164 | + sum += gauss; |
| 165 | + } |
| 166 | + //normalize and overlay our results onto the screen |
| 167 | + fixed4 blurred = output / sum; |
| 168 | + return lerp(tex2D(_MainTex, i.uv), blurred, _BlurEdgeRefine); |
| 169 | + } |
| 170 | + //if its not the right place to blur, just return the original screen color |
| 171 | + return tex2D(_MainTex, i.uv); |
| 172 | + } |
| 173 | + ENDCG |
| 174 | + } |
| 175 | + |
| 176 | + // Gaussian Blur Second Pass (index 2) |
| 177 | + Pass { |
| 178 | + CGPROGRAM |
| 179 | + #pragma vertex vp |
| 180 | + #pragma fragment fp |
| 181 | + |
| 182 | + //where all the rendering work is at |
| 183 | + fixed4 fp(v2f i) : SV_Target { |
| 184 | + //Scale the uv to desired center position |
| 185 | + fixed2 uv = i.uv1; |
| 186 | + uv -= 0.5; |
| 187 | + uv.x /= _Scale; //- 0.06f; |
| 188 | + uv.y /= _Scale; //- 0.02f; |
| 189 | + //uv /= _Scale; |
| 190 | + uv += 0.5; |
| 191 | + |
| 192 | + fixed4 transit = tex2D(_KeyholeTex, uv); |
| 193 | + |
| 194 | + fixed maskValue = transit.b; |
| 195 | + //get the edge factor and apply the gaussian blur on it |
| 196 | + fixed edgeFactor = isEdge(maskValue, _Cutoff); |
| 197 | + if (edgeFactor > 0.0) { |
| 198 | + fixed4 output = 0; |
| 199 | + fixed sum = 0; |
| 200 | + //gaussian blur stuff |
| 201 | + for (int y = -9; y <= 9; ++y) { |
| 202 | + fixed2 offset = float2(0, y) * _MainTex_TexelSize.xy; |
| 203 | + fixed4 c = tex2D(_MainTex, i.uv + offset); |
| 204 | + fixed gauss = gaussian(_BlurAmount, y); |
| 205 | + |
| 206 | + output += c * gauss; |
| 207 | + sum += gauss; |
| 208 | + } |
| 209 | + //normalize and overlay our results onto the screen |
| 210 | + fixed4 blurred = output / sum; |
| 211 | + return lerp(tex2D(_MainTex, i.uv), blurred, _BlurEdgeRefine); |
| 212 | + } |
| 213 | + //if its not the right place to blur, just return the original screen color |
| 214 | + return tex2D(_MainTex, i.uv); |
| 215 | + } |
| 216 | + ENDCG |
| 217 | + } |
| 218 | + } |
| 219 | +} |
0 commit comments