浏览代码

Merge pull request #966 from Unity-Technologies/decals/clustered

Decals/clustered
/main
GitHub 6 年前
当前提交
e8bd5bcf
共有 17 个文件被更改,包括 507 次插入114 次删除
  1. 371
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs
  2. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDCustomSamplerId.cs
  3. 48
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
  4. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  5. 33
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs
  6. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs.hlsl
  7. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-bigtile.compute
  8. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-clustered.compute
  9. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild.compute
  10. 11
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs
  11. 16
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs.hlsl
  12. 10
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl
  13. 7
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl
  14. 96
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl
  15. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitData.hlsl
  16. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitData.hlsl
  17. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl

371
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs


}
private const int kDefaultDrawDistance = 1000;
static public int DrawDistance
public int DrawDistance
{
get
{

}
}
private static readonly int m_NormalToWorldID = Shader.PropertyToID("normalToWorld");
public TextureCache2D TextureAtlas
{
get
{
if (m_DecalAtlas == null)
{
m_DecalAtlas = new TextureCache2D();
m_DecalAtlas.AllocTextureArray(2048, 128, 128, TextureFormat.RGBA32, true);
}
return m_DecalAtlas;
}
}
public Camera CurrentCamera
{
get
{
return m_Camera;
}
set
{
m_Camera = value;
}
}
private static MaterialPropertyBlock m_PropertyBlock = new MaterialPropertyBlock();
private const int kDecalBlockSize = 128;

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
static public DecalData[] m_DecalDatas = new DecalData[kDecalBlockSize];
static public SFiniteLightBound[] m_Bounds = new SFiniteLightBound[kDecalBlockSize];
static public LightVolumeData[] m_LightVolumes = new LightVolumeData[kDecalBlockSize];
static public int m_DecalDatasCount = 0;
private TextureCache2D m_DecalAtlas = null;
// current camera
private Camera m_Camera;
static public int m_DecalsVisibleThisFrame = 0;
private void InitializeMaterialValues()
{
m_DiffuseTexture = m_Material.GetTexture("_BaseColorMap");
m_NormalTexture = m_Material.GetTexture("_NormalMap");
m_MaskTexture = m_Material.GetTexture("_MaskMap");
m_Blend = m_Material.GetFloat("_DecalBlend");
}
public DecalSet(Material material)
{
m_Material = material;
InitializeMaterialValues();
}
private BoundingSphere GetDecalProjectBoundingSphere(Matrix4x4 decalToWorld)
{
Vector4 min = new Vector4();

BoundingSphere res = new BoundingSphere();
res.position = (max + min) / 2;
res.radius = ((Vector3)(max - min)).magnitude / 2;
res.radius = ((Vector3) (max - min)).magnitude / 2;
m_CachedTransforms[decal.CullIndex] = decal.transform.localToWorldMatrix;
m_CachedDecalToWorld[decal.CullIndex] = decal.transform.localToWorldMatrix;
float y0 = decalRotation.m01;
float y1 = decalRotation.m11;
float y2 = decalRotation.m21;
decalRotation.m01 = decalRotation.m02;
decalRotation.m11 = decalRotation.m12;
decalRotation.m21 = decalRotation.m22;
decalRotation.m02 = y0;
decalRotation.m12 = y1;
decalRotation.m22 = y2;
float y0 = decalRotation.m01;
float y1 = decalRotation.m11;
float y2 = decalRotation.m21;
decalRotation.m01 = decalRotation.m02;
decalRotation.m11 = decalRotation.m12;
decalRotation.m21 = decalRotation.m22;
decalRotation.m02 = y0;
decalRotation.m12 = y1;
decalRotation.m22 = y2;
// draw distance can't be more than global draw distance
m_CachedDrawDistances[decal.CullIndex].x = decal.m_DrawDistance < DrawDistance ? decal.m_DrawDistance : DrawDistance;
// draw distance can't be more than global draw distance
m_CachedDrawDistances[decal.CullIndex].x = decal.m_DrawDistance < instance.DrawDistance
? decal.m_DrawDistance
: instance.DrawDistance;
m_BoundingSpheres[decal.CullIndex] = GetDecalProjectBoundingSphere(m_CachedTransforms[decal.CullIndex]);
m_BoundingSpheres[decal.CullIndex] = GetDecalProjectBoundingSphere(m_CachedDecalToWorld[decal.CullIndex]);
}
public void AddDecal(DecalProjectorComponent decal)

m_Decals.CopyTo(newDecals, 0);
m_BoundingSpheres.CopyTo(newSpheres, 0);
m_CachedTransforms.CopyTo(newCachedTransforms, 0);
m_CachedDecalToWorld.CopyTo(newCachedTransforms, 0);
m_CachedDrawDistances.CopyTo(newCachedDrawDistances, 0);
m_CachedDrawDistances.CopyTo(newCachedDrawDistances, 0);
m_CachedTransforms = newCachedTransforms;
m_CachedDecalToWorld = newCachedTransforms;
m_CachedDrawDistances = newCachedDrawDistances;
m_CachedDrawDistances = newCachedDrawDistances;
}
m_Decals[m_DecalsCount] = decal;

