217 lines
6.4 KiB
Plaintext
Raw Normal View History

2025-07-21 12:13:06 +08:00
Shader "XRP/PlanarShadow"
2025-07-20 17:26:12 +08:00
{
SubShader
{
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#ifdef LOW_SOFT_QUALITY
#define OPERATOR_SIZE 10
#elif defined(MEDIUM_SOFT_QUALITY)
#define OPERATOR_SIZE 16
#else
#define OPERATOR_SIZE 32
#endif
struct Varyings
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
TEXTURE2D(_SourceTex);
SAMPLER(sampler_SourceTex);
TEXTURE2D(_DistanceTex);
SAMPLER(sampler_DistanceTex);
SAMPLER(sampler_LinearClamp);
float4 _PossionOperator[32];
float4 _EdgeMapTexelSize;
float4 _SourceTex_TexelSize;
float2 _ShadowScreenHDir;
float2 _ShadowScreenVDir;
float _MinSoft;
float _SoftScaleByDistance;
Varyings FullScreenVert(uint vertexID: SV_VertexID)
{
Varyings o;
o.vertex = GetFullScreenTriangleVertexPosition(vertexID);
o.uv = GetFullScreenTriangleTexCoord(vertexID);
return o;
}
half4 buildSoftEdgeVFrag(Varyings input) : SV_Target
{
half2 uv = input.uv;
half2 uvStep = _EdgeMapTexelSize.xy * _ShadowScreenVDir * 0.6f;
UNITY_UNROLL
for(int i = 0;i<4;i++)
{
half dis = SAMPLE_TEXTURE2D(_SourceTex, sampler_SourceTex, uv - i * uvStep).r;
if(dis > 0)
return dis;
}
return 0;
}
half4 buildSoftEdgeHFrag(Varyings input) : SV_Target
{
half2 uv = input.uv;
half2 uvStep = _SourceTex_TexelSize.xy * _ShadowScreenHDir* 0.6f;
UNITY_UNROLL
for(int i = 0; i < 6; i++)
{
half dis = SAMPLE_TEXTURE2D(_SourceTex, sampler_SourceTex, uv - i * uvStep).r;
half dis2 = SAMPLE_TEXTURE2D(_SourceTex, sampler_SourceTex, uv + i * uvStep).r;
if(dis > 0)
return dis;
if(dis2 > 0)
return dis2;
}
return 0;
}
half4 CircleVisiualFrag(Varyings input) : SV_Target
{
half2 uv = input.uv;
half blurSize = SAMPLE_TEXTURE2D(_DistanceTex, sampler_DistanceTex, uv).r;
half2 uvStep = _SourceTex_TexelSize.xy * (_MinSoft + (1 - _MinSoft) * blurSize) * _SoftScaleByDistance;
half col = 0;
if(blurSize == 0)
return SAMPLE_TEXTURE2D(_SourceTex, sampler_LinearClamp, uv).g;
UNITY_UNROLL
for(int i = 0; i < OPERATOR_SIZE;i++)
{
col += SAMPLE_TEXTURE2D(_SourceTex, sampler_LinearClamp, uv + uvStep * _PossionOperator[i].xy).g * _PossionOperator[i].z;
}
return half4(col.rrr,1);
}
ENDHLSL
Pass
{
Name "BlurV"
HLSLPROGRAM
#pragma vertex FullScreenVert
#pragma fragment buildSoftEdgeVFrag
ENDHLSL
}
Pass
{
Name "BlurH"
HLSLPROGRAM
#pragma vertex FullScreenVert
#pragma fragment buildSoftEdgeHFrag
ENDHLSL
}
Pass
{
Name "CircleVisiual"
HLSLPROGRAM
#pragma multi_compile _ LOW_SOFT_QUALITY MEDIUM_SOFT_QUALITY
#pragma vertex FullScreenVert
#pragma fragment CircleVisiualFrag
ENDHLSL
}
Pass
{
Tags { "LightMode" = "PlanarShadow" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#pragma enable_d3d11_debug_symbols
#pragma shader_feature_local TRANSPARENT_SHADOW_CASTER
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
float4 _PlanarShadowCastPlane;
float _PlanarShadowMaxSoftDistance;
half4 _PlanarShadowColor;
TEXTURE2D(_PlanarShadowMap);
SAMPLER(sampler_PlanarShadowMap);
void CastVertexToPlane(float3 oriPositionWS, float3 lightDirection, out float3 positionWS, out float shadowSoftScale, float objtY)
{
float3 planeNor = _PlanarShadowCastPlane.xyz;
float w = _PlanarShadowCastPlane.w + objtY;
// https://zhuanlan.zhihu.com/p/42781261
float castDistance = (w - dot(oriPositionWS.xyz, planeNor)) / dot(lightDirection, planeNor);
positionWS = oriPositionWS.xyz + castDistance * lightDirection;
shadowSoftScale = max(0, castDistance / _PlanarShadowMaxSoftDistance);
}
half3 GetPlanarScreenShadowAttenuation(float2 screenUV)
{
#ifdef PLANAR_SHADOW
half attenutaion = SAMPLE_TEXTURE2D(_PlanarShadowMap, sampler_PlanarShadowMap, screenUV).r;
return lerp(1, _PlanarShadowColor, attenutaion);
#else
return 1;
#endif
}
struct attribute
{
float4 vertex : POSITION;
float2 uv : TEXCOORD;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
float softValue : TEXCOORD1;
};
sampler2D _MainTexture;
v2f vert (attribute v)
{
v2f o;
float4 worldPos = mul(UNITY_MATRIX_M, v.vertex);
float3 lightDir = -_MainLightPosition.xyz;
float y = UNITY_MATRIX_M[1][3];
float3 castPosWS;
float softValue;
CastVertexToPlane(worldPos.xyz, lightDir, castPosWS, softValue, y);
o.softValue = softValue;
o.vertex = mul(UNITY_MATRIX_VP, float4(castPosWS, 1));
o.uv = v.uv;
return o;
}
half4 frag (v2f i) : SV_Target
{
#ifdef TRANSPARENT_SHADOW_CASTER
float4 col = tex2D(_MainTexture, i.uv);
#else
float4 col = 1;
#endif
return half4(i.softValue,col.a,0, 0);
}
ENDHLSL
}
}
}