#ifndef UTS_COMMON #define UTS_COMMON #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" #define inverselerp(a, b, x) saturate(((x) - (a)) / ((b) - (a))) #define APPLY_WEIGHT(x, y, t) lerp(x, x * y, t) float2 GetWHRatio() { return float2(_ScreenParams.y / _ScreenParams.x, 1); } float StepAntiAliasing(float x, float y) { float v = x - y; return saturate(v / fwidth(v) + HALF_MIN); //fwidth(x) = abs(ddx(x) + ddy(x)) } float Remap(float In, float2 InMinMax, float2 OutMinMax) { return OutMinMax.x + (In - InMinMax.x) * (OutMinMax.y - OutMinMax.x) / (InMinMax.y - InMinMax.x); } float3 ToonMaping(float3 x) { x = x * (2.51 * x + 0.03) / (x * (2.43 * x + 0.59) + 0.14); return x; } float3 GetSmoothedWorldNormal(float2 uv, float3x3 t_tbn) { float3 normal = float3(uv, 0); normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy))); return mul(normal, t_tbn); } float3 UtsComputeDiffuseColor(float3 baseColor, float metallic, float min) { #if _PBR_MODE_OFF return baseColor; #else return baseColor * (max(min, 1.0 - metallic)); #endif } float3 UtsComputeDiffuseColor(float3 baseColor, float metallic) { return UtsComputeDiffuseColor(baseColor, metallic, 0.0); } float Random(float2 uv) { return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453); } float unity_noise_interpolate (float a, float b, float t) { return (1.0-t)*a + (t*b); } float ValueNoise (float2 uv) { float2 i = floor(uv); float2 f = frac(uv); f = f * f * (3.0 - 2.0 * f); uv = abs(frac(uv) - 0.5); float2 c0 = i + float2(0.0, 0.0); float2 c1 = i + float2(1.0, 0.0); float2 c2 = i + float2(0.0, 1.0); float2 c3 = i + float2(1.0, 1.0); float r0 = Random(c0); float r1 = Random(c1); float r2 = Random(c2); float r3 = Random(c3); float bottomOfGrid = unity_noise_interpolate(r0, r1, f.x); float topOfGrid = unity_noise_interpolate(r2, r3, f.x); float t = unity_noise_interpolate(bottomOfGrid, topOfGrid, f.y); return t; } float SimpleNoise(float2 UV, float Scale) { float t = 0.0; float freq = pow(2.0, float(0)); float amp = pow(0.5, float(3-0)); t += ValueNoise(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp; freq = pow(2.0, float(1)); amp = pow(0.5, float(3-1)); t += ValueNoise(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp; freq = pow(2.0, float(2)); amp = pow(0.5, float(3-2)); t += ValueNoise(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp; return t; } #define SampleRampSignalLine(texture, u) (SAMPLE_TEXTURE2D_LOD(texture, s_linear_clamp_sampler, float2(u, 0.5), 0)) // Exposure float3 ApplyCurrentExposureMultiplier(float3 color) { return color * lerp(GetCurrentExposureMultiplier(), 1, _ToonIgnoreExposureMultiplier); } float3 ConvertFromEV100(float3 EV100) { float3 value = pow(2, EV100) * 2.5f; return value; } float3 ConvertToEV100(float3 value) { return log2(value * 0.4f); } float WeightSample(PositionInputs positionInput) { // Center-weighted const float2 kCenter = _ScreenParams.xy * 0.5; const float weight = pow(length((kCenter.xy - positionInput.positionSS.xy) / _ScreenParams.xy), 1.0); return 1.0 - saturate(weight); } float3 ApplyCompensation(float3 originalColor) { float3 ev100_Color = ConvertToEV100(originalColor) + _ToonEvAdjustmentCompensation * 0.5f; float3 resultColor = max(0, ConvertFromEV100(ev100_Color)); return resultColor; } float3 GetExposureAdjustedColor(float3 originalColor) { if (_ToonEvAdjustmentCurve != 0) { float3 ev100_Color = ConvertToEV100(originalColor); ev100_Color = clamp(ev100_Color, _ToonEvAdjustmentValueMin, _ToonEvAdjustmentValueMax); float3 ev100_remap = (ev100_Color - _ToonEvAdjustmentValueMin) * (128 - 1) / (_ToonEvAdjustmentValueMax - _ToonEvAdjustmentValueMin); ev100_remap = clamp(ev100_remap, 0.0, 127.0); int3 ev100_idx = (int3)ev100_remap; float3 ev100_lerp = ev100_remap - ev100_idx; float3 ev100_remapped; ev100_remapped.r = _ToonEvAdjustmentValueArray[ev100_idx.r] + (_ToonEvAdjustmentValueArray[ev100_idx.r + 1] - _ToonEvAdjustmentValueArray[ev100_idx.r]) * ev100_lerp.r; ev100_remapped.g = _ToonEvAdjustmentValueArray[ev100_idx.g] + (_ToonEvAdjustmentValueArray[ev100_idx.g + 1] - _ToonEvAdjustmentValueArray[ev100_idx.g]) * ev100_lerp.g; ev100_remapped.b = _ToonEvAdjustmentValueArray[ev100_idx.b] + (_ToonEvAdjustmentValueArray[ev100_idx.b + 1] - _ToonEvAdjustmentValueArray[ev100_idx.b]) * ev100_lerp.b; float3 resultColor = ConvertFromEV100(ev100_remapped); return resultColor; } else // else is neccessary to avoid warrnings. { return originalColor; } } void ApplyExposureAdjustment(inout float3 color) { color = GetExposureAdjustedColor(color); color = ApplyCompensation(color); } // ---------------------------------------------------------------------------- // Transform // ---------------------------------------------------------------------------- float3 ProjectOnPlane(float3 vec, float3 normal) { return vec - normal * dot(vec, normal); } float2 RotateUV(float2 _uv, float _radian, float2 _piv, float _time) { float RotateUV_ang = _radian; float RotateUV_cos = cos(_time * RotateUV_ang); float RotateUV_sin = sin(_time * RotateUV_ang); return(mul(_uv - _piv, float2x2(RotateUV_cos, -RotateUV_sin, RotateUV_sin, RotateUV_cos)) + _piv); } // Anti-perspective form Colin: Counteract perspective effects by replacing regular depth with uniform depth uniform float _AntiPerspectiveIntensity; void AntiPerspective(inout float4 clipPos) { float centerVSz = mul(UNITY_MATRIX_V, float4(UNITY_MATRIX_M._m03_m13_m23, 1.0)).z; clipPos.xy *= lerp(1.0, abs(clipPos.w) / - centerVSz, _AntiPerspectiveIntensity); } // ASE float2 UnStereo(float2 UV) { #if UNITY_SINGLE_PASS_STEREO float4 scaleOffset = unity_StereoScaleOffset[ unity_StereoEyeIndex ]; UV.xy = (UV.xy - scaleOffset.zw) / scaleOffset.xy; #endif return UV; } // ---------------------------------------------------------------------------- // Color // ---------------------------------------------------------------------------- float3 ShiftColorPurity(float3 color, float purity) { return lerp(Luminance(color), color, purity); } void AlphaGammaCorrection(inout float a1, inout float a2, inout float a3, inout float a4) { float4 a = float4(a1, a2, a3, a4); a = pow(abs(a), 1 / 1.48); a1 = a.x; a2 = a.y; a3 = a.z; a4 = a.w; } void AlphaGammaCorrection(inout float alpha) { alpha = pow(abs(alpha), 1 / 1.48); } void AlphaGammaCorrection(inout float alpha, inout float alpha2) { AlphaGammaCorrection(alpha, alpha2, alpha, alpha); } void AlphaGammaCorrection(inout float alpha, inout float alpha2, inout float alpha3) { AlphaGammaCorrection(alpha, alpha2, alpha3, alpha3); } // ---------------------------------------------------------------------------- // Depth // ---------------------------------------------------------------------------- float LinearEyeDepth(float z) { return LinearEyeDepth(z, _ZBufferParams); } // https://forum.unity.com/threads/what-does-unity-exactly-do-when-we-modify-z-buffer-value-using-sv_depth.526406/ float LinearEyeDepthToOutDepth(float z) { return(1 - _ZBufferParams.w * z) / (_ZBufferParams.z * z); } // Returns the forward (Right) direction of the current view in the world space. float3 GetViewRightDir() { float4x4 viewMat = GetWorldToViewMatrix(); return viewMat[0].xyz; } // ASE float3 InvertDepthDirHD(float3 In) { float3 result = In; #if !defined(ASE_SRP_VERSION) || ASE_SRP_VERSION <= 70301 || ASE_SRP_VERSION == 70503 || ASE_SRP_VERSION >= 80301 result *= float3(1, 1, -1); #endif return result; } float4x4 unity_CameraProjection; float4x4 unity_CameraInvProjection; float4x4 unity_WorldToCamera; float4x4 unity_CameraToWorld; // ASE float3 GetWorldPosFromDepthBuffer(float2 clipPos01, float cameraDepth) { #ifdef UNITY_REVERSED_Z float depth = (1.0 - cameraDepth); #else float depth = cameraDepth; #endif float3 screenPos_DepthBuffer = (float3(clipPos01, depth)); float4 clipPos = (float4((screenPos_DepthBuffer * 2.0 - 1.0), 1.0)); float4 viewPos = mul(unity_CameraInvProjection, clipPos); float3 viewPosNorm = viewPos.xyz / viewPos.w; float3 localInvertDepthDirHD = InvertDepthDirHD(viewPosNorm); return mul(unity_CameraToWorld, float4(localInvertDepthDirHD, 1.0)).xyz; } #endif