// 
 | 
// 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 
 | 
        } 
 | 
    } 
 | 
} 
 |