浏览代码

clustered decal refactor

/main
Paul Melamed 6 年前
当前提交
db42063a
共有 5 个文件被更改,包括 154 次插入43 次删除
  1. 3
      ScriptableRenderPipeline/Core/CoreRP/com.unity.render-pipelines.core.Runtime.asmdef
  2. 138
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs
  3. 14
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
  4. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  5. 39
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs

3
ScriptableRenderPipeline/Core/CoreRP/com.unity.render-pipelines.core.Runtime.asmdef


],
"optionalUnityReferences": [],
"includePlatforms": [],
"excludePlatforms": []
"excludePlatforms": [],
"allowUnsafeCode": true
}

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


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];
// static public Matrix4x4[] m_InstanceMatrices = new Matrix4x4[kDrawIndexedBatchSize];
// static public Matrix4x4[] m_InstanceNormalToWorld = new Matrix4x4[kDrawIndexedBatchSize];
static public List<DecalData> m_DecalDataList = new List<DecalData>();
static public float[] m_BoundingDistances = new float[1];
private Dictionary<int, DecalSet> m_DecalSets = new Dictionary<int, DecalSet>();

public void UpdateCachedData(DecalProjectorComponent decal)
{
m_CachedTransforms[decal.CullIndex] = decal.transform.localToWorldMatrix;
m_CachedDecalToWorld[decal.CullIndex] = decal.transform.localToWorldMatrix;
Matrix4x4 decalRotation = Matrix4x4.Rotate(decal.transform.rotation);
// z/y axis swap for normal to decal space, Unity is column major

? decal.m_DrawDistance
: instance.DrawDistance;
m_CachedDrawDistances[decal.CullIndex].y = decal.m_FadeScale;
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_CachedTransforms = newCachedTransforms;
m_CachedDecalToWorld = newCachedTransforms;
m_CachedNormalToWorld = newCachedNormalToWorld;
m_CachedDrawDistances = newCachedDrawDistances;
}

// 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_CachedNormalToWorld[removeAtIndex] = m_CachedNormalToWorld[m_DecalsCount - 1];
m_CachedDrawDistances[removeAtIndex] = m_CachedDrawDistances[m_DecalsCount - 1];
m_DecalsCount--;

return m_NumResults;
}
private 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 = m_CullingGroup.targetCamera.transform.position;
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)
{
// dbuffer 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
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.normalToWorld = normalToWorldBatch[instanceCount];
m_DecalDataList.Add(decalData);
instanceCount++;
if (instanceCount == kDrawIndexedBatchSize)
{
instanceCount = 0;
batchCount++;
AssignCurrentBatches(ref decalToWorldBatch, ref normalToWorldBatch, batchCount);
}
}
}
}
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))

instance.TextureAtlas.RemoveEntryFromSlice(m_MaskTexture);
}
}
public void UpdateCachedMaterialData(CommandBuffer cmd)
{
InitializeMaterialValues(); // refresh in case they changed in the UI
UpdateTextureCache(cmd);
}
public void Render(ScriptableRenderContext renderContext, HDCamera camera, CommandBuffer cmd, LightLoop lightLoop)
public void RenderIntoDBuffer(CommandBuffer cmd)
InitializeMaterialValues(); // refresh in case they changed in the UI
UpdateTextureCache(cmd);
int batchIndex = 0;
int totalToDraw = m_NumResults;
for (; batchIndex < m_NumResults / kDrawIndexedBatchSize; batchIndex++)
{
m_PropertyBlock.SetMatrixArray(m_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(m_NormalToWorldID, m_NormalToWorld[batchIndex]);
cmd.DrawMeshInstanced(m_DecalMesh, 0, KeyMaterial, 0, m_DecalToWorld[batchIndex], totalToDraw, m_PropertyBlock);
}
/*
var worldToView = Matrix4x4.Scale(new Vector3(1, 1, -1)) * camera.camera.worldToCameraMatrix;
int instanceCount = 0;
Vector3 cameraPos = camera.cameraPos;

{
m_PropertyBlock.SetMatrixArray(m_NormalToWorldID, m_InstanceNormalToWorld);
cmd.DrawMeshInstanced(m_DecalMesh, 0, KeyMaterial, 0, m_InstanceMatrices, instanceCount, m_PropertyBlock);
}
}*/
public Material KeyMaterial
{
get

}
}
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 Matrix4x4[] m_CachedNormalToWorld = new Matrix4x4[kDecalBlockSize];
private Vector2[] m_CachedDrawDistances = new Vector2[kDecalBlockSize]; // x - draw distance, y - fade scale
private Material m_Material;

