summaryrefslogtreecommitdiff
path: root/VRCSDK3Avatars/Assets/Resources/RalivDynamicPenetrationSystem/Plugins/Xiexes-Unity-Shaders-development/Main/CGIncludes/XSShadowCaster.cginc
blob: c3baae399e135d073dbf7a456e6b7ad4f1676e8e (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include "UnityCG.cginc"
#include "UnityShaderVariables.cginc"

// Do dithering for alpha blended shadows on SM3+/desktop, and Dithered transparency;
// on lesser systems do simple alpha-tested shadows
#if defined(_ALPHABLEND_ON) || defined(_ALPHATEST_ON)
    #if !((SHADER_TARGET < 30) || defined (SHADER_API_MOBILE) || defined(SHADER_API_D3D11_9X) || defined (SHADER_API_PSP2) || defined (SHADER_API_PSM))
        #define UNITY_STANDARD_USE_DITHER_MASK 1
    #endif
#endif

// Need to output UVs in shadow caster, since we need to sample texture and do clip/dithering based on it
#if defined(_ALPHABLEND_ON) || defined(_ALPHATEST_ON)
    #define UNITY_STANDARD_USE_SHADOW_UVS 1
#endif

uniform float4      _ClipAgainstVertexColorGreaterZeroFive, _ClipAgainstVertexColorLessZeroFive;
uniform float4      _Color;
uniform float       _Cutoff;
uniform sampler2D   _MainTex;
uniform sampler2D   _CutoutMask;
uniform sampler2D   _ClipMap;
uniform float4      _MainTex_ST;
uniform float       _FadeDither;
uniform float       _FadeDitherDistance;
uniform int         _BlendMode;
#ifdef UNITY_STANDARD_USE_DITHER_MASK
    uniform sampler3D   _DitherMaskLOD;
#endif

struct VertexInput
{
    float4 vertex   : POSITION;
    float3 normal   : NORMAL;
    float2 uv0      : TEXCOORD0;
    float4 color    : COLOR;
};


// Don't make the structure if it's empty (it's an error to have empty structs on some platforms...)
#if !defined(V2F_SHADOW_CASTER_NOPOS_IS_EMPTY) || defined(UNITY_STANDARD_USE_SHADOW_UVS)
struct VertexOutputShadowCaster
{
    V2F_SHADOW_CASTER_NOPOS
        // Need to output UVs in shadow caster, since we need to sample texture and do clip/dithering based on it
    #if defined(UNITY_STANDARD_USE_SHADOW_UVS)
        float2 tex : TEXCOORD1;
    #endif

    float4 worldPos : TEXCOORD2;
    float4 screenPos : TEXCOORD3;
    float4 color : COLOR;
};
#endif

half2 calcScreenUVs(half4 screenPos)
{
    half2 uv = screenPos / (screenPos.w + 0.0000000001); //0.0x1 Stops division by 0 warning in console.
    #if UNITY_SINGLE_PASS_STEREO
        uv.xy *= half2(_ScreenParams.x * 2, _ScreenParams.y);
    #else
        uv.xy *= _ScreenParams.xy;
    #endif

    return uv;
}

inline half Dither8x8Bayer( int x, int y )
{
    const half dither[ 64 ] = {
    1, 49, 13, 61,  4, 52, 16, 64,
    33, 17, 45, 29, 36, 20, 48, 32,
    9, 57,  5, 53, 12, 60,  8, 56,
    41, 25, 37, 21, 44, 28, 40, 24,
    3, 51, 15, 63,  2, 50, 14, 62,
    35, 19, 47, 31, 34, 18, 46, 30,
    11, 59,  7, 55, 10, 58,  6, 54,
    43, 27, 39, 23, 42, 26, 38, 22};
    int r = y * 8 + x;
    return dither[r] / 64;
}

half calcDither(half2 screenPos)
{
    half dither = Dither8x8Bayer(fmod(screenPos.x, 8), fmod(screenPos.y, 8));
    return dither;
}

// We have to do these dances of outputting SV_POSITION separately from the vertex shader,
// and inputting VPOS in the pixel shader, since they both map to "POSITION" semantic on
// some platforms, and then things don't go well.


void vertShadowCaster(VertexInput v,
    #if !defined(V2F_SHADOW_CASTER_NOPOS_IS_EMPTY) || defined(UNITY_STANDARD_USE_SHADOW_UVS)
        out VertexOutputShadowCaster o,
    #endif
    out float4 opos : SV_POSITION)
{
    TRANSFER_SHADOW_CASTER_NOPOS(o, opos)
    #if defined(UNITY_STANDARD_USE_SHADOW_UVS)
        o.tex = TRANSFORM_TEX(v.uv0, _MainTex);
        o.color = v.color;
        o.worldPos = mul(unity_ObjectToWorld, v.vertex);
        o.screenPos = ComputeScreenPos(opos);
    #endif
}

float AlphaAdjust(float alphaToAdj, float3 vColor)
{
    _ClipAgainstVertexColorGreaterZeroFive = saturate(_ClipAgainstVertexColorGreaterZeroFive); //So the lerp doesn't go crazy
    _ClipAgainstVertexColorLessZeroFive = saturate(_ClipAgainstVertexColorLessZeroFive);

    float modR = vColor.r < 0.5 ? _ClipAgainstVertexColorLessZeroFive.r : _ClipAgainstVertexColorGreaterZeroFive.r;
    float modG = vColor.g < 0.5 ? _ClipAgainstVertexColorLessZeroFive.g : _ClipAgainstVertexColorGreaterZeroFive.g;
    float modB = vColor.b < 0.5 ? _ClipAgainstVertexColorLessZeroFive.b : _ClipAgainstVertexColorGreaterZeroFive.b;

    alphaToAdj *= lerp(0, 1, lerp(1, modR, step(0.01, vColor.r)));
    alphaToAdj *= lerp(0, 1, lerp(1, modG, step(0.01, vColor.g)));
    alphaToAdj *= lerp(0, 1, lerp(1, modB, step(0.01, vColor.b)));

    return alphaToAdj;
}

half4 fragShadowCaster(
    #if !defined(V2F_SHADOW_CASTER_NOPOS_IS_EMPTY) || defined(UNITY_STANDARD_USE_SHADOW_UVS)
        VertexOutputShadowCaster i
    #endif
    #ifdef UNITY_STANDARD_USE_DITHER_MASK
        , UNITY_VPOS_TYPE vpos : VPOS
    #endif
) : SV_Target
{
    #if defined(UNITY_STANDARD_USE_SHADOW_UVS)
        half alpha = 1;
        float4 albedo = tex2D(_MainTex, i.tex).a * _Color.a;
        float4 clipMap = tex2D(_ClipMap, i.tex);
        float modifiedAlpha = AlphaAdjust(albedo.a, clipMap.rgb);

        #if defined(_ALPHABLEND_ON) || defined(_ALPHATEST_ON)
            float2 screenUV = calcScreenUVs(i.screenPos);
            if(_BlendMode >= 3)
            {
                half dither = calcDither(screenUV);
                alpha = modifiedAlpha - (dither * (1-albedo.a) * 0.15);
            }

            if(_BlendMode == 2)
            {
                half dither = calcDither(screenUV);

                float fadeDist = abs(_FadeDitherDistance);
                float d = distance(_WorldSpaceCameraPos, i.worldPos);
                d = smoothstep(fadeDist, fadeDist + 0.05, d);
                d = lerp(d, 1-d, saturate(step(0, _FadeDitherDistance)));
                dither += lerp(0, d, saturate(_FadeDither));
                clip(modifiedAlpha - dither);
            }

            if(_BlendMode == 1)
            {
                clip(modifiedAlpha - _Cutoff);
            }
        #else
            alpha = modifiedAlpha;
        #endif
    #endif

    SHADOW_CASTER_FRAGMENT(i)
}