209 lines
7.5 KiB
HLSL
209 lines
7.5 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Common.ush"
|
|
#include "SceneData.ush"
|
|
|
|
//
|
|
// Functions to get instanced stereo properties from a VF. They have to be macros as hlslcc does not support member functions (as of May 2022 it is still used for a couple platforms),
|
|
// whereas defining them as overloaded functions (taking VF as parameter) doesn't work as some VFs can be identical for typeless HLSL overloading rules.
|
|
//
|
|
#if INSTANCED_STEREO
|
|
#define GetInstanceIdFromVF(VFInput) (VFInput.InstanceId)
|
|
#define GetEyeIndexFromVF(VFInput) (IsInstancedStereo() ? (GetInstanceIdFromVF(VFInput) & 1) : 0)
|
|
#elif MOBILE_MULTI_VIEW
|
|
#define GetInstanceIdFromVF(VFInput) (0)
|
|
#define GetEyeIndexFromVF(VFInput) (VFInput.ViewId)
|
|
#else
|
|
#define GetInstanceIdFromVF(VFInput) (0)
|
|
#define GetEyeIndexFromVF(VFInput) (0)
|
|
#endif
|
|
|
|
#if MOBILE_MULTI_VIEW && !INSTANCED_STEREO
|
|
#define VF_MOBILE_MULTI_VIEW_DECLARE_INPUT_BLOCK() \
|
|
uint ViewId : SV_ViewID;
|
|
#else
|
|
#define VF_MOBILE_MULTI_VIEW_DECLARE_INPUT_BLOCK()
|
|
#endif // MOBILE_MULTI_VIEW && !INSTANCED_STEREO
|
|
|
|
//
|
|
// Required VF inputs to support dynamic instancing
|
|
//
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
#if SHADER_USES_PRIMITIVE_UBO
|
|
#define VF_GPUSCENE_DECLARE_INPUT_BLOCK(Attr0) \
|
|
uint DrawInstanceId : SV_InstanceID;
|
|
|
|
#define VF_GPUSCENE_GET_INTERMEDIATES(VFInput) \
|
|
GetSceneDataIntermediates(0u, VFInput.DrawInstanceId)
|
|
#else
|
|
#define VF_GPUSCENE_DECLARE_INPUT_BLOCK(Attr0) \
|
|
uint InstanceIdOffset : ATTRIBUTE##Attr0; \
|
|
uint DrawInstanceId : SV_InstanceID;
|
|
|
|
#define VF_GPUSCENE_GET_INTERMEDIATES(VFInput) \
|
|
GetSceneDataIntermediates(VFInput.InstanceIdOffset, VFInput.DrawInstanceId)
|
|
#endif //SHADER_USES_PRIMITIVE_UBO
|
|
|
|
#define VF_GPUSCENE_GET_LIGHTMAP_UV_SCALE_BIAS(VFInput, LightmapDataIndex) \
|
|
GetLightmapData(LightmapDataIndex, VFInput.DrawInstanceId).LightMapCoordinateScaleBias
|
|
|
|
#define VF_GPUSCENE_GET_SHADOWMAP_UV_SCALE_BIAS(VFInput, LightmapDataIndex) \
|
|
GetLightmapData(LightmapDataIndex, VFInput.DrawInstanceId).ShadowMapCoordinateScaleBias
|
|
|
|
#define VF_GPUSCENE_SET_INPUT_FOR_RT(_VFInputOut_, _InstanceId_, _DrawInstanceId_) \
|
|
_VFInputOut_.InstanceIdOffset = _InstanceId_ - _DrawInstanceId_; \
|
|
_VFInputOut_.DrawInstanceId = _DrawInstanceId_;
|
|
|
|
// GPUCULL_TODO: Makes use of DynamicDraw workaround, should instead refactor VF interfaces and provide the instance ID data directly.
|
|
#define VF_GPUSCENE_SET_INPUT_FOR_HAIR(_VFInputOut_, _PrimitiveId_, _DrawInstanceId_) \
|
|
_VFInputOut_.InstanceIdOffset = (_PrimitiveId_) | VF_TREAT_INSTANCE_ID_OFFSET_AS_PRIMITIVE_ID_FLAG; \
|
|
_VFInputOut_.DrawInstanceId = _DrawInstanceId_;
|
|
|
|
#define VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()
|
|
|
|
#undef GetInstanceIdFromVF
|
|
#define GetInstanceIdFromVF(VFInput) (VFInput.DrawInstanceId)
|
|
#else
|
|
#define VF_GPUSCENE_DECLARE_INPUT_BLOCK(Attr0)
|
|
#define VF_GPUSCENE_GET_INTERMEDIATES(VFInput) GetSceneDataIntermediates()
|
|
#define VF_GPUSCENE_GET_LIGHTMAP_UV_SCALE_BIAS(VFInput, LightmapDataIndex) PrecomputedLightingBuffer.LightMapCoordinateScaleBias
|
|
#define VF_GPUSCENE_GET_SHADOWMAP_UV_SCALE_BIAS(VFInput, LightmapDataIndex) PrecomputedLightingBuffer.ShadowMapCoordinateScaleBias
|
|
#define VF_GPUSCENE_SET_INPUT_FOR_RT(_VFInputOut_, _InstanceId_, _DrawInstanceId_)
|
|
#define VF_GPUSCENE_SET_INPUT_FOR_HAIR(_VFInputOut_, _PrimitiveId_, _DrawInstanceId_)
|
|
|
|
#if INSTANCED_STEREO
|
|
#define VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK() \
|
|
uint InstanceId : SV_InstanceID;
|
|
#else
|
|
#define VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()
|
|
#endif
|
|
|
|
#endif
|
|
|
|
// In case other paths in the above #if miss the declaration, catch this early
|
|
#if !defined(VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK)
|
|
#error VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK() should be defined for a vertex factory
|
|
#endif
|
|
|
|
#if !defined(GetInstanceIdFromVF)
|
|
#error GetInstanceIdFromVF() should be defined.
|
|
#endif
|
|
|
|
#if !defined(GetEyeIndexFromVF)
|
|
#error GetEyeIndexFromVF() should be defined.
|
|
#endif
|
|
|
|
#if INSTANCED_STEREO
|
|
#define StereoSetupVF(VFInput, Output) StereoSetupVS((IsInstancedStereo() ? (GetInstanceIdFromVF(VFInput) & 1) : 0), Output);
|
|
#elif MOBILE_MULTI_VIEW
|
|
#define StereoSetupVF(VFInput, Output) StereoSetupVS(VFInput.ViewId, Output);
|
|
#else
|
|
#define StereoSetupVF(VFInput, Output) StereoSetupVS(0, Output); // This will resolve the view regardless of the EyeIndex
|
|
#endif
|
|
|
|
FDFVector3 TransformLocalToWorld(float3 LocalPosition, FDFMatrix LocalToWorld)
|
|
{
|
|
return DFMultiply(LocalPosition, LocalToWorld);
|
|
}
|
|
|
|
FDFVector3 TransformLocalToWorld(float3 LocalPosition)
|
|
{
|
|
return TransformLocalToWorld(LocalPosition, GetPrimitiveDataFromUniformBuffer().LocalToWorld);
|
|
}
|
|
|
|
float4 TransformLocalToTranslatedWorld(float3 LocalPosition, FDFMatrix LocalToWorld)
|
|
{
|
|
return DFTransformLocalToTranslatedWorld(LocalPosition, LocalToWorld, ResolvedView.PreViewTranslation);
|
|
}
|
|
|
|
float4 TransformLocalToTranslatedWorld(float3 LocalPosition, float4x4 LocalToWorld)
|
|
{
|
|
return TransformLocalToTranslatedWorld(LocalPosition, DFPromote(LocalToWorld));
|
|
}
|
|
|
|
float4 TransformPreviousLocalPositionToTranslatedWorld(float3 PrevLocalPosition, FDFMatrix PrevLocalToWorld)
|
|
{
|
|
return DFTransformLocalToTranslatedWorld(PrevLocalPosition, PrevLocalToWorld, ResolvedView.PrevPreViewTranslation);
|
|
}
|
|
|
|
float4 TransformPreviousLocalPositionToTranslatedWorld(float3 PrevLocalPosition, float4x4 PrevLocalToWorld)
|
|
{
|
|
return TransformPreviousLocalPositionToTranslatedWorld(PrevLocalPosition, DFPromote(PrevLocalToWorld));
|
|
}
|
|
|
|
float3 RotateLocalToWorld(float3 LocalDirection, float3x3 LocalToWorld, float3 InvScale)
|
|
{
|
|
return
|
|
InvScale.x * LocalToWorld[0] * LocalDirection.xxx +
|
|
InvScale.y * LocalToWorld[1] * LocalDirection.yyy +
|
|
InvScale.z * LocalToWorld[2] * LocalDirection.zzz;
|
|
}
|
|
|
|
float3 RotateLocalToWorld(float3 LocalDirection, float4x4 LocalToWorld, float3 InvScale)
|
|
{
|
|
return RotateLocalToWorld(LocalDirection, (float3x3)LocalToWorld, InvScale);
|
|
}
|
|
|
|
float3 RotateLocalToWorld(float3 LocalDirection, FDFMatrix LocalToWorld, float3 InvScale)
|
|
{
|
|
return RotateLocalToWorld(LocalDirection, DFToFloat3x3(LocalToWorld), InvScale);
|
|
}
|
|
|
|
#if !VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
float4 TransformLocalToTranslatedWorld(float3 LocalPosition)
|
|
{
|
|
return TransformLocalToTranslatedWorld(LocalPosition, GetPrimitiveDataFromUniformBuffer().LocalToWorld);
|
|
}
|
|
|
|
float3 RotateLocalToWorld(float3 LocalDirection)
|
|
{
|
|
FPrimitiveSceneData PrimitiveData = GetPrimitiveDataFromUniformBuffer();
|
|
return RotateLocalToWorld(LocalDirection, PrimitiveData.LocalToWorld, PrimitiveData.InvNonUniformScale);
|
|
}
|
|
|
|
float3 RotateWorldToLocal(float3 WorldDirection)
|
|
{
|
|
FPrimitiveSceneData PrimitiveData = GetPrimitiveDataFromUniformBuffer();
|
|
const float3 InvScale = PrimitiveData.InvNonUniformScale;
|
|
const float3x3 LocalToWorld = DFToFloat3x3(PrimitiveData.LocalToWorld);
|
|
float3x3 InvRot = {
|
|
InvScale.x * LocalToWorld[0],
|
|
InvScale.y * LocalToWorld[1],
|
|
InvScale.z * LocalToWorld[2]
|
|
};
|
|
InvRot = transpose(InvRot);
|
|
return mul(WorldDirection, InvRot);
|
|
}
|
|
|
|
#endif // !VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
// Octahedron Normal Vectors
|
|
// [Cigolle 2014, "A Survey of Efficient Representations for Independent Unit Vectors"]
|
|
// Mean Max
|
|
// oct 8:8 0.33709 0.94424
|
|
// snorm 8:8:8 0.17015 0.38588
|
|
// oct 10:10 0.08380 0.23467
|
|
// snorm 10:10:10 0.04228 0.09598
|
|
// oct 12:12 0.02091 0.05874
|
|
|
|
float2 UnitToOct( float3 N )
|
|
{
|
|
N.xy /= dot( 1, abs(N) );
|
|
if( N.z <= 0 )
|
|
{
|
|
N.xy = ( 1 - abs(N.yx) ) * select( N.xy >= 0, float2(1,1), float2(-1,-1) );
|
|
}
|
|
return N.xy;
|
|
}
|
|
|
|
float3 OctToUnit( float2 Oct )
|
|
{
|
|
float3 N = float3( Oct, 1 - dot( 1, abs(Oct) ) );
|
|
if( N.z < 0 )
|
|
{
|
|
N.xy = ( 1 - abs(N.yx) ) * select( N.xy >= 0, float2(1,1), float2(-1,-1) );
|
|
}
|
|
return normalize(N);
|
|
}
|