// update the bounding spheres array
m_BoundingSpheres[removeAtIndex] = m_BoundingSpheres[m_DecalsCount - 1];
m_CachedTransforms[removeAtIndex] = m_CachedTransforms[m_DecalsCount - 1];
m_CachedDecalToWorld[removeAtIndex] = m_CachedDecalToWorld[m_DecalsCount - 1];
m_CachedDrawDistances[removeAtIndex] = m_CachedDrawDistances[m_DecalsCount - 1];
m_CachedDrawDistances[removeAtIndex] = m_CachedDrawDistances[m_DecalsCount - 1];
public void BeginCull(Camera camera)
public void BeginCull()
{
if (m_CullingGroup != null)
{

// let the culling group code do some of the heavy lifting for global draw distance
m_BoundingDistances[0] = DrawDistance;
// let the culling group code do some of the heavy lifting for global draw distance
m_BoundingDistances[0] = DecalSystem.instance.DrawDistance;
m_CullingGroup.targetCamera = camera;
m_CullingGroup.SetDistanceReferencePoint(camera.transform.position);
m_CullingGroup.SetBoundingDistances(m_BoundingDistances);
m_CullingGroup.targetCamera = instance.CurrentCamera;
m_CullingGroup.SetDistanceReferencePoint( m_CullingGroup.targetCamera.transform.position);
m_CullingGroup.SetBoundingDistances(m_BoundingDistances);
m_CullingGroup.SetBoundingSpheres(m_BoundingSpheres);
m_CullingGroup.SetBoundingSphereCount(m_DecalsCount);
}

return m_NumResults;
}
private void GetDecalVolumeDataAndBound(Matrix4x4 decalToWorld, Matrix4x4 worldToView)
{
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
m_Bounds[m_DecalDatasCount].center = influencePositionVS;
m_Bounds[m_DecalDatasCount].boxAxisX = influenceRightVS * influenceExtents.x;
m_Bounds[m_DecalDatasCount].boxAxisY = influenceUpVS * influenceExtents.y;
m_Bounds[m_DecalDatasCount].boxAxisZ = influenceForwardVS * influenceExtents.z;
m_Bounds[m_DecalDatasCount].scaleXY.Set(1.0f, 1.0f);
m_Bounds[m_DecalDatasCount].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)
m_LightVolumes[m_DecalDatasCount].lightCategory = (uint)LightCategory.Decal;
m_LightVolumes[m_DecalDatasCount].lightVolume = (uint)LightVolumeType.Box;
m_LightVolumes[m_DecalDatasCount].featureFlags = (uint)LightFeatureFlags.Env;
m_LightVolumes[m_DecalDatasCount].lightPos = influencePositionVS;
m_LightVolumes[m_DecalDatasCount].lightAxisX = influenceRightVS;
m_LightVolumes[m_DecalDatasCount].lightAxisY = influenceUpVS;
m_LightVolumes[m_DecalDatasCount].lightAxisZ = influenceForwardVS;
m_LightVolumes[m_DecalDatasCount].boxInnerDist = influenceExtents - LightLoop.k_BoxCullingExtentThreshold;
m_LightVolumes[m_DecalDatasCount].boxInvRange.Set(1.0f / LightLoop.k_BoxCullingExtentThreshold.x, 1.0f /LightLoop. k_BoxCullingExtentThreshold.y, 1.0f / LightLoop.k_BoxCullingExtentThreshold.z);
}
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;
int instanceCount = 0;
int batchCount = 0;
Matrix4x4[] decalToWorldBatch = null;
Matrix4x4[] normalToWorldBatch = null;
AssignCurrentBatches(ref decalToWorldBatch, ref normalToWorldBatch, batchCount);
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];
// do additional culling based on individual decal draw distances
float distanceToDecal = (cameraPos - m_BoundingSpheres[decalIndex].position).magnitude;
float cullDistance = m_CachedDrawDistances[decalIndex].x + m_BoundingSpheres[decalIndex].radius;
if (distanceToDecal < cullDistance)
{
// 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);
normalToWorldBatch[instanceCount].m03 = fadeFactor * m_Blend; // vector3 rotation matrix so bottom row and last column can be used for other data to save space
normalToWorldBatch[instanceCount].m13 = m_DiffuseTexIndex; // texture atlas indices needed for clustered
normalToWorldBatch[instanceCount].m23 = m_NormalTexIndex;
normalToWorldBatch[instanceCount].m33 = m_MaskTexIndex;
// clustered forward data
m_DecalDatas[m_DecalDatasCount].worldToDecal = decalToWorldBatch[instanceCount].inverse;
m_DecalDatas[m_DecalDatasCount].normalToWorld = normalToWorldBatch[instanceCount];
GetDecalVolumeDataAndBound(decalToWorldBatch[instanceCount], worldToView);
m_DecalDatasCount++;
instanceCount++;
if (instanceCount == kDrawIndexedBatchSize)
{
instanceCount = 0;
batchCount++;
AssignCurrentBatches(ref decalToWorldBatch, ref normalToWorldBatch, batchCount);
}
}
}
}
public void EndCull()
{
if (m_CullingGroup == null)

}
}
public void Render(ScriptableRenderContext renderContext, HDCamera camera, CommandBuffer cmd)
void UpdateTextureCache(CommandBuffer cmd)
{
if (m_DiffuseTexture != null)
{
m_DiffuseTexIndex = instance.TextureAtlas.FetchSlice(cmd, m_DiffuseTexture);
}
else
{
m_DiffuseTexIndex = -1;
}
if (m_NormalTexture != null)
{
m_NormalTexIndex = instance.TextureAtlas.FetchSlice(cmd, m_NormalTexture);
}
else
{
m_NormalTexIndex = -1;
}
if (m_MaskTexture != null)
{
m_MaskTexIndex = instance.TextureAtlas.FetchSlice(cmd, m_MaskTexture);
}
else
{
m_MaskTexIndex = -1;
}
}
public void RemoveFromTextureCache()
int instanceCount = 0;
Vector3 cameraPos = camera.cameraPos;
for (int resultIndex = 0; resultIndex < m_NumResults; resultIndex++)
if (m_DiffuseTexture != null)
int decalIndex = m_ResultIndices[resultIndex];
// do additional culling based on individual decal draw distances
float distanceToDecal = (cameraPos - m_BoundingSpheres[decalIndex].position).magnitude;
float cullDistance = m_CachedDrawDistances[decalIndex].x + m_BoundingSpheres[decalIndex].radius;
if (distanceToDecal < cullDistance)
{
m_InstanceMatrices[instanceCount] = m_CachedTransforms[decalIndex];
m_InstanceNormalToWorld[instanceCount] = m_CachedNormalToWorld[decalIndex];
float fadeFactor = (cullDistance - distanceToDecal) / (cullDistance * (1.0f - m_CachedDrawDistances[decalIndex].y));
m_InstanceNormalToWorld[instanceCount].m03 = fadeFactor; // rotation only matrix so 3rd column can be used to pass some values
instanceCount++;
if (instanceCount == kDrawIndexedBatchSize)
{
m_PropertyBlock.SetMatrixArray(m_NormalToWorldID, m_InstanceNormalToWorld);
cmd.DrawMeshInstanced(m_DecalMesh, 0, KeyMaterial, 0, m_InstanceMatrices, kDrawIndexedBatchSize, m_PropertyBlock);
instanceCount = 0;
}
}
instance.TextureAtlas.RemoveEntryFromSlice(m_DiffuseTexture);
}
if (m_NormalTexture != null)
{
instance.TextureAtlas.RemoveEntryFromSlice(m_NormalTexture);
if (instanceCount > 0)
if (m_MaskTexture != null)
m_PropertyBlock.SetMatrixArray(m_NormalToWorldID, m_InstanceNormalToWorld);
cmd.DrawMeshInstanced(m_DecalMesh, 0, KeyMaterial, 0, m_InstanceMatrices, instanceCount, m_PropertyBlock);
instance.TextureAtlas.RemoveEntryFromSlice(m_MaskTexture);
public void UpdateCachedMaterialData(CommandBuffer cmd)
{
InitializeMaterialValues(); // refresh in case they changed in the UI
UpdateTextureCache(cmd);
}
public void RenderIntoDBuffer(CommandBuffer cmd)
{
if(m_NumResults == 0)
return;
int batchIndex = 0;
int totalToDraw = m_NumResults;
for (; batchIndex < m_NumResults / kDrawIndexedBatchSize; batchIndex++)
{
m_PropertyBlock.SetMatrixArray(HDShaderIDs._NormalToWorldID, m_NormalToWorld[batchIndex]);
cmd.DrawMeshInstanced(m_DecalMesh, 0, KeyMaterial, 0, m_DecalToWorld[batchIndex], kDrawIndexedBatchSize, m_PropertyBlock);
totalToDraw -= kDrawIndexedBatchSize;
}
if(totalToDraw > 0)
{
m_PropertyBlock.SetMatrixArray(HDShaderIDs._NormalToWorldID, m_NormalToWorld[batchIndex]);
cmd.DrawMeshInstanced(m_DecalMesh, 0, KeyMaterial, 0, m_DecalToWorld[batchIndex], totalToDraw, m_PropertyBlock);
}
}
public Material KeyMaterial
{
get

set
{
this.m_Material = value;
}
}
public int Count

}
}
private List<Matrix4x4[]> m_DecalToWorld = new List<Matrix4x4[]>();
private List<Matrix4x4[]> m_NormalToWorld = new List<Matrix4x4[]>();
private CullingGroup m_CullingGroup = null;
private BoundingSphere[] m_BoundingSpheres = new BoundingSphere[kDecalBlockSize];
private DecalProjectorComponent[] m_Decals = new DecalProjectorComponent[kDecalBlockSize];

