Files
adriadri6972 d3d9c5f833 upload project
2025-07-31 15:21:08 +02:00

151 lines
6.3 KiB
GLSL

Shader "Occlusion/Soft/DepthPreprocessing"
{
SubShader
{
Pass
{
Name "Environment Depth Preprocessing Pass"
ZWrite Off
CGPROGRAM
#pragma target 4.5
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ XR_LINEAR_DEPTH
#include "Utils.hlsl"
Texture2DArray_half _EnvironmentDepthTexture;
SamplerState sampler_EnvironmentDepthTexture;
float4 _EnvironmentDepthTexture_TexelSize;
struct Attributes
{
uint vertexId : SV_VertexID;
uint instanceId : SV_InstanceID;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
uint depthSlice : SV_RenderTargetArrayIndex;
};
float4 CalculateMinMaxDepth(float2 uv, float slice)
{
const int NUM_SAMPLES = 5;
static const float2 offsets[NUM_SAMPLES] =
{
float2(2.0f, 0.0f),
float2(0.0f, 2.0f),
float2(-2.0f, 0.0f),
float2(0.0f, 0.0f),
float2(0.0f, -2.0f)
};
float4 depths[NUM_SAMPLES];
const float2 onePixelOffset = _EnvironmentDepthTexture_TexelSize.xy;
float minDepth = 1.0f;
float maxDepth = 0.0f;
float depthSum = 0.0f;
int sampleIndex = 0;
// Find the local min and max, and collect all depth samples in the sampling grid
while (sampleIndex < NUM_SAMPLES)
{
float2 uvSample = uv + (offsets[sampleIndex] + 0.5f) * onePixelOffset;
depths[sampleIndex] = _EnvironmentDepthTexture.Gather(sampler_EnvironmentDepthTexture, float3(uvSample.x, uvSample.y, slice));
#ifdef XR_LINEAR_DEPTH
depths[sampleIndex].x = ConvertDepthToNonSymmetricRange(LinearDepthToSymmetricRangeNDC(depths[sampleIndex].x));
depths[sampleIndex].y = ConvertDepthToNonSymmetricRange(LinearDepthToSymmetricRangeNDC(depths[sampleIndex].y));
depths[sampleIndex].z = ConvertDepthToNonSymmetricRange(LinearDepthToSymmetricRangeNDC(depths[sampleIndex].z));
depths[sampleIndex].w = ConvertDepthToNonSymmetricRange(LinearDepthToSymmetricRangeNDC(depths[sampleIndex].w));
#endif
depthSum += dot(depths[sampleIndex], float4(0.25f, 0.25, 0.25, 0.25));
float localMax = max(max(depths[sampleIndex].x, depths[sampleIndex].y), max(depths[sampleIndex].z, depths[sampleIndex].w));
float localMin = min(min(depths[sampleIndex].x, depths[sampleIndex].y), min(depths[sampleIndex].z, depths[sampleIndex].w));
maxDepth = max(maxDepth, localMax);
minDepth = min(minDepth, localMin);
sampleIndex++;
}
float maxSumDepth = 0.0f;
float minSumDepth = 0.0f;
float maxSumCount = 0.0f;
float minSumCount = 0.0f;
const float kMaxDepthMultiplier = 0.8846f; // depths scaled symmetric to 1.15 scale. 1-1/1.15==0.13 k=1/(1+0.13)==0.8846
const float kMinDepthMultiplier = 1.15f;
const float normalDepthScale = 1.0f;
const float depthReciprocalScaleMax = 1.0f / kMaxDepthMultiplier;
const float depthReciprocalScaleMin = 1.0f / kMinDepthMultiplier;
const float depthMaxBase = 1.0f - normalDepthScale * depthReciprocalScaleMax;
const float depthMinBase = 1.0f - normalDepthScale * depthReciprocalScaleMin;
// Adjusting depth thresholds by applying reciprocal scaling to modify depth impact
float depthThrMax = depthMaxBase + maxDepth * depthReciprocalScaleMax;
float depthThrMin = depthMinBase + minDepth * depthReciprocalScaleMin;
float avg = depthSum * (1.0f / float(NUM_SAMPLES));
if (depthThrMax < minDepth && depthThrMin > maxDepth)
{
// Degenerate case: the entire neighborhood is within min-max thresholds for averaging
// therefore minAvg == maxAvg == avg.
// Directly output the encoded fragColor as:
// (1 - minAvg, 1 - maxAvg, avg - minAvg, maxAvg - minAvg)
return float4(1.0f - avg, 1.0f - avg, 0.0f, 0.0f);
}
sampleIndex = 0;
while (sampleIndex < NUM_SAMPLES)
{
float4 maxMask = depths[sampleIndex] >= float4(depthThrMax, depthThrMax, depthThrMax, depthThrMax);
float4 minMask = depths[sampleIndex] <= float4(depthThrMin, depthThrMin, depthThrMin, depthThrMin);
minSumDepth += dot(minMask, depths[sampleIndex]);
minSumCount += dot(minMask, float4(1.0f, 1.0f, 1.0f, 1.0f));
maxSumDepth += dot(maxMask, depths[sampleIndex]);
maxSumCount += dot(maxMask, float4(1.0f, 1.0f, 1.0f, 1.0f));
// Value used to interpolate occlusion alphas between min and max values
sampleIndex++;
}
float minAvg = minSumDepth / minSumCount;
float maxAvg = maxSumDepth / maxSumCount;
return float4(1 - minAvg, 1 - maxAvg, avg - minAvg, maxAvg - minAvg);
}
Varyings vert(const Attributes input)
{
Varyings output;
const uint vertexID = input.vertexId;
const float2 uv = float2(vertexID << 1 & 2, vertexID & 2);
output.uv = float2(uv.x, 1.0 - uv.y);
output.positionCS = float4(uv * 2.0 - 1.0, 1.0, 1.0);
output.depthSlice = input.instanceId;
return output;
}
float4 frag(const Varyings input) : SV_Target
{
return CalculateMinMaxDepth(input.uv, input.depthSlice);
}
ENDCG
}
}
}