public void EndCull()
{
m_DecalDataList.Clear();
foreach (var pair in m_DecalSets)
{
pair.Value.EndCull();

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

pair.Value.Render(renderContext, camera, cmd, lightLoop);
pair.Value.RenderIntoDBuffer(cmd);
cmd.SetGlobalTexture(m_DecalAtlasID, m_DecalAtlas.GetTexCache());
cmd.SetGlobalTexture(m_DecalAtlasID, TextureAtlas.GetTexCache());
}
public void UpdateCachedMaterialData(CommandBuffer cmd)
{
foreach (var pair in m_DecalSets)
{
pair.Value.UpdateCachedMaterialData(cmd);
}
}
public void InvertDecalDataWorldToDecal()
{
for(int i = 0; i < m_DecalDataList.Count; i++)
{
DecalData decalData = m_DecalDataList[i];
decalData.worldToDecal = decalData.worldToDecal.inverse;
m_DecalDataList[i] = decalData;
}
}
}
}

14
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs


// decal system needs to be updated with current camera
if (m_FrameSettings.enableDBuffer)
{
DecalSystem.instance.UpdateCachedMaterialData(cmd);
}
ReflectionSystem.PrepareCull(camera, m_ReflectionProbeCullResults);
using (new ProfilingSample(cmd, "CullResults.Cull", CustomSamplerId.CullResultsCull.GetSampler()))

RenderObjectsVelocity(m_CullResults, hdCamera, renderContext, cmd);
RenderDBuffer(hdCamera, renderContext, cmd);
m_LightLoop.UpdateDataBuffers();
RenderDBuffer(hdCamera, cmd);
RenderGBuffer(m_CullResults, hdCamera, 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)
{
if (!m_FrameSettings.enableDBuffer)
return;

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, m_LightLoop);
DecalSystem.instance.RenderIntoDBuffer(cmd);
m_DbufferManager.UnSetHTile(cmd);
m_DbufferManager.SetHTileTexture(cmd);
DecalSystem.instance.SetAtlas(cmd);

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


public static readonly int _SSSHTile = Shader.PropertyToID("_SSSHTile");
public static readonly int _DecalHTileTexture = Shader.PropertyToID("_DecalHTileTexture");
public static readonly int _StencilTexture = Shader.PropertyToID("_StencilTexture");
public static readonly int _DecalHTileTexture = Shader.PropertyToID("_DecalHTileTexture");
public static readonly int _ViewMatrix = Shader.PropertyToID("_ViewMatrix");
public static readonly int _InvViewMatrix = Shader.PropertyToID("_InvViewMatrix");
public static readonly int _ProjMatrix = Shader.PropertyToID("_ProjMatrix");

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


public List<LightData> lights;
public List<EnvLightData> envLights;
public List<ShadowData> shadows;
public List<DecalData> decals;
public List<SFiniteLightBound> bounds;
public List<LightVolumeData> lightVolumes;

lights.Clear();
envLights.Clear();
shadows.Clear();
decals.Clear();
bounds.Clear();
lightVolumes.Clear();

lights = new List<LightData>();
envLights = new List<EnvLightData>();
shadows = new List<ShadowData>();
decals = new List<DecalData>();
bounds = new List<SFiniteLightBound>();
lightVolumes = new List<LightVolumeData>();

return true;
}
public void GetDecalVolumeDataAndBound(DecalData decalData, Matrix4x4 decalToWorld, Matrix4x4 worldToView)
public void GetDecalVolumeDataAndBound(DecalData decalData, 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
// worldToDecal is actually decalToWorld when it first gets passed in
var influenceX = decalData.worldToDecal.GetColumn(0) * 0.5f;
var influenceY = decalData.worldToDecal.GetColumn(1) * 0.5f;
var influenceZ = decalData.worldToDecal.GetColumn(2) * 0.5f;
var pos = decalData.worldToDecal.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;

m_lightList.bounds.Add(bound);
m_lightList.lightVolumes.Add(lightVolumeData);
m_lightList.decals.Add(decalData);
m_lightCount++;
}
public void GetEnvLightVolumeDataAndBound(ProbeWrapper probe, LightVolumeType lightVolumeType, Matrix4x4 worldToView)

// 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;
var worldToView = WorldToCamera(camera);
// Note: Light with null intensity/Color are culled by the C++, no need to test it here
if (cullResults.visibleLights.Count != 0 || cullResults.visibleReflectionProbes.Count != 0)

// 2. Go through all lights, convert them to GPU format.
// Create simultaneously data for culling (LigthVolumeData and rendering)
var worldToView = WorldToCamera(camera);
for (int sortIndex = 0; sortIndex < sortCount; ++sortIndex)
{
// In 1. we have already classify and sorted the light, we need to use this sorted order here

}
}
m_lightCount = m_lightList.lights.Count + m_lightList.envLights.Count;
// add decals to the list
foreach(var decalData in DecalSystem.m_DecalDataList)
{
GetDecalVolumeDataAndBound(decalData, worldToView);
}
DecalSystem.instance.InvertDecalDataWorldToDecal();
m_lightCount = m_lightList.lights.Count + m_lightList.envLights.Count + DecalSystem.m_DecalDataList.Count;
// UpdateDataBuffers();
UpdateDataBuffers();
m_maxShadowDistance = shadowSettings.maxShadowDistance;

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

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

正在加载...
取消
保存