// types
public static int MAX_TYPES = 3 ;
public static int MAX_VOLUME_TYPES = 3 ;
public static int SPOT_LIGHT = 0 ;
public static int SPHERE_LIGHT = 1 ;
public static int BOX_LIGHT = 2 ;
public static int DIRECTIONAL_LIGHT = 3 ;
public static int SPOT_VOLUME = 0 ;
public static int SPHERE_VOLUME = 1 ;
public static int BOX_VOLUME = 2 ;
public static int DIRECTIONAL_VOLUME = 3 ;
public static int NR_LIGHT_MODELS = 2 ;
public static int DIRECT_LIGHT = 0 ;
public static int REFLECTION_LIGHT = 1 ;
public static int NR_LIGHT_CATEGORIES = 3 ;
public static int DIRECT_LIGHT_CATEGORY = 0 ;
public static int REFLECTION_LIGHT_CATEGORY = 1 ;
public static int AREA_LIGHT_CATEGORY = 2 ;
public enum DebugViewTilesFlags
{
DirectLighting = 1 ,
Reflection = 2
} ;
[GenerateHLSL]
public struct SFiniteLightBound
{
public Vector3 boxAxisX ;
public uint lightIndex ; // Index in light tabs like LightData / EnvLightData
public Vector3 lightAxisX ;
public uint lightTyp e ;
public uint lightVolum e ;
public Vector3 lightAxisY ;
public float radiusSq ;
public Vector3 boxInnerDist ;
public uint lightCategory ; // DIRECT_LIGHT=0, REFLECTION_LIGHT=1
public uint lightCategory ; // DIRECT_LIGHT=0, REFLECTION_LIGHT=1, AREA_LIGHT=2
public Vector3 boxInvRange ;
public float unused2 ;
private static int s_GenListPerBigTileKernel ;
// clustered light list specific buffers and data begin
public DebugViewTilesFlags debugViewTilesFlags = 0 ;
public int debugViewTilesFlags = 0 ;
public bool enableClustered = false ;
public bool disableFptlWhenClustered = true ; // still useful on opaques. Should be false by default to force tile on opaque.
public bool enableBigTilePrepass = true ;
const int capacityUShortsPerTile = 3 2 ;
const int dwordsPerTile = ( capacityUShortsPerTile + 1 ) > > 1 ; // room for 31 lights and a nrLights value.
s_LightList = new ComputeBuffer ( LightDefinitions . NR_LIGHT_MODEL S * dwordsPerTile * nrTiles , sizeof ( uint ) ) ; // enough list memory for a 4k x 4k display
s_LightList = new ComputeBuffer ( LightDefinitions . NR_LIGHT_CATEGORIE S * dwordsPerTile * nrTiles , sizeof ( uint ) ) ; // enough list memory for a 4k x 4k display
s_PerVoxelOffset = new ComputeBuffer ( LightDefinitions . NR_LIGHT_MODEL S * ( 1 < < k_Log2NumClusters ) * nrTiles , sizeof ( uint ) ) ;
s_PerVoxelOffset = new ComputeBuffer ( LightDefinitions . NR_LIGHT_CATEGORIE S * ( 1 < < k_Log2NumClusters ) * nrTiles , sizeof ( uint ) ) ;
s_PerVoxelLightLists = new ComputeBuffer ( NumLightIndicesPerClusteredTile ( ) * nrTiles , sizeof ( uint ) ) ;
if ( k_UseDepthBuffer )
public void PrepareLightsForGPU ( CullResults cullResults , Camera camera , HDRenderLoop . LightList lightList )
{
var numModels = ( int ) LightDefinitions . NR_LIGHT_MODELS ;
var numVolTypes = ( int ) LightDefinitions . MAX_TYPES ;
var numCategories = ( int ) LightDefinitions . NR_LIGHT_CATEGORIES ;
var numVolTypes = ( int ) LightDefinitions . MAX_VOLUME_TYPES ;
var numEntries = new int [ numModels , numVolTypes ] ;
var offsets = new int [ numModels , numVolTypes ] ;
var numEntries = new int [ numCategories , numVolTypes ] ;
var offsets = new int [ numCategories , numVolTypes ] ;
var numEntries2nd = new int [ numModels , numVolTypes ] ;
var numEntries2nd = new int [ numCategories , numVolTypes ] ;
// TODO manage area lights
var volType = punctualLight . lightType = = GPULightType . Spot ? LightDefinitions . SPOT_LIGHT : ( punctualLight . lightType = = GPULightType . Point ? LightDefinitions . SPHERE_LIGHT : - 1 ) ;
var volType = punctualLight . lightType = = GPULightType . Spot ? LightDefinitions . SPOT_VOLUME : ( punctualLight . lightType = = GPULightType . Point ? LightDefinitions . SPHERE_VOLUME : - 1 ) ;
+ + numEntries [ LightDefinitions . DIRECT_LIGHT , volType ] ;
+ + numEntries [ LightDefinitions . DIRECT_LIGHT_CATEGORY , volType ] ;
var volType = LightDefinitions . BOX_LIGHT ; // always a box for now
+ + numEntries [ LightDefinitions . REFLECTION_LIGHT , volType ] ;
var volType = LightDefinitions . BOX_VOLUME ; // always a box for now
+ + numEntries [ LightDefinitions . REFLECTION_LIGHT_CATEGORY , volType ] ;
foreach ( var areaLight in lightList . areaLights )
{
var volType = LightDefinitions . BOX_VOLUME ;
+ + numEntries [ LightDefinitions . AREA_LIGHT_CATEGORY , volType ] ;
}
for ( int m = 0 ; m < numModels ; m + + )
for ( int category = 0 ; category < numCategories ; category + + )
offsets [ m , 0 ] = m = = 0 ? 0 : ( numEntries [ m - 1 , numVolTypes - 1 ] + offsets [ m - 1 , numVolTypes - 1 ] ) ;
offsets [ category , 0 ] = category = = 0 ? 0 : ( numEntries [ category - 1 , numVolTypes - 1 ] + offsets [ category - 1 , numVolTypes - 1 ] ) ;
offsets [ m , v ] = numEntries [ m , v - 1 ] + offsets [ m , v - 1 ] ;
offsets [ category , v ] = numEntries [ category , v - 1 ] + offsets [ category , v - 1 ] ;
}
}
var lightShapeData = new LightShapeData ( ) ;
int index = - 1 ;
lightShapeData . lightCategory = ( uint ) LightDefinitions . DIRECT_LIGHT ;
lightShapeData . lightCategory = ( uint ) LightDefinitions . DIRECT_LIGHT_CATEGORY ;
lightShapeData . lightIndex = ( uint ) lightIndex ;
if ( punctualLightData . lightType = = GPULightType . Spot | | punctualLightData . lightType = = GPULightType . ProjectorPyramid )
lightShapeData . lightAxisX = vx ;
lightShapeData . lightAxisY = vy ;
lightShapeData . lightAxisZ = vz ;
lightShapeData . lightTyp e = ( uint ) LightDefinitions . SPOT_LIGHT ;
lightShapeData . lightVolum e = ( uint ) LightDefinitions . SPOT_VOLUME ;
int i = LightDefinitions . DIRECT_LIGHT , j = LightDefinitions . SPOT_LIGHT ;
int i = LightDefinitions . DIRECT_LIGHT_CATEGORY , j = LightDefinitions . SPOT_VOLUME ;
index = numEntries2nd [ i , j ] + offsets [ i , j ] ; + + numEntries2nd [ i , j ] ;
}
else // if (punctualLightData.lightType == GPULightType.Point)
lightShapeData . lightAxisX = vx ;
lightShapeData . lightAxisY = vy ;
lightShapeData . lightAxisZ = vz ;
lightShapeData . lightTyp e = ( uint ) LightDefinitions . SPHERE_LIGHT ;
lightShapeData . lightVolum e = ( uint ) LightDefinitions . SPHERE_VOLUME ;
int i = LightDefinitions . DIRECT_LIGHT , j = LightDefinitions . SPHERE_LIGHT ;
int i = LightDefinitions . DIRECT_LIGHT_CATEGORY , j = LightDefinitions . SPHERE_VOLUME ;
index = numEntries2nd [ i , j ] + offsets [ i , j ] ; + + numEntries2nd [ i , j ] ;
}
//Vector3 C = bnds.center; // P + boxOffset;
var C = mat . MultiplyPoint ( boxOffset ) ; // same as commented out line above when rot is identity
var combinedExtent = e + new Vector3 ( blendDistance , blendDistance , blendDistance ) ;
var combinedExtent = e + new Vector3 ( blendDistance , blendDistance , blendDistance ) ;
Vector3 vx = mat . GetColumn ( 0 ) ;
Vector3 vy = mat . GetColumn ( 1 ) ;
bound . radius = combinedExtent . magnitude ;
var lightShapeData = new LightShapeData ( ) ;
lightShapeData . lightTyp e = ( uint ) LightDefinitions . BOX_LIGHT ;
lightShapeData . lightCategory = ( uint ) LightDefinitions . REFLECTION_LIGHT ;
lightShapeData . lightVolum e = ( uint ) LightDefinitions . BOX_VOLUME ;
lightShapeData . lightCategory = ( uint ) LightDefinitions . REFLECTION_LIGHT_CATEGORY ;
lightShapeData . lightIndex = ( uint ) envIndex ;
lightShapeData . lightPos = Cw ;
lightShapeData . boxInnerDist = e ;
lightShapeData . boxInvRange . Set ( 1.0f / delta . x , 1.0f / delta . y , 1.0f / delta . z ) ;
int i = LightDefinitions . REFLECTION_LIGHT , j = LightDefinitions . BOX_LIGHT ;
int i = LightDefinitions . REFLECTION_LIGHT_CATEGORY , j = LightDefinitions . BOX_VOLUME ;
int index = numEntries2nd [ i , j ] + offsets [ i , j ] ; + + numEntries2nd [ i , j ] ;
m_boundData [ index ] = bound ;
m_lightShapeData [ index ] = lightShapeData ;
}
for ( int areaLightIndex = 0 ; areaLightIndex < lightList . areaLights . Count ; areaLightIndex + + )
{
LightData areaLightData = lightList . areaLights [ areaLightIndex ] ;
// Fill bounds
var bound = new SFiniteLightBound ( ) ;
var lightShapeData = new LightShapeData ( ) ;
lightShapeData . lightVolume = ( uint ) LightDefinitions . BOX_VOLUME ;
lightShapeData . lightCategory = ( uint ) LightDefinitions . AREA_LIGHT_CATEGORY ;
lightShapeData . lightIndex = ( uint ) areaLightIndex ;
if ( areaLightData . lightType = = GPULightType . Rectangle )
{
Vector3 centerVS = worldToView . MultiplyPoint ( areaLightData . positionWS ) ;
Vector3 xAxisVS = worldToView . MultiplyVector ( areaLightData . right ) ;
Vector3 yAxisVS = worldToView . MultiplyVector ( areaLightData . up ) ;
Vector3 zAxisVS = worldToView . MultiplyVector ( areaLightData . forward ) ;
float radius = 1.0f / Mathf . Sqrt ( areaLightData . invSqrAttenuationRadius ) ;
Vector3 dimensions = new Vector3 ( areaLightData . size . x * 0.5f + radius , areaLightData . size . y * 0.5f + radius , radius ) ;
if ( ! areaLightData . twoSided )
{
centerVS - = zAxisVS * radius * 0.5f ;
dimensions . z * = 0.5f ;
}
bound . center = centerVS ;
bound . boxAxisX = dimensions . x * xAxisVS ;
bound . boxAxisY = dimensions . y * yAxisVS ;
bound . boxAxisZ = dimensions . z * zAxisVS ;
bound . scaleXY . Set ( 1.0f , 1.0f ) ;
bound . radius = dimensions . magnitude ;
lightShapeData . lightPos = centerVS ;
lightShapeData . lightAxisX = xAxisVS ;
lightShapeData . lightAxisY = yAxisVS ;
lightShapeData . lightAxisZ = zAxisVS ;
lightShapeData . boxInnerDist = dimensions ;
lightShapeData . boxInvRange . Set ( 1 e5f , 1 e5f , 1 e5f ) ;
}
else if ( areaLightData . lightType = = GPULightType . Line )
{
Vector3 centerVS = worldToView . MultiplyPoint ( areaLightData . positionWS ) ;
Vector3 xAxisVS = worldToView . MultiplyVector ( areaLightData . right ) ;
Vector3 yAxisVS = worldToView . MultiplyVector ( areaLightData . up ) ;
Vector3 zAxisVS = worldToView . MultiplyVector ( areaLightData . forward ) ;
float radius = 1.0f / Mathf . Sqrt ( areaLightData . invSqrAttenuationRadius ) ;
Vector3 dimensions = new Vector3 ( areaLightData . size . x * 0.5f + radius , radius , radius ) ;
bound . center = centerVS ;
bound . boxAxisX = dimensions . x * xAxisVS ;
bound . boxAxisY = dimensions . y * yAxisVS ;
bound . boxAxisZ = dimensions . z * zAxisVS ;
bound . scaleXY . Set ( 1.0f , 1.0f ) ;
bound . radius = dimensions . magnitude ;
lightShapeData . lightPos = centerVS ;
lightShapeData . lightAxisX = xAxisVS ;
lightShapeData . lightAxisY = yAxisVS ;
lightShapeData . lightAxisZ = zAxisVS ;
lightShapeData . boxInnerDist = new Vector3 ( areaLightData . size . x * 0.5f , 0.01f , 0.01f ) ;
lightShapeData . boxInvRange . Set ( 1.0f / radius , 1.0f / radius , 1.0f / radius ) ;
}
else
{
Debug . Assert ( false ) ;
}
int i = LightDefinitions . AREA_LIGHT_CATEGORY , j = LightDefinitions . BOX_VOLUME ;
for ( var m = 0 ; m < numModels ; m + + )
for ( var category = 0 ; category < numCategories ; category + + )
Debug . Assert ( numEntries [ m , v ] = = numEntries2nd [ m , v ] , "count mismatch on second pass!" ) ;
Debug . Assert ( numEntries [ category , v ] = = numEntries2nd [ category , v ] , "count mismatch on second pass!" ) ;
m_lightCount = lightList . punctualLights . Count + lightList . envLights . Count ;
m_lightCount = lightList . punctualLights . Count + lightList . envLights . Count + lightList . areaLights . Count ;
s_ConvexBoundsBuffer . SetData ( m_boundData ) ; // TODO: check with Vlad what is happening here, do we copy 1024 element always ? Could we setup the size we want to copy ?
s_LightShapeDataBuffer . SetData ( m_lightShapeData ) ;
}
m_DebugViewTilesMaterial . SetMatrix ( "_InvViewProjMatrix" , invViewProj ) ;
m_DebugViewTilesMaterial . SetVector ( "_ScreenSize" , screenSize ) ;
m_DebugViewTilesMaterial . SetInt ( "_ViewTilesFlags" , ( int ) debugViewTilesFlags ) ;
m_DebugViewTilesMaterial . SetInt ( "_ViewTilesFlags" , debugViewTilesFlags ) ;
m_DebugViewTilesMaterial . EnableKeyword ( bUseClusteredForDeferred ? "USE_CLUSTERED_LIGHTLIST" : "USE_FPTL_LIGHTLIST" ) ;
m_DebugViewTilesMaterial . DisableKeyword ( ! bUseClusteredForDeferred ? "USE_CLUSTERED_LIGHTLIST" : "USE_FPTL_LIGHTLIST" ) ;