private Matrix4x4[] m_CachedTransforms = new Matrix4x4[kDecalBlockSize];
private Matrix4x4[] m_CachedDecalToWorld = new Matrix4x4[kDecalBlockSize];
private Texture m_DiffuseTexture = null;
private Texture m_NormalTexture = null;
private Texture m_MaskTexture = null;
private float m_Blend = 0;
private int m_DiffuseTexIndex = -1;
private int m_NormalTexIndex = -1;
private int m_MaskTexIndex = -1;
}
public void AddDecal(DecalProjectorComponent decal)

int key = decal.m_Material.GetInstanceID();
if (!m_DecalSets.TryGetValue(key, out decalSet))
{
decalSet = new DecalSet();
decalSet.KeyMaterial = decal.m_Material;
decalSet = new DecalSet(decal.m_Material);
m_DecalSets.Add(key, decalSet);
}
decalSet.AddDecal(decal);

decalSet.RemoveDecal(decal);
if (decalSet.Count == 0)
{
decalSet.RemoveFromTextureCache();
m_DecalSets.Remove(key);
}
}

}
}
public void BeginCull(Camera camera)
public void BeginCull()
pair.Value.BeginCull(camera);
pair.Value.BeginCull();
public int QueryCullResults()
private int QueryCullResults()
{
int totalVisibleDecals = 0;
foreach (var pair in m_DecalSets)

public void EndCull()
{
m_DecalsVisibleThisFrame = QueryCullResults();
foreach (var pair in m_DecalSets)
{
pair.Value.EndCull();

public void Render(ScriptableRenderContext renderContext, HDCamera camera, CommandBuffer cmd)
// need a better way than passing light loop here
public void RenderIntoDBuffer(CommandBuffer cmd)
{
if (m_DecalMesh == null)
m_DecalMesh = CoreUtils.CreateCubeMesh(kMin, kMax);

pair.Value.Render(renderContext, camera, cmd);
pair.Value.RenderIntoDBuffer(cmd);
}
public void SetAtlas(CommandBuffer cmd)
{
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)
{
pair.Value.UpdateCachedMaterialData(cmd);
}
}
public void CreateDrawData()
{
m_DecalDatasCount = 0;
// reallocate if needed
if (m_DecalsVisibleThisFrame > m_DecalDatas.Length)
{
int newDecalDatasSize = ((m_DecalsVisibleThisFrame + kDecalBlockSize - 1) / kDecalBlockSize) * kDecalBlockSize;
m_DecalDatas = new DecalData[newDecalDatasSize];
m_Bounds = new SFiniteLightBound[newDecalDatasSize];
m_LightVolumes = new LightVolumeData[newDecalDatasSize];
}
foreach (var pair in m_DecalSets)
{
pair.Value.CreateDrawData();
}
}
}
}

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDCustomSamplerId.cs


