#ifndef SSR_BLENDS #define SSR_BLENDS // Copyright (c) Kronnect - All Rights Reserved. #if UNITY_VERSION < 202100 #define kMaterialFlagSpecularSetup 0 #define UnpackMaterialFlags(x) x #else #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityGBuffer.hlsl" #endif TEXTURE2D_X(_MainTex); float4 _MainTex_TexelSize; float4 _SSRSettings; #define THICKNESS _SSRSettings.x float4 _SSRSettings4; #define SEPARATION_POS _SSRSettings4.x #define REFLECTIONS_MIN_INTENSITY _SSRSettings4.y #define REFLECTIONS_MAX_INTENSITY _SSRSettings4.z float _MinimumBlur; float _MinimumThickness; #define MINIMUM_THICKNESS _MinimumThickness float4 _SSRSettings2; #define REFLECTIONS_MULTIPLIER _SSRSettings2.z float4 _SSRSettings6; #define NEAR_CAMERA_ATTENUATION_START _SSRSettings6.x #define NEAR_CAMERA_ATTENUATION_RANGE _SSRSettings6.y #define METALLIC_BOOST _SSRSettings6.z #define METALLIC_BOOST_THRESHOLD _SSRSettings6.w float4 _SSRSettings7; #define FAR_CAMERA_ATTENUATION_START _SSRSettings7.x #define FAR_CAMERA_ATTENUATION_RANGE _SSRSettings7.y #define MAX_BRIGHTNESS _SSRSettings7.z #define MAX_REFLECTION_DISTANCE (FAR_CAMERA_ATTENUATION_START + FAR_CAMERA_ATTENUATION_RANGE) float _EdgeAwareEnabled; float _DebugDepthMultiplier; TEXTURE2D_X(_RayCastRT); TEXTURE2D_X(_BlurRTMip0); TEXTURE2D_X(_BlurRTMip1); TEXTURE2D_X(_BlurRTMip2); TEXTURE2D_X(_BlurRTMip3); TEXTURE2D_X(_BlurRTMip4); TEXTURE2D_X(_GBuffer0); TEXTURE2D_X(_GBuffer1); TEXTURE2D_X(_GBuffer2); // for normals debug TEXTURE2D_X(_SmoothnessMetallicRT); TEXTURE2D_X(_SSRCustomDepthTexture); struct AttributesFS { float4 positionHCS : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct VaryingsSSR { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO }; VaryingsSSR VertSSR(AttributesFS input) { VaryingsSSR output; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); output.positionCS = float4(input.positionHCS.xyz, 1.0); #if UNITY_UV_STARTS_AT_TOP output.positionCS.y *= -1; #endif output.uv = input.uv; return output; } half4 FragCopy (VaryingsSSR i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); i.uv = SSRStereoTransformScreenSpaceTex(i.uv); half4 pixel = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv); return pixel; } half4 FragCopyExact (VaryingsSSR i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); i.uv = SSRStereoTransformScreenSpaceTex(i.uv); half4 pixel = SAMPLE_TEXTURE2D_X(_MainTex, sampler_PointClamp, i.uv); pixel = max(pixel, 0.0); return pixel; } half4 FragCopyDepth (VaryingsSSR i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); i.uv = UnityStereoTransformScreenSpaceTex(i.uv); float rawDepth = SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, i.uv.xy).r; float depth; #if SSR_ORTHO_SUPPORT #if UNITY_REVERSED_Z float orthoRawDepth = 1.0 - rawDepth; #else float orthoRawDepth = rawDepth; #endif depth = lerp(_ProjectionParams.y, _ProjectionParams.z, orthoRawDepth); #else depth = LinearEyeDepth(rawDepth, _ZBufferParams); #endif #if SSR_DEPTH_PREPASS float depthPrepassRaw = SAMPLE_TEXTURE2D_X(_SSRCustomDepthTexture, sampler_PointClamp, i.uv.xy).r; float depthPrepass; #if SSR_ORTHO_SUPPORT #if UNITY_REVERSED_Z float orthoRawPrepass = 1.0 - depthPrepassRaw; #else float orthoRawPrepass = depthPrepassRaw; #endif depthPrepass = lerp(_ProjectionParams.y, _ProjectionParams.z, orthoRawPrepass); #else depthPrepass = LinearEyeDepth(depthPrepassRaw, _ZBufferParams); #endif depth = min(depth, depthPrepass); #endif #if SSR_BACK_FACES float backDepthRaw = SAMPLE_TEXTURE2D_X(_DownscaledShinyBackDepthRT, sampler_PointClamp, i.uv.xy).r; float backDepth; #if SSR_ORTHO_SUPPORT #if UNITY_REVERSED_Z float orthoRawBack = 1.0 - backDepthRaw; #else float orthoRawBack = backDepthRaw; #endif backDepth = lerp(_ProjectionParams.y, _ProjectionParams.z, orthoRawBack); #else backDepth = LinearEyeDepth(backDepthRaw, _ZBufferParams); #endif backDepth = clamp(backDepth, depth + MINIMUM_THICKNESS, depth + THICKNESS); return half4(depth, backDepth, 0, 1.0); #else return half4(depth.xxx, 1.0); #endif } half4 Combine(VaryingsSSR i) { half4 mip2 = SAMPLE_TEXTURE2D_X_LOD(_BlurRTMip1, sampler_LinearClamp, i.uv, 0); if (mip2.w <= 0) return half4(0,0,0,0); float depth = GetLinearDepth(i.uv); if (depth > MAX_REFLECTION_DISTANCE) return half4(0,0,0,0); half4 reflData = SAMPLE_TEXTURE2D_X_LOD(_RayCastRT, sampler_PointClamp, i.uv, 0); #if SSR_SKYBOX if (reflData.w < 0) { // skybox reflection reflData.z = (1.0 - saturate(-reflData.w)) * 5.0; } #endif #if SSR_DARK_REFLECTIONS half reflInt = clamp(reflData.w * REFLECTIONS_MULTIPLIER, REFLECTIONS_MIN_INTENSITY, REFLECTIONS_MAX_INTENSITY); reflInt /= max(1.0 + reflData.z, _MinimumBlur); half4 refl; refl.a = saturate(reflInt); refl.rgb = 0; #else half4 mip0 = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv); half4 mip1 = SAMPLE_TEXTURE2D_X(_BlurRTMip0, sampler_LinearClamp, i.uv); half4 mip3 = SAMPLE_TEXTURE2D_X(_BlurRTMip2, sampler_LinearClamp, i.uv); half4 mip4 = SAMPLE_TEXTURE2D_X(_BlurRTMip3, sampler_LinearClamp, i.uv); half4 mip5 = SAMPLE_TEXTURE2D_X(_BlurRTMip4, sampler_LinearClamp, i.uv); half r = mip5.a; if (reflData.z > 0) { r = min(reflData.z, r); } half roughness = clamp(r + _MinimumBlur, 0, 5); half w0 = max(0, 1.0 - roughness); half w1 = max(0, 1.0 - abs(roughness - 1.0)); half w2 = max(0, 1.0 - abs(roughness - 2.0)); half w3 = max(0, 1.0 - abs(roughness - 3.0)); half w4 = max(0, 1.0 - abs(roughness - 4.0)); half w5 = max(0, 1.0 - abs(roughness - 5.0)); if (_EdgeAwareEnabled > 0.5) { w3 *= mip3.w; w4 *= mip4.w; w5 *= mip5.w; } half4 refl = mip0 * w0 + mip1 * w1 + mip2 * w2 + mip3 * w3 + mip4 * w4 + mip5 * w5; refl.a = 0; #if SSR_METALLIC_BOOST #if SSR_CUSTOM_SMOOTHNESS_METALLIC_PASS float2 smoothnessMetallic = SAMPLE_TEXTURE2D_X(_SmoothnessMetallicRT, sampler_PointClamp, i.uv).rg; float reflectivity = smoothnessMetallic.g; #else float4 gbuffer0 = SAMPLE_TEXTURE2D_X(_GBuffer0, sampler_PointClamp, i.uv); float4 gbuffer1 = SAMPLE_TEXTURE2D_X(_GBuffer1, sampler_PointClamp, i.uv); float reflectivity; uint materialFlags = UnpackMaterialFlags(gbuffer0.a); if (materialFlags & kMaterialFlagSpecularSetup) { reflectivity = max(gbuffer1.r, max(gbuffer1.g, gbuffer1.b)); } else { reflectivity = gbuffer1.r; } #endif refl.rgb = 0.5 + (refl.rgb - 0.5) * (1.0 + max(0, (reflectivity - METALLIC_BOOST_THRESHOLD) * METALLIC_BOOST)); #endif #endif // attenuates near to camera if (NEAR_CAMERA_ATTENUATION_START > 0) { refl *= saturate ( (depth - NEAR_CAMERA_ATTENUATION_START) / NEAR_CAMERA_ATTENUATION_RANGE); } // clamp maximum brightness to prevent overly bright spots refl.rgb = min(refl.rgb, MAX_BRIGHTNESS); return refl; } half4 FragCombine (VaryingsSSR i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); i.uv = SSRStereoTransformScreenSpaceTex(i.uv); return Combine(i); } half4 FragCombineWithCompare (VaryingsSSR i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); i.uv = SSRStereoTransformScreenSpaceTex(i.uv); if (i.uv.x < SEPARATION_POS - _MainTex_TexelSize.x * 3) { return 0; } else if (i.uv.x < SEPARATION_POS + _MainTex_TexelSize.x * 3) { return 1.0; } else { return Combine(i); } } half4 FragDebugDepth (VaryingsSSR i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); i.uv = SSRStereoTransformScreenSpaceTex(i.uv); float depth = GetLinearDepth(i.uv); depth *= _DebugDepthMultiplier; return half4(depth.xxx, 1.0); } half4 FragDebugNormals (VaryingsSSR i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); i.uv = SSRStereoTransformScreenSpaceTex(i.uv); float4 normals = SAMPLE_TEXTURE2D_X_LOD(_GBuffer2, sampler_PointClamp, i.uv, 0); #if defined(_GBUFFER_NORMALS_OCT) half2 remappedOctNormalWS = Unpack888ToFloat2(normals.xyz); // values between [ 0, 1] half2 octNormalWS = remappedOctNormalWS.xy * 2.0h - 1.0h; // values between [-1, +1] float3 normalWS = UnpackNormalOctQuadEncode(octNormalWS); #else float3 normalWS = normals.xyz; #endif return half4(normalWS, 1.0); } #endif // SSR_BLENDS