private ComputeShader buildDispatchIndirectShader { get { return m_Resources . buildDispatchIndirectShader ; } }
private ComputeShader clearDispatchIndirectShader { get { return m_Resources . clearDispatchIndirectShader ; } }
private ComputeShader deferredComputeShader { get { return m_Resources . deferredComputeShader ; } }
private ComputeShader deferredDirectional ShadowComputeShader { get { return m_Resources . deferredDirectional ShadowComputeShader; } }
private ComputeShader screenSpace ShadowComputeShader { get { return m_Resources . screenSpace ShadowComputeShader; } }
static int s_GenAABBKernel ;
static int s_deferredDirectionalShadowKernel ;
static int s_deferredDirectionalShadow_Contact_Kernel ;
static int s_deferredContactShadowKernel ;
static ComputeBuffer s_LightVolumeDataBuffer = null ;
static ComputeBuffer s_ConvexBoundsBuffer = null ;
FrameSettings m_FrameSettings = null ;
RenderPipelineResources m_Resources = null ;
ContactShadows m_ContactShadows = null ;
bool m_EnableContactShadow = false ;
// Following is an array of material of size eight for all combination of keyword: OUTPUT_SPLIT_LIGHTING - LIGHTLOOP_TILE_PASS - SHADOWS_SHADOWMASK - USE_FPTL_LIGHTLIST/USE_CLUSTERED_LIGHTLIST - DEBUG_DISPLAY
Material [ ] m_deferredLightingMaterial ;
Material m_DebugViewTilesMaterial ;
Light m_CurrentSunLight ;
int m_CurrentSunLightShadowIndex = - 1 ;
// Used to get the current dominant casting shadow light on screen (the one which takes the biggest part of the screen)
int m_DominantLightIndex = - 1 ;
float m_DominantLightValue ;
// Store the dominant light to give to ScreenSpaceShadow.compute (null is the dominant light is directional)
LightData m_DominantLightData ;
public Light GetCurrentSunLight ( ) { return m_CurrentSunLight ; }
s_shadeOpaqueDirectShadowMaskFptlKernel = deferredComputeShader . FindKernel ( "Deferred_Direct_ShadowMask_Fptl" ) ;
s_shadeOpaqueDirectShadowMaskFptlDebugDisplayKernel = deferredComputeShader . FindKernel ( "Deferred_Direct_ShadowMask_Fptl_DebugDisplay" ) ;
s_deferredDirectionalShadowKernel = deferredDirectionalShadowComputeShader . FindKernel ( "DeferredDirectionalShadow" ) ;
s_deferredDirectionalShadow_Contact_Kernel = deferredDirectionalShadowComputeShader . FindKernel ( "DeferredDirectionalShadow_Contact" ) ;
s_deferredDirectionalShadowKernel = screenSpaceShadowComputeShader . FindKernel ( "DeferredDirectionalShadow" ) ;
s_deferredDirectionalShadow_Contact_Kernel = screenSpaceShadowComputeShader . FindKernel ( "DeferredDirectionalShadow_Contact" ) ;
s_deferredContactShadowKernel = screenSpaceShadowComputeShader . FindKernel ( "DeferredContactShadow" ) ;
for ( int variant = 0 ; variant < LightDefinitions . s_NumFeatureVariants ; variant + + )
{
{
m_FrameSettings = frameSettings ;
m_ContactShadows = VolumeManager . instance . stack . GetComponent < ContactShadows > ( ) ;
m_EnableContactShadow = m_FrameSettings . enableContactShadows & & m_ContactShadows . enable & & m_ContactShadows . length > 0 ;
// Cluster
{
var clustPrepassSourceIdx = m_FrameSettings . lightLoopSettings . enableBigTilePrepass ? ClusterPrepassSource . BigTile : ClusterPrepassSource . None ;
return new Vector3 ( light . finalColor . r , light . finalColor . g , light . finalColor . b ) ;
}
bool GetDominantLightWithShadows ( AdditionalShadowData additionalShadowData , VisibleLight light , int lightIndex = - 1 )
{
// Ratio of the size of the light on screen and its intensity, gives a value used to compare light importance
float lightDominanceValue = light . screenRect . size . magnitude * light . light . intensity ;
if ( additionalShadowData = = null | | ! additionalShadowData . contactShadows | | light . light . shadows = = LightShadows . None )
return false ;
if ( lightDominanceValue < = m_DominantLightValue | | m_DominantLightValue = = Single . PositiveInfinity )
return false ;
if ( light . lightType = = LightType . Directional )
m_DominantLightValue = Single . PositiveInfinity ;
else
{
m_DominantLightData = m_lightList . lights [ lightIndex ] ;
m_DominantLightIndex = lightIndex ;
m_DominantLightValue = lightDominanceValue ;
}
return true ;
}
public bool GetDirectionalLightData ( CommandBuffer cmd , ShadowSettings shadowSettings , GPULightType gpuLightType , VisibleLight light , HDAdditionalLightData additionalData , AdditionalShadowData additionalShadowData , int lightIndex )
{
var directionalLightData = new DirectionalLightData ( ) ;
if ( diffuseDimmer < = 0.0f & & specularDimmer < = 0.0f )
return false ;
// Light direction for directional is opposite to the forward direction
directionalLightData . forward = light . light . transform . forward ;
// Rescale for cookies and windowing.
// Fallback to the first non shadow casting directional light.
m_CurrentSunLight = m_CurrentSunLight = = null ? light . light : m_CurrentSunLight ;
directionalLightData . contactShadowIndex = - 1 ;
// The first shadow casting directional light with contact shadow enabled is always taken as dominant light
if ( GetDominantLightWithShadows ( additionalShadowData , light ) )
directionalLightData . contactShadowIndex = 0 ;
m_lightList . directionalLights . Add ( directionalLightData ) ;
lightData . shadowMaskSelector . x = - 1.0f ;
lightData . nonLightmappedOnly = 0 ;
}
lightData . contactShadowIndex = - 1 ;
// Check if the current light is dominant and store it's index to change it's property later,
// as we can't know which one will be dominant before checking all the lights
GetDominantLightWithShadows ( additionalshadowData , light , m_lightList . lights . Count - 1 ) ;
return true ;
}
// We need to properly reset this here otherwise if we go from 1 light to no visible light we would keep the old reference active.
m_CurrentSunLight = null ;
m_CurrentSunLightShadowIndex = - 1 ;
m_DominantLightIndex = - 1 ;
m_DominantLightValue = 0 ;
var stereoEnabled = m_FrameSettings . enableStereo ;
int lightCount = Math . Min ( cullResults . visibleLights . Count , k_MaxLightsOnScreen ) ;
var sortKeys = new uint [ lightCount ] ;
int sortCount = 0 ;
for ( int lightIndex = 0 , numLights = cullResults . visibleLights . Count ; ( lightIndex < numLights ) & & ( sortCount < lightCount ) ; + + lightIndex )
{
var light = cullResults . visibleLights [ lightIndex ] ;
}
}
//Activate contact shadows on dominant light
if ( m_DominantLightIndex ! = - 1 )
{
m_DominantLightData = m_lightList . lights [ m_DominantLightIndex ] ;
m_DominantLightData . contactShadowIndex = 0 ;
m_lightList . lights [ m_DominantLightIndex ] = m_DominantLightData ;
}
// Sanity check
Debug . Assert ( m_lightList . directionalLights . Count = = directionalLightcount ) ;
Debug . Assert ( m_lightList . lights . Count = = areaLightCount + punctualLightcount ) ;
public void RenderDeferredDirectionalShadow ( HDCamera hdCamera , RTHandleSystem . RTHandle deferredShadowRT , RenderTargetIdentifier depthTexture , CommandBuffer cmd )
{
if ( m_CurrentSunLight = = null | | m_CurrentSunLight . GetComponent < AdditionalShadowData > ( ) = = null | | m_CurrentSunLightShadowIndex < 0 )
bool sunLightShadow = m_CurrentSunLight ! = null & & m_CurrentSunLight . GetComponent < AdditionalShadowData > ( ) ! = null & & m_CurrentSunLightShadowIndex > = 0 ;
// if there is no directional light shadows or no need to compute contact shadows, we just quit
if ( ! sunLightShadow & & m_DominantLightIndex = = - 1 )
cmd . SetGlobalTexture ( HDShaderIDs . _DeferredShadowTexture , RuntimeUtilities . blackTexture ) ;
cmd . SetGlobalTexture ( HDShaderIDs . _DeferredShadowTexture , RuntimeUtilities . whiteTexture ) ;
ContactShadows contactShadows = VolumeManager . instance . stack . GetComponent < ContactShadows > ( ) ;
Vector4 lightDirection = Vector4 . zero ;
Vector4 lightPosition = Vector4 . zero ;
int kernel ;
bool enableContactShadows = m_FrameSettings . enableContactShadows & & contactShadows . enable & & contactShadows . length > 0.0f ;
int kernel ;
if ( enableContactShadows )
kernel = s_deferredDirectionalShadow_Contact_Kernel ;
// Here we have three cases:
// - if there is a sun light casting shadow, we need to use comput directional light shadows
// and contact shadows of the dominant light (or the directional if contact shadows are enabled on it)
// - if there is no sun or it's not casting shadows, we don't need to compute it's costy directional
// shadows so we only compute contact shadows for the dominant light
// - if there is no contact shadows then we only compute the directional light shadows
if ( m_EnableContactShadow )
{
if ( sunLightShadow )
kernel = s_deferredDirectionalShadow_Contact_Kernel ;
else
kernel = s_deferredContactShadowKernel ;
}
// We use the .w component of the direction/position vectors to choose in the shader the
// light direction of the contact shadows (direction light direction or (pixel position - light position))
if ( m_CurrentSunLight ! = null )
{
lightDirection = - m_CurrentSunLight . transform . forward ;
lightDirection . w = 1 ;
}
if ( m_DominantLightIndex ! = - 1 )
{
lightPosition = m_DominantLightData . positionWS ;
lightPosition . w = 1 ;
lightDirection . w = 0 ;
}
m_ShadowMgr . BindResources ( cmd , deferredDirectionalShadowComputeShader , kernel ) ;
m_ShadowMgr . BindResources ( cmd , screenSpaceShadowComputeShader , kernel ) ;
if ( enableContactShadows )
if ( m_ContactShadows )
float contactShadowRange = Mathf . Clamp ( contactShadows . fadeDistance , 0.0f , contactShadows . maxDistance ) ;
float contactShadowFadeEnd = contactShadows . maxDistance ;
float contactShadowRange = Mathf . Clamp ( m_ContactShadows . fadeDistance , 0.0f , m_ContactShadows . maxDistance ) ;
float contactShadowFadeEnd = m_ContactShadows . maxDistance ;
Vector4 contactShadowParams = new Vector4 ( contactShadows . length , contactShadows . distanceScaleFactor , contactShadowFadeEnd , contactShadowOneOverFadeRange ) ;
cmd . SetComputeVectorParam ( deferredDirectionalShadowComputeShader , HDShaderIDs . _DirectionalContactShadowParams , contactShadowParams ) ;
cmd . SetComputeIntParam ( deferredDirectionalShadowComputeShader , HDShaderIDs . _DirectionalContactShadowSampleCount , contactShadows . sampleCount ) ;
Vector4 contactShadowParams = new Vector4 ( m_ContactShadows . length , m_ContactShadows . distanceScaleFactor , contactShadowFadeEnd , contactShadowOneOverFadeRange ) ;
cmd . SetComputeVectorParam ( screenSpaceShadowComputeShader , HDShaderIDs . _DirectionalContactShadowParams , contactShadowParams ) ;
cmd . SetComputeIntParam ( screenSpaceShadowComputeShader , HDShaderIDs . _DirectionalContactShadowSampleCount , m_ContactShadows . sampleCount ) ;
cmd . SetComputeIntParam ( deferredDirectionalShadowComputeShader , HDShaderIDs . _DirectionalShadowIndex , m_CurrentSunLightShadowIndex ) ;
cmd . SetComputeVectorParam ( deferredDirectionalShadowComputeShader , HDShaderIDs . _DirectionalLightDirection , - m_CurrentSunLight . transform . forward ) ;
cmd . SetComputeTextureParam ( deferredDirectionalShadowComputeShader , kernel , HDShaderIDs . _DeferredShadowTextureUAV , deferredShadowRT ) ;
cmd . SetComputeTextureParam ( deferredDirectionalShadowComputeShader , kernel , HDShaderIDs . _CameraDepthTexture , depthTexture ) ;
cmd . SetComputeIntParam ( screenSpaceShadowComputeShader , HDShaderIDs . _DirectionalShadowIndex , m_CurrentSunLightShadowIndex ) ;
cmd . SetComputeVectorParam ( screenSpaceShadowComputeShader , HDShaderIDs . _DirectionalLightDirection , lightDirection ) ;
cmd . SetComputeVectorParam ( screenSpaceShadowComputeShader , HDShaderIDs . _PunctualLightPosition , lightPosition ) ;
cmd . SetComputeTextureParam ( screenSpaceShadowComputeShader , kernel , HDShaderIDs . _DeferredShadowTextureUAV , deferredShadowRT ) ;
cmd . SetComputeTextureParam ( screenSpaceShadowComputeShader , kernel , HDShaderIDs . _CameraDepthTexture , depthTexture ) ;
int deferredShadowTileSize = 1 6 ; // Must match DeferreDirectionalShadow.compute
int numTilesX = ( hdCamera . actualWidth + ( deferredShadowTileSize - 1 ) ) / deferredShadowTileSize ;
cmd . DispatchCompute ( deferredDirectionalShadowComputeShader , kernel , numTilesX , numTilesY , 1 ) ;
cmd . DispatchCompute ( screenSpaceShadowComputeShader , kernel , numTilesX , numTilesY , 1 ) ;
cmd . SetGlobalTexture ( HDShaderIDs . _DeferredShadowTexture , deferredShadowRT ) ;
}