Files
UnrealEngine/Engine/Shaders/Private/HairStrands/HairStrandsVisibilityVS.usf
2025-05-18 13:04:45 +08:00

132 lines
5.9 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "../Common.ush"
#include "../VelocityCommon.ush"
#include "/Engine/Generated/Material.ush"
#include "/Engine/Generated/VertexFactory.ush"
#include "HairStrandsVisibilityCommon.ush"
struct FHairVisibilityAccumulateVSToPS
{
#if HAIR_RENDER_MODE == RENDER_MODE_MSAA_VISIBILITY
nointerpolation uint HairControlPointId : HAIR_PRIMITIVE_ID;
#else
FVertexFactoryInterpolantsVSToPS FactoryInterpolants;
#endif
float4 Position : SV_POSITION;
#if HAIR_RENDER_MODE != RENDER_MODE_MSAA_VISIBILITY
float WorldStrandRadius : TEXCOORD8;
#endif
#if HAIR_RENDER_MODE == RENDER_MODE_PPLL
INVARIANT_OUTPUT float4 PackedVelocityA : TEXCOORD9;
INVARIANT_OUTPUT float4 PackedVelocityC : TEXCOORD12;
#endif
};
#define VS_OUTPUT_TYPE FHairVisibilityAccumulateVSToPS
#if VERTEXSHADER
void Main(
FVertexFactoryInput Input,
out VS_OUTPUT_TYPE Output
)
#if HAIR_RENDER_MODE == RENDER_MODE_MSAA_VISIBILITY && HAIR_STRAND_MESH_FACTORY
{
ResolvedView = ResolveView();
const bool bUseStableRasterization = UseStableRasterization();
const FHairRenderInfo HairRenderInfo = GetHairRenderInfo(ResolvedView.HairRenderInfo, ResolvedView.HairRenderInfoBits, bUseStableRasterization);
const float VelocityScale = 0;
FHairViewInfo HairViewInfo;
HairViewInfo.TranslatedWorldCameraOrigin = ResolvedView.TranslatedWorldCameraOrigin;
HairViewInfo.ViewForward = ResolvedView.ViewForward;
HairViewInfo.RadiusAtDepth1 = lerp(HairRenderInfo.RadiusAtDepth1Primary, HairRenderInfo.RadiusAtDepth1Velocity, VelocityScale);
HairViewInfo.bIsOrthoView = HairRenderInfo.bIsOrthoView;
uint HairControlPointId = 0;
const float4 WorldPosition = VertexFactoryGetWorldPosition_Visibility(Input, HairViewInfo, HairControlPointId);
Output.Position = mul(WorldPosition, View.TranslatedWorldToClip);
Output.HairControlPointId = HairControlPointId;
}
#else // HAIR_RENDER_MODE == RENDER_MODE_MSAA_VISIBILITY
{
ResolvedView = ResolveView();
// #hair_todo: This is a hack/quick term solution, in order to generate valide light/view direction in the case of hair strand factory, as this is used for alighning the strand with the view.
//ResolvedView.TranslatedWorldCameraOrigin = -HairVisibilityPass.LightDirection * 1000; // Hack for strand rendering which use the camera position for deriving the view vector for forcing strand view facing
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
#if HAIR_STRAND_MESH_FACTORY
// Use a raw position (rather than quad facing position) as the pre-position is not expanded into quad (for perf. reason)
float4 WorldPositionRaw = VertexFactoryGetWorldPositionRaw(Input, VFIntermediates);
#else
float4 WorldPositionRaw = VertexFactoryGetWorldPosition(Input, VFIntermediates);
#endif
bool bUseStableRasterization = false;
#if HAIR_STRAND_MESH_FACTORY
bUseStableRasterization = UseStableRasterization();
#endif
// Velocity computation
// The velocity is used to adapt/increase the minimum rasterization size in order to avoid aliasing under heavy-motion.
// The higher the velocity, the larger a strand becomes.
float VelocityScale = 0;
const FHairRenderInfo HairRenderInfo = GetHairRenderInfo(ResolvedView.HairRenderInfo, ResolvedView.HairRenderInfoBits, bUseStableRasterization);
#if HAIR_RENDER_MODE == RENDER_MODE_PPLL
{
const float4 PrevWorldPosition = VertexFactoryGetPreviousWorldPosition(Input, VFIntermediates);
const float4 ScreenPos = mul(float4(WorldPositionRaw.xyz, 1), ResolvedView.TranslatedWorldToClip);
const float4 PrevScreenPosObj = mul(float4(PrevWorldPosition.xyz, 1), ResolvedView.PrevTranslatedWorldToClip);
Output.PackedVelocityA = INVARIANT(ScreenPos);
Output.PackedVelocityC = INVARIANT(PrevScreenPosObj);
const float2 ScreenVelocity = Calculate3DVelocity(Output.PackedVelocityA, Output.PackedVelocityC).xy;
VelocityScale = saturate(max(abs(ScreenVelocity.x), abs(ScreenVelocity.y)) / HairRenderInfo.VelocityMagnitudeScale);
}
#endif
float3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);
#if HAIR_STRAND_MESH_FACTORY
FHairViewInfo HairViewInfo;
HairViewInfo.TranslatedWorldCameraOrigin = ResolvedView.TranslatedWorldCameraOrigin;
HairViewInfo.ViewForward = ResolvedView.ViewForward;
HairViewInfo.RadiusAtDepth1 = lerp(HairRenderInfo.RadiusAtDepth1Primary, HairRenderInfo.RadiusAtDepth1Velocity, VelocityScale);
HairViewInfo.bIsOrthoView = HairRenderInfo.bIsOrthoView;
float4 WorldPosition = VertexFactoryGetWorldPosition(Input, VFIntermediates, HairViewInfo);
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPosition.xyz, TangentToLocal, HairViewInfo);
#else
float4 WorldPosition = VertexFactoryGetWorldPosition(Input, VFIntermediates);
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPosition.xyz, TangentToLocal);
#endif
// Isolate instructions used for world position offset on xbox 360,
// As these cause the optimizer to generate different position calculating instructions in each pass, resulting in self-z-fighting.
// This is only necessary for shaders used in passes that have depth testing enabled.
//ISOLATE
//{
// WorldPosition.xyz += GetMaterialWorldPositionOffset(VertexParameters);
// WorldPositionRaw.xyz += GetMaterialWorldPositionOffset(VertexParameters);
// PrevWorldPosition.xyz += GetMaterialPreviousWorldPositionOffset(VertexParameters);
//}
Output.Position = mul(WorldPosition, View.TranslatedWorldToClip);
#if HAIR_RENDER_MODE == RENDER_MODE_MSAA_VISIBILITY
Output.HairControlPointId = VFIntermediates.HairControlPointId;
#else
Output.FactoryInterpolants = VertexFactoryGetInterpolantsVSToPS(Input, VFIntermediates, VertexParameters);
#ifdef HAIR_STRAND_MESH_FACTORY
Output.WorldStrandRadius = VFIntermediates.HairDimensions.y;
#else
Output.WorldStrandRadius = 1;
#endif
#endif
}
#endif // HAIR_RENDER_MODE == RENDER_MODE_MSAA_VISIBILITY
#endif // VERTEXSHADER