107 lines
3.6 KiB
Plaintext
107 lines
3.6 KiB
Plaintext
|
// Overlaps two projections, prioritizes closer pixels
|
||
|
|
||
|
Shader "Hidden/ftFarSphereProjClip"
|
||
|
{
|
||
|
Properties
|
||
|
{
|
||
|
}
|
||
|
SubShader
|
||
|
{
|
||
|
// No culling or depth
|
||
|
Cull Off ZWrite Off ZTest Always
|
||
|
|
||
|
Pass
|
||
|
{
|
||
|
CGPROGRAM
|
||
|
#pragma vertex vert
|
||
|
#pragma fragment frag
|
||
|
|
||
|
#include "UnityCG.cginc"
|
||
|
|
||
|
struct v2f
|
||
|
{
|
||
|
float4 vertex : SV_POSITION;
|
||
|
float2 uv : TEXCOORD0;
|
||
|
};
|
||
|
|
||
|
v2f vert (uint id : SV_VertexID)
|
||
|
{
|
||
|
v2f o;
|
||
|
float4 pos[6];
|
||
|
pos[0] = float4(-1, -1, 0.5, 1);
|
||
|
pos[1] = float4(-1, 1, 0.5, 1);
|
||
|
pos[2] = float4(1, 1, 0.5, 1);
|
||
|
|
||
|
pos[3] = float4(1, 1, 0.5, 1);
|
||
|
pos[4] = float4(1, -1, 0.5, 1);
|
||
|
pos[5] = float4(-1, -1, 0.5, 1);
|
||
|
|
||
|
o.vertex = pos[id];
|
||
|
o.uv = o.vertex.xy * 0.5f + 0.5f;
|
||
|
o.uv.y = 1.0f - o.uv.y;
|
||
|
return o;
|
||
|
}
|
||
|
|
||
|
sampler2D _CurDepth, _ProjDepth, _CurNormal;
|
||
|
float4x4 _CurInvViewProj, _ProjViewProj;
|
||
|
float3 _CurPos, _ProjPos;
|
||
|
float _InvCubeSize;
|
||
|
|
||
|
float4 ComputeClipSpacePosition(float2 positionNDC, float deviceDepth)
|
||
|
{
|
||
|
float4 positionCS = float4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0);
|
||
|
positionCS.y = -positionCS.y;
|
||
|
return positionCS;
|
||
|
}
|
||
|
|
||
|
float3 ComputeViewSpacePosition(float2 positionNDC, float deviceDepth, float4x4 invProjMatrix)
|
||
|
{
|
||
|
float4 positionCS = ComputeClipSpacePosition(positionNDC, deviceDepth);
|
||
|
float4 hpositionVS = mul(invProjMatrix, positionCS);
|
||
|
return hpositionVS.xyz / hpositionVS.w;
|
||
|
}
|
||
|
|
||
|
float4 frag (v2f i) : SV_Target
|
||
|
{
|
||
|
float curDepth = tex2D(_CurDepth, i.uv).r; // closer is whiter
|
||
|
float3 curWPos = ComputeViewSpacePosition(i.uv, curDepth, _CurInvViewProj); // use different matrix to world
|
||
|
|
||
|
float distToCur = distance(_CurPos, curWPos);
|
||
|
float distToProj = distance(_ProjPos, curWPos);
|
||
|
if (distToCur < distToProj) discard; // keep current if it's closer
|
||
|
|
||
|
float texelOffset = _InvCubeSize;
|
||
|
|
||
|
float3 curWNormal = tex2D(_CurNormal, i.uv).xyz * 2 - 1;
|
||
|
float3 dir = normalize(curWPos - _ProjPos);
|
||
|
if (dot(-dir, curWNormal) <= 0) discard; // keep backfacing
|
||
|
|
||
|
float4 projPos = mul(_ProjViewProj, float4(curWPos, 1));
|
||
|
projPos.xyz /= projPos.w;
|
||
|
if (projPos.x < -1 || projPos.y < -1 || projPos.x > 1 || projPos.y > 1 || projPos.z < 0) discard; // keep current outside of projection
|
||
|
projPos.y = -projPos.y;
|
||
|
|
||
|
float2 projUV = projPos.xy * 0.5f + 0.5f;
|
||
|
float occlusion = 0;
|
||
|
int holeDilate = 2;
|
||
|
for(int y=-holeDilate; y<=holeDilate; y++)
|
||
|
{
|
||
|
for(int x=-holeDilate; x<=holeDilate; x++)
|
||
|
{
|
||
|
float projDepth = tex2D(_ProjDepth, projUV + float2(x,y) * texelOffset).r;
|
||
|
projDepth -= 0.0001f;
|
||
|
|
||
|
bool occluded = projDepth > projPos.z;
|
||
|
if (occluded) occlusion += 1;
|
||
|
}
|
||
|
}
|
||
|
if (occlusion > 0) discard;
|
||
|
|
||
|
// clear curDepth
|
||
|
return 0;
|
||
|
}
|
||
|
ENDCG
|
||
|
}
|
||
|
}
|
||
|
}
|