// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
ShadowDepthVertexShader.usf: Vertex shader for writing shadow depth.
=============================================================================*/
// needs to before Common.usf
#define SHADOW_DEPTH_SHADER 1
#define USE_STENCIL_LOD_DITHER 0
#include "LPVListEntry.ush"
#include "Common.ush"
// Reroute SceneTexturesStruct uniform buffer references to the shadow depth pass uniform buffer
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5
#define PassStruct ShadowDepthPass
#define SceneTexturesStruct ShadowDepthPass.SceneTextures
#else
#define PassStruct MobileShadowDepthPass
#define MobileSceneTextures MobileShadowDepthPass.SceneTextures
#endif
#include "/Engine/Generated/Material.ush"
#include "/Engine/Generated/VertexFactory.ush"
#include "ShadowDepthCommon.ush"
void SetShadowDepthOutputs(
float4x4 WorldToClipMatrix,
float4x4 WorldToShadowMatrix,
float4 WorldPosition,
float3 WorldVertexNormal,
out float4 OutPosition,
out float ShadowDepth
#if PERSPECTIVE_CORRECT_DEPTH
, out float OutDepthBias
#endif
)
{
OutPosition = mul(WorldPosition, WorldToClipMatrix);
// Clamp the vertex to the near plane if it is in front of the near plane
// This has problems if some vertices of a triangle get clamped and others do not, also causes artifacts with non-ortho projections
if (PassStruct.bClampToNearPlane > 0 && OutPosition.z < 0)
{
OutPosition.z = 0.000001f;
OutPosition.w = 1.0f;
}
#if ONEPASS_POINTLIGHT_SHADOW
const float3 ViewDirection = -normalize(mul(WorldPosition, WorldToShadowMatrix).xyz);
const float3 ViewNormal = mul(float4(WorldVertexNormal,0), WorldToShadowMatrix).xyz;
const float NoL = abs(dot(ViewDirection, ViewNormal));
#else
const float NoL = abs(dot(
float3(WorldToShadowMatrix[0].z, WorldToShadowMatrix[1].z, WorldToShadowMatrix[2].z),
WorldVertexNormal));
#endif
const float MaxSlopeDepthBias = PassStruct.ShadowParams.z;
const float Slope = clamp(abs(NoL) > 0 ? sqrt(saturate(1 - NoL*NoL)) / NoL : MaxSlopeDepthBias, 0, MaxSlopeDepthBias);
const float SlopeDepthBias = PassStruct.ShadowParams.y;
const float SlopeBias = SlopeDepthBias * Slope;
const float ConstantDepthBias = PassStruct.ShadowParams.x;
const float DepthBias = SlopeBias + ConstantDepthBias;
#if PERSPECTIVE_CORRECT_DEPTH
ShadowDepth = OutPosition.z;
OutDepthBias = DepthBias;
#elif ONEPASS_POINTLIGHT_SHADOW
ShadowDepth = 0;
//OutPosition.z += DepthBias;
#else
// Output linear, normalized depth
const float InvMaxSubjectDepth = PassStruct.ShadowParams.w;
ShadowDepth = OutPosition.z * InvMaxSubjectDepth + DepthBias;
OutPosition.z = ShadowDepth * OutPosition.w;
#endif
}
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4 && ONEPASS_POINTLIGHT_SHADOW
// Layer Id per draw call for Vertex-Shader-Layer implementation
#if VERTEXSHADER && USING_VERTEX_SHADER_LAYER
uint LayerId;
#endif
struct FShadowDepthGSToPS
{
#if INTERPOLATE_VF_ATTRIBUTES
FShadowDepthVSToPS PSInputs;
#endif
float4 OutPosition : SV_POSITION;
/** Controls which of the cube map faces to rasterize the primitive to, only the value from the first vertex is used. */
uint RTIndex : SV_RenderTargetArrayIndex;
};
bool IsTriangleInFrustum(float4 ClipSpacePositions[3])
{
float4 FrustumTests0 = saturate(ClipSpacePositions[0].xyxy * float4(-1, -1, 1, 1) - ClipSpacePositions[0].w);
float4 FrustumTests1 = saturate(ClipSpacePositions[1].xyxy * float4(-1, -1, 1, 1) - ClipSpacePositions[1].w);
float4 FrustumTests2 = saturate(ClipSpacePositions[2].xyxy * float4(-1, -1, 1, 1) - ClipSpacePositions[2].w);
float4 FrustumTests = FrustumTests0 * FrustumTests1 * FrustumTests2;
float2 FrustumTestsZ0 = saturate(ClipSpacePositions[0].zz * float2(-1, 1) - ClipSpacePositions[0].w);
float2 FrustumTestsZ1 = saturate(ClipSpacePositions[1].zz * float2(-1, 1) - ClipSpacePositions[1].w);
float2 FrustumTestsZ2 = saturate(ClipSpacePositions[2].zz * float2(-1, 1) - ClipSpacePositions[2].w);
float2 FrustumTestsZ = FrustumTestsZ0 * FrustumTestsZ1 * FrustumTestsZ2;
return !( any(FrustumTests != 0) || any(FrustumTestsZ != 0) );
}
/** Allocate space for cloning to all 6 faces which is the worst case. */
[maxvertexcount(18)]
void MainOnePassPointLightGS(triangle FShadowDepthVSToGS Input[3], inout TriangleStream<FShadowDepthGSToPS> OutStream)
{
UNROLL
// Clone the triangle to each face
for (int CubeFaceIndex = 0; CubeFaceIndex < 6; CubeFaceIndex++)
{
float4 ClipSpacePositions[3];
UNROLL
for (int VertexIndex = 0; VertexIndex < 3; VertexIndex++)
{
// Calculate the clip space position for each cube face
// Note: We don't apply any constant/slop bias here. A constant bias is applied in the shadow projection
// code (see CubemapHardwarePCF() in ShadowProjectionCommon.ush)
// If one want to use this code path, don't forget to remove the bias in CubemapHardwarePCF().
#if 0
const float4 WorldPosition = Input[VertexIndex].GSPosition;
const float3 WorldVertexNormal = Input[VertexIndex].WorldNormal;
float4 ClipSpacePosition;
float ShadowDepth;
SetShadowDepthOutputs(
PassStruct.ShadowViewProjectionMatrices[CubeFaceIndex],
PassStruct.ShadowViewMatrices[CubeFaceIndex],
WorldPosition,
WorldVertexNormal,
ClipSpacePosition,
ShadowDepth);
ClipSpacePositions[VertexIndex] = ClipSpacePosition;
#else
ClipSpacePositions[VertexIndex] = mul(Input[VertexIndex].GSPosition, PassStruct.ShadowViewProjectionMatrices[CubeFaceIndex]);
#endif
}
// Frustum culling, saves GPU time with high poly meshes
BRANCH
if (IsTriangleInFrustum(ClipSpacePositions))
{
FShadowDepthGSToPS Output;
Output.RTIndex = CubeFaceIndex;
UNROLL
for (int VertexIndex = 0; VertexIndex < 3; VertexIndex++)
{
Output.OutPosition = ClipSpacePositions[VertexIndex];
#if INTERPOLATE_VF_ATTRIBUTES
Output.PSInputs.FactoryInterpolants = Input[VertexIndex].FactoryInterpolants;
#endif
#if INTERPOLATE_POSITION
Output.PSInputs.PixelPosition = Input[VertexIndex].GSPosition.xyz;
#endif
OutStream.Append(Output);
}
OutStream.RestartStrip();
}
}
}
#endif
#if USING_TESSELLATION
struct FShadowDepthVSToDS
{
FVertexFactoryInterpolantsVSToDS FactoryInterpolants;
float4 Position : VS_to_DS_Position;
OPTIONAL_VertexID_VS_To_DS
#if ONEPASS_POINTLIGHT_SHADOW && USING_VERTEX_SHADER_LAYER
uint LayerIndex : VS_to_DS_RenderTargetArrayIndex;
#endif
};
struct FShadowDepthDSToPS : FShadowDepthVSToPS
{
#if ONEPASS_POINTLIGHT_SHADOW
#if USING_VERTEX_SHADER_LAYER
float4 Position : SV_POSITION;
float4 InterpPosition : TEXCOORD6;
uint LayerIndex : SV_RenderTargetArrayIndex;
#else
float4 Position : TEXCOORD6;
#endif
float3 WorldNormal : TEXCOORD8;
#else
float4 Position : SV_POSITION;
#endif
};
#define FPassSpecificVSToDS FShadowDepthVSToDS
#define FPassSpecificVSToPS FShadowDepthDSToPS
FShadowDepthVSToDS PassInterpolate(FShadowDepthVSToDS a, float aInterp, FShadowDepthVSToDS b, float bInterp)
{
FShadowDepthVSToDS O;
O.FactoryInterpolants = VertexFactoryInterpolate(a.FactoryInterpolants, aInterp, b.FactoryInterpolants, bInterp);
#if ONEPASS_POINTLIGHT_SHADOW && USING_VERTEX_SHADER_LAYER
O.LayerIndex = a.LayerIndex;
#endif
return O;
}
FShadowDepthDSToPS PassFinalizeTessellationOutput(FShadowDepthVSToDS Interpolants, float4 WorldPosition, FMaterialTessellationParameters MaterialParameters)
{
FShadowDepthDSToPS O;
#if INTERPOLATE_VF_ATTRIBUTES
O.FactoryInterpolants = VertexFactoryAssignInterpolants(Interpolants.FactoryInterpolants);
#endif
const float3 WorldNormal = MaterialParameters.TangentToWorld[2];
#if ONEPASS_POINTLIGHT_SHADOW
#if USING_VERTEX_SHADER_LAYER
O.LayerIndex = Interpolants.LayerIndex;
O.Position = WorldPosition = mul(WorldPosition, PassStruct.ShadowViewProjectionMatrices[Interpolants.LayerIndex]);
O.InterpPosition = WorldPosition;
#else
O.Position = WorldPosition;
#endif // USING_VERTEX_SHADER_LAYER
O.WorldNormal = WorldNormal;
#else
float ShadowDepth;
SetShadowDepthOutputs(
PassStruct.ProjectionMatrix,
PassStruct.ViewMatrix,
WorldPosition,
WorldNormal,
O.Position,
#if PERSPECTIVE_CORRECT_DEPTH
O.ShadowDepth,
O.DepthBias
#else
ShadowDepth
#endif
);
#endif
// Conditions below are derived. See struct FShadowDepthVSToPS in ShadowDepthCommon.ush
#if !PERSPECTIVE_CORRECT_DEPTH && !COMPILER_SUPPORTS_EMPTY_STRUCTS && !ONEPASS_POINTLIGHT_SHADOW
O.Dummy = 0;
#endif
#if INTERPOLATE_POSITION
O.PixelPosition = WorldPosition.xyz;
#endif
return O;
}
#include "Tessellation.ush"
#endif // #if USING_TESSELLATION
void Main(
FVertexFactoryInput Input,
#if USING_TESSELLATION
out FShadowDepthVSToDS OutParameters,
#elif ONEPASS_POINTLIGHT_SHADOW
out FShadowDepthVSToGS OutParameters,
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4 && USING_VERTEX_SHADER_LAYER
out uint LayerIndex : SV_RenderTargetArrayIndex,
#endif
#else
out FShadowDepthVSToPS OutParameters,
#endif
OPTIONAL_VertexID
out float4 OutPosition : SV_POSITION
)
{
ResolvedView = ResolveView();
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
float4 WorldPos = VertexFactoryGetWorldPosition(Input, VFIntermediates);
float3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPos.xyz, TangentToLocal);
const float3 WorldNormal = VertexFactoryGetWorldNormal(Input, VFIntermediates);
WorldPos.xyz += GetMaterialWorldPositionOffset(VertexParameters);
#if USING_TESSELLATION
OutPosition = OutParameters.Position = WorldPos;
// Tessellated materials need vertex coords for displacement
OutParameters.FactoryInterpolants = VertexFactoryGetInterpolantsVSToDS(Input, VFIntermediates, VertexParameters);
#if ONEPASS_POINTLIGHT_SHADOW && USING_VERTEX_SHADER_LAYER && VERTEXSHADER
OutParameters.LayerIndex = LayerId;
#endif
#elif ONEPASS_POINTLIGHT_SHADOW
OutPosition = OutParameters.GSPosition = WorldPos;
OutParameters.WorldNormal = WorldNormal;
#if INTERPOLATE_VF_ATTRIBUTES
// Masked materials need texture coords to clip
OutParameters.FactoryInterpolants = VertexFactoryGetInterpolantsVSToPS(Input, VFIntermediates, VertexParameters);
#endif
#if INTERPOLATE_POSITION
OutParameters.PixelPosition = WorldPos.xyz;
#endif
#if USING_VERTEX_SHADER_LAYER && VERTEXSHADER
LayerIndex = LayerId;
OutPosition = mul(WorldPos, PassStruct.ShadowViewProjectionMatrices[LayerIndex]);
#if INTERPOLATE_VF_ATTRIBUTES
OutParameters.GSPosition = OutPosition;
#endif
#endif
#else
float Dummy;
SetShadowDepthOutputs(
PassStruct.ProjectionMatrix,
PassStruct.ViewMatrix,
WorldPos,
WorldNormal,
OutPosition,
#if !PERSPECTIVE_CORRECT_DEPTH
Dummy
#else
OutParameters.ShadowDepth,
OutParameters.DepthBias
#endif
);
#if INTERPOLATE_VF_ATTRIBUTES
// Masked materials need texture coords to clip
OutParameters.FactoryInterpolants = VertexFactoryGetInterpolantsVSToPS(Input, VFIntermediates, VertexParameters);
#endif
#if INTERPOLATE_POSITION
OutParameters.PixelPosition = WorldPos.xyz;
#endif
#if !PERSPECTIVE_CORRECT_DEPTH && !COMPILER_SUPPORTS_EMPTY_STRUCTS
OutParameters.Dummy = 0;
#endif
#endif
OutputVertexID( OutParameters );
}
#if IS_FOR_GEOMETRY_SHADER
// Vertex shader exports must match GS inputs.
// This is a requirement on some platforms.
void MainForGS(
OPTIONAL_VertexID
FVertexFactoryInput Input,
#if USING_TESSELLATION
out FShadowDepthVSToDS OutParameters
#elif ONEPASS_POINTLIGHT_SHADOW
out FShadowDepthVSToGS OutParameters
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4 && USING_VERTEX_SHADER_LAYER
, out uint LayerIndex : SV_RenderTargetArrayIndex
#endif
#else
#error Invalid permutation for MainForGS
#endif
#if COMPILER_METAL
#define SKIP_UNUSED_POSITION
// Metal needs a position output
, out float4 UnusedPosition : SV_POSITION
#endif
)
{
#ifndef SKIP_UNUSED_POSITION
float4 UnusedPosition;
#endif
Main(Input,
OutParameters,
OPTIONAL_VertexID_PARAM
#if !USING_TESSELLATION && (FEATURE_LEVEL >= FEATURE_LEVEL_SM4 && ONEPASS_POINTLIGHT_SHADOW && USING_VERTEX_SHADER_LAYER)
LayerIndex,
#endif
UnusedPosition);
}
#endif // IS_FOR_GEOMETRY_SHADER
#define USING_ONEPASS_POINT_VERTEX_LAYER (FEATURE_LEVEL >= FEATURE_LEVEL_SM4 && ONEPASS_POINTLIGHT_SHADOW && USING_VERTEX_SHADER_LAYER)
#if POSITION_ONLY
void PositionOnlyMain(
in FPositionAndNormalOnlyVertexFactoryInput Input,
#if USING_ONEPASS_POINT_VERTEX_LAYER
out uint LayerIndex : SV_RenderTargetArrayIndex,
#endif
#if ONEPASS_POINTLIGHT_SHADOW
out FShadowDepthVSToGS OutParameters,
#else
out FShadowDepthVSToPS OutParameters,
#endif
out float4 OutPosition : SV_POSITION
)
{
ResolvedView = ResolveView();
float4 WorldPos = VertexFactoryGetWorldPosition(Input);
#if INTERPOLATE_VF_ATTRIBUTES
OutParameters.FactoryInterpolants = (FVertexFactoryInterpolantsVSToPS)0;
#endif
float3 WorldNormal = VertexFactoryGetWorldNormal(Input);
#if ONEPASS_POINTLIGHT_SHADOW
OutPosition = OutParameters.GSPosition = WorldPos;
OutParameters.WorldNormal = WorldNormal;
#if USING_ONEPASS_POINT_VERTEX_LAYER
LayerIndex = LayerId;
OutPosition = mul(WorldPos, PassStruct.ShadowViewProjectionMatrices[LayerIndex]);
#if INTERPOLATE_VF_ATTRIBUTES
OutParameters.GSPosition = OutPosition;
#endif
#endif
#else // #if ONEPASS_POINTLIGHT_SHADOW
float ShadowDepth;
SetShadowDepthOutputs(
PassStruct.ProjectionMatrix,
PassStruct.ViewMatrix,
WorldPos,
WorldNormal,
OutPosition,
#if PERSPECTIVE_CORRECT_DEPTH
OutParameters.ShadowDepth,
OutParameters.DepthBias
#else
ShadowDepth
#endif
);
#if !PERSPECTIVE_CORRECT_DEPTH && !COMPILER_SUPPORTS_EMPTY_STRUCTS
OutParameters.Dummy = 0;
#endif
#endif // #if ONEPASS_POINTLIGHT_SHADOW
#if INTERPOLATE_POSITION
OutParameters.PixelPosition = WorldPos.xyz;
#endif
}
#if IS_FOR_GEOMETRY_SHADER
// Vertex shader exports must match GS inputs.
// This is a requirement on some platforms.
void PositionOnlyMainForGS(
in FPositionAndNormalOnlyVertexFactoryInput Input,
#if USING_ONEPASS_POINT_VERTEX_LAYER
out uint LayerIndex : SV_RenderTargetArrayIndex,
#endif
#if ONEPASS_POINTLIGHT_SHADOW
out FShadowDepthVSToGS OutParameters
#else
#error Invalid permutation for PositionOnlyMainForGS
#endif
#if COMPILER_METAL
#ifndef SKIP_UNUSED_POSITION
#define SKIP_UNUSED_POSITION
#endif
// Metal needs a position output
, out float4 UnusedPosition : SV_POSITION
#endif
)
{
#ifndef SKIP_UNUSED_POSITION
float4 UnusedPosition;
#endif
PositionOnlyMain(Input,
#if USING_ONEPASS_POINT_VERTEX_LAYER
LayerIndex,
#endif
OutParameters, UnusedPosition);
}
#endif // IS_FOR_GEOMETRY_SHADER
#endif
UE4阴影渲染-Shader-ShadowDepthVertexShader.usf
猜你喜欢
转载自blog.csdn.net/sh15285118586/article/details/124768778
今日推荐
周排行