UnityGame/Library/PackageCache/com.unity.render-pipelines.universal/Shaders/2D/Include/ShadowProjectVertex.hlsl

116 lines
4.2 KiB
HLSL
Raw Normal View History

2024-10-27 10:53:47 +03:00
#if !defined(SHADOW_PROJECT_VERTEX)
#define SHADOW_PROJECT_VERTEX
#define ToFloat(x) x
#define Deg2Rad(x) (x * 3.14159265359f / 180)
#define MIN_SHADOW_Y 0.000001f
struct Attributes
{
float3 vertex : POSITION;
float4 packed0 : TANGENT;
};
struct Varyings
{
float4 vertex : SV_POSITION;
float2 shadow : TEXCOORD0;
};
uniform float3 _LightPos;
uniform float4x4 _ShadowModelMatrix; // This is a custom model matrix without scaling
uniform float4x4 _ShadowModelInvMatrix;
uniform float3 _ShadowModelScale; // This is the scale
uniform float _ShadowRadius;
uniform float _ShadowContractionDistance;
uniform float _SoftShadowAngle;
float AngleFromDir(float3 dir)
{
// Assumes dir is normalized. Will return -180 to 180
float angle = acos(dir.x);
float gt180 = ceil(saturate(-dir.y)); // Greater than 180
return gt180 * -angle + (1 - gt180) * angle;
}
float3 DirFromAngle(float angle)
{
return float3(cos(angle), sin(angle), 0);
}
float2 CalculateShadowValue(float shadowType)
{
float isLeft = ToFloat(shadowType == 1);
float isRight = ToFloat(shadowType == 3);
return float2(-isLeft + isRight, isLeft + isRight);
}
float3 SoftShadowDir(float3 lightDir, float3 vertex0, float3 vertex1, float angleOp, float softShadowAngle)
{
float lightAngle = AngleFromDir(lightDir);
float edgeAngle = AngleFromDir(normalize(vertex1 - vertex0));
float softAngle = lightAngle + angleOp * softShadowAngle;
return DirFromAngle(softAngle);
}
float4 ProjectShadowVertexToWS(float2 vertex, float2 otherEndPt, float2 contractDir, float shadowType, float3 lightPos, float3 shadowModelScale, float4x4 shadowModelMatrix, float4x4 shadowModelInvMatrix, float shadowContractionDistance, float shadowRadius, float softShadowAngle)
{
float3 vertexOS0 = float3(vertex.x * shadowModelScale.x, vertex.y * shadowModelScale.y, 0);
float3 vertexOS1 = float3(otherEndPt.x * shadowModelScale.x, otherEndPt.y * shadowModelScale.y, 0); // the tangent has the adjacent point stored in zw
float3 lightPosOS = float3(mul(shadowModelInvMatrix, float4(lightPos.x, lightPos.y, lightPos.z, 1)).xy, 0); // Transform the light into local space
float3 unnormalizedLightDir0 = vertexOS0 - lightPosOS;
float3 unnormalizedLightDir1 = vertexOS1 - lightPosOS;
float3 lightDir0 = normalize(unnormalizedLightDir0);
float3 lightDir1 = normalize(unnormalizedLightDir1);
float3 avgLightDir = normalize(lightDir0 + lightDir1);
float isSoftShadow = ToFloat(shadowType >= 1);
float isHardShadow = ToFloat(shadowType == 0);
float isShadowVertex = saturate(isSoftShadow + isHardShadow);
float3 softShadowDir = SoftShadowDir(lightDir0, vertexOS0, vertexOS1, shadowType - 2, softShadowAngle);
float3 hardShadowDir = lightDir0;
float3 shadowDir = isSoftShadow * softShadowDir + isHardShadow * hardShadowDir;
float lightDistance = length(unnormalizedLightDir0);
float hardShadowLength = max(shadowRadius / dot(lightDir0, avgLightDir), lightDistance);
float softShadowLength = shadowRadius * (1 / cos(softShadowAngle));
// Tests to make sure the light is between 0-90 degrees to the normal. Will be one if it is, zero if not.
float3 shadowOffset = (isSoftShadow * softShadowLength + isHardShadow * hardShadowLength) * shadowDir;
float3 contractedVertexPos = vertexOS0 + float3(shadowContractionDistance * contractDir.xy, 0);
// If we are suppose to extrude this point, then
float3 finalVertexOS = isShadowVertex * (lightPosOS + shadowOffset) + (1 - isShadowVertex) * contractedVertexPos;
return mul(shadowModelMatrix, float4(finalVertexOS, 1));
}
Varyings ProjectShadow(Attributes v)
{
Varyings o;
float2 otherEndPt = v.packed0.zw;
float shadowType = v.packed0.x;
float2 position = v.vertex.xy;
float softShadowAngle = _SoftShadowAngle;
float2 contractDir = 0;
float4 positionWS = ProjectShadowVertexToWS(position, otherEndPt, contractDir, shadowType, _LightPos, _ShadowModelScale, _ShadowModelMatrix, _ShadowModelInvMatrix, _ShadowContractionDistance, _ShadowRadius, softShadowAngle);
o.vertex = mul(GetWorldToHClipMatrix(), positionWS);
o.shadow = CalculateShadowValue(shadowType);
return o;
}
#endif