Files
2026-03-10 10:07:11 +08:00

159 lines
4.3 KiB
HLSL

#ifndef BADDOG_WATER_SSR
#define BADDOG_WATER_SSR
float UVJitter(in float2 uv)
{
return frac((52.9829189 * frac(dot(uv, float2(0.06711056, 0.00583715)))));
}
void SSRRayConvert(float3 worldPos, out float4 clipPos, out float3 screenPos)
{
clipPos = TransformWorldToHClip(worldPos);
float k = ((1.0) / (clipPos.w));
screenPos.xy = ComputeScreenPos(clipPos).xy * k;
#if defined(_BGWATER_ORTHO_ON)
screenPos.z = GetOrthoEyeDepth(clipPos.z);
clipPos.w = screenPos.z;
#else
screenPos.z = k;
#endif
#if defined(UNITY_SINGLE_PASS_STEREO)
screenPos.xy = UnityStereoTransformScreenSpaceTex(screenPos.xy);
#endif
}
float3 SSRRayMarch(BGWaterVertexOutput vertexOutput, BGLightingData lightingData)
{
float4 startClipPos;
float3 startScreenPos;
SSRRayConvert(lightingData.worldPos, startClipPos, startScreenPos);
float4 endClipPos;
float3 endScreenPos;
SSRRayConvert(lightingData.worldPos + lightingData.R, endClipPos, endScreenPos);
if (((endClipPos.w) < (startClipPos.w)))
{
return float3(0, 0, 0);
}
float3 screenDir = endScreenPos - startScreenPos;
float screenDirX = abs(screenDir.x);
float screenDirY = abs(screenDir.y);
float dirMultiplier = lerp( 1 / (_ScreenParams.y * screenDirY), 1 / (_ScreenParams.x * screenDirX), screenDirX > screenDirY ) * _SSRSampleStep;
screenDir *= dirMultiplier;
half lastRayDepth = startClipPos.w;
half sampleCount = 1 + UVJitter(vertexOutput.pos) * 0.1;
float3 lastScreenMarchUVZ = startScreenPos;
float lastDeltaDepth = 0;
#if defined (SHADER_API_OPENGL) || defined (SHADER_API_D3D11) || defined (SHADER_API_D3D12)
[unroll(64)]
#else
UNITY_LOOP
#endif
for(int i = 0; i < _SSRMaxSampleCount; i++)
{
float3 screenMarchUVZ = startScreenPos + screenDir * sampleCount;
if((screenMarchUVZ.x <= 0) || (screenMarchUVZ.x >= 1) || (screenMarchUVZ.y <= 0) || (screenMarchUVZ.y >= 1))
{
break;
}
#if defined(_BGWATER_ORTHO_ON)
float sceneDepth = GetOrthoEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, screenMarchUVZ.xy));
#else
float sceneDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, screenMarchUVZ.xy), _ZBufferParams);
#endif
#if defined(_BGWATER_ORTHO_ON)
half rayDepth = screenMarchUVZ.z;
#else
half rayDepth = 1.0 / screenMarchUVZ.z;
#endif
half deltaDepth = rayDepth - sceneDepth;
if((deltaDepth > 0) && (sceneDepth > startClipPos.w) && (deltaDepth < (abs(rayDepth - lastRayDepth) * 2)))
{
float samplePercent = saturate(lastDeltaDepth / (lastDeltaDepth - deltaDepth));
samplePercent = lerp(samplePercent, 1, rayDepth >= _ProjectionParams.z);
float3 hitScreenUVZ = lerp(lastScreenMarchUVZ, screenMarchUVZ, samplePercent);
return float3(hitScreenUVZ.xy, 1);
}
lastRayDepth = rayDepth;
sampleCount += 1;
lastScreenMarchUVZ = screenMarchUVZ;
lastDeltaDepth = deltaDepth;
}
float4 farClipPos;
float3 farScreenPos;
SSRRayConvert(lightingData.worldPos + lightingData.R * 100000, farClipPos, farScreenPos);
if((farScreenPos.x > 0) && (farScreenPos.x < 1) && (farScreenPos.y > 0) && (farScreenPos.y < 1))
{
#if defined(_BGWATER_ORTHO_ON)
float farDepth = GetOrthoEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, farScreenPos.xy));
#else
float farDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, farScreenPos.xy), _ZBufferParams);
#endif
if(farDepth > startClipPos.w)
{
return float3(farScreenPos.xy, 1);
}
}
return float3(0, 0, 0);
}
float3 GetSSRUVZ(BGWaterVertexOutput vertexOutput, BGLightingData lightingData)
{
#if defined(UNITY_SINGLE_PASS_STEREO)
half ssrWeight = 1;
half NoV = lightingData.NoV * 2;
ssrWeight *= (1 - NoV * NoV);
#else
float screenUV = lightingData.screenUV * 2 - 1;
screenUV *= screenUV;
half ssrWeight = saturate(1 - dot(screenUV, screenUV));
half NoV = lightingData.NoV * 2.5;
ssrWeight *= (1 - NoV * NoV);
#endif
if (ssrWeight > 0.005)
{
float3 uvz = SSRRayMarch(vertexOutput, lightingData);
uvz.z *= ssrWeight;
return uvz;
}
return float3(0, 0, 0);
}
float3 GetSSRUVZOrtho(BGWaterVertexOutput vertexOutput, BGLightingData lightingData)
{
float3 uvz = SSRRayMarch(vertexOutput, lightingData);
return uvz;
}
#endif