DepthPrepass,
TransparentDepthPrepass,
GBuffer,
DBuffer,
DBufferRender,
DBufferPrepareDrawData,
DisplayDebugViewMaterial,
DebugViewMaterialGBuffer,
BlitDebugViewMaterialDebug,

48
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs


ScriptableRenderContext.EmitWorldGeometryForSceneView(camera);
}
#endif
// decal system needs to be updated with current camera
DecalSystem.instance.BeginCull(camera);
{
// decal system needs to be updated with current camera, it needs it to set up culling and light list generation parameters
DecalSystem.instance.CurrentCamera = camera;
DecalSystem.instance.BeginCull();
}
ReflectionSystem.PrepareCull(camera, m_ReflectionProbeCullResults);

m_ReflectionProbeCullResults.Cull();
m_DbufferManager.vsibleDecalCount = 0;
if (m_FrameSettings.enableDBuffer)
using (new ProfilingSample(cmd, "DBufferPrepareDrawData", CustomSamplerId.DBufferPrepareDrawData.GetSampler()))
m_DbufferManager.vsibleDecalCount = DecalSystem.instance.QueryCullResults();
DecalSystem.instance.EndCull();
if (m_FrameSettings.enableDBuffer)
{
DecalSystem.instance.EndCull();
m_DbufferManager.vsibleDecalCount = DecalSystem.m_DecalsVisibleThisFrame;
DecalSystem.instance.UpdateCachedMaterialData(cmd); // textures, alpha or fade distances could've changed
DecalSystem.instance.CreateDrawData(); // prepare data is separate from draw
}
renderContext.SetupCameraProperties(camera, m_FrameSettings.enableStereo);
PushGlobalParams(hdCamera, cmd, diffusionProfileSettings);

RenderObjectsVelocity(m_CullResults, hdCamera, renderContext, cmd);
RenderDBuffer(hdCamera, renderContext, cmd);
RenderDBuffer(hdCamera, cmd);
RenderGBuffer(m_CullResults, hdCamera, enableBakeShadowMask, renderContext, cmd);
RenderGBuffer(m_CullResults, hdCamera, enableBakeShadowMask, renderContext, cmd);
// In both forward and deferred, everything opaque should have been rendered at this point so we can safely copy the depth buffer for later processing.
CopyDepthBufferIfNeeded(cmd);

}
}
void RenderDBuffer(HDCamera camera, ScriptableRenderContext renderContext, CommandBuffer cmd)
void RenderDBuffer(HDCamera camera, CommandBuffer cmd)
using (new ProfilingSample(cmd, "DBuffer", CustomSamplerId.DBuffer.GetSampler()))
using (new ProfilingSample(cmd, "DBufferRender", CustomSamplerId.DBufferRender.GetSampler()))
{
// We need to copy depth buffer texture if we want to bind it at this stage
CopyDepthBufferIfNeeded(cmd);

HDUtils.SetRenderTarget(cmd, camera, m_DbufferManager.GetBuffersRTI(), m_CameraDepthStencilBuffer); // do not clear anymore
m_DbufferManager.SetHTile(m_DbufferManager.bufferCount, cmd);
DecalSystem.instance.Render(renderContext, camera, cmd);
DecalSystem.instance.RenderIntoDBuffer(cmd);
m_DbufferManager.SetHTileTexture(cmd);
m_DbufferManager.SetHTileTexture(cmd); // mask per 8x8 tile used for optimization when looking up dbuffer values
}
}

