123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- using Unity.Collections;
- using UnityEngine.Experimental.Rendering;
-
- namespace UnityEngine.Rendering.Universal
- {
- /// <summary>
- /// Abstract class that render decals using <see cref="DecalDrawCallChunk"/>.
- /// Supports rendering with <see cref="CommandBuffer"/> and graphics draw calls.
- /// </summary>
- internal abstract class DecalDrawSystem
- {
- readonly static internal uint MaxBatchSize = 250;
-
- protected DecalEntityManager m_EntityManager;
- private Matrix4x4[] m_WorldToDecals;
- private Matrix4x4[] m_NormalToDecals;
- private float[] m_DecalLayerMasks;
- private ProfilingSampler m_Sampler;
-
- public Material overrideMaterial { get; set; }
-
- public DecalDrawSystem(string sampler, DecalEntityManager entityManager)
- {
- m_EntityManager = entityManager;
-
- m_WorldToDecals = new Matrix4x4[MaxBatchSize];
- m_NormalToDecals = new Matrix4x4[MaxBatchSize];
- m_DecalLayerMasks = new float[MaxBatchSize];
-
- m_Sampler = new ProfilingSampler(sampler);
- }
-
- public void Execute(CommandBuffer cmd)
- {
- Execute(CommandBufferHelpers.GetRasterCommandBuffer(cmd));
- }
-
- internal void Execute(RasterCommandBuffer cmd)
- {
- using (new ProfilingScope(cmd, m_Sampler))
- {
- for (int i = 0; i < m_EntityManager.chunkCount; ++i)
- {
- Execute(
- cmd,
- m_EntityManager.entityChunks[i],
- m_EntityManager.cachedChunks[i],
- m_EntityManager.drawCallChunks[i],
- m_EntityManager.entityChunks[i].count);
- }
- }
- }
-
- protected virtual Material GetMaterial(DecalEntityChunk decalEntityChunk) => decalEntityChunk.material;
-
- protected abstract int GetPassIndex(DecalCachedChunk decalCachedChunk);
-
- private void Execute(RasterCommandBuffer cmd, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int count)
- {
- decalCachedChunk.currentJobHandle.Complete();
- decalDrawCallChunk.currentJobHandle.Complete();
-
- Material material = GetMaterial(decalEntityChunk);
- int passIndex = GetPassIndex(decalCachedChunk);
-
- if (count == 0 || passIndex == -1 || material == null)
- return;
-
- if (SystemInfo.supportsInstancing && material.enableInstancing)
- {
- DrawInstanced(cmd, decalEntityChunk, decalCachedChunk, decalDrawCallChunk, passIndex);
- }
- else
- {
- Draw(cmd, decalEntityChunk, decalCachedChunk, decalDrawCallChunk, passIndex);
- }
- }
-
- private void Draw(RasterCommandBuffer cmd, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int passIndex)
- {
- var mesh = m_EntityManager.decalProjectorMesh;
- var material = GetMaterial(decalEntityChunk);
- decalCachedChunk.propertyBlock.SetVector("unity_LightData", new Vector4(1, 1, 1, 0)); // GetMainLight requires z component to be set
-
- int subCallCount = decalDrawCallChunk.subCallCount;
- for (int i = 0; i < subCallCount; ++i)
- {
- var subCall = decalDrawCallChunk.subCalls[i];
-
- for (int j = subCall.start; j < subCall.end; ++j)
- {
- decalCachedChunk.propertyBlock.SetMatrix("_NormalToWorld", decalDrawCallChunk.normalToDecals[j]);
- decalCachedChunk.propertyBlock.SetFloat("_DecalLayerMaskFromDecal", decalDrawCallChunk.renderingLayerMasks[j]);
- cmd.DrawMesh(mesh, decalDrawCallChunk.decalToWorlds[j], material, 0, passIndex, decalCachedChunk.propertyBlock);
- }
- }
- }
-
- private void DrawInstanced(RasterCommandBuffer cmd, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int passIndex)
- {
- var mesh = m_EntityManager.decalProjectorMesh;
- var material = GetMaterial(decalEntityChunk);
- decalCachedChunk.propertyBlock.SetVector("unity_LightData", new Vector4(1, 1, 1, 0)); // GetMainLight requires z component to be set
-
- int subCallCount = decalDrawCallChunk.subCallCount;
- for (int i = 0; i < subCallCount; ++i)
- {
- var subCall = decalDrawCallChunk.subCalls[i];
-
- var decalToWorldSlice = decalDrawCallChunk.decalToWorlds.Reinterpret<Matrix4x4>();
- NativeArray<Matrix4x4>.Copy(decalToWorldSlice, subCall.start, m_WorldToDecals, 0, subCall.count);
-
- var normalToWorldSlice = decalDrawCallChunk.normalToDecals.Reinterpret<Matrix4x4>();
- NativeArray<Matrix4x4>.Copy(normalToWorldSlice, subCall.start, m_NormalToDecals, 0, subCall.count);
-
- var decalLayerMaskSlice = decalDrawCallChunk.renderingLayerMasks.Reinterpret<float>();
- NativeArray<float>.Copy(decalLayerMaskSlice, subCall.start, m_DecalLayerMasks, 0, subCall.count);
-
- decalCachedChunk.propertyBlock.SetMatrixArray("_NormalToWorld", m_NormalToDecals);
- decalCachedChunk.propertyBlock.SetFloatArray("_DecalLayerMaskFromDecal", m_DecalLayerMasks);
- cmd.DrawMeshInstanced(mesh, 0, material, passIndex, m_WorldToDecals, subCall.end - subCall.start, decalCachedChunk.propertyBlock);
- }
- }
-
- public void Execute(in CameraData cameraData)
- {
- using (new ProfilingScope(m_Sampler))
- {
- for (int i = 0; i < m_EntityManager.chunkCount; ++i)
- {
- Execute(
- cameraData,
- m_EntityManager.entityChunks[i],
- m_EntityManager.cachedChunks[i],
- m_EntityManager.drawCallChunks[i],
- m_EntityManager.entityChunks[i].count);
- }
- }
- }
-
- private void Execute(in CameraData cameraData, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int count)
- {
- decalCachedChunk.currentJobHandle.Complete();
- decalDrawCallChunk.currentJobHandle.Complete();
-
- Material material = GetMaterial(decalEntityChunk);
- int passIndex = GetPassIndex(decalCachedChunk);
-
- if (count == 0 || passIndex == -1 || material == null)
- return;
-
- if (SystemInfo.supportsInstancing && material.enableInstancing)
- {
- DrawInstanced(cameraData, decalEntityChunk, decalCachedChunk, decalDrawCallChunk);
- }
- else
- {
- Draw(cameraData, decalEntityChunk, decalCachedChunk, decalDrawCallChunk);
- }
- }
-
- private void Draw(in CameraData cameraData, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk)
- {
- var mesh = m_EntityManager.decalProjectorMesh;
- var material = GetMaterial(decalEntityChunk);
- int subCallCount = decalDrawCallChunk.subCallCount;
- for (int i = 0; i < subCallCount; ++i)
- {
- var subCall = decalDrawCallChunk.subCalls[i];
-
- for (int j = subCall.start; j < subCall.end; ++j)
- {
- decalCachedChunk.propertyBlock.SetMatrix("_NormalToWorld", decalDrawCallChunk.normalToDecals[j]);
- decalCachedChunk.propertyBlock.SetFloat("_DecalLayerMaskFromDecal", decalDrawCallChunk.renderingLayerMasks[j]);
- // RENDERGRAPH TODO: schedule drawmesh through commandBuffer?
- Graphics.DrawMesh(mesh, decalDrawCallChunk.decalToWorlds[j], material, decalCachedChunk.layerMasks[j], cameraData.camera, 0, decalCachedChunk.propertyBlock);
- }
- }
- }
-
- private void DrawInstanced(in CameraData cameraData, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk)
- {
- var mesh = m_EntityManager.decalProjectorMesh;
- var material = GetMaterial(decalEntityChunk);
- decalCachedChunk.propertyBlock.SetVector("unity_LightData", new Vector4(1, 1, 1, 0)); // GetMainLight requires z component to be set
-
- int subCallCount = decalDrawCallChunk.subCallCount;
- for (int i = 0; i < subCallCount; ++i)
- {
- var subCall = decalDrawCallChunk.subCalls[i];
-
- var decalToWorldSlice = decalDrawCallChunk.decalToWorlds.Reinterpret<Matrix4x4>();
- NativeArray<Matrix4x4>.Copy(decalToWorldSlice, subCall.start, m_WorldToDecals, 0, subCall.count);
-
- var normalToWorldSlice = decalDrawCallChunk.normalToDecals.Reinterpret<Matrix4x4>();
- NativeArray<Matrix4x4>.Copy(normalToWorldSlice, subCall.start, m_NormalToDecals, 0, subCall.count);
-
- var decalLayerMaskSlice = decalDrawCallChunk.renderingLayerMasks.Reinterpret<float>();
- NativeArray<float>.Copy(decalLayerMaskSlice, subCall.start, m_DecalLayerMasks, 0, subCall.count);
-
- decalCachedChunk.propertyBlock.SetMatrixArray("_NormalToWorld", m_NormalToDecals);
- decalCachedChunk.propertyBlock.SetFloatArray("_DecalLayerMaskFromDecal", m_DecalLayerMasks);
- // RENDERGRAPH TODO: schedule drawmesh through commandBuffer?
- Graphics.DrawMeshInstanced(mesh, 0, material,
- m_WorldToDecals, subCall.count, decalCachedChunk.propertyBlock, ShadowCastingMode.On, true, 0, cameraData.camera);
- }
- }
- }
- }
|