You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1002 lines
46 KiB
1002 lines
46 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering.RenderGraphModule;
|
|
using UnityEngine.VFX;
|
|
|
|
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,
|
|
All = Opaque | CastShadow | AmbientOcclusion | Reflection | GlobalIllumination | RecursiveRendering | PathTracing,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flags returned when trying to add a renderer into the ray tracing acceleration structure.
|
|
/// </summary>
|
|
public enum AccelerationStructureStatus
|
|
{
|
|
/// <summary>Initial flag state.</summary>
|
|
Clear = 0x0,
|
|
/// <summary>Flag that indicates that the renderer was successfully added to the ray tracing acceleration structure.</summary>
|
|
Added = 0x1,
|
|
/// <summary>Flag that indicates that the renderer was excluded from the ray tracing acceleration structure.</summary>
|
|
Excluded = 0x02,
|
|
/// <summary>Flag that indicates that the renderer was added to the ray tracing acceleration structure, but it had transparent and opaque sub-meshes.</summary>
|
|
TransparencyIssue = 0x04,
|
|
/// <summary>Flag that indicates that the renderer was not included into the ray tracing acceleration structure because of a missing material</summary>
|
|
NullMaterial = 0x08,
|
|
/// <summary>Flag that indicates that the renderer was not included into the ray tracing acceleration structure because of a missing mesh</summary>
|
|
MissingMesh = 0x10
|
|
}
|
|
|
|
public partial class HDRenderPipeline
|
|
{
|
|
// Data used for runtime evaluation
|
|
static readonly string m_RTASDebugRTKernel = "RTASDebug";
|
|
HDRTASManager m_RTASManager;
|
|
HDRaytracingLightCluster m_RayTracingLightCluster;
|
|
bool m_ValidRayTracingState = false;
|
|
bool m_ValidRayTracingCluster = false;
|
|
bool m_ValidRayTracingClusterCulling = false;
|
|
bool m_RayTracedShadowsRequired = false;
|
|
bool m_RayTracedContactShadowsRequired = false;
|
|
|
|
// Denoisers
|
|
HDTemporalFilter m_TemporalFilter;
|
|
HDDiffuseDenoiser m_DiffuseDenoiser;
|
|
HDDiffuseShadowDenoiser m_DiffuseShadowDenoiser;
|
|
ReBlurDenoiser m_ReBlurDenoiser;
|
|
|
|
// Ray-count manager data
|
|
RayCountManager m_RayCountManager;
|
|
|
|
// Static variables used for the dirtiness and manual rtas management
|
|
const int maxNumSubMeshes = 32;
|
|
static RayTracingSubMeshFlags[] subMeshFlagArray = new RayTracingSubMeshFlags[maxNumSubMeshes];
|
|
static uint[] vfxSystemMasks = new uint[maxNumSubMeshes];
|
|
static List<Material> materialArray = new List<Material>(maxNumSubMeshes);
|
|
static Dictionary<int, int> m_MaterialCRCs = new Dictionary<int, int>();
|
|
|
|
// Global shader variables ray tracing lightloop constant buffer
|
|
ShaderVariablesRaytracingLightLoop m_ShaderVariablesRaytracingLightLoopCB = new ShaderVariablesRaytracingLightLoop();
|
|
|
|
internal bool GetMaterialDirtiness(HDCamera hdCamera)
|
|
{
|
|
RayTracingSettings rtSettings = hdCamera.volumeStack.GetComponent<RayTracingSettings>();
|
|
#if UNITY_EDITOR
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic || hdCamera.camera.cameraType == CameraType.SceneView)
|
|
#else
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic)
|
|
#endif
|
|
{
|
|
return m_RTASManager.materialsDirty;
|
|
}
|
|
else
|
|
{
|
|
return hdCamera.materialsDirty;
|
|
}
|
|
}
|
|
|
|
internal void ResetMaterialDirtiness(HDCamera hdCamera)
|
|
{
|
|
RayTracingSettings rtSettings = hdCamera.volumeStack.GetComponent<RayTracingSettings>();
|
|
#if UNITY_EDITOR
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic || hdCamera.camera.cameraType == CameraType.SceneView)
|
|
#else
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic)
|
|
#endif
|
|
{
|
|
m_RTASManager.materialsDirty = false;
|
|
}
|
|
else
|
|
{
|
|
hdCamera.materialsDirty = false;
|
|
}
|
|
}
|
|
|
|
internal bool GetTransformDirtiness(HDCamera hdCamera)
|
|
{
|
|
RayTracingSettings rtSettings = hdCamera.volumeStack.GetComponent<RayTracingSettings>();
|
|
#if UNITY_EDITOR
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic || hdCamera.camera.cameraType == CameraType.SceneView)
|
|
#else
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic)
|
|
#endif
|
|
{
|
|
return m_RTASManager.transformsDirty;
|
|
}
|
|
else
|
|
{
|
|
return hdCamera.transformsDirty;
|
|
}
|
|
}
|
|
|
|
internal void ResetTransformDirtiness(HDCamera hdCamera)
|
|
{
|
|
RayTracingSettings rtSettings = hdCamera.volumeStack.GetComponent<RayTracingSettings>();
|
|
#if UNITY_EDITOR
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic || hdCamera.camera.cameraType == CameraType.SceneView)
|
|
#else
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic)
|
|
#endif
|
|
{
|
|
m_RTASManager.transformsDirty = false;
|
|
}
|
|
else
|
|
{
|
|
hdCamera.transformsDirty = false;
|
|
}
|
|
}
|
|
|
|
internal void InitRayTracingManager()
|
|
{
|
|
// Init the ray count manager
|
|
m_RayCountManager = new RayCountManager();
|
|
m_RayCountManager.Init(rayTracingResources);
|
|
|
|
// Initialize the light cluster
|
|
m_RayTracingLightCluster = new HDRaytracingLightCluster();
|
|
m_RayTracingLightCluster.Initialize(this);
|
|
|
|
// Initialize the RTAS manager
|
|
m_RTASManager = new HDRTASManager();
|
|
m_RTASManager.Initialize();
|
|
}
|
|
|
|
internal void ReleaseRayTracingManager()
|
|
{
|
|
if (m_RTASManager != null)
|
|
m_RTASManager.ReleaseResources();
|
|
|
|
if (m_RayTracingLightCluster != null)
|
|
m_RayTracingLightCluster.ReleaseResources();
|
|
if (m_RayCountManager != null)
|
|
m_RayCountManager.Release();
|
|
|
|
if (m_TemporalFilter != null)
|
|
m_TemporalFilter.Release();
|
|
if (m_DiffuseShadowDenoiser != null)
|
|
m_DiffuseShadowDenoiser.Release();
|
|
if (m_DiffuseDenoiser != null)
|
|
m_DiffuseDenoiser.Release();
|
|
if (m_ReBlurDenoiser != null)
|
|
{
|
|
m_ReBlurDenoiser.Release();
|
|
m_ReBlurDenoiser = null;
|
|
}
|
|
}
|
|
|
|
static bool IsValidRayTracedMaterial(Material currentMaterial)
|
|
{
|
|
if (currentMaterial == null || currentMaterial.shader == null)
|
|
return false;
|
|
|
|
// For the time being, we only consider non-decal HDRP materials as valid
|
|
return currentMaterial.GetTag("RenderPipeline", false) == "HDRenderPipeline" && !DecalSystem.IsDecalMaterial(currentMaterial);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
private static bool UpdateMaterialCRC(int matInstanceId, int matCRC)
|
|
{
|
|
int matPrevCRC;
|
|
if (m_MaterialCRCs.TryGetValue(matInstanceId, out matPrevCRC))
|
|
{
|
|
m_MaterialCRCs[matInstanceId] = matCRC;
|
|
return (matCRC != matPrevCRC);
|
|
}
|
|
else
|
|
{
|
|
m_MaterialCRCs.Add(matInstanceId, matCRC);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Function that adds a renderer to a ray tracing acceleration structure.
|
|
/// </summary>
|
|
/// <param name="targetRTAS">Ray Tracing Acceleration structure the renderer should be added to.</param>
|
|
/// <param name="currentRenderer">The renderer that should be added to the RTAS.</param>
|
|
/// <param name="effectsParameters">Structure defining the enabled ray tracing and path tracing effects for a camera.</param>
|
|
/// <param name="transformDirty">Flag that indicates if the renderer's transform has changed.</param>
|
|
/// <param name="materialsDirty">Flag that indicates if any of the renderer's materials have changed.</param>
|
|
/// <returns></returns>
|
|
public static AccelerationStructureStatus AddInstanceToRAS(RayTracingAccelerationStructure targetRTAS, Renderer currentRenderer, HDEffectsParameters effectsParameters, ref bool transformDirty, ref bool materialsDirty)
|
|
{
|
|
if (currentRenderer is VFXRenderer vfxRenderer)
|
|
return AddVFXInstanceToRAS(targetRTAS, vfxRenderer, effectsParameters, ref transformDirty, ref materialsDirty);
|
|
return AddRegularInstanceToRAS(targetRTAS, currentRenderer, effectsParameters, ref transformDirty, ref materialsDirty);
|
|
}
|
|
|
|
private static AccelerationStructureStatus AddRegularInstanceToRAS(RayTracingAccelerationStructure targetRTAS,
|
|
Renderer currentRenderer, HDEffectsParameters effectsParameters, ref bool transformDirty, ref bool materialsDirty)
|
|
{
|
|
// For every sub-mesh/sub-material let's build the right flags
|
|
int numSubMeshes = 1;
|
|
if (currentRenderer.GetType() == typeof(SkinnedMeshRenderer))
|
|
{
|
|
SkinnedMeshRenderer skinnedMesh = (SkinnedMeshRenderer)currentRenderer;
|
|
if (skinnedMesh.sharedMesh == null) return AccelerationStructureStatus.MissingMesh;
|
|
currentRenderer.GetSharedMaterials(materialArray);
|
|
numSubMeshes = skinnedMesh.sharedMesh.subMeshCount;
|
|
}
|
|
else
|
|
{
|
|
currentRenderer.TryGetComponent(out MeshFilter meshFilter);
|
|
if (meshFilter == null || meshFilter.sharedMesh == null) return AccelerationStructureStatus.MissingMesh;
|
|
currentRenderer.GetSharedMaterials(materialArray);
|
|
numSubMeshes = meshFilter.sharedMesh.subMeshCount;
|
|
}
|
|
|
|
// If the material array is null, we are done
|
|
if (materialArray == null) return AccelerationStructureStatus.NullMaterial;
|
|
|
|
// Let's clamp the number of sub-meshes to avoid throwing an unwanted error
|
|
numSubMeshes = Mathf.Min(numSubMeshes, maxNumSubMeshes);
|
|
|
|
bool doubleSided = false;
|
|
bool materialIsOnlyTransparent = true;
|
|
bool hasTransparentSubMaterial = false;
|
|
for (int subGeomIdx = 0; subGeomIdx < numSubMeshes; ++subGeomIdx)
|
|
{
|
|
// Initially we consider the potential mesh as invalid
|
|
bool validMesh = false;
|
|
if (materialArray.Count > subGeomIdx)
|
|
{
|
|
// Grab the material for the current sub-mesh
|
|
Material currentMaterial = materialArray[subGeomIdx];
|
|
|
|
// 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;
|
|
|
|
// Evaluate what kind of materials we are dealing with
|
|
bool alphaTested = IsAlphaTestedMaterial(currentMaterial);
|
|
bool transparentMaterial = IsTransparentMaterial(currentMaterial);
|
|
|
|
// Aggregate the transparency info
|
|
materialIsOnlyTransparent &= transparentMaterial;
|
|
hasTransparentSubMaterial |= transparentMaterial;
|
|
|
|
ComputeSubMeshFlag(subGeomIdx, transparentMaterial, alphaTested, currentMaterial, ref doubleSided);
|
|
|
|
// Check if the material has changed since last time we were here
|
|
if (!materialsDirty)
|
|
{
|
|
materialsDirty |= UpdateMaterialCRC(currentMaterial.GetInstanceID(), currentMaterial.ComputeCRC());
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the mesh was not valid, exclude it (without affecting sidedness)
|
|
if (!validMesh)
|
|
subMeshFlagArray[subGeomIdx] = RayTracingSubMeshFlags.Disabled;
|
|
}
|
|
|
|
// If the material is considered opaque, every sub-mesh has to be enabled and with unique any hit calls
|
|
if (!materialIsOnlyTransparent && hasTransparentSubMaterial)
|
|
for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx)
|
|
subMeshFlagArray[meshIdx] = RayTracingSubMeshFlags.Enabled | RayTracingSubMeshFlags.UniqueAnyHitCalls;
|
|
|
|
// We need to build the instance flag for this renderer
|
|
uint instanceFlag = ComputeInstanceFlag(currentRenderer, currentRenderer.shadowCastingMode, effectsParameters,
|
|
hasTransparentSubMaterial, materialIsOnlyTransparent);
|
|
|
|
// If the object was not referenced
|
|
if (instanceFlag == 0) return AccelerationStructureStatus.Added;
|
|
|
|
targetRTAS.AddInstance(currentRenderer, subMeshFlags: subMeshFlagArray, enableTriangleCulling: !doubleSided,
|
|
mask: instanceFlag);
|
|
|
|
// Indicates that a transform has changed in our scene (mesh or light)
|
|
transformDirty |= currentRenderer.transform.hasChanged;
|
|
currentRenderer.transform.hasChanged = false;
|
|
|
|
// return the status
|
|
return (!materialIsOnlyTransparent && hasTransparentSubMaterial)
|
|
? AccelerationStructureStatus.TransparencyIssue
|
|
: AccelerationStructureStatus.Added;
|
|
}
|
|
|
|
private static AccelerationStructureStatus AddVFXInstanceToRAS(RayTracingAccelerationStructure targetRTAS, VFXRenderer currentRenderer, HDEffectsParameters effectsParameters, ref bool transformDirty, ref bool materialsDirty)
|
|
{
|
|
|
|
// If we should exclude Visual effects, skip right now
|
|
if (!effectsParameters.includeVFX)
|
|
return AccelerationStructureStatus.Excluded;
|
|
|
|
currentRenderer.GetSharedMaterials(materialArray);
|
|
int numSubGeom = materialArray.Count;
|
|
|
|
// If the material array is null, we are done
|
|
if (materialArray == null) return AccelerationStructureStatus.NullMaterial;
|
|
|
|
// Let's clamp the number of sub-meshes to avoid throwing an unwanted error
|
|
numSubGeom = Mathf.Min(numSubGeom, maxNumSubMeshes);
|
|
|
|
bool materialIsOnlyTransparent = true;
|
|
bool hasTransparentSubMaterial = false;
|
|
int compactedSubGeomIndex = 0; // For VFX, we expect no holes in the system mask array
|
|
bool hasAnyValidInstance = false;
|
|
for (int subGeomIdx = 0; subGeomIdx < numSubGeom; ++subGeomIdx)
|
|
{
|
|
if (materialArray.Count > subGeomIdx)
|
|
{
|
|
// Grab the material for the current sub-mesh
|
|
Material currentMaterial = materialArray[subGeomIdx];
|
|
|
|
// Make sure that the material is HDRP's and non-decal
|
|
if (IsValidRayTracedMaterial(currentMaterial))
|
|
{
|
|
// Evaluate what kind of materials we are dealing with
|
|
bool transparentMaterial = IsTransparentMaterial(currentMaterial);
|
|
|
|
// Aggregate the transparency info
|
|
materialIsOnlyTransparent &= transparentMaterial;
|
|
hasTransparentSubMaterial |= transparentMaterial;
|
|
|
|
ShadowCastingMode shadowCastingMode = currentMaterial.FindPass("ShadowCaster") != -1 ? ShadowCastingMode.On : ShadowCastingMode.Off;
|
|
uint instanceFlag = ComputeInstanceFlag(currentRenderer, shadowCastingMode, effectsParameters, transparentMaterial, transparentMaterial);
|
|
hasAnyValidInstance |= (instanceFlag != 0);
|
|
vfxSystemMasks[compactedSubGeomIndex] = instanceFlag;
|
|
compactedSubGeomIndex++;
|
|
|
|
// Check if the material has changed since last time we were here
|
|
if (!materialsDirty)
|
|
{
|
|
materialsDirty |= UpdateMaterialCRC(currentMaterial.GetInstanceID(), currentMaterial.ComputeCRC());
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// If the object was not referenced
|
|
if (!hasAnyValidInstance) return AccelerationStructureStatus.Added;
|
|
|
|
// Add it to the acceleration structure
|
|
targetRTAS.AddVFXInstances(currentRenderer, vfxSystemMasks);
|
|
|
|
// Indicates that a transform has changed in our scene (mesh or light)
|
|
transformDirty |= currentRenderer.transform.hasChanged;
|
|
currentRenderer.transform.hasChanged = false;
|
|
|
|
// return the status
|
|
return (!materialIsOnlyTransparent && hasTransparentSubMaterial) ? AccelerationStructureStatus.TransparencyIssue : AccelerationStructureStatus.Added;
|
|
}
|
|
|
|
private static void ComputeSubMeshFlag(int meshIdx, bool transparentMaterial, bool alphaTested,
|
|
Material currentMaterial,
|
|
ref bool doubleSided)
|
|
{
|
|
// Mark the thing as valid
|
|
subMeshFlagArray[meshIdx] = RayTracingSubMeshFlags.Enabled;
|
|
|
|
// Append the additional flags depending on what kind of sub mesh this is
|
|
if (!transparentMaterial && !alphaTested)
|
|
subMeshFlagArray[meshIdx] |= RayTracingSubMeshFlags.ClosestHitOnly;
|
|
else if (transparentMaterial)
|
|
subMeshFlagArray[meshIdx] |= RayTracingSubMeshFlags.UniqueAnyHitCalls;
|
|
|
|
// 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");
|
|
}
|
|
|
|
private static uint ComputeInstanceFlag(Renderer currentRenderer, ShadowCastingMode shadowCastingMode, HDEffectsParameters effectsParameters,
|
|
bool hasTransparentSubMaterial, bool materialIsOnlyTransparent)
|
|
{
|
|
uint instanceFlag = 0x00;
|
|
|
|
// Get the layer of this object
|
|
int objectLayerValue = 1 << currentRenderer.gameObject.layer;
|
|
|
|
// We disregard the ray traced shadows option when in Path Tracing
|
|
bool rayTracedShadow = effectsParameters.shadows && !effectsParameters.pathTracing;
|
|
|
|
// Deactivate Path Tracing if the object does not belong to the path traced layer(s)
|
|
bool pathTracing = effectsParameters.pathTracing && (bool)((effectsParameters.ptLayerMask & objectLayerValue) != 0);
|
|
|
|
// Propagate the opacity mask only if all sub materials are opaque
|
|
bool isOpaque = !hasTransparentSubMaterial;
|
|
if (isOpaque)
|
|
{
|
|
instanceFlag |= (uint)(RayTracingRendererFlag.Opaque);
|
|
}
|
|
|
|
if (rayTracedShadow || pathTracing)
|
|
{
|
|
if (hasTransparentSubMaterial)
|
|
{
|
|
// Raise the shadow casting flag if needed
|
|
instanceFlag |= ((shadowCastingMode != ShadowCastingMode.Off)
|
|
? (uint)(RayTracingRendererFlag.CastShadowTransparent)
|
|
: 0x00);
|
|
}
|
|
else
|
|
{
|
|
// Raise the shadow casting flag if needed
|
|
instanceFlag |= ((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 = shadowCastingMode != ShadowCastingMode.ShadowsOnly;
|
|
|
|
if (effectsParameters.ambientOcclusion && !materialIsOnlyTransparent && meshIsVisible)
|
|
{
|
|
// Raise the Ambient Occlusion flag if needed
|
|
instanceFlag |= ((effectsParameters.aoLayerMask & objectLayerValue) != 0)
|
|
? (uint)(RayTracingRendererFlag.AmbientOcclusion)
|
|
: 0x00;
|
|
}
|
|
|
|
if (effectsParameters.reflections && !materialIsOnlyTransparent && meshIsVisible)
|
|
{
|
|
// Raise the Screen Space Reflection flag if needed
|
|
instanceFlag |= ((effectsParameters.reflLayerMask & objectLayerValue) != 0)
|
|
? (uint)(RayTracingRendererFlag.Reflection)
|
|
: 0x00;
|
|
}
|
|
|
|
if (effectsParameters.globalIllumination && !materialIsOnlyTransparent && meshIsVisible)
|
|
{
|
|
// Raise the Global Illumination flag if needed
|
|
instanceFlag |= ((effectsParameters.giLayerMask & objectLayerValue) != 0)
|
|
? (uint)(RayTracingRendererFlag.GlobalIllumination)
|
|
: 0x00;
|
|
}
|
|
|
|
if (effectsParameters.recursiveRendering && meshIsVisible)
|
|
{
|
|
// Raise the Recursive Rendering flag if needed
|
|
instanceFlag |= ((effectsParameters.recursiveLayerMask & objectLayerValue) != 0)
|
|
? (uint)(RayTracingRendererFlag.RecursiveRendering)
|
|
: 0x00;
|
|
}
|
|
|
|
if (effectsParameters.pathTracing && meshIsVisible)
|
|
{
|
|
// Raise the Path Tracing flag if needed
|
|
instanceFlag |= (uint)(RayTracingRendererFlag.PathTracing);
|
|
}
|
|
|
|
return instanceFlag;
|
|
}
|
|
|
|
void GatherLightInformationForRayTracing(HDCamera hdCamera, ref bool transformDirty)
|
|
{
|
|
// fetch all the lights in the scene
|
|
HDLightRenderDatabase lightEntities = HDLightRenderDatabase.instance;
|
|
for (int lightIdx = 0; lightIdx < lightEntities.lightCount; ++lightIdx)
|
|
{
|
|
HDLightRenderEntity lightRenderEntity = lightEntities.lightEntities[lightIdx];
|
|
HDAdditionalLightData hdLight = lightEntities.hdAdditionalLightData[lightIdx];
|
|
if (hdLight != null && hdLight.enabled && hdLight != HDUtils.s_DefaultHDAdditionalLightData)
|
|
{
|
|
Light light = hdLight.gameObject.GetComponent<Light>();
|
|
// If the light is null or disabled, skip it
|
|
if (light == null || !light.enabled)
|
|
continue;
|
|
|
|
// If the light is flagged as baked and has been effectively been baked, skip it, except if we are path tracing
|
|
bool isPathTracingEnabled = hdCamera.IsPathTracingEnabled();
|
|
if (!isPathTracingEnabled && light.bakingOutput.lightmapBakeType == LightmapBakeType.Baked && light.bakingOutput.isBaked)
|
|
continue;
|
|
|
|
// If this light should not be included when ray tracing is active on the camera, skip it, except if we are path tracing
|
|
if (!isPathTracingEnabled && hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && !hdLight.includeForRayTracing)
|
|
continue;
|
|
|
|
// If path tracing is enabled and the light should not be included in path tracing, skip it
|
|
if(isPathTracingEnabled && hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && !hdLight.includeForPathTracing)
|
|
continue;
|
|
|
|
// Flag that needs to be overriden by the light and tells us if the light will need the RTAS
|
|
bool hasRayTracedShadows = false;
|
|
|
|
// Indicates that a transform has changed in our scene (mesh or light)
|
|
transformDirty |= hdLight.transform.hasChanged;
|
|
hdLight.transform.hasChanged = false;
|
|
|
|
switch (hdLight.legacyLight.type)
|
|
{
|
|
case LightType.Directional:
|
|
{
|
|
hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useScreenSpaceShadows && hdLight.useRayTracedShadows;
|
|
}
|
|
break;
|
|
case LightType.Point:
|
|
case LightType.Spot:
|
|
case LightType.Pyramid:
|
|
case LightType.Box:
|
|
{
|
|
hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useRayTracedShadows;
|
|
}
|
|
break;
|
|
case LightType.Rectangle:
|
|
{
|
|
hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useRayTracedShadows;
|
|
}
|
|
break;
|
|
case LightType.Tube:
|
|
{
|
|
hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useRayTracedShadows;
|
|
}
|
|
break;
|
|
case LightType.Disc:
|
|
{
|
|
hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useRayTracedShadows;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Check if there is a ray traced shadow in the scene
|
|
m_RayTracedShadowsRequired |= hasRayTracedShadows;
|
|
m_RayTracedContactShadowsRequired |= (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Function that returns the ray tracing and path tracing effects that are enabled for a given camera.
|
|
/// </summary>
|
|
/// <param name="hdCamera">The input camera</param>
|
|
/// <param name="rayTracedShadows">Flag that defines if at least one light has ray traced shadows.</param>
|
|
/// <param name="rayTracedContactShadows">Flag that defines if at least one light has ray traced contact shadows</param>
|
|
/// <returns>HDEffectsParameters type.</returns>
|
|
public static HDEffectsParameters EvaluateEffectsParameters(HDCamera hdCamera, bool rayTracedShadows, bool rayTracedContactShadows)
|
|
{
|
|
HDEffectsParameters parameters = new HDEffectsParameters();
|
|
|
|
// Aggregate the shadow requirements
|
|
parameters.shadows = hdCamera.frameSettings.IsEnabled(FrameSettingsField.ScreenSpaceShadows) && (rayTracedShadows || rayTracedContactShadows);
|
|
|
|
// Aggregate the ambient occlusion parameters
|
|
var aoSettings = hdCamera.volumeStack.GetComponent<ScreenSpaceAmbientOcclusion>();
|
|
parameters.ambientOcclusion = aoSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSAO);
|
|
parameters.aoLayerMask = aoSettings.layerMask.value;
|
|
|
|
// Aggregate the reflections parameters
|
|
ScreenSpaceReflection reflSettings = hdCamera.volumeStack.GetComponent<ScreenSpaceReflection>();
|
|
bool opaqueReflections = hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSR) && reflSettings.enabled.value;
|
|
bool transparentReflections = hdCamera.frameSettings.IsEnabled(FrameSettingsField.TransparentSSR) && reflSettings.enabledTransparent.value;
|
|
parameters.reflections = ScreenSpaceReflection.RayTracingActive(reflSettings) && (opaqueReflections || transparentReflections);
|
|
parameters.reflLayerMask = reflSettings.layerMask.value;
|
|
|
|
// Aggregate the global illumination parameters
|
|
GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent<GlobalIllumination>();
|
|
parameters.globalIllumination = giSettings.enable.value && GlobalIllumination.RayTracingActive(giSettings) && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSGI);
|
|
parameters.giLayerMask = giSettings.layerMask.value;
|
|
|
|
// Aggregate the global illumination parameters
|
|
RecursiveRendering recursiveSettings = hdCamera.volumeStack.GetComponent<RecursiveRendering>();
|
|
parameters.recursiveRendering = recursiveSettings.enable.value;
|
|
parameters.recursiveLayerMask = recursiveSettings.layerMask.value;
|
|
|
|
// Aggregate the sub surface parameters
|
|
SubSurfaceScattering sssSettings = hdCamera.volumeStack.GetComponent<SubSurfaceScattering>();
|
|
parameters.subSurface = sssSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SubsurfaceScattering);
|
|
|
|
// Aggregate the path parameters
|
|
PathTracing pathTracingSettings = hdCamera.volumeStack.GetComponent<PathTracing>();
|
|
parameters.pathTracing = pathTracingSettings.enable.value;
|
|
parameters.ptLayerMask = pathTracingSettings.layerMask.value;
|
|
|
|
// Aggregate the VFX parameters
|
|
parameters.includeVFX = hdCamera.frameSettings.IsEnabled(FrameSettingsField.RaytracingVFX);
|
|
|
|
// We need to check if at least one effect will require the acceleration structure
|
|
parameters.rayTracingRequired = parameters.ambientOcclusion || parameters.reflections
|
|
|| parameters.globalIllumination || parameters.recursiveRendering || parameters.subSurface
|
|
|| parameters.pathTracing || parameters.shadows;
|
|
|
|
// Return the result
|
|
return parameters;
|
|
}
|
|
|
|
internal void BuildRayTracingAccelerationStructure(HDCamera hdCamera)
|
|
{
|
|
// Resets the rtas manager
|
|
m_RTASManager.Reset();
|
|
|
|
// Reset all the flags
|
|
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;
|
|
|
|
if (m_VFXRayTracingSupported && hdCamera.frameSettings.IsEnabled(FrameSettingsField.RaytracingVFX))
|
|
VFXManager.RequestRtasAabbConstruction();
|
|
|
|
GatherLightInformationForRayTracing(hdCamera, ref m_RTASManager.transformsDirty);
|
|
|
|
// Evaluate the parameters of the effects
|
|
HDEffectsParameters effectParameters = EvaluateEffectsParameters(hdCamera, m_RayTracedShadowsRequired, m_RayTracedContactShadowsRequired);
|
|
|
|
if (!effectParameters.rayTracingRequired)
|
|
return;
|
|
|
|
// Grab the ray tracing settings
|
|
RayTracingSettings rtSettings = hdCamera.volumeStack.GetComponent<RayTracingSettings>();
|
|
#if UNITY_EDITOR
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic || hdCamera.camera.cameraType == CameraType.SceneView)
|
|
#else
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic)
|
|
#endif
|
|
{
|
|
// Cull the scene for the RTAS
|
|
RayTracingInstanceCullingResults cullingResults = m_RTASManager.Cull(hdCamera, effectParameters);
|
|
|
|
// Update the material dirtiness for the PT
|
|
if (effectParameters.pathTracing)
|
|
{
|
|
m_RTASManager.transformsDirty |= cullingResults.transformsChanged;
|
|
for (int i = 0; i < cullingResults.materialsCRC.Length; i++)
|
|
{
|
|
RayTracingInstanceMaterialCRC matCRC = cullingResults.materialsCRC[i];
|
|
m_RTASManager.materialsDirty |= UpdateMaterialCRC(matCRC.instanceID, matCRC.crc);
|
|
}
|
|
}
|
|
|
|
// Build the ray tracing acceleration structure
|
|
m_RTASManager.Build(hdCamera);
|
|
|
|
// tag the structures as valid
|
|
m_ValidRayTracingState = true;
|
|
}
|
|
else
|
|
{
|
|
// If the user fed a non null ray tracing acceleration structure, then we are all set.
|
|
if (hdCamera.rayTracingAccelerationStructure != null)
|
|
m_ValidRayTracingState = true;
|
|
}
|
|
}
|
|
|
|
class RTASDebugPassData
|
|
{
|
|
// Camera data
|
|
public int actualWidth;
|
|
public int actualHeight;
|
|
public int viewCount;
|
|
|
|
// Evaluation parameters
|
|
public int debugMode;
|
|
public uint layerMask;
|
|
public Matrix4x4 pixelCoordToViewDirWS;
|
|
|
|
// Other parameters
|
|
public RayTracingShader debugRTASRT;
|
|
public RayTracingAccelerationStructure rayTracingAccelerationStructure;
|
|
|
|
// Output
|
|
public TextureHandle outputTexture;
|
|
}
|
|
|
|
static uint LayerFromRTASDebugView(RTASDebugView debugView, HDCamera hdCamera)
|
|
{
|
|
switch (debugView)
|
|
{
|
|
case RTASDebugView.Shadows:
|
|
{
|
|
return (uint)RayTracingRendererFlag.CastShadow;
|
|
}
|
|
case RTASDebugView.AmbientOcclusion:
|
|
{
|
|
return (uint)RayTracingRendererFlag.AmbientOcclusion;
|
|
}
|
|
case RTASDebugView.GlobalIllumination:
|
|
{
|
|
return (uint)RayTracingRendererFlag.GlobalIllumination;
|
|
}
|
|
case RTASDebugView.Reflections:
|
|
{
|
|
return (uint)RayTracingRendererFlag.Reflection;
|
|
}
|
|
case RTASDebugView.RecursiveRayTracing:
|
|
{
|
|
return (uint)RayTracingRendererFlag.RecursiveRendering;
|
|
}
|
|
case RTASDebugView.PathTracing:
|
|
{
|
|
return (uint)RayTracingRendererFlag.PathTracing;
|
|
}
|
|
default:
|
|
{
|
|
return (uint)RayTracingRendererFlag.All;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void EvaluateRTASDebugView(RenderGraph renderGraph, HDCamera hdCamera)
|
|
{
|
|
// If the ray tracing state is not valid, we cannot evaluate the debug view
|
|
if (!m_ValidRayTracingState)
|
|
return;
|
|
|
|
RTASDebugPassData passData;
|
|
|
|
using (var builder = renderGraph.AddUnsafePass<RTASDebugPassData>("Debug view of the RTAS", out passData, ProfilingSampler.Get(HDProfileId.RaytracingBuildAccelerationStructureDebug)))
|
|
{
|
|
// Camera data
|
|
passData.actualWidth = hdCamera.actualWidth;
|
|
passData.actualHeight = hdCamera.actualHeight;
|
|
passData.viewCount = hdCamera.viewCount;
|
|
|
|
// Evaluation parameters
|
|
passData.debugMode = (int)m_CurrentDebugDisplaySettings.data.rtasDebugMode;
|
|
passData.layerMask = LayerFromRTASDebugView(m_CurrentDebugDisplaySettings.data.rtasDebugView, hdCamera);
|
|
passData.pixelCoordToViewDirWS = hdCamera.mainViewConstants.pixelCoordToViewDirWS;
|
|
|
|
// Other parameters
|
|
passData.debugRTASRT = rayTracingResources.debugRTASRT;
|
|
passData.rayTracingAccelerationStructure = RequestAccelerationStructure(hdCamera);
|
|
|
|
// Depending of if we will have to denoise (or not), we need to allocate the final format, or a bigger texture
|
|
passData.outputTexture = renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
|
|
{ format = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "RTAS Debug" });
|
|
builder.UseTexture(passData.outputTexture, AccessFlags.Write);
|
|
|
|
builder.SetRenderFunc(
|
|
(RTASDebugPassData data, UnsafeGraphContext ctx) =>
|
|
{
|
|
// Define the shader pass to use for the reflection pass
|
|
ctx.cmd.SetRayTracingShaderPass(data.debugRTASRT, "DebugDXR");
|
|
|
|
// Set the acceleration structure for the pass
|
|
ctx.cmd.SetRayTracingAccelerationStructure(data.debugRTASRT, HDShaderIDs._RaytracingAccelerationStructureName, data.rayTracingAccelerationStructure);
|
|
|
|
// Layer mask
|
|
ctx.cmd.SetRayTracingIntParam(data.debugRTASRT, "_DebugMode", data.debugMode);
|
|
ctx.cmd.SetRayTracingIntParam(data.debugRTASRT, "_LayerMask", (int)data.layerMask);
|
|
ctx.cmd.SetRayTracingMatrixParam(data.debugRTASRT, HDShaderIDs._PixelCoordToViewDirWS, data.pixelCoordToViewDirWS);
|
|
|
|
// Set the output texture
|
|
ctx.cmd.SetRayTracingTextureParam(data.debugRTASRT, "_OutputDebugBuffer", data.outputTexture);
|
|
|
|
// Evaluate the debug view
|
|
ctx.cmd.DispatchRays(data.debugRTASRT, m_RTASDebugRTKernel, (uint)data.actualWidth, (uint)data.actualHeight, (uint)data.viewCount, null);
|
|
});
|
|
}
|
|
|
|
// Use the debug texture to do the full screen debug
|
|
PushFullScreenDebugTexture(renderGraph, passData.outputTexture, FullScreenDebugMode.RayTracingAccelerationStructure);
|
|
}
|
|
|
|
internal static int RayTracingFrameIndex(HDCamera hdCamera, int targetFrameCount = 8)
|
|
{
|
|
return hdCamera.ActiveRayTracingAccumulation() ? (int)hdCamera.GetCameraFrameCount() % targetFrameCount : 0;
|
|
}
|
|
|
|
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 &&
|
|
(ScreenSpaceReflection.RayTracingActive(reflSettings)
|
|
|| GlobalIllumination.RayTracingActive(giSettings)
|
|
|| 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_WorldLights, m_WorldLightsVolumes);
|
|
m_ValidRayTracingClusterCulling = true;
|
|
}
|
|
}
|
|
|
|
internal void ReserveRayTracingCookieAtlasSlots()
|
|
{
|
|
if (m_ValidRayTracingState && m_ValidRayTracingClusterCulling)
|
|
{
|
|
m_RayTracingLightCluster.ReserveCookieAtlasSlots(m_WorldLights);
|
|
}
|
|
}
|
|
|
|
internal void BuildRayTracingLightData(CommandBuffer cmd, HDCamera hdCamera)
|
|
{
|
|
if (m_ValidRayTracingState && m_ValidRayTracingClusterCulling)
|
|
{
|
|
m_ValidRayTracingCluster = true;
|
|
|
|
UpdateShaderVariablesRaytracingLightLoopCB(hdCamera, cmd);
|
|
|
|
m_RayTracingLightCluster.BuildLightClusterBuffer(cmd, hdCamera, m_WorldLightsVolumes);
|
|
}
|
|
}
|
|
|
|
static internal float EvaluateHistoryValidity(HDCamera hdCamera)
|
|
{
|
|
// We need to check if something invalidated the history buffers
|
|
float historyValidity = (((int)hdCamera.GetCameraFrameCount() > 1) && hdCamera.ActiveRayTracingAccumulation()) ? 1.0f : 0.0f;
|
|
return historyValidity;
|
|
}
|
|
|
|
internal bool RayTracingHalfResAllowed()
|
|
{
|
|
return DynamicResolutionHandler.instance.GetCurrentScale() >= (currentPlatformRenderPipelineSettings.dynamicResolutionSettings.rayTracingHalfResThreshold / 100.0f);
|
|
}
|
|
|
|
internal static Vector4 EvaluateRayTracingHistorySizeAndScale(HDCamera hdCamera, RTHandle buffer)
|
|
{
|
|
return new Vector4(hdCamera.historyRTHandleProperties.previousViewportSize.x,
|
|
hdCamera.historyRTHandleProperties.previousViewportSize.y,
|
|
(float)hdCamera.historyRTHandleProperties.previousViewportSize.x / buffer.rt.width,
|
|
(float)hdCamera.historyRTHandleProperties.previousViewportSize.y / buffer.rt.height);
|
|
}
|
|
|
|
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();
|
|
|
|
ConstantBuffer.PushGlobal(cmd, m_ShaderVariablesRaytracingLightLoopCB, HDShaderIDs._ShaderVariablesRaytracingLightLoop);
|
|
}
|
|
|
|
internal bool RayTracedContactShadowsRequired()
|
|
{
|
|
return m_RayTracedContactShadowsRequired;
|
|
}
|
|
|
|
internal RayTracingAccelerationStructure RequestAccelerationStructure(HDCamera hdCamera)
|
|
{
|
|
if (m_ValidRayTracingState)
|
|
{
|
|
RayTracingSettings rtSettings = hdCamera.volumeStack.GetComponent<RayTracingSettings>();
|
|
#if UNITY_EDITOR
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic || hdCamera.camera.cameraType == CameraType.SceneView)
|
|
#else
|
|
if (rtSettings.buildMode.value == RTASBuildMode.Automatic)
|
|
#endif
|
|
return m_RTASManager.rtas;
|
|
else
|
|
return hdCamera.rayTracingAccelerationStructure;
|
|
}
|
|
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 PipelineSupportsRayTracing(RenderPipelineSettings rpSetting)
|
|
=> rpSetting.supportRayTracing && currentSystemSupportsRayTracing;
|
|
|
|
static internal bool currentSystemSupportsRayTracing => SystemInfo.supportsRayTracing
|
|
#if UNITY_EDITOR
|
|
&& (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.StandaloneWindows64
|
|
|| UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.StandaloneWindows
|
|
|| UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.GameCoreXboxSeries
|
|
|| UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.PS5);
|
|
#else
|
|
;
|
|
#endif
|
|
|
|
internal BlueNoise GetBlueNoiseManager()
|
|
{
|
|
return m_BlueNoise;
|
|
}
|
|
|
|
internal HDTemporalFilter GetTemporalFilter()
|
|
{
|
|
if (m_TemporalFilter == null)
|
|
{
|
|
m_TemporalFilter = new HDTemporalFilter();
|
|
m_TemporalFilter.Init(this);
|
|
}
|
|
return m_TemporalFilter;
|
|
}
|
|
|
|
internal HDDiffuseDenoiser GetDiffuseDenoiser()
|
|
{
|
|
if (m_DiffuseDenoiser == null)
|
|
{
|
|
m_DiffuseDenoiser = new HDDiffuseDenoiser();
|
|
m_DiffuseDenoiser.Init(this);
|
|
}
|
|
return m_DiffuseDenoiser;
|
|
}
|
|
|
|
internal ReBlurDenoiser GetReBlurDenoiser()
|
|
{
|
|
if (m_ReBlurDenoiser == null)
|
|
{
|
|
m_ReBlurDenoiser = new ReBlurDenoiser();
|
|
m_ReBlurDenoiser.Init(rayTracingResources);
|
|
}
|
|
return m_ReBlurDenoiser;
|
|
}
|
|
|
|
internal HDDiffuseShadowDenoiser GetDiffuseShadowDenoiser()
|
|
{
|
|
if (m_DiffuseShadowDenoiser == null)
|
|
{
|
|
m_DiffuseShadowDenoiser = new HDDiffuseShadowDenoiser();
|
|
m_DiffuseShadowDenoiser.Init(rayTracingResources);
|
|
}
|
|
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);
|
|
return temporalFilter.HistoryValidity(renderGraph, hdCamera, historyValidity, depthBuffer, normalBuffer, motionVectorsBuffer);
|
|
}
|
|
else
|
|
return renderGraph.defaultResources.whiteTexture;
|
|
}
|
|
}
|
|
}
|