Files
UnrealEngine/Engine/Shaders/Private/Lumen/LumenCardTile.ush
2025-05-18 13:04:45 +08:00

174 lines
5.4 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
LumenCardTiles.ush
=============================================================================*/
#pragma once
#include "/Engine/Shared/LumenDefinitions.h"
#define CARD_TILE_SIZE 8
#define NULL_PACKED_CARD_TILE 0xFFFFFFFF
struct FCardTileData
{
uint CardPageIndex;
uint2 TileCoord;
};
FCardTileData UnpackCardTileData(uint PackedTile)
{
FCardTileData TileData;
TileData.CardPageIndex = PackedTile & 0xFFFFFF;
TileData.TileCoord.x = (PackedTile >> 24) & 0xF;
TileData.TileCoord.y = (PackedTile >> 28) & 0xF;
return TileData;
}
uint PackCardTileData(FCardTileData CardTile)
{
uint PackedTile = CardTile.CardPageIndex;
PackedTile |= (CardTile.TileCoord.x << 24);
PackedTile |= (CardTile.TileCoord.y << 28);
return PackedTile;
}
struct FLightTileForCompactionPass
{
uint LightIndex;
uint ViewIndex;
uint bHasShadowMask;
uint CardTileIndex;
uint CulledLightIndex;
uint LightType;
};
struct FLightTileForShadowMaskPass
{
uint LightIndex;
uint ViewIndex;
uint CardPageIndex;
uint2 TileCoord;
};
struct FLightTileForLightPass
{
uint LightIndex;
uint ViewIndex;
uint ShadowMaskIndex;
};
FLightTileForCompactionPass UnpackLightTileForCompactionPass(uint2 PackedTile)
{
FLightTileForCompactionPass Tile;
Tile.LightIndex = BitFieldExtractU32(PackedTile.x, 28, 0);
Tile.ViewIndex = BitFieldExtractU32(PackedTile.x, 3, 28);
Tile.bHasShadowMask = BitFieldExtractU32(PackedTile.x, 1, 31);
Tile.CardTileIndex = BitFieldExtractU32(PackedTile.y, 24, 0);
Tile.CulledLightIndex = BitFieldExtractU32(PackedTile.y, 6, 24);
Tile.LightType = BitFieldExtractU32(PackedTile.y, 2, 30);
return Tile;
}
FLightTileForShadowMaskPass UnpackLightTileForShadowMaskPass(uint2 PackedTile)
{
FLightTileForShadowMaskPass Tile;
Tile.LightIndex = BitFieldExtractU32(PackedTile.x, 28, 0);
Tile.ViewIndex = BitFieldExtractU32(PackedTile.x, 4, 28);
Tile.CardPageIndex = BitFieldExtractU32(PackedTile.y, 24, 0);
Tile.TileCoord.x = BitFieldExtractU32(PackedTile.y, 4, 24);
Tile.TileCoord.y = BitFieldExtractU32(PackedTile.y, 4, 28);
return Tile;
}
FLightTileForLightPass UnpackLightTileForLightPass(uint2 PackedTile)
{
FLightTileForLightPass Tile;
Tile.LightIndex = BitFieldExtractU32(PackedTile.x, 28, 0);
Tile.ViewIndex = BitFieldExtractU32(PackedTile.x, 4, 28);
Tile.ShadowMaskIndex = PackedTile.y;
return Tile;
}
uint2 PackLightTileForCompactionPass(FLightTileForCompactionPass Tile)
{
uint2 PackedTile;
PackedTile.x = Tile.LightIndex | (Tile.ViewIndex << 28) | (Tile.bHasShadowMask << 31);
PackedTile.y = Tile.CardTileIndex | (Tile.CulledLightIndex << 24) | (Tile.LightType << 30);
return PackedTile;
}
uint2 PackLightTileForShadowMaskPass(FLightTileForShadowMaskPass Tile)
{
uint2 PackedTile;
PackedTile.x = Tile.LightIndex | (Tile.ViewIndex << 28);
PackedTile.y = Tile.CardPageIndex;
PackedTile.y |= (Tile.TileCoord.x << 24);
PackedTile.y |= (Tile.TileCoord.y << 28);
return PackedTile;
}
uint2 PackLightTileForLightPass(FLightTileForLightPass Tile)
{
uint2 PackedTile;
PackedTile.x = Tile.LightIndex | (Tile.ViewIndex << 28);
PackedTile.y = Tile.ShadowMaskIndex;
return PackedTile;
}
float4x4 FrustumTranslatedWorldToClip[LUMEN_MAX_VIEWS];
float4 PreViewTranslationHigh[LUMEN_MAX_VIEWS];
float4 PreViewTranslationLow[LUMEN_MAX_VIEWS];
float2 ViewExposure;
FDFVector3 GetPreViewTranslation(uint ViewIndex)
{
return MakeDFVector3(PreViewTranslationHigh[ViewIndex].xyz, PreViewTranslationLow[ViewIndex].xyz);
}
uint GetCardViewIndex(FLumenCardPageData CardPage, FLumenCardData Card, float2 UVMin, float2 UVMax, float2 CardTileDepthRange, uint NumViews, bool bPrioritizeWhenInFrustum)
{
float3 CardPageLocalCenter;
float3 CardPageLocalExtent;
GetCardLocalBBox(CardPage, Card, UVMin, UVMax, CardTileDepthRange, CardPageLocalCenter, CardPageLocalExtent);
uint ViewIndex = 0;
if (NumViews > 1)
{
FDFVector3 PreViewTranslation0 = GetPreViewTranslation(0);
FDFVector3 PreViewTranslation1 = GetPreViewTranslation(1);
float3 CardTranslatedWorldOrigin0 = DFFastToTranslatedWorld(Card.Origin, PreViewTranslation0);
float3 CardTranslatedWorldOrigin1 = DFFastToTranslatedWorld(Card.Origin, PreViewTranslation1);
float View0Distance = length(CardTranslatedWorldOrigin0);
float View1Distance = length(CardTranslatedWorldOrigin1);
#define IN_FRUSTUM_DISTANCE 1
#if IN_FRUSTUM_DISTANCE
float3 CardPageRotated = mul(Card.WorldToLocalRotation, CardPageLocalCenter);
float3 CardPageTranslatedWorldCenter0 = CardPageRotated + CardTranslatedWorldOrigin0;
float3 CardPageTranslatedWorldCenter1 = CardPageRotated + CardTranslatedWorldOrigin1;
if (bPrioritizeWhenInFrustum)
{
float4 CardOriginClipSpace0 = mul(float4(CardPageTranslatedWorldCenter0, 1.0f), FrustumTranslatedWorldToClip[0]);
if (all(CardOriginClipSpace0.xy >= CardOriginClipSpace0.w) && all(CardOriginClipSpace0.xy <= CardOriginClipSpace0.w) && CardOriginClipSpace0.z < 1.0f)
{
View0Distance = .5f * CardOriginClipSpace0.w;
}
float4 CardOriginClipSpace1 = mul(float4(CardPageTranslatedWorldCenter1, 1.0f), FrustumTranslatedWorldToClip[1]);
if (all(CardOriginClipSpace1.xy >= CardOriginClipSpace1.w) && all(CardOriginClipSpace1.xy <= CardOriginClipSpace1.w) && CardOriginClipSpace1.z < 1.0f)
{
View1Distance = .5f * CardOriginClipSpace1.w;
}
}
#endif
ViewIndex = View0Distance < View1Distance ? 0 : 1;
}
return ViewIndex;
}