293 lines
10 KiB
HLSL
293 lines
10 KiB
HLSL
#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 |