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.
383 lines
18 KiB
383 lines
18 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering.RenderGraphModule;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
/// <summary>
|
|
/// Structure that keeps track of the ray tracing and path tracing effects that are enabled for a given camera.
|
|
/// </summary>
|
|
public struct HDEffectsParameters
|
|
{
|
|
/// <summary>
|
|
/// Specifies if ray traced shadows are active.
|
|
/// </summary>
|
|
public bool shadows;
|
|
/// <summary>
|
|
/// Specifies if ray traced ambient occlusion is active.
|
|
/// </summary>
|
|
public bool ambientOcclusion;
|
|
/// <summary>
|
|
/// Specifies the layer mask that will be used to evaluate ray traced ambient occlusion.
|
|
/// </summary>
|
|
public int aoLayerMask;
|
|
/// <summary>
|
|
/// Specifies if ray traced reflections are active.
|
|
/// </summary>
|
|
public bool reflections;
|
|
/// <summary>
|
|
/// Specifies the layer mask that will be used to evaluate ray traced reflections.
|
|
/// </summary>
|
|
public int reflLayerMask;
|
|
/// <summary>
|
|
/// Specifies if ray traced global illumination is active.
|
|
/// </summary>
|
|
public bool globalIllumination;
|
|
/// <summary>
|
|
/// Specifies the layer mask that will be used to evaluate ray traced global illumination.
|
|
/// </summary>
|
|
public int giLayerMask;
|
|
/// <summary>
|
|
/// Specifies if recursive rendering is active.
|
|
/// </summary>
|
|
public bool recursiveRendering;
|
|
/// <summary>
|
|
/// Specifies the layer mask that will be used to evaluate recursive rendering.
|
|
/// </summary>
|
|
public int recursiveLayerMask;
|
|
/// <summary>
|
|
/// Specifies if ray traced sub-surface scattering is active.
|
|
/// </summary>
|
|
public bool subSurface;
|
|
/// <summary>
|
|
/// Specifies if path tracing is active.
|
|
/// </summary>
|
|
public bool pathTracing;
|
|
/// <summary>
|
|
/// Specifies the layer mask that will be used to evaluate path tracing.
|
|
/// </summary>
|
|
public int ptLayerMask;
|
|
/// <summary>
|
|
/// Specifies if at least one ray tracing effect is enabled.
|
|
/// </summary>
|
|
public bool rayTracingRequired;
|
|
/// <summary>
|
|
/// Specifies if the visual effects should be included in the ray tracing acceleration structure.
|
|
/// </summary>
|
|
public bool includeVFX;
|
|
};
|
|
|
|
class HDRTASManager
|
|
{
|
|
public RayTracingAccelerationStructure rtas = null;
|
|
public RayTracingInstanceCullingConfig cullingConfig = new RayTracingInstanceCullingConfig();
|
|
public List<RayTracingInstanceCullingTest> instanceTestArray = new List<RayTracingInstanceCullingTest>();
|
|
internal Plane[] rtCullingPlaneArray = new Plane[6];
|
|
|
|
// Culling tests
|
|
RayTracingInstanceCullingTest ShT_CT = new RayTracingInstanceCullingTest();
|
|
RayTracingInstanceCullingTest ShO_CT = new RayTracingInstanceCullingTest();
|
|
RayTracingInstanceCullingTest AO_CT = new RayTracingInstanceCullingTest();
|
|
RayTracingInstanceCullingTest Refl_CT = new RayTracingInstanceCullingTest();
|
|
RayTracingInstanceCullingTest GI_CT = new RayTracingInstanceCullingTest();
|
|
RayTracingInstanceCullingTest RR_CT = new RayTracingInstanceCullingTest();
|
|
RayTracingInstanceCullingTest SSS_CT = new RayTracingInstanceCullingTest();
|
|
RayTracingInstanceCullingTest PT_CT = new RayTracingInstanceCullingTest();
|
|
|
|
// Path tracing dirtiness parameters
|
|
public bool transformsDirty;
|
|
public bool materialsDirty;
|
|
|
|
public void Initialize()
|
|
{
|
|
// We only support perspective projection in HDRP, so we flag the lod parameters as always non orthographic.
|
|
cullingConfig.lodParameters.orthoSize = 0;
|
|
cullingConfig.lodParameters.isOrthographic = false;
|
|
|
|
// Opaque sub meshes need to be included and do not need to have their any hit enabled
|
|
cullingConfig.subMeshFlagsConfig.opaqueMaterials = RayTracingSubMeshFlags.Enabled | RayTracingSubMeshFlags.ClosestHitOnly;
|
|
|
|
// Transparent sub meshes need to be included and we need the guarantee that they will trigger their any hit only once
|
|
cullingConfig.subMeshFlagsConfig.transparentMaterials = RayTracingSubMeshFlags.Enabled | RayTracingSubMeshFlags.UniqueAnyHitCalls;
|
|
|
|
// Alpha tested sub meshes need to be included. (Note, not sure how it combines with transparency)
|
|
cullingConfig.subMeshFlagsConfig.alphaTestedMaterials = RayTracingSubMeshFlags.Enabled;
|
|
|
|
// Controls for the double sidedness
|
|
cullingConfig.triangleCullingConfig.checkDoubleSidedGIMaterial = true;
|
|
cullingConfig.triangleCullingConfig.frontTriangleCounterClockwise = false;
|
|
cullingConfig.triangleCullingConfig.optionalDoubleSidedShaderKeywords = new string[1];
|
|
cullingConfig.triangleCullingConfig.optionalDoubleSidedShaderKeywords[0] = "_DOUBLESIDED_ON";
|
|
|
|
// Flags for the alpha testing
|
|
cullingConfig.alphaTestedMaterialConfig.renderQueueLowerBound = HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.lowerBound;
|
|
cullingConfig.alphaTestedMaterialConfig.renderQueueUpperBound = HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.upperBound;
|
|
cullingConfig.alphaTestedMaterialConfig.optionalShaderKeywords = new string[1];
|
|
cullingConfig.alphaTestedMaterialConfig.optionalShaderKeywords[0] = "_ALPHATEST_ON";
|
|
|
|
// Flags for the transparency
|
|
cullingConfig.transparentMaterialConfig.renderQueueLowerBound = HDRenderQueue.k_RenderQueue_PreRefraction.lowerBound;
|
|
cullingConfig.transparentMaterialConfig.renderQueueUpperBound = HDRenderQueue.k_RenderQueue_Transparent.upperBound;
|
|
cullingConfig.transparentMaterialConfig.optionalShaderKeywords = new string[1];
|
|
cullingConfig.transparentMaterialConfig.optionalShaderKeywords[0] = "_SURFACE_TYPE_TRANSPARENT";
|
|
|
|
// Flags that define which shaders to include (HDRP shaders only)
|
|
cullingConfig.materialTest.requiredShaderTags = new RayTracingInstanceCullingShaderTagConfig[1];
|
|
cullingConfig.materialTest.requiredShaderTags[0].tagId = new ShaderTagId("RenderPipeline");
|
|
cullingConfig.materialTest.requiredShaderTags[0].tagValueId = new ShaderTagId("HDRenderPipeline");
|
|
cullingConfig.materialTest.deniedShaderPasses = DecalSystem.s_MaterialDecalPassNames;
|
|
cullingConfig.instanceTests = new RayTracingInstanceCullingTest[9];
|
|
|
|
// Setup the culling data for transparent shadows
|
|
ShT_CT.allowOpaqueMaterials = true;
|
|
ShT_CT.allowAlphaTestedMaterials = true;
|
|
ShT_CT.allowTransparentMaterials = true;
|
|
ShT_CT.layerMask = -1;
|
|
ShT_CT.shadowCastingModeMask = (1 << (int)ShadowCastingMode.On) | (1 << (int)ShadowCastingMode.TwoSided) | (1 << (int)ShadowCastingMode.ShadowsOnly);
|
|
ShT_CT.instanceMask = (uint)RayTracingRendererFlag.CastShadowTransparent;
|
|
|
|
// Setup the culling data for opaque shadows
|
|
ShO_CT.allowOpaqueMaterials = true;
|
|
ShO_CT.allowAlphaTestedMaterials = true;
|
|
ShO_CT.allowTransparentMaterials = false;
|
|
ShO_CT.layerMask = -1;
|
|
ShO_CT.shadowCastingModeMask = (1 << (int)ShadowCastingMode.On) | (1 << (int)ShadowCastingMode.TwoSided) | (1 << (int)ShadowCastingMode.ShadowsOnly);
|
|
ShO_CT.instanceMask = (uint)RayTracingRendererFlag.CastShadowOpaque;
|
|
|
|
// Setup the culling data for the ambient occlusion
|
|
AO_CT.allowOpaqueMaterials = true;
|
|
AO_CT.allowAlphaTestedMaterials = true;
|
|
AO_CT.allowTransparentMaterials = false;
|
|
AO_CT.layerMask = -1;
|
|
AO_CT.shadowCastingModeMask = (1 << (int)ShadowCastingMode.Off) | (1 << (int)ShadowCastingMode.On) | (1 << (int)ShadowCastingMode.TwoSided);
|
|
AO_CT.instanceMask = (uint)RayTracingRendererFlag.AmbientOcclusion;
|
|
|
|
// Setup the culling data for the reflections
|
|
Refl_CT.allowOpaqueMaterials = true;
|
|
Refl_CT.allowAlphaTestedMaterials = true;
|
|
Refl_CT.allowTransparentMaterials = false;
|
|
Refl_CT.layerMask = -1;
|
|
Refl_CT.shadowCastingModeMask = (1 << (int)ShadowCastingMode.Off) | (1 << (int)ShadowCastingMode.On) | (1 << (int)ShadowCastingMode.TwoSided);
|
|
Refl_CT.instanceMask = (uint)RayTracingRendererFlag.Reflection;
|
|
|
|
// Setup the culling data for the global illumination
|
|
GI_CT.allowOpaqueMaterials = true;
|
|
GI_CT.allowAlphaTestedMaterials = true;
|
|
GI_CT.allowTransparentMaterials = false;
|
|
GI_CT.layerMask = -1;
|
|
GI_CT.shadowCastingModeMask = (1 << (int)ShadowCastingMode.Off) | (1 << (int)ShadowCastingMode.On) | (1 << (int)ShadowCastingMode.TwoSided);
|
|
GI_CT.instanceMask = (uint)RayTracingRendererFlag.GlobalIllumination;
|
|
|
|
// Setup the culling data for the recursive rendering
|
|
RR_CT.allowOpaqueMaterials = true;
|
|
RR_CT.allowAlphaTestedMaterials = true;
|
|
RR_CT.allowTransparentMaterials = true;
|
|
RR_CT.layerMask = -1;
|
|
RR_CT.shadowCastingModeMask = (1 << (int)ShadowCastingMode.Off) | (1 << (int)ShadowCastingMode.On) | (1 << (int)ShadowCastingMode.TwoSided);
|
|
RR_CT.instanceMask = (uint)RayTracingRendererFlag.RecursiveRendering;
|
|
|
|
// Setup the culling data for the recursive rendering
|
|
RR_CT.allowOpaqueMaterials = true;
|
|
RR_CT.allowAlphaTestedMaterials = true;
|
|
RR_CT.allowTransparentMaterials = true;
|
|
RR_CT.layerMask = -1;
|
|
RR_CT.shadowCastingModeMask = (1 << (int)ShadowCastingMode.Off) | (1 << (int)ShadowCastingMode.On) | (1 << (int)ShadowCastingMode.TwoSided);
|
|
RR_CT.instanceMask = (uint)RayTracingRendererFlag.RecursiveRendering;
|
|
|
|
// Setup the culling data for the SSS
|
|
SSS_CT.allowOpaqueMaterials = true;
|
|
SSS_CT.allowAlphaTestedMaterials = true;
|
|
SSS_CT.allowTransparentMaterials = false;
|
|
SSS_CT.layerMask = -1;
|
|
SSS_CT.shadowCastingModeMask = -1;
|
|
SSS_CT.instanceMask = (uint)RayTracingRendererFlag.Opaque;
|
|
|
|
// Setup the culling data for the recursive rendering
|
|
PT_CT.allowOpaqueMaterials = true;
|
|
PT_CT.allowAlphaTestedMaterials = true;
|
|
PT_CT.allowTransparentMaterials = true;
|
|
PT_CT.layerMask = -1;
|
|
PT_CT.shadowCastingModeMask = (1 << (int)ShadowCastingMode.Off) | (1 << (int)ShadowCastingMode.On) | (1 << (int)ShadowCastingMode.TwoSided);
|
|
PT_CT.instanceMask = (uint)RayTracingRendererFlag.PathTracing;
|
|
}
|
|
|
|
void SetupCullingData(HDCamera hdCamera, bool pathTracingEnabled)
|
|
{
|
|
// Grab the ray tracing settings parameter
|
|
RayTracingSettings rtSettings = hdCamera.volumeStack.GetComponent<RayTracingSettings>();
|
|
switch (rtSettings.cullingMode.value)
|
|
{
|
|
case RTASCullingMode.ExtendedFrustum:
|
|
{
|
|
// We'll be using an extension
|
|
cullingConfig.flags = RayTracingInstanceCullingFlags.EnablePlaneCulling;
|
|
|
|
// Build the culling plane data
|
|
Vector3 camerPosWS = hdCamera.camera.transform.position;
|
|
Vector3 forward = hdCamera.camera.transform.forward;
|
|
Vector3 right = hdCamera.camera.transform.right;
|
|
Vector3 up = hdCamera.camera.transform.up;
|
|
|
|
float far, height, width;
|
|
far = hdCamera.camera.farClipPlane;
|
|
height = Mathf.Tan(Mathf.Deg2Rad * hdCamera.camera.fieldOfView * 0.5f) * far;
|
|
float horizontalFov = Camera.VerticalToHorizontalFieldOfView(hdCamera.camera.fieldOfView, hdCamera.camera.aspect);
|
|
width = Mathf.Tan(Mathf.Deg2Rad * horizontalFov * 0.5f) * far;
|
|
|
|
// Front plane
|
|
rtCullingPlaneArray[0].normal = -forward;
|
|
rtCullingPlaneArray[0].distance = -Vector3.Dot(camerPosWS + forward * far, -forward);
|
|
|
|
// Back plane
|
|
rtCullingPlaneArray[1].normal = forward;
|
|
rtCullingPlaneArray[1].distance = -Vector3.Dot(camerPosWS - forward * far, forward);
|
|
|
|
// Right plane
|
|
rtCullingPlaneArray[2].normal = -right;
|
|
rtCullingPlaneArray[2].distance = -Vector3.Dot(camerPosWS + right * width, -right);
|
|
|
|
// Left plane
|
|
rtCullingPlaneArray[3].normal = right;
|
|
rtCullingPlaneArray[3].distance = -Vector3.Dot(camerPosWS - right * width, right);
|
|
|
|
// Top plane
|
|
rtCullingPlaneArray[4].normal = -up;
|
|
rtCullingPlaneArray[4].distance = -Vector3.Dot(camerPosWS + up * height, -up);
|
|
|
|
// Bottom plane
|
|
rtCullingPlaneArray[5].normal = up;
|
|
rtCullingPlaneArray[5].distance = -Vector3.Dot(camerPosWS - up * height, up);
|
|
|
|
// Set the planes
|
|
cullingConfig.planes = rtCullingPlaneArray;
|
|
}
|
|
break;
|
|
case RTASCullingMode.Sphere:
|
|
{
|
|
// We use a sphere
|
|
cullingConfig.flags = RayTracingInstanceCullingFlags.EnableSphereCulling;
|
|
cullingConfig.sphereRadius = rtSettings.cullingDistance.value;
|
|
cullingConfig.sphereCenter = hdCamera.camera.transform.position;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
// We explicitly want no culling.
|
|
cullingConfig.flags = RayTracingInstanceCullingFlags.None;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// We want the LODs to match the rasterization and we want to exclude reflection probes
|
|
cullingConfig.flags |= RayTracingInstanceCullingFlags.EnableLODCulling | RayTracingInstanceCullingFlags.IgnoreReflectionProbes;
|
|
|
|
// Dirtiness need to be kept track of for the path tracing (when enabled)
|
|
if (pathTracingEnabled)
|
|
cullingConfig.flags |= RayTracingInstanceCullingFlags.ComputeMaterialsCRC;
|
|
}
|
|
|
|
public RayTracingInstanceCullingResults Cull(HDCamera hdCamera, in HDEffectsParameters parameters)
|
|
{
|
|
// The list of instanceTestArray needs to be cleared every frame as the list depends on the active effects and their parameters.
|
|
instanceTestArray.Clear();
|
|
|
|
// Set up the culling data
|
|
SetupCullingData(hdCamera, parameters.pathTracing);
|
|
|
|
// Set up the LOD flags
|
|
cullingConfig.lodParameters.fieldOfView = hdCamera.camera.fieldOfView;
|
|
cullingConfig.lodParameters.cameraPosition = hdCamera.camera.transform.position;
|
|
cullingConfig.lodParameters.cameraPixelHeight = hdCamera.camera.pixelHeight;
|
|
|
|
// If we have path tracing, the shadow inclusion constraints must be aggregated with the layer masks of the path tracing.
|
|
if (parameters.pathTracing)
|
|
{
|
|
ShO_CT.layerMask = parameters.ptLayerMask;
|
|
ShT_CT.layerMask = parameters.ptLayerMask;
|
|
ShO_CT.allowVisualEffects = false;
|
|
ShT_CT.allowVisualEffects = false;
|
|
}
|
|
|
|
if (parameters.shadows || parameters.pathTracing)
|
|
{
|
|
ShO_CT.allowVisualEffects = parameters.includeVFX;
|
|
ShT_CT.allowVisualEffects = parameters.includeVFX;
|
|
instanceTestArray.Add(ShO_CT);
|
|
instanceTestArray.Add(ShT_CT);
|
|
}
|
|
|
|
if (parameters.ambientOcclusion)
|
|
{
|
|
AO_CT.layerMask = parameters.aoLayerMask;
|
|
AO_CT.allowVisualEffects = parameters.includeVFX;
|
|
instanceTestArray.Add(AO_CT);
|
|
}
|
|
|
|
if (parameters.reflections)
|
|
{
|
|
Refl_CT.layerMask = parameters.reflLayerMask;
|
|
Refl_CT.allowVisualEffects = parameters.includeVFX;
|
|
instanceTestArray.Add(Refl_CT);
|
|
}
|
|
|
|
if (parameters.globalIllumination)
|
|
{
|
|
GI_CT.layerMask = parameters.giLayerMask;
|
|
GI_CT.allowVisualEffects = parameters.includeVFX;
|
|
instanceTestArray.Add(GI_CT);
|
|
}
|
|
|
|
if (parameters.recursiveRendering)
|
|
{
|
|
RR_CT.layerMask = parameters.recursiveLayerMask;
|
|
RR_CT.allowVisualEffects = parameters.includeVFX;
|
|
instanceTestArray.Add(RR_CT);
|
|
}
|
|
|
|
if (parameters.subSurface)
|
|
{
|
|
SSS_CT.allowVisualEffects = parameters.includeVFX;
|
|
instanceTestArray.Add(SSS_CT);
|
|
}
|
|
|
|
if (parameters.pathTracing)
|
|
{
|
|
PT_CT.layerMask = parameters.ptLayerMask;
|
|
PT_CT.allowVisualEffects = false;
|
|
instanceTestArray.Add(PT_CT);
|
|
}
|
|
|
|
// avoid reallocation uf previous instanceTests array is the same size as the current one
|
|
if (cullingConfig.instanceTests.Length != instanceTestArray.Count)
|
|
cullingConfig.instanceTests = instanceTestArray.ToArray();
|
|
else
|
|
instanceTestArray.CopyTo(0, cullingConfig.instanceTests, 0, instanceTestArray.Count);
|
|
|
|
return rtas.CullInstances(ref cullingConfig);
|
|
}
|
|
|
|
public void Build(HDCamera hdCamera)
|
|
{
|
|
if (ShaderConfig.s_CameraRelativeRendering != 0)
|
|
rtas.Build(hdCamera.mainViewConstants.worldSpaceCameraPos);
|
|
else
|
|
rtas.Build();
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
// Clear all the per frame-data or allocate the rtas if it is the first time)
|
|
if (rtas != null)
|
|
rtas.ClearInstances();
|
|
else
|
|
rtas = new RayTracingAccelerationStructure();
|
|
}
|
|
|
|
public void ReleaseResources()
|
|
{
|
|
if (rtas != null)
|
|
rtas.Dispose();
|
|
}
|
|
}
|
|
}
|