ArabDesert/Assets/Bakery/ftFarSphereProjClip.shader

107 lines
3.6 KiB
Plaintext
Raw Normal View History

2024-05-25 09:10:35 +03:00
// 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
}
}
}