// In case of forward SSS we will bind all the required target. It is up to the shader to write into it or not.
if (m_FrameSettings.enableSubsurfaceScattering)
{
RenderTargetIdentifier[] m_MRTWithSSS = new RenderTargetIdentifier[2 + m_SSSBufferManager.sssBufferCount];
RenderTargetIdentifier[] m_MRTWithSSS =
new RenderTargetIdentifier[2 + m_SSSBufferManager.sssBufferCount];
m_MRTWithSSS[0] = m_CameraColorBuffer; // Store the specular color
m_MRTWithSSS[1] = m_CameraSssDiffuseLightingBuffer;
for (int i = 0; i < m_SSSBufferManager.sssBufferCount; ++i)

HDUtils.SetRenderTarget(cmd, hdCamera, m_CameraColorBuffer, m_CameraDepthStencilBuffer);
}
m_ForwardAndForwardOnlyPassNames[0] = m_ForwardOnlyPassNames[0] = HDShaderPassNames.s_ForwardOnlyName;
m_ForwardAndForwardOnlyPassNames[0] = m_ForwardOnlyPassNames[0] =
HDShaderPassNames.s_ForwardOnlyName;
var passNames = m_FrameSettings.enableForwardRenderingOnly ? m_ForwardAndForwardOnlyPassNames : m_ForwardOnlyPassNames;
var passNames = m_FrameSettings.enableForwardRenderingOnly
? m_ForwardAndForwardOnlyPassNames
: m_ForwardOnlyPassNames;
if (m_FrameSettings.enableDBuffer) // enable d-buffer flag value is being interpreted more like enable decals in general now that we have clustered
{
DecalSystem.instance.SetAtlas(cmd); // for clustered decals
}
RenderTransparentRenderList(cullResults, camera, renderContext, cmd, m_AllTransparentPassNames, m_currentRendererConfigurationBakedLighting, pass == ForwardPass.PreRefraction ? HDRenderQueue.k_RenderQueue_PreRefraction : HDRenderQueue.k_RenderQueue_Transparent);
}
}

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


public static readonly int _SrcBlend = Shader.PropertyToID("_SrcBlend");
public static readonly int _DstBlend = Shader.PropertyToID("_DstBlend");
public static readonly int _HTile = Shader.PropertyToID("_HTile");
// all decal properties
public static readonly int _NormalToWorldID = Shader.PropertyToID("_NormalToWorld");
public static readonly int _DecalAtlasID = Shader.PropertyToID("_DecalAtlas");
public static readonly int _DecalIndexShift = Shader.PropertyToID("_DecalIndexShift");
public static readonly int _DecalCount = Shader.PropertyToID("_DecalCount");
public static readonly int _DecalDatas = Shader.PropertyToID("_DecalDatas");
public static readonly int _ViewMatrix = Shader.PropertyToID("_ViewMatrix");
public static readonly int _InvViewMatrix = Shader.PropertyToID("_InvViewMatrix");

33
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs


Punctual,
Area,
Env,
Decal,
Count
}

Env = 1 << 15,
Sky = 1 << 16,
SSRefraction = 1 << 17,
SSReflection = 1 << 18,
SSReflection = 1 << 18
// If adding more light be sure to not overflow LightDefinitions.s_LightFeatureMaskFlags
}

Environment = 4,
EnvironmentAndPunctual = 5,
EnvironmentAndArea = 6,
EnvironmentAndAreaAndPunctual = 7
EnvironmentAndAreaAndPunctual = 7,
Decal = 8
public const int k_MaxLightsOnScreen = k_MaxDirectionalLightsOnScreen + k_MaxPunctualLightsOnScreen + k_MaxAreaLightsOnScreen;
public const int k_MaxDecalsOnScreen = 512;
public const int k_MaxLightsOnScreen = k_MaxDirectionalLightsOnScreen + k_MaxPunctualLightsOnScreen + k_MaxAreaLightsOnScreen + k_MaxDecalsOnScreen;
static readonly Vector3 k_BoxCullingExtentThreshold = Vector3.one * 0.01f;
public static readonly Vector3 k_BoxCullingExtentThreshold = Vector3.one * 0.01f;
// Static keyword is required here else we get a "DestroyBuffer can only be called from the main thread"
static ComputeBuffer s_DirectionalLightDatas = null;

static ComputeBuffer s_DecalDatas = null;
static Texture2DArray s_DefaultTexture2DArray;
static Cubemap s_DefaultTextureCube;

public List<SFiniteLightBound> bounds;
public List<LightVolumeData> lightVolumes;
public void Clear()
{

s_LightDatas = new ComputeBuffer(k_MaxPunctualLightsOnScreen + k_MaxAreaLightsOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(LightData)));
s_EnvLightDatas = new ComputeBuffer(k_MaxEnvLightsOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(EnvLightData)));
s_shadowDatas = new ComputeBuffer(k_MaxCascadeCount + k_MaxShadowOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(ShadowData)));
s_DecalDatas = new ComputeBuffer(k_MaxDecalsOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(DecalData)));
GlobalLightLoopSettings gLightLoopSettings = hdAsset.GetRenderPipelineSettings().lightLoopSettings;
m_CookieTexArray = new TextureCache2D();

