#include "Sampling.hlsl" //Always present in every shader TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex); //Present in every shader TEXTURE2D_SAMPLER2D(_CameraDepthNormalsTexture, sampler_CameraDepthNormalsTexture); float4 _MainTex_TexelSize; #define fixed half #define fixed2 half2 #define fixed3 half3 #define fixed4 half4 #define fixed4x4 half4x4 #define fixed3x3 half3x3 #define fixed2x2 half2x2 #define sampler2D_half sampler2D #define sampler2D_float sampler2D #define samplerCUBE_half samplerCUBE #define samplerCUBE_float samplerCUBE //------------------------------------------------------------------------------------------------------ // Blend Functions //------------------------------------------------------------------------------------------------------ half4 BlendOperation_Burn(half4 Base, half4 Blend, half Opacity) { half4 Out = 1.0 - (1.0 - Blend) / Base; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Darken(half4 Base, half4 Blend, half Opacity) { half4 Out = min(Blend, Base); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Difference(half4 Base, half4 Blend, half Opacity) { half4 Out = abs(Blend - Base); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Dodge(half4 Base, half4 Blend, half Opacity) { half4 Out = Base / (1.0 - Blend); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Divide(half4 Base, half4 Blend, half Opacity) { half4 Out = Base / (Blend + 0.000000000001); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Exclusion(half4 Base, half4 Blend, half Opacity) { half4 Out = Blend + Base - (2.0 * Blend * Base); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_HardLight(half4 Base, half4 Blend, half Opacity) { float4 result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend); float4 result2 = 2.0 * Base * Blend; float4 zeroOrOne = step(Blend, 0.5); half4 Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_HardMix(half4 Base, half4 Blend, half Opacity) { half4 Out = step(1 - Base, Blend); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Lighten(half4 Base, half4 Blend, half Opacity) { half4 Out = max(Blend, Base); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_LinearBurn(half4 Base, half4 Blend, half Opacity) { half4 Out = Base + Blend - 1.0; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_LinearDodge(half4 Base, half4 Blend, half Opacity) { half4 Out = Base + Blend; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_LinearLight(half4 Base, half4 Blend, half Opacity) { half4 Out = Blend < 0.5 ? max(Base + (2 * Blend) - 1, 0): min(Base + 2 * (Blend - 0.5), 1); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_LinearLightAddSub(half4 Base, half4 Blend, half Opacity) { half4 Out = Blend + 2.0 * Base - 1.0; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Multiply(half4 Base, half4 Blend, half Opacity) { half4 Out = Base * Blend; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Negation(half4 Base, half4 Blend, half Opacity) { half4 Out = 1.0 - abs(1.0 - Blend - Base); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Overlay(half4 Base, half4 Blend, half Opacity) { half4 result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend); half4 result2 = 2.0 * Base * Blend; half4 zeroOrOne = step(Base, 0.5); half4 Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_PinLight(half4 Base, half4 Blend, half Opacity) { half4 check = step(0.5, Blend); half4 result1 = check * max(2.0 * (Base - 0.5), Blend); half4 Out = result1 + (1.0 - check) * min(2.0 * Base, Blend); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Screen(half4 Base, half4 Blend, half Opacity) { half4 Out = 1.0 - (1.0 - Blend) * (1.0 - Base); Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_SoftLight(half4 Base, half4 Blend, half Opacity) { half4 result1 = 2.0 * Base * Blend + Base * Base * (1.0 - 2.0 * Blend); half4 result2 = sqrt(Base) * (2.0 * Blend - 1.0) + 2.0 * Base * (1.0 - Blend); half4 zeroOrOne = step(0.5, Blend); half4 Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Subtract(half4 Base, half4 Blend, half Opacity) { half4 Out = Base - Blend; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_VividLight(half4 Base, half4 Blend, half Opacity) { half4 result1 = 1.0 - (1.0 - Blend) / (2.0 * Base); half4 result2 = Blend / (2.0 * (1.0 - Base)); half4 zeroOrOne = step(0.5, Base); half4 Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1; Out = lerp(Base, Out, Opacity); return Out; } half4 BlendOperation_Overwrite(half4 Base, half4 Blend, half Opacity) { half4 Out = lerp(Base, Blend, Opacity); return Out; } //------------------------------------------------------------------------------------------------------ // Generic functions //------------------------------------------------------------------------------------------------------ float rand(float n) { return frac(sin(n) * 13758.5453123 * 0.01); } float rand(float2 n) { return frac(sin(dot(n, float2(12.9898, 78.233))) * 43758.5453); } float2 RotateUV(float2 uv, float rotation) { float cosine = cos(rotation); float sine = sin(rotation); float2 pivot = float2(0.5, 0.5); float2 rotator = (mul(uv - pivot, float2x2(cosine, -sine, sine, cosine)) + pivot); return saturate(rotator); } float3 ChromaticAberration(TEXTURE2D_ARGS(tex, samplerTex), float4 texelSize, float2 uv, float amount) { float2 direction = normalize((float2(0.5, 0.5) - uv)); float3 distortion = float3(-texelSize.x * amount, 0, texelSize.x * amount); float red = SAMPLE_TEXTURE2D(tex, samplerTex, uv + direction * distortion.r).r; float green = SAMPLE_TEXTURE2D(tex, samplerTex, uv + direction * distortion.g).g; float blue = SAMPLE_TEXTURE2D(tex, samplerTex, uv + direction * distortion.b).b; return float3(red, green, blue); } /* float3 PositionFromDepth(float depth, float2 uv, float4 inverseViewMatrix) { float4 clip = float4((uv.xy * 2.0f - 1.0f) * float2(1, -1), 0.0f, 1.0f); float3 worldDirection = mul(inverseViewMatrix, clip) - _WorldSpaceCameraPos; float3 worldspace = worldDirection * depth + _WorldSpaceCameraPos; return float3(frac((worldspace.rgb)) + float3(0, 0, 0.1)); } */ // (returns 1.0 when orthographic) float CheckPerspective(float x) { return lerp(x, 1.0, unity_OrthoParams.w); } // Reconstruct view-space position from UV and depth. float3 ReconstructViewPos(float2 uv, float depth) { float3 worldPos = float3(0, 0, 0); worldPos.xy = (uv.xy * 2.0 - 1.0 - float2(unity_CameraProjection._13, unity_CameraProjection._23)) / float2(unity_CameraProjection._11, unity_CameraProjection._22) * CheckPerspective(depth); worldPos.z = depth; return worldPos; } float2 FisheyeUV(half2 uv, half amount, half zoom) { half2 center = uv.xy - half2(0.5, 0.5); half CdotC = dot(center, center); half f = 1.0 + CdotC * (amount * sqrt(CdotC)); return f * zoom * center + 0.5; } float2 Distort(float2 uv) { #if DISTORT { uv = (uv - 0.5) * _Distortion_Amount.z + 0.5; float2 ruv = _Distortion_CenterScale.zw * (uv - 0.5 - _Distortion_CenterScale.xy); float ru = length(float2(ruv)); UNITY_BRANCH if (_Distortion_Amount.w > 0.0) { float wu = ru * _Distortion_Amount.x; ru = tan(wu) * (1.0 / (ru * _Distortion_Amount.y)); uv = uv + ruv * (ru - 1.0); } else { ru = (1.0 / ru) * _Distortion_Amount.x * atan(ru * _Distortion_Amount.y); uv = uv + ruv * (ru - 1.0); } } #endif return uv; } //---------------------------------------------------------------- // Common vertex functions //-------------------------------------------------------------- float4 _BlurOffsets; struct v2fGaussian { float4 pos: POSITION; float2 uv: TEXCOORD0; float4 uv01: TEXCOORD1; float4 uv23: TEXCOORD2; float4 uv45: TEXCOORD3; }; v2fGaussian VertGaussian(AttributesDefault v) { v2fGaussian o; o.pos = float4(v.vertex.xy, 0, 1); o.uv.xy = TransformTriangleVertexToUV(o.pos.xy); #if UNITY_UV_STARTS_AT_TOP o.uv = o.uv * float2(1.0, -1.0) + float2(0.0, 1.0); #endif //UNITY_SINGLE_PASS_STEREO o.uv = TransformStereoScreenSpaceTex(o.uv, 1.0); o.uv01 = o.uv.xyxy + _BlurOffsets.xyxy * float4(1, 1, -1, -1); o.uv23 = o.uv.xyxy + _BlurOffsets.xyxy * float4(1, 1, -1, -1) * 2.0; o.uv45 = o.uv.xyxy + _BlurOffsets.xyxy * float4(1, 1, -1, -1) * 6.0; return o; } float4 FragBlurBox(VaryingsDefault i): SV_Target { return DownsampleBox4Tap(TEXTURE2D_PARAM(_MainTex, sampler_MainTex), i.texcoord, _BlurOffsets.xy).rgba; } float4 FragBlurGaussian(v2fGaussian i): SV_Target { half4 color = float4(0, 0, 0, 0); color += 0.40 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); color += 0.15 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.xy); color += 0.15 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.zw); color += 0.10 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.xy); color += 0.10 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.zw); color += 0.05 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.xy); color += 0.05 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.zw); return color; } half simpleNoise(half x, half y, half seed, half phase) { half n = x * y * phase * seed; return fmod(n, 13) * fmod(n, 123); } half3 Lut2D(TEXTURE2D_ARGS(tex, samplerTex), float3 uvw, float2 texelSize, half tileAmount) { uvw.z *= tileAmount; float shift = floor(uvw.z); uvw.xy = uvw.xy * tileAmount * texelSize.xy + texelSize.xy * 0.5; uvw.x += shift * texelSize.y; uvw.xyz = lerp( SAMPLE_TEXTURE2D(tex, samplerTex, uvw.xy).rgb, SAMPLE_TEXTURE2D(tex, samplerTex, uvw.xy + float2(texelSize.y, 0.0)).rgb, uvw.z - shift ); return uvw; } half3 Lut2D_InvertY(TEXTURE2D_ARGS(tex, samplerTex), float3 uvw, float2 texelSize, half tileAmount) { // Strip format where `height = sqrt(width)` uvw.z *= tileAmount; float shift = floor(uvw.z); uvw.xy = uvw.xy * tileAmount * texelSize.xy + texelSize.xy * 0.5; uvw.x += shift * texelSize.y; //uvw.y = 1 - uvw.y; uvw.xyz = lerp( SAMPLE_TEXTURE2D(tex, samplerTex, uvw.xy).rgb, SAMPLE_TEXTURE2D(tex, samplerTex, uvw.xy + float2(texelSize.y, 0.0)).rgb, uvw.z - shift ); return uvw; } //------------------------------------------------------------------------------------------- // Lift, Gamma (pre-inverted), Gain tuned for HDR use - best used with the ACES tonemapper as // negative values will creep in the result // Expected workspace: ACEScg (linear) //------------------------------------------------------------------------------------------- half3 LiftGammaGain_HDR(half3 c, half3 lift, float3 invgamma, half3 gain) { c = c * gain + lift; // ACEScg will output negative values, as clamping to 0 will lose precious information we'll // mirror the gamma function instead return FastSign(c) * pow(abs(c), invgamma); } half3 Luminance_V1(half3 color) { return(color.r * 0.3 + color.g * 0.59 + color.b * 0.11); } half Luminance_V2(half3 color) { return dot(color, half3(0.222, 0.707, 0.071)); } half4 LuminanceThreshold(half4 color, half threshold) { half br = Max3(color.r, color.g, color.b); half contrib = max(0, br - threshold); contrib /= max(br, 0.001); return color * contrib; } float4 GetDepthNormal_ViewSpace(float2 uv) { float4 cdn = SAMPLE_TEXTURE2D(_CameraDepthNormalsTexture, sampler_CameraDepthNormalsTexture, uv); float4 Normal_ViewSpace = float4(DecodeViewNormalStereo(cdn), 1); return Normal_ViewSpace; } float GetSinusoidWave(float len, float pi, float time) { float wave = sin(8.0f * pi * len + time); wave = 0.5 * wave + 0.2; wave *= wave * wave; return wave; }