summaryrefslogtreecommitdiff
path: root/VRCSDK3Worlds/Assets/Bakery/ftFarSphereProjClip.shader
blob: 10040df7b07bf646bc83016a6a98b0682f4d8f82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// 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
        }
    }
}