CoreUtils.SafeRelease(s_LightDatas);
CoreUtils.SafeRelease(s_EnvLightDatas);
CoreUtils.SafeRelease(s_shadowDatas);
CoreUtils.SafeRelease(s_DecalDatas);
if (m_ReflectionProbeCache != null)
{

}
}
static Matrix4x4 WorldToCamera(Camera camera)
public static Matrix4x4 WorldToCamera(Camera camera)
{
// camera.worldToCameraMatrix is RHS and Unity's transforms are LHS
// We need to flip it to work with transforms

envLightData.proxyPositionWS = proxyToWorld.GetColumn(3);
m_lightList.envLights.Add(envLightData);
public void GetEnvLightVolumeDataAndBound(ProbeWrapper probe, LightVolumeType lightVolumeType, Matrix4x4 worldToView)
{
var bound = new SFiniteLightBound();

}
}
m_lightCount = m_lightList.lights.Count + m_lightList.envLights.Count;
m_lightList.bounds.AddRange(DecalSystem.m_Bounds);
m_lightList.lightVolumes.AddRange(DecalSystem.m_LightVolumes);
m_lightCount = m_lightList.lights.Count + m_lightList.envLights.Count + DecalSystem.m_DecalDatasCount;
Debug.Assert(m_lightList.bounds.Count == m_lightCount);
Debug.Assert(m_lightList.lightVolumes.Count == m_lightCount);

bool isOrthographic = camera.orthographic;
cmd.SetComputeIntParam(buildPerVoxelLightListShader, HDShaderIDs.g_isOrthographic, isOrthographic ? 1 : 0);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, HDShaderIDs._EnvLightIndexShift, m_lightList.lights.Count);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, HDShaderIDs._DecalIndexShift, m_lightList.lights.Count + m_lightList.envLights.Count);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, HDShaderIDs.g_iNrVisibLights, m_lightCount);
cmd.SetComputeMatrixParam(buildPerVoxelLightListShader, HDShaderIDs.g_mScrProjection, projscr);
cmd.SetComputeMatrixParam(buildPerVoxelLightListShader, HDShaderIDs.g_mInvScrProjection, invProjscr);

cmd.SetComputeIntParam(buildPerBigTileLightListShader, HDShaderIDs.g_isOrthographic, isOrthographic ? 1 : 0);
cmd.SetComputeIntParams(buildPerBigTileLightListShader, HDShaderIDs.g_viDimensions, s_TempIntArray);
cmd.SetComputeIntParam(buildPerBigTileLightListShader, HDShaderIDs._EnvLightIndexShift, m_lightList.lights.Count);
cmd.SetComputeIntParam(buildPerBigTileLightListShader, HDShaderIDs._DecalIndexShift, m_lightList.lights.Count + m_lightList.envLights.Count);
cmd.SetComputeIntParam(buildPerBigTileLightListShader, HDShaderIDs.g_iNrVisibLights, m_lightCount);
cmd.SetComputeMatrixParam(buildPerBigTileLightListShader, HDShaderIDs.g_mScrProjection, projscr);
cmd.SetComputeMatrixParam(buildPerBigTileLightListShader, HDShaderIDs.g_mInvScrProjection, invProjscr);

cmd.SetComputeIntParam(buildPerTileLightListShader, HDShaderIDs.g_isOrthographic, isOrthographic ? 1 : 0);
cmd.SetComputeIntParams(buildPerTileLightListShader, HDShaderIDs.g_viDimensions, s_TempIntArray);
cmd.SetComputeIntParam(buildPerTileLightListShader, HDShaderIDs._EnvLightIndexShift, m_lightList.lights.Count);
cmd.SetComputeIntParam(buildPerTileLightListShader, HDShaderIDs._DecalIndexShift, m_lightList.lights.Count + m_lightList.envLights.Count);
cmd.SetComputeIntParam(buildPerTileLightListShader, HDShaderIDs.g_iNrVisibLights, m_lightCount);
cmd.SetComputeBufferParam(buildPerTileLightListShader, s_GenListPerTileKernel, HDShaderIDs.g_vBoundsBuffer, s_AABBBoundsBuffer);

PushGlobalParams(hdCamera, cmd);
}
private void UpdateDataBuffers()
void UpdateDataBuffers()
s_DecalDatas.SetData(DecalSystem.m_DecalDatas);
// These two buffers have been set in Rebuild()
s_ConvexBoundsBuffer.SetData(m_lightList.bounds);

cmd.SetGlobalInt(HDShaderIDs._AreaLightCount, m_areaLightCount);
cmd.SetGlobalBuffer(HDShaderIDs._EnvLightDatas, s_EnvLightDatas);
cmd.SetGlobalInt(HDShaderIDs._EnvLightCount, m_lightList.envLights.Count);
cmd.SetGlobalBuffer(HDShaderIDs._DecalDatas, s_DecalDatas);
cmd.SetGlobalInt(HDShaderIDs._DecalCount, DecalSystem.m_DecalDatasCount);
cmd.SetGlobalBuffer(HDShaderIDs._ShadowDatas, s_shadowDatas);
cmd.SetGlobalInt(HDShaderIDs._NumTileFtplX, GetNumTileFtplX(hdCamera));

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs.hlsl


