// For now we don't use shadow cascade borders.
static public readonly bool s_UseCascadeBorders = false ;
// Keep sorting array around to avoid garbage
uint [ ] m_SortKeys = null ;
void UpdateSortKeysArray ( int count )
{
if ( m_SortKeys = = null | | count > m_SortKeys . Length )
{
m_SortKeys = new uint [ count ] ;
}
}
// Matrix used for Light list building
// Keep them around to avoid allocations
Matrix4x4 [ ] m_LightListProjMatrices = new Matrix4x4 [ 2 ] ;
Matrix4x4 [ ] m_LightListProjscrMatrices = new Matrix4x4 [ 2 ] ;
Matrix4x4 [ ] m_LightListInvProjscrMatrices = new Matrix4x4 [ 2 ] ;
Matrix4x4 [ ] m_LightListProjHMatrices = new Matrix4x4 [ 2 ] ;
Matrix4x4 [ ] m_LightListInvProjHMatrices = new Matrix4x4 [ 2 ] ;
public class LightList
{
public List < DirectionalLightData > directionalLights ;
int areaLightCount = 0 ;
int lightCount = Math . Min ( cullResults . visibleLights . Count , k_MaxLightsOnScreen ) ;
var sortKeys = new uint [ lightCount ] ;
UpdateSortKeysArray ( lightCount ) ;
int sortCount = 0 ;
for ( int lightIndex = 0 , numLights = cullResults . visibleLights . Count ; ( lightIndex < numLights ) & & ( sortCount < lightCount ) ; + + lightIndex )
{
uint shadow = m_ShadowIndices . ContainsKey ( lightIndex ) ? 1 u : 0 ;
// 5 bit (0x1F) light category, 5 bit (0x1F) GPULightType, 5 bit (0x1F) lightVolume, 1 bit for shadow casting, 16 bit index
s ortKeys[ sortCount + + ] = ( uint ) lightCategory < < 2 7 | ( uint ) gpuLightType < < 2 2 | ( uint ) lightVolumeType < < 1 7 | shadow < < 1 6 | ( uint ) lightIndex ;
m_S ortKeys[ sortCount + + ] = ( uint ) lightCategory < < 2 7 | ( uint ) gpuLightType < < 2 2 | ( uint ) lightVolumeType < < 1 7 | shadow < < 1 6 | ( uint ) lightIndex ;
CoreUtils . QuickSort ( s ortKeys, 0 , sortCount - 1 ) ; // Call our own quicksort instead of Array.Sort(sortKeys, 0, sortCount) so we don't allocate memory (note the SortCount-1 that is different from original call).
CoreUtils . QuickSort ( m_S ortKeys, 0 , sortCount - 1 ) ; // Call our own quicksort instead of Array.Sort(sortKeys, 0, sortCount) so we don't allocate memory (note the SortCount-1 that is different from original call).
// TODO: Refactor shadow management
// The good way of managing shadow:
for ( int sortIndex = 0 ; sortIndex < sortCount ; + + sortIndex )
{
// In 1. we have already classify and sorted the light, we need to use this sorted order here
uint sortKey = s ortKeys[ sortIndex ] ;
uint sortKey = m_S ortKeys[ sortIndex ] ;
LightCategory lightCategory = ( LightCategory ) ( ( sortKey > > 2 7 ) & 0 x1F ) ;
GPULightType gpuLightType = ( GPULightType ) ( ( sortKey > > 2 2 ) & 0 x1F ) ;
LightVolumeType lightVolumeType = ( LightVolumeType ) ( ( sortKey > > 1 7 ) & 0 x1F ) ;
var totalProbes = cullResults . visibleReflectionProbes . Count + reflectionProbeCullResults . visiblePlanarReflectionProbeCount ;
int probeCount = Math . Min ( totalProbes , k_MaxEnvLightsOnScreen ) ;
sortKeys = new uint [ probeCount ] ;
UpdateSortKeysArray ( probeCount ) ;
sortCount = 0 ;
for ( int probeIndex = 0 , numProbes = totalProbes ; ( probeIndex < numProbes ) & & ( sortCount < probeCount ) ; probeIndex + + )
var logVolume = CalculateProbeLogVolume ( probe . bounds ) ;
s ortKeys[ sortCount + + ] = PackProbeKey ( logVolume , lightVolumeType , 0 u , probeIndex ) ; // Sort by volume
m_S ortKeys[ sortCount + + ] = PackProbeKey ( logVolume , lightVolumeType , 0 u , probeIndex ) ; // Sort by volume
}
else
{
var logVolume = CalculateProbeLogVolume ( probe . bounds ) ;
s ortKeys[ sortCount + + ] = PackProbeKey ( logVolume , lightVolumeType , 1 u , planarProbeIndex ) ; // Sort by volume
m_S ortKeys[ sortCount + + ] = PackProbeKey ( logVolume , lightVolumeType , 1 u , planarProbeIndex ) ; // Sort by volume
CoreUtils . QuickSort ( s ortKeys, 0 , sortCount - 1 ) ; // Call our own quicksort instead of Array.Sort(sortKeys, 0, sortCount) so we don't allocate memory (note the SortCount-1 that is different from original call).
CoreUtils . QuickSort ( m_S ortKeys, 0 , sortCount - 1 ) ; // Call our own quicksort instead of Array.Sort(sortKeys, 0, sortCount) so we don't allocate memory (note the SortCount-1 that is different from original call).
uint sortKey = s ortKeys[ sortIndex ] ;
uint sortKey = m_S ortKeys[ sortIndex ] ;
LightVolumeType lightVolumeType ;
int probeIndex ;
int listType ;
bool isOrthographic = camera . orthographic ;
// camera to screen matrix (and it's inverse)
var projArr = new Matrix4x4 [ 2 ] ;
var projscrArr = new Matrix4x4 [ 2 ] ;
var invProjscrArr = new Matrix4x4 [ 2 ] ;
if ( m_FrameSettings . enableStereo )
{
// XRTODO: If possible, we could generate a non-oblique stereo projection
// Once we generate this non-oblique projection matrix, it can be shared across both eyes (un-array)
for ( int eyeIndex = 0 ; eyeIndex < 2 ; eyeIndex + + )
{
projArr [ eyeIndex ] = CameraProjectionStereoLHS ( hdCamera . camera , ( Camera . StereoscopicEye ) eyeIndex ) ;
projscrArr [ eyeIndex ] = temp * projArr [ eyeIndex ] ;
invProjscrArr [ eyeIndex ] = projscrArr [ eyeIndex ] . inverse ;
m_LightListProjMatrices [ eyeIndex ] = CameraProjectionStereoLHS ( hdCamera . camera , ( Camera . StereoscopicEye ) eyeIndex ) ;
m_LightListProjscrMatrices [ eyeIndex ] = temp * m_LightListProjMatrices [ eyeIndex ] ;
m_LightListInvProjscrMatrices [ eyeIndex ] = m_LightListProjscrMatrices [ eyeIndex ] . inverse ;
projArr [ 0 ] = GeometryUtils . GetProjectionMatrixLHS ( hdCamera . camera ) ;
projscrArr [ 0 ] = temp * projArr [ 0 ] ;
invProjscrArr [ 0 ] = projscrArr [ 0 ] . inverse ;
m_LightListProjMatrices [ 0 ] = GeometryUtils . GetProjectionMatrixLHS ( hdCamera . camera ) ;
m_LightListProjscrMatrices [ 0 ] = temp * m_LightListProjMatrices [ 0 ] ;
m_LightListInvProjscrMatrices [ 0 ] = m_LightListProjscrMatrices [ 0 ] . inverse ;
var isProjectionOblique = GeometryUtils . IsProjectionMatrixOblique ( projArr [ 0 ] ) ;
var isProjectionOblique = GeometryUtils . IsProjectionMatrixOblique ( m_LightListProjMatrices [ 0 ] ) ;
// generate screen-space AABBs (used for both fptl and clustered).
if ( m_lightCount ! = 0 )
temp . SetRow ( 2 , new Vector4 ( 0.0f , 0.0f , 0.5f , 0.5f ) ) ;
temp . SetRow ( 3 , new Vector4 ( 0.0f , 0.0f , 0.0f , 1.0f ) ) ;
var projhArr = new Matrix4x4 [ 2 ] ;
var invProjhArr = new Matrix4x4 [ 2 ] ;
projhArr [ eyeIndex ] = temp * projArr [ eyeIndex ] ;
invProjhArr [ eyeIndex ] = projhArr [ eyeIndex ] . inverse ;
m_LightListProjHMatrices [ eyeIndex ] = temp * m_LightListProjMatrices [ eyeIndex ] ;
m_LightListInvProjHMatrices [ eyeIndex ] = m_LightListProjHMatrices [ eyeIndex ] . inverse ;
projhArr [ 0 ] = temp * projArr [ 0 ] ;
invProjhArr [ 0 ] = projhArr [ 0 ] . inverse ;
m_LightListProjHMatrices [ 0 ] = temp * m_LightListProjMatrices [ 0 ] ;
m_LightListInvProjHMatrices [ 0 ] = m_LightListProjHMatrices [ 0 ] . inverse ;
}
var genAABBKernel = isProjectionOblique ? s_GenAABBKernel_Oblique : s_GenAABBKernel ;
cmd . SetComputeIntParam ( buildScreenAABBShader , HDShaderIDs . g_iNrVisibLights , m_lightCount ) ;
cmd . SetComputeBufferParam ( buildScreenAABBShader , genAABBKernel , HDShaderIDs . g_data , s_ConvexBoundsBuffer ) ;
cmd . SetComputeMatrixArrayParam ( buildScreenAABBShader , HDShaderIDs . g_mProjectionArr , projhArr ) ;
cmd . SetComputeMatrixArrayParam ( buildScreenAABBShader , HDShaderIDs . g_mInvProjectionArr , invProjhArr ) ;
cmd . SetComputeMatrixArrayParam ( buildScreenAABBShader , HDShaderIDs . g_mProjectionArr , m_LightListProjHMatrices ) ;
cmd . SetComputeMatrixArrayParam ( buildScreenAABBShader , HDShaderIDs . g_mInvProjectionArr , m_LightListInvProjHMatrices ) ;
// In stereo, we output two sets of AABB bounds
cmd . SetComputeBufferParam ( buildScreenAABBShader , genAABBKernel , HDShaderIDs . g_vBoundsBuffer , s_AABBBoundsBuffer ) ;
cmd . SetComputeIntParam ( buildPerBigTileLightListShader , HDShaderIDs . _EnvLightIndexShift , m_lightList . lights . Count ) ;
cmd . SetComputeIntParam ( buildPerBigTileLightListShader , HDShaderIDs . _DecalIndexShift , m_lightList . lights . Count + m_lightList . envLights . Count ) ;
cmd . SetComputeMatrixArrayParam ( buildPerBigTileLightListShader , HDShaderIDs . g_mScrProjectionArr , projscrArr ) ;
cmd . SetComputeMatrixArrayParam ( buildPerBigTileLightListShader , HDShaderIDs . g_mInvScrProjectionArr , invProjscrArr ) ;
cmd . SetComputeMatrixArrayParam ( buildPerBigTileLightListShader , HDShaderIDs . g_mScrProjectionArr , m_LightListProjscrMatrices ) ;
cmd . SetComputeMatrixArrayParam ( buildPerBigTileLightListShader , HDShaderIDs . g_mInvScrProjectionArr , m_LightListInvProjscrMatrices ) ;
cmd . SetComputeFloatParam ( buildPerBigTileLightListShader , HDShaderIDs . g_fNearPlane , camera . nearClipPlane ) ;
cmd . SetComputeFloatParam ( buildPerBigTileLightListShader , HDShaderIDs . g_fFarPlane , camera . farClipPlane ) ;
cmd . SetComputeBufferParam ( buildPerTileLightListShader , genListPerTileKernel , HDShaderIDs . _LightVolumeData , s_LightVolumeDataBuffer ) ;
cmd . SetComputeBufferParam ( buildPerTileLightListShader , genListPerTileKernel , HDShaderIDs . g_data , s_ConvexBoundsBuffer ) ;
cmd . SetComputeMatrixParam ( buildPerTileLightListShader , HDShaderIDs . g_mScrProjection , projscrArr [ 0 ] ) ;
cmd . SetComputeMatrixParam ( buildPerTileLightListShader , HDShaderIDs . g_mInvScrProjection , invProjscrArr [ 0 ] ) ;
cmd . SetComputeMatrixParam ( buildPerTileLightListShader , HDShaderIDs . g_mScrProjection , m_LightListProjscrMatrices [ 0 ] ) ;
cmd . SetComputeMatrixParam ( buildPerTileLightListShader , HDShaderIDs . g_mInvScrProjection , m_LightListInvProjscrMatrices [ 0 ] ) ;
cmd . SetComputeTextureParam ( buildPerTileLightListShader , genListPerTileKernel , HDShaderIDs . g_depth_tex , cameraDepthBufferRT ) ;
cmd . SetComputeBufferParam ( buildPerTileLightListShader , genListPerTileKernel , HDShaderIDs . g_vLightList , s_LightList ) ;
}
// Cluster
VoxelLightListGeneration ( cmd , hdCamera , projscrArr , invProjscrArr , cameraDepthBufferRT ) ;
VoxelLightListGeneration ( cmd , hdCamera , m_LightListProjscrMatrices , m_LightListInvProjscrMatrices , cameraDepthBufferRT ) ;
if ( enableFeatureVariants )
{