170 lines
5.7 KiB
HLSL
170 lines
5.7 KiB
HLSL
|
#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)
|
||
|
}
|