| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
- Shader "Hidden/Tonemapper" {
- Properties {
- _MainTex ("", 2D) = "black" {}
- _SmallTex ("", 2D) = "grey" {}
- _Curve ("", 2D) = "black" {}
- }
-
- CGINCLUDE
-
- #include "UnityCG.cginc"
-
- struct v2f {
- float4 pos : SV_POSITION;
- float2 uv : TEXCOORD0;
- };
-
- sampler2D _MainTex;
- sampler2D _SmallTex;
- sampler2D _Curve;
-
- float4 _HdrParams;
- float2 intensity;
- float4 _MainTex_TexelSize;
- float _AdaptionSpeed;
- float _ExposureAdjustment;
- float _RangeScale;
-
- v2f vert( appdata_img v )
- {
- v2f o;
- o.pos = UnityObjectToClipPos(v.vertex);
- o.uv = v.texcoord.xy;
- return o;
- }
- float4 fragLog(v2f i) : SV_Target
- {
- const float DELTA = 0.0001f;
-
- float fLogLumSum = 0.0f;
-
- fLogLumSum += log( Luminance(tex2D(_MainTex, i.uv + _MainTex_TexelSize.xy * float2(-1,-1)).rgb) + DELTA);
- fLogLumSum += log( Luminance(tex2D(_MainTex, i.uv + _MainTex_TexelSize.xy * float2(1,1)).rgb) + DELTA);
- fLogLumSum += log( Luminance(tex2D(_MainTex, i.uv + _MainTex_TexelSize.xy * float2(-1,1)).rgb) + DELTA);
- fLogLumSum += log( Luminance(tex2D(_MainTex, i.uv + _MainTex_TexelSize.xy * float2(1,-1)).rgb) + DELTA);
- float avg = fLogLumSum / 4.0;
- return float4(avg, avg, avg, avg);
- }
- float4 fragExp(v2f i) : SV_Target
- {
- float2 lum = float2(0.0f, 0.0f);
-
- lum += tex2D(_MainTex, i.uv + _MainTex_TexelSize.xy * float2(-1,-1)).xy;
- lum += tex2D(_MainTex, i.uv + _MainTex_TexelSize.xy * float2(1,1)).xy;
- lum += tex2D(_MainTex, i.uv + _MainTex_TexelSize.xy * float2(1,-1)).xy;
- lum += tex2D(_MainTex, i.uv + _MainTex_TexelSize.xy * float2(-1,1)).xy;
- lum = exp(lum / 4.0f);
-
- return float4(lum.x, lum.y, lum.x, saturate(0.0125 * _AdaptionSpeed));
- }
-
- float3 ToCIE(float3 FullScreenImage)
- {
- // RGB -> XYZ conversion
- // http://www.w3.org/Graphics/Color/sRGB
- // The official sRGB to XYZ conversion matrix is (following ITU-R BT.709)
- // 0.4125 0.3576 0.1805
- // 0.2126 0.7152 0.0722
- // 0.0193 0.1192 0.9505
-
- float3x3 RGB2XYZ = {0.5141364, 0.3238786, 0.16036376, 0.265068, 0.67023428, 0.06409157, 0.0241188, 0.1228178, 0.84442666};
-
- float3 XYZ = mul(RGB2XYZ, FullScreenImage.rgb);
-
- // XYZ -> Yxy conversion
-
- float3 Yxy;
-
- Yxy.r = XYZ.g;
-
- // x = X / (X + Y + Z)
- // y = X / (X + Y + Z)
-
- float temp = dot(float3(1.0,1.0,1.0), XYZ.rgb);
-
- Yxy.gb = XYZ.rg / temp;
-
- return Yxy;
- }
-
- float3 FromCIE(float3 Yxy)
- {
- float3 XYZ;
- // Yxy -> XYZ conversion
- XYZ.r = Yxy.r * Yxy.g / Yxy. b;
-
- // X = Y * x / y
- XYZ.g = Yxy.r;
-
- // copy luminance Y
- XYZ.b = Yxy.r * (1 - Yxy.g - Yxy.b) / Yxy.b;
-
- // Z = Y * (1-x-y) / y
-
- // XYZ -> RGB conversion
- // The official XYZ to sRGB conversion matrix is (following ITU-R BT.709)
- // 3.2410 -1.5374 -0.4986
- // -0.9692 1.8760 0.0416
- // 0.0556 -0.2040 1.0570
-
- float3x3 XYZ2RGB = { 2.5651,-1.1665,-0.3986, -1.0217, 1.9777, 0.0439, 0.0753, -0.2543, 1.1892};
- return mul(XYZ2RGB, XYZ);
- }
-
- // NOTE/OPTIMIZATION: we're not going the extra CIE detour anymore, but
- // scale with the OUT/IN luminance ratio,this is sooooo much faster
-
- float4 fragAdaptive(v2f i) : SV_Target
- {
- float avgLum = tex2D(_SmallTex, i.uv).x;
- float4 color = tex2D (_MainTex, i.uv);
-
- float cieLum = max(0.000001, Luminance(color.rgb)); //ToCIE(color.rgb);
-
- float lumScaled = cieLum * _HdrParams.z / (0.001 + avgLum.x);
-
- lumScaled = (lumScaled * (1.0f + lumScaled / (_HdrParams.w)))/(1.0f + lumScaled);
-
- //cie.r = lumScaled;
-
- color.rgb = color.rgb * (lumScaled / cieLum);
-
- //color.rgb = FromCIE(cie);
- return color;
- }
-
- float4 fragAdaptiveAutoWhite(v2f i) : SV_Target
- {
- float2 avgLum = tex2D(_SmallTex, i.uv).xy;
- float4 color = tex2D(_MainTex, i.uv);
-
- float cieLum = max(0.000001, Luminance(color.rgb)); //ToCIE(color.rgb);
-
- float lumScaled = cieLum * _HdrParams.z / (0.001 + avgLum.x);
-
- lumScaled = (lumScaled * (1.0f + lumScaled / (avgLum.y*avgLum.y)))/(1.0f + lumScaled);
-
- //cie.r = lumScaled;
-
- color.rgb = color.rgb * (lumScaled / cieLum);
-
- //color.rgb = FromCIE(cie);
- return color;
- }
-
- float4 fragCurve(v2f i) : SV_Target
- {
- float4 color = tex2D(_MainTex, i.uv);
- float3 cie = ToCIE(color.rgb);
-
- // Remap to new lum range
- float newLum = tex2D(_Curve, float2(cie.r * _RangeScale, 0.5)).r;
- cie.r = newLum;
- color.rgb = FromCIE(cie);
-
- return color;
- }
-
- float4 fragHable(v2f i) : SV_Target
- {
- const float A = 0.15;
- const float B = 0.50;
- const float C = 0.10;
- const float D = 0.20;
- const float E = 0.02;
- const float F = 0.30;
- const float W = 11.2;
- float3 texColor = tex2D(_MainTex, i.uv).rgb;
- texColor *= _ExposureAdjustment;
- float ExposureBias = 2.0;
- float3 x = ExposureBias*texColor;
- float3 curr = ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
-
- x = W;
- float3 whiteScale = 1.0f/(((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F);
- float3 color = curr*whiteScale;
- // float3 retColor = pow(color,1/2.2); // we have SRGB write enabled at this stage
- return float4(color, 1.0);
- }
- // we are doing it on luminance here (better color preservation, but some other problems like very fast saturation)
- float4 fragSimpleReinhard(v2f i) : SV_Target
- {
- float4 texColor = tex2D(_MainTex, i.uv);
- float lum = Luminance(texColor.rgb);
- float lumTm = lum * _ExposureAdjustment;
- float scale = lumTm / (1+lumTm);
- return float4(texColor.rgb * scale / lum, texColor.a);
- }
-
- float4 fragOptimizedHejiDawson(v2f i) : SV_Target
- {
- float4 texColor = tex2D(_MainTex, i.uv );
- texColor *= _ExposureAdjustment;
- float4 X = max(float4(0.0,0.0,0.0,0.0), texColor-0.004);
- float4 retColor = (X*(6.2*X+.5))/(X*(6.2*X+1.7)+0.06);
- return retColor*retColor;
- }
- float4 fragPhotographic(v2f i) : SV_Target
- {
- float4 texColor = tex2D(_MainTex, i.uv);
- return 1-exp2(-_ExposureAdjustment * texColor);
- }
-
- float4 fragDownsample(v2f i) : SV_Target
- {
- float4 tapA = tex2D(_MainTex, i.uv + _MainTex_TexelSize * 0.5);
- float4 tapB = tex2D(_MainTex, i.uv - _MainTex_TexelSize * 0.5);
- float4 tapC = tex2D(_MainTex, i.uv + _MainTex_TexelSize * float2(0.5,-0.5));
- float4 tapD = tex2D(_MainTex, i.uv - _MainTex_TexelSize * float2(0.5,-0.5));
-
- float4 average = (tapA+tapB+tapC+tapD)/4;
- average.y = max(max(tapA.y,tapB.y), max(tapC.y,tapD.y));
-
- return average;
- }
-
- ENDCG
-
- Subshader {
- // adaptive reinhhard apply
- Pass {
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragAdaptive
- ENDCG
- }
- // 1
- Pass {
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragLog
- ENDCG
- }
- // 2
- Pass {
- ZTest Always Cull Off ZWrite Off
- Blend SrcAlpha OneMinusSrcAlpha
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragExp
- ENDCG
- }
- // 3
- Pass {
- ZTest Always Cull Off ZWrite Off
- Blend Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragExp
- ENDCG
- }
-
- // 4 user controllable tonemap curve
- Pass {
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragCurve
- ENDCG
- }
- // 5 tonemapping in uncharted
- Pass {
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragHable
- ENDCG
- }
- // 6 simple tonemapping based reinhard
- Pass {
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragSimpleReinhard
- ENDCG
- }
- // 7 OptimizedHejiDawson
- Pass {
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragOptimizedHejiDawson
- ENDCG
- }
-
- // 8 Photographic
- Pass {
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragPhotographic
- ENDCG
- }
- // 9 Downsample with auto white detection
- Pass {
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragDownsample
- ENDCG
- }
-
- // 10 adaptive reinhhard apply with auto white
- Pass {
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment fragAdaptiveAutoWhite
- ENDCG
- }
- }
- Fallback off
-
- } // shader
|