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.
 
 
 
 
 

288 lines
18 KiB

using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.HighDefinition
{
public partial class HDRenderPipeline
{
static float EvaluateHistoryValidityDirectionalShadow(HDCamera hdCamera, int dirShadowIndex, HDAdditionalLightData additionalLightData)
{
// We need to set the history as invalid if the directional light has rotated
float historyValidity = 1.0f;
if (hdCamera.shadowHistoryUsage[dirShadowIndex].transform != additionalLightData.transform.localToWorldMatrix
|| !hdCamera.ValidShadowHistory(additionalLightData, dirShadowIndex, GPULightType.Directional))
historyValidity = 0.0f;
// We need to check if something invalidated the history buffers
historyValidity *= hdCamera.ActiveRayTracingAccumulation() ? EvaluateHistoryValidity(hdCamera) : 0.0f;
return historyValidity;
}
TextureHandle DenoiseDirectionalScreenSpaceShadow(RenderGraph renderGraph, HDCamera hdCamera,
TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVetorsBuffer, TextureHandle historyValidityBuffer,
TextureHandle noisyBuffer, TextureHandle velocityBuffer, TextureHandle distanceBuffer)
{
// Is the history still valid?
int dirShadowIndex = m_CurrentSunLightDirectionalLightData.screenSpaceShadowIndex & (int)LightDefinitions.s_ScreenSpaceShadowIndexMask;
float historyValidity = EvaluateHistoryValidityDirectionalShadow(hdCamera, dirShadowIndex, m_CurrentSunLightAdditionalLightData);
// Grab the history buffers for shadows
RTHandle shadowHistoryArray = RequestShadowHistoryBuffer(hdCamera);
RTHandle shadowHistoryDistanceArray = RequestShadowHistoryDistanceBuffer(hdCamera);
RTHandle shadowHistoryValidityArray = RequestShadowHistoryValidityBuffer(hdCamera);
// Evaluate the slot of the directional light (given that it may be a color shadow, we need to use the mask to get the actual slot indices)
GetShadowChannelMask(dirShadowIndex, m_CurrentSunLightAdditionalLightData.colorShadow ? ScreenSpaceShadowType.Color : ScreenSpaceShadowType.GrayScale, ref m_ShadowChannelMask0);
GetShadowChannelMask(dirShadowIndex, ScreenSpaceShadowType.GrayScale, ref m_ShadowChannelMask1);
// Apply the temporal denoiser
HDTemporalFilter.TemporalDenoiserArrayOutputData temporalFilterResult = GetTemporalFilter().DenoiseBuffer(renderGraph, hdCamera,
depthBuffer, normalBuffer, motionVetorsBuffer, historyValidityBuffer,
noisyBuffer, shadowHistoryArray,
distanceBuffer, shadowHistoryDistanceArray,
velocityBuffer,
shadowHistoryValidityArray,
dirShadowIndex / 4, m_ShadowChannelMask0, m_ShadowChannelMask1,
true, !m_CurrentSunLightAdditionalLightData.colorShadow, historyValidity);
// Apply the spatial denoiser
HDDiffuseShadowDenoiser shadowDenoiser = GetDiffuseShadowDenoiser();
TextureHandle denoisedBuffer = shadowDenoiser.DenoiseBufferDirectional(renderGraph, hdCamera,
depthBuffer, normalBuffer,
temporalFilterResult.outputSignal, temporalFilterResult.outputSignalDistance,
m_CurrentSunLightAdditionalLightData.filterSizeTraced, m_CurrentSunLightAdditionalLightData.angularDiameter * 0.5f, !m_CurrentSunLightAdditionalLightData.colorShadow);
// Now that we have overriden this history, mark is as used by this light
hdCamera.PropagateShadowHistory(m_CurrentSunLightAdditionalLightData, dirShadowIndex, GPULightType.Directional);
return denoisedBuffer;
}
class RTSDirectionalTracePassData
{
// Camera parameters
public int texWidth;
public int texHeight;
public int viewCount;
// Evaluation parameters
public bool softShadow;
public int numShadowSamples;
public bool colorShadow;
public float maxShadowLength;
// Kernels
public int clearShadowKernel;
public int directionalShadowSample;
// Other parameters
public RayTracingShader screenSpaceShadowRT;
public ComputeShader screenSpaceShadowCS;
public RayTracingAccelerationStructure accelerationStructure;
public ShaderVariablesRaytracing shaderVariablesRayTracingCB;
public BlueNoise.DitheredTextureSet ditheredTextureSet;
public TextureHandle depthStencilBuffer;
public TextureHandle normalBuffer;
public TextureHandle directionBuffer;
public TextureHandle rayCountTexture;
public TextureHandle velocityBuffer;
public TextureHandle distanceBuffer;
public TextureHandle outputShadowBuffer;
}
void RenderRayTracedDirectionalScreenSpaceShadow(RenderGraph renderGraph, HDCamera hdCamera,
TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVetorsBuffer, TextureHandle historyValidityBuffer,
TextureHandle rayCountTexture, TextureHandle screenSpaceShadowArray)
{
TextureHandle directionalShadow;
TextureHandle velocityBuffer;
TextureHandle distanceBuffer;
bool softShadows = m_CurrentSunLightAdditionalLightData.angularDiameter > 0.0 ? true : false;
using (var builder = renderGraph.AddRenderPass<RTSDirectionalTracePassData>("Directional RT Shadow", out var passData, ProfilingSampler.Get(HDProfileId.RaytracingDirectionalLightShadow)))
{
RayTracingSettings rayTracingSettings = hdCamera.volumeStack.GetComponent<RayTracingSettings>();
// Set the camera parameters
passData.texWidth = hdCamera.actualWidth;
passData.texHeight = hdCamera.actualHeight;
passData.viewCount = hdCamera.viewCount;
// Evaluation parameters
passData.softShadow = softShadows;
// If the surface is infinitively small, we force it to one sample.
passData.numShadowSamples = passData.softShadow ? m_CurrentSunLightAdditionalLightData.numRayTracingSamples : 1;
passData.colorShadow = m_CurrentSunLightAdditionalLightData.colorShadow;
passData.maxShadowLength = rayTracingSettings.directionalShadowRayLength.value;
// Kernels
passData.clearShadowKernel = m_ClearShadowTexture;
passData.directionalShadowSample = m_RaytracingDirectionalShadowSample;
// Grab the acceleration structure for the target camera
passData.accelerationStructure = RequestAccelerationStructure(hdCamera);
passData.screenSpaceShadowCS = m_ScreenSpaceShadowsCS;
passData.screenSpaceShadowRT = m_ScreenSpaceShadowsRT;
passData.shaderVariablesRayTracingCB = m_ShaderVariablesRayTracingCB;
passData.ditheredTextureSet = GetBlueNoiseManager().DitheredTextureSet8SPP();
// Input Buffer
passData.depthStencilBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.Read);
passData.normalBuffer = builder.ReadTexture(normalBuffer);
passData.directionBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Direction Buffer" });
// Debug buffers
passData.rayCountTexture = builder.ReadWriteTexture(rayCountTexture);
// Output Buffers
passData.velocityBuffer = builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
{ colorFormat = GraphicsFormat.R8_SNorm, enableRandomWrite = true, clearBuffer = true, name = "Velocity Buffer" }));
passData.distanceBuffer = builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
{ colorFormat = GraphicsFormat.R32_SFloat, enableRandomWrite = true, clearBuffer = true, name = "Distance Buffer" }));
passData.outputShadowBuffer = builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, clearBuffer = true, name = "RT Directional Shadow" }));
builder.SetRenderFunc(
(RTSDirectionalTracePassData data, RenderGraphContext ctx) =>
{
// Inject the ray-tracing sampling data
BlueNoise.BindDitheredTextureSet(ctx.cmd, data.ditheredTextureSet);
// Evaluate the dispatch parameters
int shadowTileSize = 8;
int numTilesX = (data.texWidth + (shadowTileSize - 1)) / shadowTileSize;
int numTilesY = (data.texHeight + (shadowTileSize - 1)) / shadowTileSize;
// Clear the integration texture
ctx.cmd.SetComputeTextureParam(data.screenSpaceShadowCS, data.clearShadowKernel, HDShaderIDs._RaytracedShadowIntegration, data.outputShadowBuffer);
ctx.cmd.DispatchCompute(data.screenSpaceShadowCS, data.clearShadowKernel, numTilesX, numTilesY, data.viewCount);
ctx.cmd.SetComputeTextureParam(data.screenSpaceShadowCS, data.clearShadowKernel, HDShaderIDs._RaytracedShadowIntegration, data.velocityBuffer);
ctx.cmd.DispatchCompute(data.screenSpaceShadowCS, data.clearShadowKernel, numTilesX, numTilesY, data.viewCount);
ctx.cmd.SetComputeTextureParam(data.screenSpaceShadowCS, data.clearShadowKernel, HDShaderIDs._RaytracedShadowIntegration, data.distanceBuffer);
ctx.cmd.DispatchCompute(data.screenSpaceShadowCS, data.clearShadowKernel, numTilesX, numTilesY, data.viewCount);
// Grab and bind the acceleration structure for the target camera
ctx.cmd.SetRayTracingAccelerationStructure(data.screenSpaceShadowRT, HDShaderIDs._RaytracingAccelerationStructureName, data.accelerationStructure);
// Make sure the right closest hit/any hit will be triggered by using the right multi compile
CoreUtils.SetKeyword(ctx.cmd, "TRANSPARENT_COLOR_SHADOW", data.colorShadow);
// Define which ray generation shaders we shall be using
string directionaLightShadowShader = data.colorShadow ? m_RayGenDirectionalColorShadowSingleName : m_RayGenDirectionalShadowSingleName;
// Loop through the samples of this frame
for (int sampleIdx = 0; sampleIdx < data.numShadowSamples; ++sampleIdx)
{
// Update global Constant Buffer
data.shaderVariablesRayTracingCB._RaytracingSampleIndex = sampleIdx;
data.shaderVariablesRayTracingCB._RaytracingNumSamples = data.numShadowSamples;
ConstantBuffer.PushGlobal(ctx.cmd, data.shaderVariablesRayTracingCB, HDShaderIDs._ShaderVariablesRaytracing);
// Input Buffer
ctx.cmd.SetComputeTextureParam(data.screenSpaceShadowCS, data.directionalShadowSample, HDShaderIDs._DepthTexture, data.depthStencilBuffer);
ctx.cmd.SetComputeTextureParam(data.screenSpaceShadowCS, data.directionalShadowSample, HDShaderIDs._StencilTexture, data.depthStencilBuffer, 0, RenderTextureSubElement.Stencil);
ctx.cmd.SetComputeTextureParam(data.screenSpaceShadowCS, data.directionalShadowSample, HDShaderIDs._NormalBufferTexture, data.normalBuffer);
// Output buffer
ctx.cmd.SetComputeTextureParam(data.screenSpaceShadowCS, data.directionalShadowSample, HDShaderIDs._RaytracingDirectionBuffer, data.directionBuffer);
// Generate a new direction
ctx.cmd.DispatchCompute(data.screenSpaceShadowCS, data.directionalShadowSample, numTilesX, numTilesY, data.viewCount);
// Define the shader pass to use for the shadow pass
ctx.cmd.SetRayTracingShaderPass(data.screenSpaceShadowRT, "VisibilityDXR");
// Input Uniforms
ctx.cmd.SetRayTracingFloatParam(data.screenSpaceShadowRT, HDShaderIDs._DirectionalMaxRayLength, data.maxShadowLength);
// Set ray count texture
ctx.cmd.SetRayTracingTextureParam(data.screenSpaceShadowRT, HDShaderIDs._RayCountTexture, data.rayCountTexture);
// Input buffers
ctx.cmd.SetRayTracingTextureParam(data.screenSpaceShadowRT, HDShaderIDs._DepthTexture, data.depthStencilBuffer);
ctx.cmd.SetRayTracingTextureParam(data.screenSpaceShadowRT, HDShaderIDs._NormalBufferTexture, data.normalBuffer);
ctx.cmd.SetRayTracingTextureParam(data.screenSpaceShadowRT, HDShaderIDs._RaytracingDirectionBuffer, data.directionBuffer);
// Output buffer
ctx.cmd.SetRayTracingTextureParam(data.screenSpaceShadowRT, data.colorShadow ? HDShaderIDs._RaytracedColorShadowIntegration : HDShaderIDs._RaytracedShadowIntegration, data.outputShadowBuffer);
ctx.cmd.SetRayTracingTextureParam(data.screenSpaceShadowRT, HDShaderIDs._VelocityBuffer, data.velocityBuffer);
ctx.cmd.SetRayTracingTextureParam(data.screenSpaceShadowRT, HDShaderIDs._RaytracingDistanceBufferRW, data.distanceBuffer);
// Evaluate the visibility
ctx.cmd.DispatchRays(data.screenSpaceShadowRT, directionaLightShadowShader, (uint)data.texWidth, (uint)data.texHeight, (uint)data.viewCount);
}
// Now that we are done with the ray tracing bit, disable the multi compile that was potentially enabled
CoreUtils.SetKeyword(ctx.cmd, "TRANSPARENT_COLOR_SHADOW", false);
});
directionalShadow = passData.outputShadowBuffer;
velocityBuffer = passData.velocityBuffer;
distanceBuffer = passData.distanceBuffer;
}
// If required, denoise the shadow
if (m_CurrentSunLightAdditionalLightData.filterTracedShadow && softShadows)
{
directionalShadow = DenoiseDirectionalScreenSpaceShadow(renderGraph, hdCamera,
depthBuffer, normalBuffer, motionVetorsBuffer, historyValidityBuffer,
directionalShadow, velocityBuffer, distanceBuffer);
}
int dirShadowIndex = m_CurrentSunLightDirectionalLightData.screenSpaceShadowIndex & (int)LightDefinitions.s_ScreenSpaceShadowIndexMask;
ScreenSpaceShadowType shadowType = m_CurrentSunLightAdditionalLightData.colorShadow ? ScreenSpaceShadowType.Color : ScreenSpaceShadowType.GrayScale;
// Write the result texture to the screen space shadow buffer
WriteScreenSpaceShadow(renderGraph, hdCamera, directionalShadow, screenSpaceShadowArray, dirShadowIndex, shadowType);
}
class SSSDirectionalTracePassData
{
public int depthSlice;
public TextureHandle normalBuffer;
public TextureHandle screenSpaceShadowArray;
}
void RenderDirectionalLightScreenSpaceShadow(RenderGraph renderGraph, HDCamera hdCamera,
TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVectorsBuffer, TextureHandle historyValidityBuffer,
TextureHandle rayCountTexture, TextureHandle screenSpaceShadowArray)
{
// Should we be executing anything really?
bool screenSpaceShadowRequired = m_CurrentSunLightAdditionalLightData != null && (m_CurrentSunShadowMapFlags & HDProcessedVisibleLightsBuilder.ShadowMapFlags.WillRenderScreenSpaceShadow) != 0;
// Render directional screen space shadow if required
if (screenSpaceShadowRequired)
{
bool rayTracedDirectionalRequired = (m_CurrentSunShadowMapFlags & HDProcessedVisibleLightsBuilder.ShadowMapFlags.WillRenderRayTracedShadow) != 0 && GetRayTracingState();
// If the shadow is flagged as ray traced, we need to evaluate it completely
if (rayTracedDirectionalRequired)
RenderRayTracedDirectionalScreenSpaceShadow(renderGraph, hdCamera, depthBuffer, normalBuffer, motionVectorsBuffer, historyValidityBuffer, rayCountTexture, screenSpaceShadowArray);
else
{
using (var builder = renderGraph.AddRenderPass<SSSDirectionalTracePassData>("Directional RT Shadow", out var passData, ProfilingSampler.Get(HDProfileId.RaytracingDirectionalLightShadow)))
{
passData.depthSlice = m_CurrentSunLightDirectionalLightData.screenSpaceShadowIndex;
passData.normalBuffer = builder.ReadTexture(normalBuffer);
passData.screenSpaceShadowArray = builder.ReadWriteTexture(screenSpaceShadowArray);
builder.SetRenderFunc(
(SSSDirectionalTracePassData data, RenderGraphContext ctx) =>
{
// If it is screen space but not ray traced, then we can rely on the shadow map
// WARNING: This pattern only works because we can only have one directional and the directional shadow is evaluated first.
var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock();
CoreUtils.SetRenderTarget(ctx.cmd, data.screenSpaceShadowArray, depthSlice: data.depthSlice);
mpb.SetTexture(HDShaderIDs._NormalBufferTexture, data.normalBuffer);
HDUtils.DrawFullScreen(ctx.cmd, s_ScreenSpaceShadowsMat, data.screenSpaceShadowArray, mpb);
});
}
}
}
}
}
}