res-avatar-unity/Assets/RalivDynamicPenetrationSystem/Plugins/Xiexes-Unity-Shaders-development/Main/CGIncludes/XSShadowCaster.cginc

170 lines
5.7 KiB
HLSL
Raw Permalink Normal View History

2023-07-16 02:51:23 +00:00
#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)
}