154 lines
5.4 KiB
HLSL
154 lines
5.4 KiB
HLSL
#ifndef SSR_SOLVE
|
|
#define SSR_SOLVE
|
|
|
|
// Copyright 2021 Kronnect - All Rights Reserved.
|
|
TEXTURE2D_X(_MainTex);
|
|
float4 _MainTex_TexelSize;
|
|
TEXTURE2D_X(_RayCastRT);
|
|
float4 _RayCastRT_TexelSize;
|
|
TEXTURE2D_X(_ReflectionsOpaqueRT);
|
|
|
|
float4 _MaterialData;
|
|
#define FRESNEL _MaterialData.y
|
|
#define FUZZYNESS _MaterialData.z
|
|
|
|
float4 _SSRSettings2;
|
|
#define REFLECTIONS_MULTIPLIER _SSRSettings2.z
|
|
|
|
float4 _SSRSettings7;
|
|
#define VIGNETTE_RADIAL _SSRSettings7.w
|
|
|
|
float4 _SSRSettings4;
|
|
#define REFLECTIONS_MIN_INTENSITY _SSRSettings4.y
|
|
#define REFLECTIONS_MAX_INTENSITY _SSRSettings4.z
|
|
|
|
float4 _SSRSettings5;
|
|
#define SKYBOX_INTENSITY _SSRSettings5.z
|
|
#define OPAQUE_REFLECTIONS_BLENDING _SSRSettings5.w
|
|
|
|
samplerCUBE _SkyboxCubemap;
|
|
float3 _CameraViewDir;
|
|
#define CAMERA_VIEW_DIR _CameraViewDir
|
|
|
|
float4 _SSRBlurStrength;
|
|
#define VIGNETTE_SIZE _SSRBlurStrength.z
|
|
#define VIGNETTE_POWER _SSRBlurStrength.w
|
|
|
|
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 FragResolve (VaryingsSSR i) : SV_Target {
|
|
|
|
UNITY_SETUP_INSTANCE_ID(i);
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
|
|
i.uv = SSRStereoTransformScreenSpaceTex(i.uv);
|
|
|
|
half4 reflData = SAMPLE_TEXTURE2D_X(_RayCastRT, sampler_PointClamp, i.uv);
|
|
if (reflData.w == 0) return 0;
|
|
|
|
// anti-fireflies / despeckle
|
|
float2 texelSize = _RayCastRT_TexelSize.xy;
|
|
half4 reflData1 = SAMPLE_TEXTURE2D_X(_RayCastRT, sampler_PointClamp, i.uv + texelSize.xy);
|
|
half4 reflData2 = SAMPLE_TEXTURE2D_X(_RayCastRT, sampler_PointClamp, i.uv - texelSize.xy);
|
|
half4 reflData3 = SAMPLE_TEXTURE2D_X(_RayCastRT, sampler_PointClamp, i.uv + float2(texelSize.x, -texelSize.y));
|
|
half4 reflData4 = SAMPLE_TEXTURE2D_X(_RayCastRT, sampler_PointClamp, i.uv - float2(texelSize.x, -texelSize.y));
|
|
half w0 = 1.0 / (reflData.w + 1.0);
|
|
half w1 = 1.0 / (reflData1.w + 1.0);
|
|
half w2 = 1.0 / (reflData2.w + 1.0);
|
|
half w3 = 1.0 / (reflData3.w + 1.0);
|
|
half w4 = 1.0 / (reflData4.w + 1.0);
|
|
half dd = 1.0 / (w0 + w1 + w2 + w3 + w4);
|
|
reflData.w = (reflData.w * w0 + reflData1.w * w1 + reflData2.w * w2 + reflData3.w * w3 + reflData4.w * w4) * dd;
|
|
|
|
half4 reflection;
|
|
#if SSR_SKYBOX
|
|
if (reflData.w < 0) {
|
|
half smoothness = -reflData.w;
|
|
#if SSR_METALLIC_WORKFLOW
|
|
float reflectivity = length(reflData.xyz);
|
|
if (reflectivity <= 0) return 0;
|
|
float3 reflDir = reflData.xyz / reflectivity;
|
|
float reflectionIntensity = reflectivity * SKYBOX_INTENSITY;
|
|
#else
|
|
float3 reflDir = reflData.xyz;
|
|
float reflectionIntensity = smoothness * SKYBOX_INTENSITY;
|
|
#endif
|
|
reflection = texCUBE(_SkyboxCubemap, reflDir);
|
|
float fresnel = 1.0 - FRESNEL * (1.0 - abs(dot(reflDir, CAMERA_VIEW_DIR)));
|
|
float reflectionAmount = reflectionIntensity * fresnel;
|
|
float blurAmount = (1 - smoothness) * 5.0;
|
|
reflData.xy = float2(0.5, 0.5);
|
|
reflData.z = blurAmount + 0.001;
|
|
reflData.w = reflectionAmount;
|
|
} else
|
|
#endif
|
|
|
|
reflection = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, reflData.xy);
|
|
reflection.rgb = min(reflection.rgb, 8.0); // stop NAN pixels
|
|
|
|
#if SSR_METALLIC_WORKFLOW
|
|
half reflectionIntensity = reflData.a * REFLECTIONS_MULTIPLIER;
|
|
#else
|
|
half reflectionIntensity = clamp(reflData.a * REFLECTIONS_MULTIPLIER, REFLECTIONS_MIN_INTENSITY, REFLECTIONS_MAX_INTENSITY);
|
|
#endif
|
|
|
|
reflection.rgb *= reflectionIntensity;
|
|
reflection.rgb = min(reflection.rgb, 1.2); // clamp max brightness
|
|
|
|
// conserve energy
|
|
half4 pixel = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv);
|
|
reflection.rgb -= min(0.5, pixel.rgb * reflectionIntensity);
|
|
|
|
// keep blur factor in alpha channel
|
|
reflection.a = reflData.z;
|
|
|
|
// vignette attenuation
|
|
half2 reflDst = (reflData.xy - 0.5) * 2.0;
|
|
half vd;
|
|
if (VIGNETTE_RADIAL > 0.5) {
|
|
vd = dot2(reflDst);
|
|
} else {
|
|
half2 edgeDist = reflDst * reflDst;
|
|
vd = max(edgeDist.x, edgeDist.y);
|
|
}
|
|
half vignette = saturate(VIGNETTE_SIZE - vd);
|
|
reflection *= vignette;
|
|
|
|
#if SSR_BLEND_REFLECTIONS
|
|
half4 reflOpaque = SAMPLE_TEXTURE2D_X(_ReflectionsOpaqueRT, sampler_LinearClamp, i.uv);
|
|
half lumaReflection = Luminance(reflection.rgb);
|
|
reflection = lerp(reflOpaque, reflection, saturate(lumaReflection * OPAQUE_REFLECTIONS_BLENDING));
|
|
#endif
|
|
|
|
return reflection;
|
|
}
|
|
|
|
|
|
|
|
#endif // SSR_SOLVE |