}
}
public DecalData [ ] DecalDatas
public Camera CurrentCamera
BuildDecalDatas ( ) ;
return m_DecalDatas ;
return m_Camera ;
}
set
{
m_Camera = value ;
private static readonly int m_NormalToWorldID = Shader . PropertyToID ( "normalToWorld" ) ;
private static readonly int m_DecalAtlasID = Shader . PropertyToID ( "_DecalAtlas" ) ;
private static MaterialPropertyBlock m_PropertyBlock = new MaterialPropertyBlock ( ) ;
private const int kDecalBlockSize = 1 2 8 ;
static Vector4 kMax = new Vector4 ( 0.5f , 0.0f , 0.5f , 1.0f ) ;
static public Mesh m_DecalMesh = null ;
// static public Matrix4x4[] m_InstanceMatrices = new Matrix4x4[kDrawIndexedBatchSize];
// static public Matrix4x4[] m_InstanceNormalToWorld = new Matrix4x4[kDrawIndexedBatchSize];
// clustered draw data
DecalData [ ] m_DecalDatas = new DecalData [ kDecalBlockSize ] ;
// static public Matrix4x4[] m_DecalToWorld = new Matrix4x4[kDecalBlockSize];
static public List < SFiniteLightBound > m_Bounds = new List < SFiniteLightBound > ( ) ;
static public List < LightVolumeData > m_LightVolumes = new List < LightVolumeData > ( ) ;
// current camera
private Camera m_Camera ;
private class DecalSet
{
decal . CullIndex = DecalProjectorComponent . kInvalidIndex ;
}
public void BeginCull ( Camera camera )
public void BeginCull ( )
{
if ( m_CullingGroup ! = null )
{
m_BoundingDistances [ 0 ] = DecalSystem . instance . DrawDistance ;
m_NumResults = 0 ;
m_CullingGroup = new CullingGroup ( ) ;
m_CullingGroup . targetCamera = camera ;
m_CullingGroup . SetDistanceReferencePoint ( camera . transform . position ) ;
m_CullingGroup . targetCamera = instan ce . CurrentC amera;
m_CullingGroup . SetDistanceReferencePoint ( m_CullingGroup . targetC amera. transform . position ) ;
m_CullingGroup . SetBoundingDistances ( m_BoundingDistances ) ;
m_CullingGroup . SetBoundingSpheres ( m_BoundingSpheres ) ;
m_CullingGroup . SetBoundingSphereCount ( m_DecalsCount ) ;
return m_NumResults ;
}
private void CreateDrawData ( )
private void GetDecalVolumeDataAndBound ( Matrix4x4 decalToWorld , Matrix4x4 worldToView )
{
var bound = new SFiniteLightBound ( ) ;
var lightVolumeData = new LightVolumeData ( ) ;
var influenceX = decalToWorld . GetColumn ( 0 ) * 0.5f ;
var influenceY = decalToWorld . GetColumn ( 1 ) * 0.5f ;
var influenceZ = decalToWorld . GetColumn ( 2 ) * 0.5f ;
var pos = decalToWorld . GetColumn ( 3 ) - influenceY ; // decal cube mesh pivot is at 0,0,0, with bottom face at -1 on the y plane
Vector3 influenceExtents = new Vector3 ( ) ;
influenceExtents . x = influenceX . magnitude ;
influenceExtents . y = influenceY . magnitude ;
influenceExtents . z = influenceZ . magnitude ;
// transform to camera space (becomes a left hand coordinate frame in Unity since Determinant(worldToView)<0)
var influenceRightVS = worldToView . MultiplyVector ( influenceX / influenceExtents . x ) ;
var influenceUpVS = worldToView . MultiplyVector ( influenceY / influenceExtents . y ) ;
var influenceForwardVS = worldToView . MultiplyVector ( influenceZ / influenceExtents . z ) ;
var influencePositionVS = worldToView . MultiplyPoint ( pos ) ; // place the mesh pivot in the center
lightVolumeData . lightCategory = ( uint ) LightCategory . Decal ;
lightVolumeData . lightVolume = ( uint ) LightVolumeType . Box ;
lightVolumeData . featureFlags = ( uint ) LightFeatureFlags . Env ;
bound . center = influencePositionVS ;
bound . boxAxisX = influenceRightVS * influenceExtents . x ;
bound . boxAxisY = influenceUpVS * influenceExtents . y ;
bound . boxAxisZ = influenceForwardVS * influenceExtents . z ;
bound . scaleXY . Set ( 1.0f , 1.0f ) ;
bound . radius = influenceExtents . magnitude ;
// The culling system culls pixels that are further
// than a threshold to the box influence extents.
// So we use an arbitrary threshold here (k_BoxCullingExtentOffset)
lightVolumeData . lightPos = influencePositionVS ;
lightVolumeData . lightAxisX = influenceRightVS ;
lightVolumeData . lightAxisY = influenceUpVS ;
lightVolumeData . lightAxisZ = influenceForwardVS ;
lightVolumeData . boxInnerDist = influenceExtents - LightLoop . k_BoxCullingExtentThreshold ;
lightVolumeData . boxInvRange . Set ( 1.0f / LightLoop . k_BoxCullingExtentThreshold . x , 1.0f / LightLoop . k_BoxCullingExtentThreshold . y , 1.0f / LightLoop . k_BoxCullingExtentThreshold . z ) ;
m_Bounds . Add ( bound ) ;
m_LightVolumes . Add ( lightVolumeData ) ;
}
private void AssignCurrentBatches ( ref Matrix4x4 [ ] decalToWorldBatch , ref Matrix4x4 [ ] normalToWorldBatch , int batchCount )
{
if ( m_DecalToWorld . Count = = batchCount )
{
decalToWorldBatch = new Matrix4x4 [ kDrawIndexedBatchSize ] ;
m_DecalToWorld . Add ( decalToWorldBatch ) ;
normalToWorldBatch = new Matrix4x4 [ kDrawIndexedBatchSize ] ;
m_NormalToWorld . Add ( normalToWorldBatch ) ;
}
else
{
decalToWorldBatch = m_DecalToWorld [ batchCount ] ;
normalToWorldBatch = m_NormalToWorld [ batchCount ] ;
}
}
public void CreateDrawData ( )
{
if ( m_NumResults = = 0 )
return ;
AssignCurrentBatches ( ref decalToWorldBatch , ref normalToWorldBatch , batchCount ) ;
Vector3 cameraPos = m_CullingGroup . targetCamera . transform . position ;
Vector3 cameraPos = instance . CurrentCamera . transform . position ;
Matrix4x4 worldToView = LightLoop . WorldToCamera ( instance . CurrentCamera ) ;
for ( int resultIndex = 0 ; resultIndex < m_NumResults ; resultIndex + + )
{
int decalIndex = m_ResultIndices [ resultIndex ] ;
if ( distanceToDecal < cullDistance )
{
// dbuffer data
// d- buffer data
decalToWorldBatch [ instanceCount ] = m_CachedDecalToWorld [ decalIndex ] ;
normalToWorldBatch [ instanceCount ] = m_CachedNormalToWorld [ decalIndex ] ;
float fadeFactor = Mathf . Clamp ( ( cullDistance - distanceToDecal ) / ( cullDistance * ( 1.0f - m_CachedDrawDistances [ decalIndex ] . y ) ) , 0.0f , 1.0f ) ;
// clustered forward data
DecalData decalData = new DecalData ( ) ;
decalData . worldToDecal = decalToWorldBatch [ instanceCount ] ; // this will be inverted by the light loop code, decal to world is needed there to create bounds
decalData . worldToDecal = decalToWorldBatch [ instanceCount ] . inverse ;
GetDecalVolumeDataAndBound ( decalToWorldBatch [ instanceCount ] , worldToView ) ;
instanceCount + + ;
if ( instanceCount = = kDrawIndexedBatchSize )
}
}
public void BuildDecalDatas ( )
{
}
public void EndCull ( )
{
if ( m_CullingGroup = = null )
else
{
CreateDrawData ( ) ;
void AssignCurrentBatches ( ref Matrix4x4 [ ] decalToWorldBatch , ref Matrix4x4 [ ] normalToWorldBatch , int batchCount )
{
if ( m_DecalToWorld . Count = = batchCount )
{
decalToWorldBatch = new Matrix4x4 [ kDrawIndexedBatchSize ] ;
m_DecalToWorld . Add ( decalToWorldBatch ) ;
normalToWorldBatch = new Matrix4x4 [ kDrawIndexedBatchSize ] ;
m_NormalToWorld . Add ( normalToWorldBatch ) ;
}
else
{
decalToWorldBatch = m_DecalToWorld [ batchCount ] ;
normalToWorldBatch = m_NormalToWorld [ batchCount ] ;
}
}
void UpdateTextureCache ( CommandBuffer cmd )
{
if ( ( m_DiffuseTexIndex = = - 1 ) & & ( m_DiffuseTexture ! = null ) )
int totalToDraw = m_NumResults ;
for ( ; batchIndex < m_NumResults / kDrawIndexedBatchSize ; batchIndex + + )
{
m_PropertyBlock . SetMatrixArray ( m _NormalToWorldID, m_NormalToWorld [ batchIndex ] ) ;
m_PropertyBlock . SetMatrixArray ( HDShaderIDs . _NormalToWorldID , m_NormalToWorld [ batchIndex ] ) ;
cmd . DrawMeshInstanced ( m_DecalMesh , 0 , KeyMaterial , 0 , m_DecalToWorld [ batchIndex ] , kDrawIndexedBatchSize , m_PropertyBlock ) ;
totalToDraw - = kDrawIndexedBatchSize ;
}
m_PropertyBlock . SetMatrixArray ( m_NormalToWorldID , m_NormalToWorld [ batchIndex ] ) ;
m_PropertyBlock . SetMatrixArray ( HDShaderIDs . _NormalToWorldID , m_NormalToWorld [ batchIndex ] ) ;
cmd . DrawMeshInstanced ( m_DecalMesh , 0 , KeyMaterial , 0 , m_DecalToWorld [ batchIndex ] , totalToDraw , m_PropertyBlock ) ;
}
}
}
}
public void BeginCull ( Camera camera )
public void BeginCull ( )
pair . Value . BeginCull ( camera ) ;
pair . Value . BeginCull ( ) ;
}
}
public void SetAtlas ( CommandBuffer cmd )
{
cmd . SetGlobalTexture ( m_DecalAtlasID , TextureAtlas . GetTexCache ( ) ) ;
cmd . SetGlobalTexture ( HDShaderIDs . _DecalAtlasID , TextureAtlas . GetTexCache ( ) ) ;
// updates textures, texture atlas indices and blend value
public void UpdateCachedMaterialData ( CommandBuffer cmd )
{
foreach ( var pair in m_DecalSets )
}
public void InvertDecalDataWorldToDecal ( )
public void CreateDrawData ( )
for ( int i = 0 ; i < m_DecalDataList . Count ; i + + )
{
DecalData decalData = m_DecalDataList [ i ] ;
decalData . worldToDecal = decalData . worldToDecal . inverse ;
m_DecalDataList [ i ] = decalData ;
}
}
void BuildDecalDatas ( )
{
m_DecalDataList . Clear ( ) ;
m_Bounds . Clear ( ) ;
m_LightVolumes . Clear ( ) ;
pair . Value . BuildDecalDatas ( ) ;
pair . Value . CreateDrawData ( ) ;
}
}
}