| // | 
| // Kino/Bloom v2 - Bloom filter for Unity | 
| // | 
| // Copyright (C) 2015, 2016 Keijiro Takahashi | 
| // | 
| // Permission is hereby granted, free of charge, to any person obtaining a copy | 
| // of this software and associated documentation files (the "Software"), to deal | 
| // in the Software without restriction, including without limitation the rights | 
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
| // copies of the Software, and to permit persons to whom the Software is | 
| // furnished to do so, subject to the following conditions: | 
| // | 
| // The above copyright notice and this permission notice shall be included in | 
| // all copies or substantial portions of the Software. | 
| // | 
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
| // THE SOFTWARE. | 
| // | 
| Shader "Hidden/Post FX/Bloom" | 
| { | 
|     Properties | 
|     { | 
|         _MainTex ("", 2D) = "" {} | 
|         _BaseTex ("", 2D) = "" {} | 
|         _AutoExposure ("", 2D) = "" {} | 
|     } | 
|   | 
|     CGINCLUDE | 
|   | 
|         #pragma target 3.0 | 
|         #include "UnityCG.cginc" | 
|         #include "Bloom.cginc" | 
|         #include "Common.cginc" | 
|   | 
|         sampler2D _BaseTex; | 
|         float2 _BaseTex_TexelSize; | 
|   | 
|         sampler2D _AutoExposure; | 
|   | 
|         float _PrefilterOffs; | 
|         float _Threshold; | 
|         float3 _Curve; | 
|         float _SampleScale; | 
|   | 
|         // ----------------------------------------------------------------------------- | 
|         // Vertex shaders | 
|   | 
|         struct VaryingsMultitex | 
|         { | 
|             float4 pos : SV_POSITION; | 
|             float2 uvMain : TEXCOORD0; | 
|             float2 uvBase : TEXCOORD1; | 
|         }; | 
|   | 
|         VaryingsMultitex VertMultitex(AttributesDefault v) | 
|         { | 
|             VaryingsMultitex o; | 
|             o.pos = UnityObjectToClipPos(v.vertex); | 
|             o.uvMain = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy, _MainTex_ST); | 
|             o.uvBase = o.uvMain; | 
|   | 
|         #if UNITY_UV_STARTS_AT_TOP | 
|             if (_BaseTex_TexelSize.y < 0.0) | 
|                 o.uvBase.y = 1.0 - o.uvBase.y; | 
|         #endif | 
|   | 
|             return o; | 
|         } | 
|   | 
|         // ----------------------------------------------------------------------------- | 
|         // Fragment shaders | 
|   | 
|         half4 FetchAutoExposed(sampler2D tex, float2 uv) | 
|         { | 
|             float autoExposure = 1.0; | 
|             uv = UnityStereoScreenSpaceUVAdjust(uv, _MainTex_ST); | 
|             autoExposure = tex2D(_AutoExposure, uv).r; | 
|             return tex2D(tex, uv) * autoExposure; | 
|         } | 
|   | 
|         half4 FragPrefilter(VaryingsDefault i) : SV_Target | 
|         { | 
|             float2 uv = i.uv + _MainTex_TexelSize.xy * _PrefilterOffs; | 
|   | 
|         #if ANTI_FLICKER | 
|             float3 d = _MainTex_TexelSize.xyx * float3(1.0, 1.0, 0.0); | 
|             half4 s0 = SafeHDR(FetchAutoExposed(_MainTex, uv)); | 
|             half3 s1 = SafeHDR(FetchAutoExposed(_MainTex, uv - d.xz).rgb); | 
|             half3 s2 = SafeHDR(FetchAutoExposed(_MainTex, uv + d.xz).rgb); | 
|             half3 s3 = SafeHDR(FetchAutoExposed(_MainTex, uv - d.zy).rgb); | 
|             half3 s4 = SafeHDR(FetchAutoExposed(_MainTex, uv + d.zy).rgb); | 
|             half3 m = Median(Median(s0.rgb, s1, s2), s3, s4); | 
|         #else | 
|             half4 s0 = SafeHDR(FetchAutoExposed(_MainTex, uv)); | 
|             half3 m = s0.rgb; | 
|         #endif | 
|   | 
|         #if UNITY_COLORSPACE_GAMMA | 
|             m = GammaToLinearSpace(m); | 
|         #endif | 
|   | 
|             // Pixel brightness | 
|             half br = Brightness(m); | 
|   | 
|             // Under-threshold part: quadratic curve | 
|             half rq = clamp(br - _Curve.x, 0.0, _Curve.y); | 
|             rq = _Curve.z * rq * rq; | 
|   | 
|             // Combine and apply the brightness response curve. | 
|             m *= max(rq, br - _Threshold) / max(br, 1e-5); | 
|   | 
|             return EncodeHDR(m); | 
|         } | 
|   | 
|         half4 FragDownsample1(VaryingsDefault i) : SV_Target | 
|         { | 
|         #if ANTI_FLICKER | 
|             return EncodeHDR(DownsampleAntiFlickerFilter(_MainTex, i.uvSPR, _MainTex_TexelSize.xy)); | 
|         #else | 
|             return EncodeHDR(DownsampleFilter(_MainTex, i.uvSPR, _MainTex_TexelSize.xy)); | 
|         #endif | 
|         } | 
|   | 
|         half4 FragDownsample2(VaryingsDefault i) : SV_Target | 
|         { | 
|             return EncodeHDR(DownsampleFilter(_MainTex, i.uvSPR, _MainTex_TexelSize.xy)); | 
|         } | 
|   | 
|         half4 FragUpsample(VaryingsMultitex i) : SV_Target | 
|         { | 
|             half3 base = DecodeHDR(tex2D(_BaseTex, i.uvBase)); | 
|             half3 blur = UpsampleFilter(_MainTex, i.uvMain, _MainTex_TexelSize.xy, _SampleScale); | 
|             return EncodeHDR(base + blur); | 
|         } | 
|   | 
|     ENDCG | 
|   | 
|     SubShader | 
|     { | 
|         ZTest Always Cull Off ZWrite Off | 
|   | 
|         Pass | 
|         { | 
|             CGPROGRAM | 
|                 #pragma multi_compile __ ANTI_FLICKER | 
|                 #pragma multi_compile __ UNITY_COLORSPACE_GAMMA | 
|                 #pragma vertex VertDefault | 
|                 #pragma fragment FragPrefilter | 
|             ENDCG | 
|         } | 
|   | 
|         Pass | 
|         { | 
|             CGPROGRAM | 
|                 #pragma multi_compile __ ANTI_FLICKER | 
|                 #pragma vertex VertDefault | 
|                 #pragma fragment FragDownsample1 | 
|             ENDCG | 
|         } | 
|   | 
|         Pass | 
|         { | 
|             CGPROGRAM | 
|                 #pragma vertex VertDefault | 
|                 #pragma fragment FragDownsample2 | 
|             ENDCG | 
|         } | 
|   | 
|         Pass | 
|         { | 
|             CGPROGRAM | 
|                 #pragma vertex VertMultitex | 
|                 #pragma fragment FragUpsample | 
|             ENDCG | 
|         } | 
|     } | 
| } |