#define LIGHTCATEGORY_PUNCTUAL (0)
#define LIGHTCATEGORY_AREA (1)
#define LIGHTCATEGORY_ENV (2)
#define LIGHTCATEGORY_COUNT (3)
#define LIGHTCATEGORY_DECAL (3)
#define LIGHTCATEGORY_COUNT (4)
//
// UnityEngine.Experimental.Rendering.HDPipeline.LightFeatureFlags: static fields

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-bigtile.compute


uniform float g_fFarPlane;
uniform uint g_isOrthographic;
uniform int _EnvLightIndexShift;
uniform int _DecalIndexShift;
StructuredBuffer<float3> g_vBoundsBuffer : register( t1 );
StructuredBuffer<LightVolumeData> _LightVolumeData : register(t2);

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-clustered.compute


float4x4 g_mScrProjection;
uint g_isOrthographic;
int _EnvLightIndexShift;
int _DecalIndexShift;
float g_fClustScale;
float g_fClustBase;

// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT];
ZERO_INITIALIZE_ARRAY(int, shiftIndex, LIGHTCATEGORY_COUNT);
shiftIndex[LIGHTCATEGORY_COUNT - 1] = _EnvLightIndexShift;
shiftIndex[LIGHTCATEGORY_COUNT - 2] = _EnvLightIndexShift;
shiftIndex[LIGHTCATEGORY_COUNT - 1] = _DecalIndexShift;
int categoryListCount[LIGHTCATEGORY_COUNT]; // direct light count and reflection lights
ZERO_INITIALIZE_ARRAY(int, categoryListCount, LIGHTCATEGORY_COUNT);

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild.compute


uniform float4x4 g_mScrProjection;
uniform uint g_isOrthographic;
uniform int _EnvLightIndexShift;
uniform int _DecalIndexShift;
uniform uint g_BaseFeatureFlags;
Texture2D g_depth_tex : register( t0 );

// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT];
ZERO_INITIALIZE_ARRAY(int, shiftIndex, LIGHTCATEGORY_COUNT);
shiftIndex[LIGHTCATEGORY_COUNT - 1] = _EnvLightIndexShift;
shiftIndex[LIGHTCATEGORY_COUNT - 2] = _EnvLightIndexShift;
shiftIndex[LIGHTCATEGORY_COUNT - 1] = _DecalIndexShift;
for(int category=0; category<LIGHTCATEGORY_COUNT; category++)
{

11
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs


sRGBFlags = m_sRGBFlags;
}
}
// normalToWorld.m03 - total blend factor
// normalToWorld.m13 - diffuse texture index in atlas
// normalToWorld.m23 - normal texture index in atlas
// normalToWorld.m33 - mask texture index in atlas
[GenerateHLSL]
public struct DecalData
{
public Matrix4x4 worldToDecal;
public Matrix4x4 normalToWorld;
};
}

16
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs.hlsl


uint HTileMask;
};
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.DecalData
// PackingRules = Exact
struct DecalData
{
float4x4 worldToDecal;
float4x4 normalToWorld;
};
//
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.DecalData
//
float4x4 GetNormalToWorld(DecalData value)
{
return value.normalToWorld;
}
//
// Debug functions
//

10
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl


CBUFFER_END
UNITY_INSTANCING_BUFFER_START(Decal)
UNITY_DEFINE_INSTANCED_PROP(float4x4, normalToWorld)
UNITY_DEFINE_INSTANCED_PROP(float4x4, _NormalToWorld)
TEXTURE2D(_DecalHTileTexture);
TEXTURE2D(_DecalHTileTexture);
uint _DecalCount;
StructuredBuffer<DecalData> _DecalDatas;
TEXTURE2D_ARRAY(_DecalAtlas);
SAMPLER(sampler_DecalAtlas);
// Must be in sync with RT declared in HDRenderPipeline.cs ::Rebuild
void EncodeIntoDBuffer( DecalSurfaceData surfaceData,

7
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl


surfaceData.normalWS = float4(0,0,0,0);
surfaceData.mask = float4(0,0,0,0);
surfaceData.HTileMask = 0;
float totalBlend = _DecalBlend * clamp(decalToWorld[0][3], 0.0f, 1.0f);
float totalBlend = clamp(decalToWorld[0][3], 0.0f, 1.0f);
UVMapping texCoord;
ZERO_INITIALIZE(UVMapping, texCoord);
texCoord.uv = texCoordDS.xy;
surfaceData.normalWS.xyz = mul((float3x3)decalToWorld, SAMPLE_UVMAPPING_NORMALMAP(_NormalMap, sampler_NormalMap, texCoord, 1)) * 0.5f + 0.5f;
surfaceData.normalWS.xyz = mul((float3x3)decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, texCoordDS))) * 0.5f + 0.5f;
surfaceData.normalWS.w = totalBlend;
surfaceData.HTileMask |= DBUFFERHTILEBIT_NORMAL;
#endif

96
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl


