123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- #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
|