2021-09-09 20:42:29 -04:00

189 lines
10 KiB
C#

using System;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.HighDefinition
{
public partial class HDRenderPipeline
{
struct SSSPunctualRayTraceParameters
{
// Camera parameters
public int texWidth;
public int texHeight;
public int viewCount;
// Evaluation parameters
public bool softShadow;
public bool distanceBasedFiltering;
public int numShadowSamples;
public bool semiTransparentShadow;
public GPULightType lightType;
public float spotAngle;
public float shapeRadius;
public int lightIndex;
// Kernels
public int clearShadowKernel;
public int shadowKernel;
// Other parameters
public RayTracingShader screenSpaceShadowRT;
public ComputeShader screenSpaceShadowCS;
public RayTracingAccelerationStructure accelerationStructure;
public ShaderVariablesRaytracing shaderVariablesRayTracingCB;
public BlueNoise.DitheredTextureSet ditheredTextureSet;
}
SSSPunctualRayTraceParameters PrepareSSSPunctualRayTraceParameters(HDCamera hdCamera, HDAdditionalLightData additionalLightData, LightData lightData, int lightIndex)
{
SSSPunctualRayTraceParameters ssprtParams = new SSSPunctualRayTraceParameters();
// Set the camera parameters
ssprtParams.texWidth = hdCamera.actualWidth;
ssprtParams.texHeight = hdCamera.actualHeight;
ssprtParams.viewCount = hdCamera.viewCount;
// Evaluation parameters
ssprtParams.softShadow = additionalLightData.shapeRadius > 0.0 ? true : false;
// If the surface is infinitively small, we force it to one sample.
ssprtParams.numShadowSamples = ssprtParams.softShadow ? additionalLightData.numRayTracingSamples : 1;
ssprtParams.distanceBasedFiltering = additionalLightData.distanceBasedFiltering;
ssprtParams.semiTransparentShadow = additionalLightData.semiTransparentShadow;
ssprtParams.lightType = lightData.lightType;
ssprtParams.spotAngle = additionalLightData.legacyLight.spotAngle;
ssprtParams.shapeRadius = additionalLightData.shapeRadius;
ssprtParams.lightIndex = lightIndex;
// Kernels
ssprtParams.clearShadowKernel = m_ClearShadowTexture;
ssprtParams.shadowKernel = lightData.lightType == GPULightType.Point ? m_RaytracingPointShadowSample : m_RaytracingSpotShadowSample;
// Grab the acceleration structure for the target camera
ssprtParams.accelerationStructure = RequestAccelerationStructure();
ssprtParams.screenSpaceShadowCS = m_ScreenSpaceShadowsCS;
ssprtParams.screenSpaceShadowRT = m_ScreenSpaceShadowsRT;
ssprtParams.shaderVariablesRayTracingCB = m_ShaderVariablesRayTracingCB;
BlueNoise blueNoise = GetBlueNoiseManager();
ssprtParams.ditheredTextureSet = blueNoise.DitheredTextureSet8SPP();
return ssprtParams;
}
struct SSSPunctualRayTraceResources
{
// Input Buffers
public RTHandle depthStencilBuffer;
public RTHandle normalBuffer;
// Intermediate buffers
public RTHandle directionBuffer;
public RTHandle rayLengthBuffer;
// Debug textures
public RTHandle rayCountTexture;
// Output buffers
public RTHandle velocityBuffer;
public RTHandle distanceBuffer;
public RTHandle outputShadowBuffer;
}
static void ExecuteSSSPunctualRayTrace(CommandBuffer cmd, SSSPunctualRayTraceParameters ssprtParams, SSSPunctualRayTraceResources ssprtResources)
{
// Inject the ray-tracing sampling data
BlueNoise.BindDitheredTextureSet(cmd, ssprtParams.ditheredTextureSet);
// Evaluate the dispatch parameters
int shadowTileSize = 8;
int numTilesX = (ssprtParams.texWidth + (shadowTileSize - 1)) / shadowTileSize;
int numTilesY = (ssprtParams.texHeight + (shadowTileSize - 1)) / shadowTileSize;
// Clear the integration textures
cmd.SetComputeTextureParam(ssprtParams.screenSpaceShadowCS, ssprtParams.clearShadowKernel, HDShaderIDs._RaytracedShadowIntegration, ssprtResources.outputShadowBuffer);
cmd.DispatchCompute(ssprtParams.screenSpaceShadowCS, ssprtParams.clearShadowKernel, numTilesX, numTilesY, ssprtParams.viewCount);
cmd.SetComputeTextureParam(ssprtParams.screenSpaceShadowCS, ssprtParams.clearShadowKernel, HDShaderIDs._RaytracedShadowIntegration, ssprtResources.velocityBuffer);
cmd.DispatchCompute(ssprtParams.screenSpaceShadowCS, ssprtParams.clearShadowKernel, numTilesX, numTilesY, ssprtParams.viewCount);
if (ssprtParams.distanceBasedFiltering)
{
cmd.SetComputeTextureParam(ssprtParams.screenSpaceShadowCS, ssprtParams.clearShadowKernel, HDShaderIDs._RaytracedShadowIntegration, ssprtResources.distanceBuffer);
cmd.DispatchCompute(ssprtParams.screenSpaceShadowCS, ssprtParams.clearShadowKernel, numTilesX, numTilesY, ssprtParams.viewCount);
}
// Set the acceleration structure for the pass
cmd.SetRayTracingAccelerationStructure(ssprtParams.screenSpaceShadowRT, HDShaderIDs._RaytracingAccelerationStructureName, ssprtParams.accelerationStructure);
// Define the shader pass to use for the reflection pass
cmd.SetRayTracingShaderPass(ssprtParams.screenSpaceShadowRT, "VisibilityDXR");
// Loop through the samples of this frame
for (int sampleIdx = 0; sampleIdx < ssprtParams.numShadowSamples; ++sampleIdx)
{
// Update global constant buffer
ssprtParams.shaderVariablesRayTracingCB._RaytracingSampleIndex = sampleIdx;
ssprtParams.shaderVariablesRayTracingCB._RaytracingNumSamples = ssprtParams.numShadowSamples;
ConstantBuffer.PushGlobal(cmd, ssprtParams.shaderVariablesRayTracingCB, HDShaderIDs._ShaderVariablesRaytracing);
// Bind the light & sampling data
cmd.SetComputeIntParam(ssprtParams.screenSpaceShadowCS, HDShaderIDs._RaytracingTargetAreaLight, ssprtParams.lightIndex);
cmd.SetComputeFloatParam(ssprtParams.screenSpaceShadowCS, HDShaderIDs._RaytracingLightRadius, ssprtParams.shapeRadius);
// If this is a spot light, inject the spot angle in radians
if (ssprtParams.lightType == GPULightType.Spot)
{
float spotAngleRadians = ssprtParams.spotAngle * (float)Math.PI / 180.0f;
cmd.SetComputeFloatParam(ssprtParams.screenSpaceShadowCS, HDShaderIDs._RaytracingSpotAngle, spotAngleRadians);
}
// Input Buffer
cmd.SetComputeTextureParam(ssprtParams.screenSpaceShadowCS, ssprtParams.shadowKernel, HDShaderIDs._DepthTexture, ssprtResources.depthStencilBuffer);
cmd.SetComputeTextureParam(ssprtParams.screenSpaceShadowCS, ssprtParams.shadowKernel, HDShaderIDs._NormalBufferTexture, ssprtResources.normalBuffer);
// Output buffers
cmd.SetComputeTextureParam(ssprtParams.screenSpaceShadowCS, ssprtParams.shadowKernel, HDShaderIDs._RaytracingDirectionBuffer, ssprtResources.directionBuffer);
cmd.SetComputeTextureParam(ssprtParams.screenSpaceShadowCS, ssprtParams.shadowKernel, HDShaderIDs._RayTracingLengthBuffer, ssprtResources.rayLengthBuffer);
// Generate a new direction
cmd.DispatchCompute(ssprtParams.screenSpaceShadowCS, ssprtParams.shadowKernel, numTilesX, numTilesY, ssprtParams.viewCount);
// Define the shader pass to use for the shadow pass
cmd.SetRayTracingShaderPass(ssprtParams.screenSpaceShadowRT, "VisibilityDXR");
// Set ray count texture
cmd.SetRayTracingTextureParam(ssprtParams.screenSpaceShadowRT, HDShaderIDs._RayCountTexture, ssprtResources.rayCountTexture);
// Input buffers
cmd.SetRayTracingTextureParam(ssprtParams.screenSpaceShadowRT, HDShaderIDs._DepthTexture, ssprtResources.depthStencilBuffer);
cmd.SetRayTracingTextureParam(ssprtParams.screenSpaceShadowRT, HDShaderIDs._NormalBufferTexture, ssprtResources.normalBuffer);
cmd.SetRayTracingTextureParam(ssprtParams.screenSpaceShadowRT, HDShaderIDs._RaytracingDirectionBuffer, ssprtResources.directionBuffer);
cmd.SetRayTracingTextureParam(ssprtParams.screenSpaceShadowRT, HDShaderIDs._RayTracingLengthBuffer, ssprtResources.rayLengthBuffer);
// Output buffer
cmd.SetRayTracingTextureParam(ssprtParams.screenSpaceShadowRT, HDShaderIDs._RaytracedShadowIntegration, ssprtResources.outputShadowBuffer);
cmd.SetRayTracingTextureParam(ssprtParams.screenSpaceShadowRT, HDShaderIDs._VelocityBuffer, ssprtResources.velocityBuffer);
cmd.SetRayTracingTextureParam(ssprtParams.screenSpaceShadowRT, HDShaderIDs._RaytracingDistanceBufferRW, ssprtResources.distanceBuffer);
CoreUtils.SetKeyword(cmd, "TRANSPARENT_COLOR_SHADOW", ssprtParams.semiTransparentShadow);
cmd.DispatchRays(ssprtParams.screenSpaceShadowRT, ssprtParams.semiTransparentShadow ? m_RayGenSemiTransparentShadowSegmentSingleName : m_RayGenShadowSegmentSingleName, (uint)ssprtParams.texWidth, (uint)ssprtParams.texHeight, (uint)ssprtParams.viewCount);
CoreUtils.SetKeyword(cmd, "TRANSPARENT_COLOR_SHADOW", false);
}
}
static float EvaluateHistoryValidityPointShadow(HDCamera hdCamera, LightData lightData, HDAdditionalLightData additionalLightData)
{
// We need to set the history as invalid if the light has moved (rotated or translated),
float historyValidity = 1.0f;
if (additionalLightData.previousTransform != additionalLightData.transform.localToWorldMatrix
|| !hdCamera.ValidShadowHistory(additionalLightData, lightData.screenSpaceShadowIndex, lightData.lightType))
historyValidity = 0.0f;
// We need to check if the camera implied an invalidation
historyValidity *= EvaluateHistoryValidity(hdCamera);
return historyValidity;
}
}
}