123 lines
5.5 KiB
HLSL
123 lines
5.5 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "../LargeWorldCoordinates.ush"
|
|
#include "../ByteBuffer.ush"
|
|
#include "/Engine/Shared/VirtualShadowMapDefinitions.h"
|
|
#include "VirtualShadowMapHandle.ush"
|
|
|
|
#define VSM_PSD_OFFSET_RESOLUTION_LOD_BIAS 236 // todo: should use structuredbuffer or improvised offsetof instead
|
|
#define VSM_PSD_OFFSET_LIGHT_TYPE 204
|
|
|
|
// Rougly the same structure as in VirtualShadowMapArray.h, with some logic around LWC values
|
|
struct FVirtualShadowMapProjectionShaderData
|
|
{
|
|
float4x4 ShadowViewToClipMatrix;
|
|
float4x4 TranslatedWorldToShadowUVMatrix;
|
|
float4x4 TranslatedWorldToShadowUVNormalMatrix;
|
|
|
|
float3 LightDirection;
|
|
uint LightType; // Matches ELightComponentType via defines in SSDDefinitions.ush
|
|
|
|
FDFVector3 PreViewTranslation;
|
|
float LightRadius;
|
|
float ResolutionLodBias;
|
|
|
|
float3 ClipmapWorldOriginOffset; // Clipmap origin, in shadow translated world
|
|
|
|
int2 ClipmapCornerRelativeOffset;
|
|
int ClipmapLevel; // "Absolute" level, can be negative
|
|
int ClipmapLevelCountRemaining; // Remaining levels, relative to this one
|
|
|
|
uint Flags;
|
|
float ClipmapLevelWPODistanceDisabledThresholdSquared;
|
|
float LightSourceRadius;
|
|
float TexelDitherScale; // Per-light additional dither filtering
|
|
uint MinMipLevel; // Minimum mip level that is used for this mip chain (only valid for local lights)
|
|
|
|
int SceneRendererPrimaryViewId;
|
|
int PersistentViewId;
|
|
|
|
// Derived data for convenience when passing the structure around
|
|
//int VirtualShadowMapId;
|
|
FVirtualShadowMapHandle VirtualShadowMapHandle;
|
|
bool bUnCached; // see VSM_PROJ_FLAG_UNCACHED
|
|
bool bUnreferenced; // see VSM_PROJ_FLAG_UNREFERENCED
|
|
bool bIsCoarseClipLevel; // see VSM_PROJ_FLAG_IS_COARSE_CLIP_LEVEL
|
|
bool bUseReceiverMask; // see VSM_PROJ_FLAG_USE_RECEIVER_MASK
|
|
};
|
|
|
|
FVirtualShadowMapProjectionShaderData DecodeVirtualShadowMapProjectionData(ByteAddressBuffer ProjectionData, FVirtualShadowMapHandle VirtualShadowMapHandle)
|
|
{
|
|
FVirtualShadowMapProjectionShaderData Result;
|
|
Result.VirtualShadowMapHandle = VirtualShadowMapHandle;
|
|
|
|
const uint VSMOffset = VirtualShadowMapHandle.GetDataIndex() * VSM_PSD_STRIDE;
|
|
uint CurrentLoadOffset = VSMOffset;
|
|
LoadAndIncrementOffset(Result.ShadowViewToClipMatrix, ProjectionData, CurrentLoadOffset);
|
|
LoadAndIncrementOffset(Result.TranslatedWorldToShadowUVMatrix, ProjectionData, CurrentLoadOffset);
|
|
LoadAndIncrementOffset(Result.TranslatedWorldToShadowUVNormalMatrix, ProjectionData, CurrentLoadOffset);
|
|
|
|
// NOTE: Stick with struct-element-sized loads for the moment since we may only be using subsets
|
|
// of the data in the calling code and we want to ensure the compiler has simple DCE options.
|
|
LoadAndIncrementOffset(Result.LightDirection, ProjectionData, CurrentLoadOffset);
|
|
LoadAndIncrementOffset(Result.LightType, ProjectionData, CurrentLoadOffset);
|
|
checkSlow(VSM_PSD_OFFSET_LIGHT_TYPE == (CurrentLoadOffset - VSMOffset));
|
|
|
|
float3 PreViewTranslationHigh;
|
|
LoadAndIncrementOffset(PreViewTranslationHigh, ProjectionData, CurrentLoadOffset);
|
|
LoadAndIncrementOffset(Result.LightRadius, ProjectionData, CurrentLoadOffset);
|
|
|
|
float3 PreViewTranslationLow;
|
|
LoadAndIncrementOffset(PreViewTranslationLow, ProjectionData, CurrentLoadOffset);
|
|
checkSlow(VSM_PSD_OFFSET_RESOLUTION_LOD_BIAS == (CurrentLoadOffset - VSMOffset));
|
|
LoadAndIncrementOffset(Result.ResolutionLodBias, ProjectionData, CurrentLoadOffset);
|
|
|
|
float3 NegativeClipmapWorldOriginOffset;
|
|
LoadAndIncrementOffset(NegativeClipmapWorldOriginOffset, ProjectionData, CurrentLoadOffset);
|
|
LoadAndIncrementOffset(Result.LightSourceRadius, ProjectionData, CurrentLoadOffset);
|
|
|
|
LoadAndIncrementOffset(Result.ClipmapCornerRelativeOffset, ProjectionData, CurrentLoadOffset);
|
|
|
|
uint ClipmapLevel_ClipmapLevelCountRemaining = 0;
|
|
LoadAndIncrementOffset(ClipmapLevel_ClipmapLevelCountRemaining, ProjectionData, CurrentLoadOffset);
|
|
if (int(ClipmapLevel_ClipmapLevelCountRemaining) != -1)
|
|
{
|
|
Result.ClipmapLevel = int(ClipmapLevel_ClipmapLevelCountRemaining >> 16u) - VSM_PACKED_CLIP_LEVEL_BIAS;
|
|
Result.ClipmapLevelCountRemaining = int(ClipmapLevel_ClipmapLevelCountRemaining & 0xFFFFu);
|
|
}
|
|
else
|
|
{
|
|
Result.ClipmapLevel = VSM_PACKED_CLIP_LEVEL_BIAS;
|
|
Result.ClipmapLevelCountRemaining = -1;
|
|
}
|
|
uint PackedCullingViewId;
|
|
LoadAndIncrementOffset(PackedCullingViewId, ProjectionData, CurrentLoadOffset);
|
|
|
|
Result.SceneRendererPrimaryViewId = int(PackedCullingViewId >> 16u) - 1;
|
|
Result.PersistentViewId = int(PackedCullingViewId & 0xFFFFu) - 1;
|
|
|
|
LoadAndIncrementOffset(Result.Flags, ProjectionData, CurrentLoadOffset);
|
|
LoadAndIncrementOffset(Result.ClipmapLevelWPODistanceDisabledThresholdSquared, ProjectionData, CurrentLoadOffset);
|
|
|
|
LoadAndIncrementOffset(Result.TexelDitherScale, ProjectionData, CurrentLoadOffset);
|
|
LoadAndIncrementOffset(Result.MinMipLevel, ProjectionData, CurrentLoadOffset);
|
|
|
|
// Computed data
|
|
Result.PreViewTranslation = MakeDFVector3(PreViewTranslationHigh, PreViewTranslationLow);
|
|
Result.ClipmapWorldOriginOffset = -NegativeClipmapWorldOriginOffset;
|
|
|
|
Result.bUnCached = (Result.Flags & VSM_PROJ_FLAG_UNCACHED) != 0U;
|
|
Result.bUnreferenced = (Result.Flags & VSM_PROJ_FLAG_UNREFERENCED) != 0U;
|
|
Result.bIsCoarseClipLevel = (Result.Flags & VSM_PROJ_FLAG_IS_COARSE_CLIP_LEVEL) != 0U;
|
|
Result.bUseReceiverMask = (Result.Flags & VSM_PROJ_FLAG_USE_RECEIVER_MASK) != 0;
|
|
|
|
return Result;
|
|
}
|
|
|
|
FVirtualShadowMapProjectionShaderData GetVirtualShadowMapProjectionData(FVirtualShadowMapHandle VirtualShadowMapHandle)
|
|
{
|
|
return DecodeVirtualShadowMapProjectionData(VirtualShadowMap.ProjectionData, VirtualShadowMapHandle);
|
|
}
|