ShadowRenderPass m_ShadowPass ;
public const int k_MaxDirectionalLightsOnSCreen = 2 ;
public const int k_MaxPunctualLightsOnSCreen = 5 1 2 ;
public const int k_MaxAreaLightsOnSCreen = 1 2 8 ;
public const int k_MaxEnvLightsOnSCreen = 6 4 ;
public class LightList
{
public List < PunctualLightData > punctualLights ;
public List < AreaLightData > areaLights ;
public List < DirectionalLightData > directionalLights ;
public List < LightData > punctualLights ;
public List < LightData > areaLights ;
public List < EnvLightData > envLights ;
public List < PunctualShadowData > punctualShadows ;
}
{
// Init light list
lightList = new LightList ( ) ;
lightList . punctualLights = new List < PunctualLightData > ( ) ;
lightList . areaLights = new List < AreaLightData > ( ) ;
lightList . directionalLights = new List < DirectionalLightData > ( ) ;
lightList . punctualLights = new List < LightData > ( ) ;
lightList . areaLights = new List < LightData > ( ) ;
lightList . envLights = new List < EnvLightData > ( ) ;
lightList . punctualShadows = new List < PunctualShadowData > ( ) ;
continue ;
}
// Note: LightType.Area is offline only, use for baking, no need to test it
// Test whether we should treat this punctual light as an area light.
// It's a temporary hack until the proper UI support is added.
if ( additionalData . treatAsAreaLight )
if ( light . lightType = = LightType . Directional )
if ( lightList . areaLights . Count > = k_MaxAreaLightsOnSCreen )
if ( lightList . areaLights . Count > = k_MaxDirectionalLightsOnSCreen )
var lightData = new AreaLightData ( ) ;
var directionalLightData = new DirectionalLightData ( ) ;
// Light direction for directional and is opposite to the forward direction
directionalLightData . direction = - light . light . transform . forward ;
directionalLightData . color = new Vector3 ( lightColorR , lightColorG , lightColorB ) ;
directionalLightData . diffuseScale = additionalData . affectDiffuse ? 1.0f : 0.0f ;
directionalLightData . specularScale = additionalData . affectSpecular ? 1.0f : 0.0f ;
directionalLightData . cosAngle = 0.0f ;
directionalLightData . sinAngle = 0.0f ;
directionalLightData . shadowIndex = - 1 ;
// TODO: add AreaShapeType.Line support for small widths.
lightData . shapeType = AreaShapeType . Rectangle ;
lightData . size = new Vector2 ( additionalData . areaLightLength , additionalData . areaLightWidth ) ;
lightData . twoSided = additionalData . isDoubleSided ;
// TODO: shadow
lightData . positionWS = light . light . transform . position ;
lightData . forward = light . light . transform . forward ; // Note: Light direction is oriented backward (-Z)
lightData . up = light . light . transform . up ;
lightData . right = light . light . transform . right ;
lightList . directionalLights . Add ( directionalLightData ) ;
lightData . color = new Vector3 ( lightColorR , lightColorG , lightColorB ) ;
lightData . diffuseScale = additionalData . affectDiffuse ? 1.0f : 0.0f ;
lightData . specularScale = additionalData . affectSpecular ? 1.0f : 0.0f ;
lightData . shadowDimmer = additionalData . shadowDimmer ;
continue ;
}
lightData . invSqrAttenuationRadius = 1.0f / ( light . range * light . range ) ;
// Note: LightType.Area is offline only, use for baking, no need to test it
var lightData = new LightData ( ) ;
lightList . areaLights . Add ( lightData ) ;
// Early out if we reach the maximum
// Test whether we should treat this punctual light as an area light.
// It's a temporary hack until the proper UI support is added.
if ( additionalData . treatAsAreaLight )
{
if ( lightList . areaLights . Count > = k_MaxAreaLightsOnSCreen )
continue ;
// TODO: shadows.
lightData . lightType = GPULightType . Rectangle ;
}
else
{
var punctualLightData = new PunctualLightData ( ) ;
if ( light . lightType = = LightType . Directional )
switch ( light . lightType )
punctualLightData . useDistanceAttenuation = 0.0f ;
// positionWS store Light direction for directional and is opposite to the forward direction
punctualLightData . positionWS = - light . light . transform . forward ;
punctualLightData . invSqrAttenuationRadius = 0.0f ;
case LightType . Directional : lightData . lightType = GPULightType . Directional ; break ;
case LightType . Spot : lightData . lightType = GPULightType . Spot ; break ;
case LightType . Point : lightData . lightType = GPULightType . Point ; break ;
else
{
punctualLightData . useDistanceAttenuation = 1.0f ;
punctualLightData . positionWS = light . light . transform . position ;
punctualLightData . invSqrAttenuationRadius = 1.0f / ( light . range * light . range ) ;
}
}
punctualLightData . color = new Vector3 ( lightColorR , lightColorG , lightColorB ) ;
lightData . positionWS = light . light . transform . position ;
lightData . invSqrAttenuationRadius = 1.0f / ( light . range * light . range ) ;
punctualLightData . forward = light . light . transform . forward ; // Note: Light direction is oriented backward (-Z)
punctualLightData . up = light . light . transform . up ;
punctualLightData . right = light . light . transform . right ;
lightData . color = new Vector3 ( lightColorR , lightColorG , lightColorB ) ;
lightData . forward = light . light . transform . forward ; // Note: Light direction is oriented backward (-Z)
lightData . up = light . light . transform . up ;
lightData . right = light . light . transform . right ;
if ( light . lightType = = LightType . Spot )
{
var spotAngle = light . spotAngle ;
if ( lightData . lightType = = GPULightType . Spot )
{
var spotAngle = light . spotAngle ;
var innerConePercent = additionalData . GetInnerSpotPercent01 ( ) ;
var cosSpotOuterHalfAngle = Mathf . Clamp ( Mathf . Cos ( spotAngle * 0.5f * Mathf . Deg2Rad ) , 0.0f , 1.0f ) ;
var cosSpotInnerHalfAngle = Mathf . Clamp ( Mathf . Cos ( spotAngle * 0.5f * innerConePercent * Mathf . Deg2Rad ) , 0.0f , 1.0f ) ; // inner cone
var innerConePercent = additionalData . GetInnerSpotPercent01 ( ) ;
var cosSpotOuterHalfAngle = Mathf . Clamp ( Mathf . Cos ( spotAngle * 0.5f * Mathf . Deg2Rad ) , 0.0f , 1.0f ) ;
var cosSpotInnerHalfAngle = Mathf . Clamp ( Mathf . Cos ( spotAngle * 0.5f * innerConePercent * Mathf . Deg2Rad ) , 0.0f , 1.0f ) ; // inner cone
var val = Mathf . Max ( 0.001f , ( cosSpotInnerHalfAngle - cosSpotOuterHalfAngle ) ) ;
punctualLightData . angleScale = 1.0f / val ;
punctualLightData . angleOffset = - cosSpotOuterHalfAngle * punctualLightData . angleScale ;
}
else
{
// 1.0f, 2.0f are neutral value allowing GetAngleAnttenuation in shader code to return 1.0
punctualLightData . angleScale = 1.0f ;
punctualLightData . angleOffset = 2.0f ;
}
var val = Mathf . Max ( 0.001f , ( cosSpotInnerHalfAngle - cosSpotOuterHalfAngle ) ) ;
lightData . angleScale = 1.0f / val ;
lightData . angleOffset = - cosSpotOuterHalfAngle * lightData . angleScale ;
}
else
{
// 1.0f, 2.0f are neutral value allowing GetAngleAnttenuation in shader code to return 1.0
lightData . angleScale = 1.0f ;
lightData . angleOffset = 2.0f ;
}
punctualLightData . diffuseScale = additionalData . affectDiffuse ? 1.0f : 0.0f ;
punctualLightData . specularScale = additionalData . affectSpecular ? 1.0f : 0.0f ;
punctualLightData . shadowDimmer = additionalData . shadowDimmer ;
lightData . diffuseScale = additionalData . affectDiffuse ? 1.0f : 0.0f ;
lightData . specularScale = additionalData . affectSpecular ? 1.0f : 0.0f ;
lightData . shadowDimmer = additionalData . shadowDimmer ;
punctualLightData . IESIndex = - 1 ;
punctualLightData . cookieIndex = - 1 ;
punctualLightData . shadowIndex = - 1 ;
lightData . IESIndex = - 1 ;
lightData . cookieIndex = - 1 ;
lightData . shadowIndex = - 1 ;
bool hasCookie = light . light . cookie ! = null ;
if ( hasCookie )
bool hasCookie = light . light . cookie ! = null ;
if ( hasCookie )
{
if ( light . lightType = = LightType . Point )
if ( light . lightType = = LightType . Point )
{
punctualLightData . cookieIndex = m_CubeCookieTexArray . FetchSlice ( light . light . cookie ) ;
}
else if ( light . lightType = = LightType . Spot )
{
punctualLightData . cookieIndex = m_CookieTexArray . FetchSlice ( light . light . cookie ) ;
}
lightData . cookieIndex = m_CubeCookieTexArray . FetchSlice ( light . light . cookie ) ;
// Setup shadow data arrays
bool hasShadows = light . light . shadows ! = LightShadows . None & & shadowOutput . GetShadowSliceCountLightIndex ( lightIndex ) ! = 0 ;
bool hasNotReachMaxLimit = lightList . punctualShadows . Count + ( light . lightType = = LightType . Point ? 6 : 1 ) < = k_MaxShadowOnScreen ;
if ( hasShadows & & hasNotReachMaxLimit ) // Note < MaxShadows should be check at shadowOutput creation
else if ( light . lightType = = LightType . Spot )
// When we have a point light, we assumed that there is 6 consecutive PunctualShadowData
punctualLightData . shadowIndex = lightList . punctualShadows . Count ;
lightData . cookieIndex = m_CookieTexArray . FetchSlice ( light . light . cookie ) ;
}
}
for ( int sliceIndex = 0 ; sliceIndex < shadowOutput . GetShadowSliceCountLightIndex ( lightIndex ) ; + + sliceIndex )
{
PunctualShadowData punctualShadowData = new PunctualShadowData ( ) ;
// Setup shadow data arrays
bool hasShadows = light . light . shadows ! = LightShadows . None & & shadowOutput . GetShadowSliceCountLightIndex ( lightIndex ) ! = 0 ;
bool hasNotReachMaxLimit = lightList . punctualShadows . Count + ( lightData . lightType = = GPULightType . Point ? 6 : 1 ) < = k_MaxShadowOnScreen ;
int shadowSliceIndex = shadowOutput . GetShadowSliceIndex ( lightIndex , sliceIndex ) ;
punctualShadowData . worldToShadow = shadowOutput . shadowSlices [ shadowSliceIndex ] . shadowTransform . transpose ; // Transpose for hlsl reading ?
if ( hasShadows & & hasNotReachMaxLimit ) // Note < MaxShadows should be check at shadowOutput creation
{
// When we have a point light, we assumed that there is 6 consecutive PunctualShadowData
lightData . shadowIndex = lightList . punctualShadows . Count ;
if ( light . lightType = = LightType . Spot )
{
punctualShadowData . shadowType = ShadowType . Spot ;
}
else if ( light . lightType = = LightType . Point )
{
punctualShadowData . shadowType = ShadowType . Point ;
}
else
{
punctualShadowData . shadowType = ShadowType . Directional ;
}
for ( int sliceIndex = 0 ; sliceIndex < shadowOutput . GetShadowSliceCountLightIndex ( lightIndex ) ; + + sliceIndex )
{
PunctualShadowData punctualShadowData = new PunctualShadowData ( ) ;
int shadowSliceIndex = shadowOutput . GetShadowSliceIndex ( lightIndex , sliceIndex ) ;
punctualShadowData . worldToShadow = shadowOutput . shadowSlices [ shadowSliceIndex ] . shadowTransform . transpose ; // Transpose for hlsl reading ?
punctualShadowData . lightType = lightData . lightType ;
punctualShadowData . bias = light . light . shadowBias ;
punctualShadowData . bias = light . light . shadowBias ;
lightList . punctualShadows . Add ( punctualShadowData ) ;
}
lightList . punctualShadows . Add ( punctualShadowData ) ;
}
lightList . punctualLights . Add ( punctualLightData ) ;
lightData . size = new Vector2 ( additionalData . areaLightLength , additionalData . areaLightWidth ) ;
lightData . twoSided = additionalData . isDoubleSided ;
if ( additionalData . treatAsAreaLight )
{
lightList . areaLights . Add ( lightData ) ;
}
else
{
lightList . punctualLights . Add ( lightData ) ;
}
}