789 lines
36 KiB
C#
789 lines
36 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Experimental.Rendering.RenderGraphModule;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
[GenerateHLSL]
|
|
internal enum RayTracingRendererFlag
|
|
{
|
|
Opaque = 0x01,
|
|
CastShadowTransparent = 0x02,
|
|
CastShadowOpaque = 0x04,
|
|
CastShadow = CastShadowOpaque | CastShadowTransparent,
|
|
AmbientOcclusion = 0x08,
|
|
Reflection = 0x10,
|
|
GlobalIllumination = 0x20,
|
|
RecursiveRendering = 0x40,
|
|
PathTracing = 0x80
|
|
}
|
|
|
|
internal enum AccelerationStructureStatus
|
|
{
|
|
Clear = 0x0,
|
|
Added = 0x1,
|
|
Excluded = 0x02,
|
|
TransparencyIssue = 0x04,
|
|
NullMaterial = 0x08,
|
|
MissingMesh = 0x10
|
|
}
|
|
|
|
class HDRayTracingLights
|
|
{
|
|
// The list of non-directional lights in the sub-scene
|
|
public List<HDAdditionalLightData> hdPointLightArray = new List<HDAdditionalLightData>();
|
|
public List<HDAdditionalLightData> hdLineLightArray = new List<HDAdditionalLightData>();
|
|
public List<HDAdditionalLightData> hdRectLightArray = new List<HDAdditionalLightData>();
|
|
public List<HDAdditionalLightData> hdLightArray = new List<HDAdditionalLightData>();
|
|
|
|
// The list of directional lights in the sub-scene
|
|
public List<HDAdditionalLightData> hdDirectionalLightArray = new List<HDAdditionalLightData>();
|
|
|
|
// The list of reflection probes
|
|
public List<HDProbe> reflectionProbeArray = new List<HDProbe>();
|
|
|
|
// Counter of the current number of lights
|
|
public int lightCount;
|
|
}
|
|
|
|
public partial class HDRenderPipeline
|
|
{
|
|
// Data used for runtime evaluation
|
|
RayTracingAccelerationStructure m_CurrentRAS = new RayTracingAccelerationStructure();
|
|
HDRaytracingLightCluster m_RayTracingLightCluster;
|
|
HDRayTracingLights m_RayTracingLights = new HDRayTracingLights();
|
|
bool m_ValidRayTracingState = false;
|
|
bool m_ValidRayTracingCluster = false;
|
|
bool m_ValidRayTracingClusterCulling = false;
|
|
bool m_RayTracedShadowsRequired = false;
|
|
bool m_RayTracedContactShadowsRequired = false;
|
|
|
|
// Denoisers
|
|
HDTemporalFilter m_TemporalFilter;
|
|
HDSimpleDenoiser m_SimpleDenoiser;
|
|
HDDiffuseDenoiser m_DiffuseDenoiser;
|
|
HDReflectionDenoiser m_ReflectionDenoiser;
|
|
HDDiffuseShadowDenoiser m_DiffuseShadowDenoiser;
|
|
SSGIDenoiser m_SSGIDenoiser;
|
|
|
|
// Ray-count manager data
|
|
RayCountManager m_RayCountManager;
|
|
|
|
const int maxNumSubMeshes = 32;
|
|
Dictionary<int, int> m_RayTracingRendererReference = new Dictionary<int, int>();
|
|
bool[] subMeshFlagArray = new bool[maxNumSubMeshes];
|
|
bool[] subMeshCutoffArray = new bool[maxNumSubMeshes];
|
|
bool[] subMeshTransparentArray = new bool[maxNumSubMeshes];
|
|
ReflectionProbe reflectionProbe = new ReflectionProbe();
|
|
List<Material> materialArray = new List<Material>(maxNumSubMeshes);
|
|
Dictionary<int, bool> m_ShaderValidityCache = new Dictionary<int, bool>();
|
|
|
|
// Used to detect material and transform changes for Path Tracing
|
|
Dictionary<int, int> m_MaterialCRCs = new Dictionary<int, int>();
|
|
bool m_MaterialsDirty = false;
|
|
bool m_TransformDirty = false;
|
|
|
|
ShaderVariablesRaytracingLightLoop m_ShaderVariablesRaytracingLightLoopCB = new ShaderVariablesRaytracingLightLoop();
|
|
|
|
internal void InitRayTracingManager()
|
|
{
|
|
// Init the ray count manager
|
|
m_RayCountManager = new RayCountManager();
|
|
m_RayCountManager.Init(m_Asset.renderPipelineRayTracingResources);
|
|
|
|
// Build the light cluster
|
|
m_RayTracingLightCluster = new HDRaytracingLightCluster();
|
|
m_RayTracingLightCluster.Initialize(this);
|
|
}
|
|
|
|
internal void ReleaseRayTracingManager()
|
|
{
|
|
if (m_RayTracingLightCluster != null)
|
|
m_RayTracingLightCluster.ReleaseResources();
|
|
if (m_RayCountManager != null)
|
|
m_RayCountManager.Release();
|
|
|
|
if (m_ReflectionDenoiser != null)
|
|
m_ReflectionDenoiser.Release();
|
|
if (m_TemporalFilter != null)
|
|
m_TemporalFilter.Release();
|
|
if (m_SimpleDenoiser != null)
|
|
m_SimpleDenoiser.Release();
|
|
if (m_SSGIDenoiser != null)
|
|
m_SSGIDenoiser.Release();
|
|
if (m_DiffuseShadowDenoiser != null)
|
|
m_DiffuseShadowDenoiser.Release();
|
|
if (m_DiffuseDenoiser != null)
|
|
m_DiffuseDenoiser.Release();
|
|
}
|
|
|
|
bool IsValidRayTracedMaterial(Material currentMaterial)
|
|
{
|
|
if (currentMaterial == null || currentMaterial.shader == null)
|
|
return false;
|
|
|
|
bool isValid;
|
|
|
|
// We use a cache, to speed up the case where materials/shaders are reused many times
|
|
int shaderId = currentMaterial.shader.GetInstanceID();
|
|
if (m_ShaderValidityCache.TryGetValue(shaderId, out isValid))
|
|
return isValid;
|
|
|
|
// For the time being, we only consider non-decal HDRP materials as valid
|
|
isValid = currentMaterial.GetTag("RenderPipeline", false) == "HDRenderPipeline" && !DecalSystem.IsDecalMaterial(currentMaterial);
|
|
|
|
m_ShaderValidityCache.Add(shaderId, isValid);
|
|
|
|
return isValid;
|
|
}
|
|
|
|
static bool IsTransparentMaterial(Material currentMaterial)
|
|
{
|
|
return currentMaterial.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT")
|
|
|| (HDRenderQueue.k_RenderQueue_Transparent.lowerBound <= currentMaterial.renderQueue
|
|
&& HDRenderQueue.k_RenderQueue_Transparent.upperBound >= currentMaterial.renderQueue);
|
|
}
|
|
|
|
static bool IsAlphaTestedMaterial(Material currentMaterial)
|
|
{
|
|
return currentMaterial.IsKeywordEnabled("_ALPHATEST_ON")
|
|
|| (HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.lowerBound <= currentMaterial.renderQueue
|
|
&& HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.upperBound >= currentMaterial.renderQueue);
|
|
}
|
|
|
|
AccelerationStructureStatus AddInstanceToRAS(Renderer currentRenderer,
|
|
bool rayTracedShadow,
|
|
bool aoEnabled, int aoLayerValue,
|
|
bool reflEnabled, int reflLayerValue,
|
|
bool giEnabled, int giLayerValue,
|
|
bool recursiveEnabled, int rrLayerValue,
|
|
bool pathTracingEnabled, int ptLayerValue)
|
|
{
|
|
// Get all the materials of the mesh renderer
|
|
currentRenderer.GetSharedMaterials(materialArray);
|
|
// If the array is null, we are done
|
|
if (materialArray == null) return AccelerationStructureStatus.NullMaterial;
|
|
|
|
// For every sub-mesh/sub-material let's build the right flags
|
|
int numSubMeshes = 1;
|
|
if (!(currentRenderer.GetType() == typeof(SkinnedMeshRenderer)))
|
|
{
|
|
currentRenderer.TryGetComponent(out MeshFilter meshFilter);
|
|
if (meshFilter == null || meshFilter.sharedMesh == null) return AccelerationStructureStatus.MissingMesh;
|
|
numSubMeshes = meshFilter.sharedMesh.subMeshCount;
|
|
}
|
|
else
|
|
{
|
|
SkinnedMeshRenderer skinnedMesh = (SkinnedMeshRenderer)currentRenderer;
|
|
if (skinnedMesh.sharedMesh == null) return AccelerationStructureStatus.MissingMesh;
|
|
numSubMeshes = skinnedMesh.sharedMesh.subMeshCount;
|
|
}
|
|
|
|
// Let's clamp the number of sub-meshes to avoid throwing an unwated error
|
|
numSubMeshes = Mathf.Min(numSubMeshes, maxNumSubMeshes);
|
|
|
|
// Get the layer of this object
|
|
int objectLayerValue = 1 << currentRenderer.gameObject.layer;
|
|
|
|
// We need to build the instance flag for this renderer
|
|
uint instanceFlag = 0x00;
|
|
|
|
bool doubleSided = false;
|
|
bool materialIsOnlyTransparent = true;
|
|
bool hasTransparentSubMaterial = false;
|
|
|
|
// We disregard the ray traced shadows option when in Path Tracing
|
|
rayTracedShadow &= !pathTracingEnabled;
|
|
|
|
// Deactivate Path Tracing if the object does not belong to the path traced layer(s)
|
|
pathTracingEnabled &= (bool)((ptLayerValue & objectLayerValue) != 0);
|
|
|
|
for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx)
|
|
{
|
|
// Initially we consider the potential mesh as invalid
|
|
bool validMesh = false;
|
|
if (materialArray.Count > meshIdx)
|
|
{
|
|
// Grab the material for the current sub-mesh
|
|
Material currentMaterial = materialArray[meshIdx];
|
|
|
|
// Make sure that the material is HDRP's and non-decal
|
|
if (IsValidRayTracedMaterial(currentMaterial))
|
|
{
|
|
// Mesh is valid given that all requirements are ok
|
|
validMesh = true;
|
|
subMeshFlagArray[meshIdx] = true;
|
|
|
|
// Is the sub material transparent?
|
|
subMeshTransparentArray[meshIdx] = currentMaterial.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT")
|
|
|| (HDRenderQueue.k_RenderQueue_Transparent.lowerBound <= currentMaterial.renderQueue
|
|
&& HDRenderQueue.k_RenderQueue_Transparent.upperBound >= currentMaterial.renderQueue);
|
|
|
|
// Aggregate the transparency info
|
|
materialIsOnlyTransparent &= subMeshTransparentArray[meshIdx];
|
|
hasTransparentSubMaterial |= subMeshTransparentArray[meshIdx];
|
|
|
|
// Is the material alpha tested?
|
|
subMeshCutoffArray[meshIdx] = currentMaterial.IsKeywordEnabled("_ALPHATEST_ON")
|
|
|| (HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.lowerBound <= currentMaterial.renderQueue
|
|
&& HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.upperBound >= currentMaterial.renderQueue);
|
|
|
|
// Check if we want to enable double-sidedness for the mesh
|
|
// (note that a mix of single and double-sided materials will result in a double-sided mesh in the AS)
|
|
doubleSided |= currentMaterial.doubleSidedGI || currentMaterial.IsKeywordEnabled("_DOUBLESIDED_ON");
|
|
|
|
// Check if the material has changed since last time we were here
|
|
if (!m_MaterialsDirty)
|
|
{
|
|
int matId = currentMaterial.GetInstanceID();
|
|
int matPrevCRC, matCurCRC = currentMaterial.ComputeCRC();
|
|
if (m_MaterialCRCs.TryGetValue(matId, out matPrevCRC))
|
|
{
|
|
m_MaterialCRCs[matId] = matCurCRC;
|
|
m_MaterialsDirty |= (matCurCRC != matPrevCRC);
|
|
}
|
|
else
|
|
{
|
|
m_MaterialCRCs.Add(matId, matCurCRC);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the mesh was not valid, exclude it (without affecting sidedness)
|
|
if (!validMesh)
|
|
{
|
|
subMeshFlagArray[meshIdx] = false;
|
|
subMeshCutoffArray[meshIdx] = false;
|
|
}
|
|
}
|
|
|
|
// If the material is considered opaque, but has some transparent sub-materials
|
|
if (!materialIsOnlyTransparent && hasTransparentSubMaterial)
|
|
{
|
|
for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx)
|
|
{
|
|
subMeshCutoffArray[meshIdx] = subMeshTransparentArray[meshIdx] ? true : subMeshCutoffArray[meshIdx];
|
|
}
|
|
}
|
|
|
|
// Propagate the opacity mask only if all sub materials are opaque
|
|
bool isOpaque = !hasTransparentSubMaterial;
|
|
if (isOpaque)
|
|
{
|
|
instanceFlag |= (uint)(RayTracingRendererFlag.Opaque);
|
|
}
|
|
|
|
if (rayTracedShadow || pathTracingEnabled)
|
|
{
|
|
if (hasTransparentSubMaterial)
|
|
{
|
|
// Raise the shadow casting flag if needed
|
|
instanceFlag |= ((currentRenderer.shadowCastingMode != ShadowCastingMode.Off) ? (uint)(RayTracingRendererFlag.CastShadowTransparent) : 0x00);
|
|
}
|
|
else
|
|
{
|
|
// Raise the shadow casting flag if needed
|
|
instanceFlag |= ((currentRenderer.shadowCastingMode != ShadowCastingMode.Off) ? (uint)(RayTracingRendererFlag.CastShadowOpaque) : 0x00);
|
|
}
|
|
}
|
|
|
|
// We consider a mesh visible by reflection, gi, etc if it is not in the shadow only mode.
|
|
bool meshIsVisible = currentRenderer.shadowCastingMode != ShadowCastingMode.ShadowsOnly;
|
|
|
|
if (aoEnabled && !materialIsOnlyTransparent && meshIsVisible)
|
|
{
|
|
// Raise the Ambient Occlusion flag if needed
|
|
instanceFlag |= ((aoLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.AmbientOcclusion) : 0x00;
|
|
}
|
|
|
|
if (reflEnabled && !materialIsOnlyTransparent && meshIsVisible)
|
|
{
|
|
// Raise the Screen Space Reflection flag if needed
|
|
instanceFlag |= ((reflLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.Reflection) : 0x00;
|
|
}
|
|
|
|
if (giEnabled && !materialIsOnlyTransparent && meshIsVisible)
|
|
{
|
|
// Raise the Global Illumination flag if needed
|
|
instanceFlag |= ((giLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.GlobalIllumination) : 0x00;
|
|
}
|
|
|
|
if (recursiveEnabled && meshIsVisible)
|
|
{
|
|
// Raise the Recursive Rendering flag if needed
|
|
instanceFlag |= ((rrLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.RecursiveRendering) : 0x00;
|
|
}
|
|
|
|
if (pathTracingEnabled && meshIsVisible)
|
|
{
|
|
// Raise the Path Tracing flag if needed
|
|
instanceFlag |= (uint)(RayTracingRendererFlag.PathTracing);
|
|
}
|
|
|
|
// If the object was not referenced
|
|
if (instanceFlag == 0) return AccelerationStructureStatus.Added;
|
|
|
|
// Add it to the acceleration structure
|
|
m_CurrentRAS.AddInstance(currentRenderer, subMeshMask: subMeshFlagArray, subMeshTransparencyFlags: subMeshCutoffArray, enableTriangleCulling: !doubleSided, mask: instanceFlag);
|
|
|
|
// Indicates that a transform has changed in our scene (mesh or light)
|
|
m_TransformDirty |= currentRenderer.transform.hasChanged;
|
|
currentRenderer.transform.hasChanged = false;
|
|
|
|
// return the status
|
|
return (!materialIsOnlyTransparent && hasTransparentSubMaterial) ? AccelerationStructureStatus.TransparencyIssue : AccelerationStructureStatus.Added;
|
|
}
|
|
|
|
internal void BuildRayTracingAccelerationStructure(HDCamera hdCamera)
|
|
{
|
|
// Clear all the per frame-data
|
|
m_RayTracingRendererReference.Clear();
|
|
m_RayTracingLights.hdDirectionalLightArray.Clear();
|
|
m_RayTracingLights.hdPointLightArray.Clear();
|
|
m_RayTracingLights.hdLineLightArray.Clear();
|
|
m_RayTracingLights.hdRectLightArray.Clear();
|
|
m_RayTracingLights.hdLightArray.Clear();
|
|
m_RayTracingLights.reflectionProbeArray.Clear();
|
|
m_RayTracingLights.lightCount = 0;
|
|
m_CurrentRAS.Dispose();
|
|
m_CurrentRAS = new RayTracingAccelerationStructure();
|
|
m_ValidRayTracingState = false;
|
|
m_ValidRayTracingCluster = false;
|
|
m_ValidRayTracingClusterCulling = false;
|
|
m_RayTracedShadowsRequired = false;
|
|
m_RayTracedContactShadowsRequired = false;
|
|
|
|
// If the camera does not have a ray tracing frame setting or it is a preview camera (due to the fact that the sphere does not exist as a game object we can't create the RTAS) we do not want to build a RTAS
|
|
if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing))
|
|
return;
|
|
|
|
// We only support ray traced shadows if the camera supports ray traced shadows
|
|
bool screenSpaceShadowsSupported = hdCamera.frameSettings.IsEnabled(FrameSettingsField.ScreenSpaceShadows);
|
|
|
|
// fetch all the lights in the scene
|
|
HDAdditionalLightData[] hdLightArray = UnityEngine.GameObject.FindObjectsOfType<HDAdditionalLightData>();
|
|
|
|
for (int lightIdx = 0; lightIdx < hdLightArray.Length; ++lightIdx)
|
|
{
|
|
HDAdditionalLightData hdLight = hdLightArray[lightIdx];
|
|
if (hdLight.enabled)
|
|
{
|
|
// Check if there is a ray traced shadow in the scene
|
|
m_RayTracedShadowsRequired |= (hdLight.useRayTracedShadows && screenSpaceShadowsSupported);
|
|
m_RayTracedContactShadowsRequired |= (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow);
|
|
|
|
// Indicates that a transform has changed in our scene (mesh or light)
|
|
m_TransformDirty |= hdLight.transform.hasChanged;
|
|
hdLight.transform.hasChanged = false;
|
|
|
|
switch (hdLight.type)
|
|
{
|
|
case HDLightType.Directional:
|
|
m_RayTracingLights.hdDirectionalLightArray.Add(hdLight);
|
|
break;
|
|
case HDLightType.Point:
|
|
case HDLightType.Spot:
|
|
m_RayTracingLights.hdPointLightArray.Add(hdLight);
|
|
break;
|
|
case HDLightType.Area:
|
|
switch (hdLight.areaLightShape)
|
|
{
|
|
case AreaLightShape.Rectangle:
|
|
m_RayTracingLights.hdRectLightArray.Add(hdLight);
|
|
break;
|
|
case AreaLightShape.Tube:
|
|
m_RayTracingLights.hdLineLightArray.Add(hdLight);
|
|
break;
|
|
//TODO: case AreaLightShape.Disc:
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Aggregate the shadow requirement
|
|
bool rayTracedShadows = m_RayTracedShadowsRequired || m_RayTracedContactShadowsRequired;
|
|
|
|
m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdPointLightArray);
|
|
m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdLineLightArray);
|
|
m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdRectLightArray);
|
|
|
|
HDAdditionalReflectionData[] reflectionProbeArray = UnityEngine.GameObject.FindObjectsOfType<HDAdditionalReflectionData>();
|
|
for (int reflIdx = 0; reflIdx < reflectionProbeArray.Length; ++reflIdx)
|
|
{
|
|
HDAdditionalReflectionData reflectionProbe = reflectionProbeArray[reflIdx];
|
|
// Add it to the list if enabled
|
|
if (reflectionProbe.enabled)
|
|
{
|
|
m_RayTracingLights.reflectionProbeArray.Add(reflectionProbe);
|
|
}
|
|
}
|
|
|
|
m_RayTracingLights.lightCount = m_RayTracingLights.hdPointLightArray.Count
|
|
+ m_RayTracingLights.hdLineLightArray.Count
|
|
+ m_RayTracingLights.hdRectLightArray.Count
|
|
+ m_RayTracingLights.reflectionProbeArray.Count;
|
|
|
|
AmbientOcclusion aoSettings = hdCamera.volumeStack.GetComponent<AmbientOcclusion>();
|
|
bool rtAOEnabled = aoSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSAO);
|
|
ScreenSpaceReflection reflSettings = hdCamera.volumeStack.GetComponent<ScreenSpaceReflection>();
|
|
bool rtREnabled = reflSettings.enabled.value && reflSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSR);
|
|
GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent<GlobalIllumination>();
|
|
bool rtGIEnabled = giSettings.enable.value && giSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSGI);
|
|
RecursiveRendering recursiveSettings = hdCamera.volumeStack.GetComponent<RecursiveRendering>();
|
|
bool rrEnabled = recursiveSettings.enable.value;
|
|
SubSurfaceScattering sssSettings = hdCamera.volumeStack.GetComponent<SubSurfaceScattering>();
|
|
bool rtSSSEnabled = sssSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SubsurfaceScattering);
|
|
PathTracing pathTracingSettings = hdCamera.volumeStack.GetComponent<PathTracing>();
|
|
bool ptEnabled = pathTracingSettings.enable.value;
|
|
|
|
// We need to check if we should be building the ray tracing acceleration structure (if required by any effect)
|
|
bool rayTracingRequired = rtAOEnabled || rtREnabled || rtGIEnabled || rrEnabled || rtSSSEnabled || ptEnabled || rayTracedShadows;
|
|
if (!rayTracingRequired)
|
|
return;
|
|
|
|
// We need to process the emissive meshes of the rectangular area lights
|
|
for (var i = 0; i < m_RayTracingLights.hdRectLightArray.Count; i++)
|
|
{
|
|
// Fetch the current renderer of the rectangular area light (if any)
|
|
MeshRenderer currentRenderer = m_RayTracingLights.hdRectLightArray[i].emissiveMeshRenderer;
|
|
|
|
// If there is none it means that there is no emissive mesh for this light
|
|
if (currentRenderer == null) continue;
|
|
|
|
// This objects should be included into the RAS
|
|
AddInstanceToRAS(currentRenderer,
|
|
rayTracedShadows,
|
|
rtAOEnabled, aoSettings.layerMask.value,
|
|
rtREnabled, reflSettings.layerMask.value,
|
|
rtGIEnabled, giSettings.layerMask.value,
|
|
rrEnabled, recursiveSettings.layerMask.value,
|
|
ptEnabled, pathTracingSettings.layerMask.value);
|
|
}
|
|
|
|
int matCount = m_MaterialCRCs.Count;
|
|
|
|
LODGroup[] lodGroupArray = UnityEngine.GameObject.FindObjectsOfType<LODGroup>();
|
|
for (var i = 0; i < lodGroupArray.Length; i++)
|
|
{
|
|
// Grab the current LOD group
|
|
LODGroup lodGroup = lodGroupArray[i];
|
|
|
|
// Get the set of LODs
|
|
LOD[] lodArray = lodGroup.GetLODs();
|
|
for (int lodIdx = 0; lodIdx < lodArray.Length; ++lodIdx)
|
|
{
|
|
LOD currentLOD = lodArray[lodIdx];
|
|
// We only want to push to the acceleration structure the lod0, we do not have defined way to select the right LOD at the moment
|
|
if (lodIdx == 0)
|
|
{
|
|
for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx)
|
|
{
|
|
// Fetch the renderer that we are interested in
|
|
Renderer currentRenderer = currentLOD.renderers[rendererIdx];
|
|
|
|
// This objects should but included into the RAS
|
|
AddInstanceToRAS(currentRenderer,
|
|
rayTracedShadows,
|
|
aoSettings.rayTracing.value, aoSettings.layerMask.value,
|
|
reflSettings.rayTracing.value, reflSettings.layerMask.value,
|
|
giSettings.rayTracing.value, giSettings.layerMask.value,
|
|
recursiveSettings.enable.value, recursiveSettings.layerMask.value,
|
|
pathTracingSettings.enable.value, pathTracingSettings.layerMask.value);
|
|
}
|
|
}
|
|
|
|
// Add them to the processed set so that they are not taken into account when processing all the renderers
|
|
for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx)
|
|
{
|
|
Renderer currentRenderer = currentLOD.renderers[rendererIdx];
|
|
if (currentRenderer == null) continue;
|
|
|
|
// Add this fella to the renderer list
|
|
// Unfortunately, we need to check that this renderer was not already pushed into the list (happens if the user uses the same mesh renderer
|
|
// for two LODs)
|
|
if (!m_RayTracingRendererReference.ContainsKey(currentRenderer.GetInstanceID()))
|
|
m_RayTracingRendererReference.Add(currentRenderer.GetInstanceID(), 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Grab all the renderers from the scene
|
|
var rendererArray = UnityEngine.GameObject.FindObjectsOfType<Renderer>();
|
|
for (var i = 0; i < rendererArray.Length; i++)
|
|
{
|
|
// Fetch the current renderer
|
|
Renderer currentRenderer = rendererArray[i];
|
|
|
|
// If it is not active skip it
|
|
if (currentRenderer.enabled == false) continue;
|
|
|
|
// Grab the current game object
|
|
GameObject gameObject = currentRenderer.gameObject;
|
|
|
|
// Has this object already been processed, just skip it
|
|
if (m_RayTracingRendererReference.ContainsKey(currentRenderer.GetInstanceID()))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Does this object have a reflection probe component? if yes we do not want to have it in the acceleration structure
|
|
if (gameObject.TryGetComponent<ReflectionProbe>(out reflectionProbe)) continue;
|
|
|
|
// This objects should be included into the RAS
|
|
AddInstanceToRAS(currentRenderer,
|
|
rayTracedShadows,
|
|
aoSettings.rayTracing.value, aoSettings.layerMask.value,
|
|
reflSettings.rayTracing.value, reflSettings.layerMask.value,
|
|
giSettings.rayTracing.value, giSettings.layerMask.value,
|
|
recursiveSettings.enable.value, recursiveSettings.layerMask.value,
|
|
pathTracingSettings.enable.value, pathTracingSettings.layerMask.value);
|
|
}
|
|
|
|
// Check if the amount of materials being tracked has changed
|
|
m_MaterialsDirty |= (matCount != m_MaterialCRCs.Count);
|
|
|
|
if (ShaderConfig.s_CameraRelativeRendering != 0)
|
|
m_CurrentRAS.Build(hdCamera.camera.transform.position);
|
|
else
|
|
m_CurrentRAS.Build();
|
|
|
|
// tag the structures as valid
|
|
m_ValidRayTracingState = true;
|
|
}
|
|
|
|
static internal bool ValidRayTracingHistory(HDCamera hdCamera)
|
|
{
|
|
return hdCamera.historyRTHandleProperties.previousViewportSize.x == hdCamera.actualWidth
|
|
&& hdCamera.historyRTHandleProperties.previousViewportSize.y == hdCamera.actualHeight;
|
|
}
|
|
|
|
internal int RayTracingFrameIndex(HDCamera hdCamera)
|
|
{
|
|
#if UNITY_HDRP_DXR_TESTS_DEFINE
|
|
if (Application.isPlaying)
|
|
return 0;
|
|
else
|
|
#endif
|
|
return (int)hdCamera.GetCameraFrameCount() % 8;
|
|
}
|
|
|
|
internal int RayTracingFrameIndex(HDCamera hdCamera, int targetFrameCount = 8)
|
|
{
|
|
#if UNITY_HDRP_DXR_TESTS_DEFINE
|
|
if (Application.isPlaying)
|
|
return 0;
|
|
else
|
|
#endif
|
|
return (int)hdCamera.GetCameraFrameCount() % targetFrameCount;
|
|
}
|
|
|
|
internal bool RayTracingLightClusterRequired(HDCamera hdCamera)
|
|
{
|
|
ScreenSpaceReflection reflSettings = hdCamera.volumeStack.GetComponent<ScreenSpaceReflection>();
|
|
GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent<GlobalIllumination>();
|
|
RecursiveRendering recursiveSettings = hdCamera.volumeStack.GetComponent<RecursiveRendering>();
|
|
PathTracing pathTracingSettings = hdCamera.volumeStack.GetComponent<PathTracing>();
|
|
SubSurfaceScattering subSurface = hdCamera.volumeStack.GetComponent<SubSurfaceScattering>();
|
|
|
|
return (m_ValidRayTracingState && (reflSettings.rayTracing.value
|
|
|| giSettings.rayTracing.value
|
|
|| recursiveSettings.enable.value
|
|
|| pathTracingSettings.enable.value
|
|
|| subSurface.rayTracing.value));
|
|
}
|
|
|
|
internal void CullForRayTracing(CommandBuffer cmd, HDCamera hdCamera)
|
|
{
|
|
if (m_ValidRayTracingState && RayTracingLightClusterRequired(hdCamera))
|
|
{
|
|
m_RayTracingLightCluster.CullForRayTracing(hdCamera, m_RayTracingLights);
|
|
m_ValidRayTracingClusterCulling = true;
|
|
}
|
|
}
|
|
|
|
internal void ReserveRayTracingCookieAtlasSlots()
|
|
{
|
|
if (m_ValidRayTracingState && m_ValidRayTracingClusterCulling)
|
|
{
|
|
m_RayTracingLightCluster.ReserveCookieAtlasSlots(m_RayTracingLights);
|
|
}
|
|
}
|
|
|
|
internal void BuildRayTracingLightData(CommandBuffer cmd, HDCamera hdCamera, DebugDisplaySettings debugDisplaySettings)
|
|
{
|
|
if (m_ValidRayTracingState && m_ValidRayTracingClusterCulling)
|
|
{
|
|
m_RayTracingLightCluster.BuildRayTracingLightData(cmd, hdCamera, m_RayTracingLights, debugDisplaySettings);
|
|
m_ValidRayTracingCluster = true;
|
|
|
|
UpdateShaderVariablesRaytracingLightLoopCB(hdCamera, cmd);
|
|
|
|
m_RayTracingLightCluster.BuildLightClusterBuffer(cmd, hdCamera, m_RayTracingLights);
|
|
}
|
|
}
|
|
|
|
static internal float EvaluateHistoryValidity(HDCamera hdCamera)
|
|
{
|
|
float historyValidity = 1.0f;
|
|
#if UNITY_HDRP_DXR_TESTS_DEFINE
|
|
if (Application.isPlaying)
|
|
historyValidity = 0.0f;
|
|
else
|
|
#endif
|
|
// We need to check if something invalidated the history buffers
|
|
historyValidity *= ValidRayTracingHistory(hdCamera) ? 1.0f : 0.0f;
|
|
return historyValidity;
|
|
}
|
|
|
|
void UpdateShaderVariablesRaytracingLightLoopCB(HDCamera hdCamera, CommandBuffer cmd)
|
|
{
|
|
m_ShaderVariablesRaytracingLightLoopCB._MinClusterPos = m_RayTracingLightCluster.GetMinClusterPos();
|
|
m_ShaderVariablesRaytracingLightLoopCB._LightPerCellCount = (uint)m_RayTracingLightCluster.GetLightPerCellCount();
|
|
m_ShaderVariablesRaytracingLightLoopCB._MaxClusterPos = m_RayTracingLightCluster.GetMaxClusterPos();
|
|
m_ShaderVariablesRaytracingLightLoopCB._PunctualLightCountRT = (uint)m_RayTracingLightCluster.GetPunctualLightCount();
|
|
m_ShaderVariablesRaytracingLightLoopCB._AreaLightCountRT = (uint)m_RayTracingLightCluster.GetAreaLightCount();
|
|
m_ShaderVariablesRaytracingLightLoopCB._EnvLightCountRT = (uint)m_RayTracingLightCluster.GetEnvLightCount();
|
|
|
|
ConstantBuffer.PushGlobal(cmd, m_ShaderVariablesRaytracingLightLoopCB, HDShaderIDs._ShaderVariablesRaytracingLightLoop);
|
|
}
|
|
|
|
internal bool RayTracedContactShadowsRequired()
|
|
{
|
|
return m_RayTracedContactShadowsRequired;
|
|
}
|
|
|
|
internal RayTracingAccelerationStructure RequestAccelerationStructure()
|
|
{
|
|
if (m_ValidRayTracingState)
|
|
{
|
|
return m_CurrentRAS;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal HDRaytracingLightCluster RequestLightCluster()
|
|
{
|
|
if (m_ValidRayTracingCluster)
|
|
{
|
|
return m_RayTracingLightCluster;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Ray Tracing is supported if the asset setting supports it and the platform supports it
|
|
static internal bool GatherRayTracingSupport(RenderPipelineSettings rpSetting)
|
|
=> rpSetting.supportRayTracing && rayTracingSupportedBySystem;
|
|
|
|
static internal bool rayTracingSupportedBySystem
|
|
=> UnityEngine.SystemInfo.supportsRayTracing
|
|
#if UNITY_EDITOR
|
|
&& (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.StandaloneWindows64
|
|
|| UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.StandaloneWindows)
|
|
#endif
|
|
;
|
|
|
|
internal BlueNoise GetBlueNoiseManager()
|
|
{
|
|
return m_BlueNoise;
|
|
}
|
|
|
|
internal HDTemporalFilter GetTemporalFilter()
|
|
{
|
|
if (m_TemporalFilter == null && m_RayTracingSupported)
|
|
{
|
|
m_TemporalFilter = new HDTemporalFilter();
|
|
m_TemporalFilter.Init(m_Asset.renderPipelineRayTracingResources);
|
|
}
|
|
return m_TemporalFilter;
|
|
}
|
|
|
|
internal HDSimpleDenoiser GetSimpleDenoiser()
|
|
{
|
|
if (m_SimpleDenoiser == null)
|
|
{
|
|
m_SimpleDenoiser = new HDSimpleDenoiser();
|
|
m_SimpleDenoiser.Init(m_Asset.renderPipelineRayTracingResources);
|
|
}
|
|
return m_SimpleDenoiser;
|
|
}
|
|
|
|
internal SSGIDenoiser GetSSGIDenoiser()
|
|
{
|
|
if (m_SSGIDenoiser == null)
|
|
{
|
|
m_SSGIDenoiser = new SSGIDenoiser();
|
|
m_SSGIDenoiser.Init(m_Asset.renderPipelineResources);
|
|
}
|
|
return m_SSGIDenoiser;
|
|
}
|
|
|
|
internal HDDiffuseDenoiser GetDiffuseDenoiser()
|
|
{
|
|
if (m_DiffuseDenoiser == null)
|
|
{
|
|
m_DiffuseDenoiser = new HDDiffuseDenoiser();
|
|
m_DiffuseDenoiser.Init(m_Asset.renderPipelineResources, m_Asset.renderPipelineRayTracingResources, this);
|
|
}
|
|
return m_DiffuseDenoiser;
|
|
}
|
|
|
|
internal HDReflectionDenoiser GetReflectionDenoiser()
|
|
{
|
|
if (m_ReflectionDenoiser == null)
|
|
{
|
|
m_ReflectionDenoiser = new HDReflectionDenoiser();
|
|
m_ReflectionDenoiser.Init(m_Asset.renderPipelineRayTracingResources);
|
|
}
|
|
return m_ReflectionDenoiser;
|
|
}
|
|
|
|
internal HDDiffuseShadowDenoiser GetDiffuseShadowDenoiser()
|
|
{
|
|
if (m_DiffuseShadowDenoiser == null)
|
|
{
|
|
m_DiffuseShadowDenoiser = new HDDiffuseShadowDenoiser();
|
|
m_DiffuseShadowDenoiser.Init(m_Asset.renderPipelineRayTracingResources);
|
|
}
|
|
return m_DiffuseShadowDenoiser;
|
|
}
|
|
|
|
internal bool GetRayTracingState()
|
|
{
|
|
return m_ValidRayTracingState;
|
|
}
|
|
|
|
internal bool GetRayTracingClusterState()
|
|
{
|
|
return m_ValidRayTracingCluster;
|
|
}
|
|
|
|
static internal float GetPixelSpreadTangent(float fov, int width, int height)
|
|
{
|
|
return Mathf.Tan(fov * Mathf.Deg2Rad * 0.5f) * 2.0f / Mathf.Min(width, height);
|
|
}
|
|
|
|
static internal float GetPixelSpreadAngle(float fov, int width, int height)
|
|
{
|
|
return Mathf.Atan(GetPixelSpreadTangent(fov, width, height));
|
|
}
|
|
|
|
internal TextureHandle EvaluateHistoryValidationBuffer(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVectorsBuffer)
|
|
{
|
|
// Grab the temporal filter
|
|
HDTemporalFilter temporalFilter = GetTemporalFilter();
|
|
|
|
// If the temporal filter is valid use it, otherwise return a white texture
|
|
if (temporalFilter != null)
|
|
{
|
|
float historyValidity = EvaluateHistoryValidity(hdCamera);
|
|
HistoryValidityParameters parameters = temporalFilter.PrepareHistoryValidityParameters(hdCamera, historyValidity);
|
|
return temporalFilter.HistoryValidity(renderGraph, hdCamera, parameters, depthBuffer, normalBuffer, motionVectorsBuffer);
|
|
}
|
|
else
|
|
return renderGraph.defaultResources.whiteTexture;
|
|
}
|
|
}
|
|
}
|