DECLARE_DBUFFER_TEXTURE(_DBufferTexture);
void AddDecalContribution(uint2 unPositionSS, inout SurfaceData surfaceData)
DecalData FetchDecal(uint start, uint i)
{
#ifdef LIGHTLOOP_TILE_PASS
int j = FetchIndex(start, i);
#else
int j = start + i;
#endif
return _DecalDatas[j];
}
void ApplyBlendNormal(inout float4 dst, inout int matMask, float2 texCoords, int sliceIndex, int mapMask, float3x3 decalToWorld, float blend)
{
float4 src;
src.xyz = mul(decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D_ARRAY(_DecalAtlas, sampler_DecalAtlas, texCoords, sliceIndex))) * 0.5f + 0.5f;
src.w = blend;
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);
dst.w = dst.w * (1.0f - src.w);
matMask |= mapMask;
}
void ApplyBlendDiffuse(inout float4 dst, inout int matMask, float2 texCoords, int sliceIndex, int mapMask, float blend)
{
float4 src = SAMPLE_TEXTURE2D_ARRAY(_DecalAtlas, sampler_DecalAtlas, texCoords, sliceIndex);
src.w *= blend;
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);
dst.w = dst.w * (1.0f - src.w);
matMask |= mapMask;
}
void ApplyBlendMask(inout float4 dst, inout int matMask, float2 texCoords, int sliceIndex, int mapMask, float blend)
{
float4 src = SAMPLE_TEXTURE2D_ARRAY(_DecalAtlas, sampler_DecalAtlas, texCoords, sliceIndex);
src.z = src.w;
src.w = blend;
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);
dst.w = dst.w * (1.0f - src.w);
matMask |= mapMask;
}
void AddDecalContribution(PositionInputs posInput, inout SurfaceData surfaceData)
DecalSurfaceData decalSurfaceData;
int mask = 0;
FETCH_DBUFFER(DBuffer, _DBufferTexture, unPositionSS);
DecalSurfaceData decalSurfaceData;
DECODE_FROM_DBUFFER(DBuffer, decalSurfaceData);
uint mask = UnpackByte(LOAD_TEXTURE2D(_DecalHTileTexture, unPositionSS / 8).x);
FETCH_DBUFFER(DBuffer, _DBufferTexture, posInput.positionSS);
#ifdef _SURFACE_TYPE_TRANSPARENT // forward transparent using clustered decals
uint decalCount, decalStart;
DBuffer0 = float4(0.0f, 0.0f, 0.0f, 1.0f);
DBuffer1 = float4(0.5f, 0.5f, 0.5f, 1.0f);
DBuffer2 = float4(0.0f, 0.0f, 0.0f, 1.0f);
#ifdef LIGHTLOOP_TILE_PASS
GetCountAndStart(posInput, LIGHTCATEGORY_DECAL, decalStart, decalCount);
#else
decalCount = _DecalCount;
decalStart = 0;
#endif
float3 positionWS = GetAbsolutePositionWS(posInput.positionWS);
uint i = 0;
for (i = 0; i < decalCount; i++)
{
DecalData decalData = FetchDecal(decalStart, i);
float3 positionDS = mul(decalData.worldToDecal, float4(positionWS, 1.0)).xyz;
positionDS = positionDS * float3(1.0, -1.0, 1.0) + float3(0.5, 0.0f, 0.5);
float decalBlend = decalData.normalToWorld[0][3];
int diffuseIndex = decalData.normalToWorld[1][3];
int normalIndex = decalData.normalToWorld[2][3];
int maskIndex = decalData.normalToWorld[3][3];
if((all(positionDS.xyz > 0.0f) && all(1.0f - positionDS.xyz > 0.0f))) // clip to decal space
{
if(diffuseIndex != -1)
{
ApplyBlendDiffuse(DBuffer0, mask, positionDS.xz, diffuseIndex, DBUFFERHTILEBIT_DIFFUSE, decalBlend);
}
if(normalIndex != -1)
{
ApplyBlendNormal(DBuffer1, mask, positionDS.xz, normalIndex, DBUFFERHTILEBIT_NORMAL, (float3x3)decalData.normalToWorld, decalBlend);
}
if(maskIndex != -1)
{
ApplyBlendMask(DBuffer2, mask, positionDS.xz, maskIndex, DBUFFERHTILEBIT_MASK, decalBlend);
}
}
}
#else
mask = UnpackByte(LOAD_TEXTURE2D(_DecalHTileTexture, posInput.positionSS / 8));
#endif
DECODE_FROM_DBUFFER(DBuffer, decalSurfaceData);
if(mask & DBUFFERHTILEBIT_NORMAL)
{
surfaceData.normalWS.xyz = normalize(surfaceData.normalWS.xyz * decalSurfaceData.normalWS.w + decalSurfaceData.normalWS.xyz);

}
}
}

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitData.hlsl


#endif
#ifndef _DISABLE_DBUFFER
AddDecalContribution(posInput.positionSS, surfaceData);
AddDecalContribution(posInput, surfaceData);
#endif
#if defined(DEBUG_DISPLAY)

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitData.hlsl


surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS);
#ifndef _DISABLE_DBUFFER
AddDecalContribution(posInput.positionSS, surfaceData);
AddDecalContribution(posInput, surfaceData);
#endif
#if defined(DEBUG_DISPLAY)

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl


clip(1.0 - positionDS); // Clip value above one
DecalSurfaceData surfaceData;
float4x4 decalToWorld = UNITY_ACCESS_INSTANCED_PROP(matrix, normalToWorld);
float4x4 decalToWorld = UNITY_ACCESS_INSTANCED_PROP(matrix, _NormalToWorld);
GetSurfaceData(positionDS.xz, decalToWorld, surfaceData);
// have to do explicit test since compiler behavior is not defined for RW resources and discard instructions

正在加载...
取消
保存