372 lines
19 KiB
C#
372 lines
19 KiB
C#
using UnityEngine.Experimental.Rendering;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
[GenerateHLSL]
|
|
// Define if we use SSGI, RTGI or none
|
|
enum IndirectDiffuseMode
|
|
{
|
|
Off,
|
|
ScreenSpace,
|
|
Raytrace
|
|
}
|
|
|
|
public partial class HDRenderPipeline
|
|
{
|
|
// The set of kernels that we shall be using
|
|
int m_TraceGlobalIlluminationKernel;
|
|
int m_TraceGlobalIlluminationHalfKernel;
|
|
int m_ReprojectGlobalIlluminationKernel;
|
|
int m_ReprojectGlobalIlluminationHalfKernel;
|
|
int m_BilateralUpSampleColorKernel;
|
|
int m_ConvertYCoCgToRGBKernel;
|
|
int m_ConvertYCoCgToRGBHalfKernel;
|
|
|
|
void InitScreenSpaceGlobalIllumination()
|
|
{
|
|
if (m_Asset.currentPlatformRenderPipelineSettings.supportSSGI)
|
|
{
|
|
// Grab the sets of shaders that we'll be using
|
|
ComputeShader ssGICS = m_Asset.renderPipelineResources.shaders.screenSpaceGlobalIlluminationCS;
|
|
ComputeShader bilateralUpsampleCS = m_Asset.renderPipelineResources.shaders.bilateralUpsampleCS;
|
|
|
|
// Grab the set of kernels that we shall be using
|
|
m_TraceGlobalIlluminationKernel = ssGICS.FindKernel("TraceGlobalIllumination");
|
|
m_TraceGlobalIlluminationHalfKernel = ssGICS.FindKernel("TraceGlobalIlluminationHalf");
|
|
m_ReprojectGlobalIlluminationKernel = ssGICS.FindKernel("ReprojectGlobalIllumination");
|
|
m_ReprojectGlobalIlluminationHalfKernel = ssGICS.FindKernel("ReprojectGlobalIlluminationHalf");
|
|
m_BilateralUpSampleColorKernel = bilateralUpsampleCS.FindKernel("BilateralUpSampleColor");
|
|
m_ConvertYCoCgToRGBKernel = ssGICS.FindKernel("ConvertYCoCgToRGB");
|
|
m_ConvertYCoCgToRGBHalfKernel = ssGICS.FindKernel("ConvertYCoCgToRGBHalf");
|
|
}
|
|
}
|
|
|
|
// This is shared between SSGI and RTGI
|
|
IndirectDiffuseMode GetIndirectDiffuseMode(HDCamera hdCamera)
|
|
{
|
|
IndirectDiffuseMode mode = IndirectDiffuseMode.Off;
|
|
|
|
if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSGI))
|
|
{
|
|
var settings = hdCamera.volumeStack.GetComponent<GlobalIllumination>();
|
|
if (settings.enable.value)
|
|
{
|
|
// RTGI is only valid if raytracing is enabled
|
|
bool raytracing = hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && settings.rayTracing.value;
|
|
mode = raytracing ? IndirectDiffuseMode.Raytrace : IndirectDiffuseMode.ScreenSpace;
|
|
}
|
|
}
|
|
return mode;
|
|
}
|
|
|
|
struct SSGITraceParameters
|
|
{
|
|
// Camera parameters
|
|
public int texWidth;
|
|
public int texHeight;
|
|
public int viewCount;
|
|
public Vector4 halfScreenSize;
|
|
|
|
// Generation parameters
|
|
public float nearClipPlane;
|
|
public float farClipPlane;
|
|
public bool fullResolutionSS;
|
|
public float thickness;
|
|
public int raySteps;
|
|
public Vector4 colorPyramidUvScaleAndLimitPrevFrame;
|
|
|
|
// Compute Shader
|
|
public ComputeShader ssGICS;
|
|
public int traceKernel;
|
|
public int projectKernel;
|
|
|
|
// Other parameters
|
|
public BlueNoise.DitheredTextureSet ditheredTextureSet;
|
|
public ShaderVariablesRaytracing shaderVariablesRayTracingCB;
|
|
public ComputeBuffer offsetBuffer;
|
|
}
|
|
|
|
SSGITraceParameters PrepareSSGITraceParameters(HDCamera hdCamera, GlobalIllumination settings)
|
|
{
|
|
SSGITraceParameters parameters = new SSGITraceParameters();
|
|
|
|
// Set the camera parameters
|
|
if (settings.fullResolutionSS)
|
|
{
|
|
parameters.texWidth = hdCamera.actualWidth;
|
|
parameters.texHeight = hdCamera.actualHeight;
|
|
parameters.halfScreenSize.Set(parameters.texWidth * 0.5f, parameters.texHeight * 0.5f, 2.0f / parameters.texWidth, 2.0f / parameters.texHeight);
|
|
}
|
|
else
|
|
{
|
|
parameters.texWidth = hdCamera.actualWidth / 2;
|
|
parameters.texHeight = hdCamera.actualHeight / 2;
|
|
parameters.halfScreenSize.Set(parameters.texWidth, parameters.texHeight, 1.0f / parameters.texWidth, 1.0f / parameters.texHeight);
|
|
}
|
|
parameters.viewCount = hdCamera.viewCount;
|
|
|
|
// Set the generation parameters
|
|
parameters.nearClipPlane = hdCamera.camera.nearClipPlane;
|
|
parameters.farClipPlane = hdCamera.camera.farClipPlane;
|
|
parameters.fullResolutionSS = settings.fullResolutionSS;
|
|
parameters.thickness = settings.depthBufferThickness.value;
|
|
parameters.raySteps = settings.raySteps;
|
|
parameters.colorPyramidUvScaleAndLimitPrevFrame = HDUtils.ComputeViewportScaleAndLimit(hdCamera.historyRTHandleProperties.previousViewportSize, hdCamera.historyRTHandleProperties.previousRenderTargetSize);
|
|
|
|
// Grab the right kernel
|
|
parameters.ssGICS = m_Asset.renderPipelineResources.shaders.screenSpaceGlobalIlluminationCS;
|
|
parameters.traceKernel = settings.fullResolutionSS ? m_TraceGlobalIlluminationKernel : m_TraceGlobalIlluminationHalfKernel;
|
|
parameters.projectKernel = settings.fullResolutionSS ? m_ReprojectGlobalIlluminationKernel : m_ReprojectGlobalIlluminationHalfKernel;
|
|
|
|
BlueNoise blueNoise = GetBlueNoiseManager();
|
|
parameters.ditheredTextureSet = blueNoise.DitheredTextureSet8SPP();
|
|
parameters.shaderVariablesRayTracingCB = m_ShaderVariablesRayTracingCB;
|
|
parameters.offsetBuffer = m_DepthBufferMipChainInfo.GetOffsetBufferData(m_DepthPyramidMipLevelOffsetsBuffer);
|
|
|
|
return parameters;
|
|
}
|
|
|
|
struct SSGITraceResources
|
|
{
|
|
// Input buffers
|
|
public RTHandle depthTexture;
|
|
public RTHandle normalBuffer;
|
|
public RTHandle motionVectorsBuffer;
|
|
public RTHandle colorPyramid;
|
|
public RTHandle historyDepth;
|
|
|
|
// Intermediate buffers
|
|
public RTHandle hitPointBuffer;
|
|
|
|
// Output buffers
|
|
public RTHandle outputBuffer0;
|
|
public RTHandle outputBuffer1;
|
|
}
|
|
|
|
static void ExecuteSSGITrace(CommandBuffer cmd, SSGITraceParameters parameters, SSGITraceResources resources)
|
|
{
|
|
int ssgiTileSize = 8;
|
|
int numTilesXHR = (parameters.texWidth + (ssgiTileSize - 1)) / ssgiTileSize;
|
|
int numTilesYHR = (parameters.texHeight + (ssgiTileSize - 1)) / ssgiTileSize;
|
|
|
|
// Inject all the input scalars
|
|
float n = parameters.nearClipPlane;
|
|
float f = parameters.farClipPlane;
|
|
float thicknessScale = 1.0f / (1.0f + parameters.thickness);
|
|
float thicknessBias = -n / (f - n) * (parameters.thickness * thicknessScale);
|
|
cmd.SetComputeFloatParam(parameters.ssGICS, HDShaderIDs._IndirectDiffuseThicknessScale, thicknessScale);
|
|
cmd.SetComputeFloatParam(parameters.ssGICS, HDShaderIDs._IndirectDiffuseThicknessBias, thicknessBias);
|
|
cmd.SetComputeIntParam(parameters.ssGICS, HDShaderIDs._IndirectDiffuseSteps, parameters.raySteps);
|
|
// Inject half screen size if required
|
|
if (!parameters.fullResolutionSS)
|
|
cmd.SetComputeVectorParam(parameters.ssGICS, HDShaderIDs._HalfScreenSize, parameters.halfScreenSize);
|
|
|
|
// Inject the ray-tracing sampling data
|
|
BlueNoise.BindDitheredTextureSet(cmd, parameters.ditheredTextureSet);
|
|
|
|
// Inject all the input textures/buffers
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.traceKernel, HDShaderIDs._DepthTexture, resources.depthTexture);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.traceKernel, HDShaderIDs._NormalBufferTexture, resources.normalBuffer);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.traceKernel, HDShaderIDs._IndirectDiffuseHitPointTextureRW, resources.hitPointBuffer);
|
|
cmd.SetComputeBufferParam(parameters.ssGICS, parameters.traceKernel, HDShaderIDs._DepthPyramidMipLevelOffsets, parameters.offsetBuffer);
|
|
|
|
// Do the ray marching
|
|
cmd.DispatchCompute(parameters.ssGICS, parameters.traceKernel, numTilesXHR, numTilesYHR, parameters.viewCount);
|
|
|
|
// Update global constant buffer.
|
|
// This should probably be a shader specific uniform instead of reusing the global constant buffer one since it's the only one updated here.
|
|
ConstantBuffer.PushGlobal(cmd, parameters.shaderVariablesRayTracingCB, HDShaderIDs._ShaderVariablesRaytracing);
|
|
|
|
// Inject all the input scalars
|
|
cmd.SetComputeVectorParam(parameters.ssGICS, HDShaderIDs._ColorPyramidUvScaleAndLimitPrevFrame, parameters.colorPyramidUvScaleAndLimitPrevFrame);
|
|
|
|
// Bind all the input buffers
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._DepthTexture, resources.depthTexture);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._NormalBufferTexture, resources.normalBuffer);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._CameraMotionVectorsTexture, resources.motionVectorsBuffer);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._IndirectDiffuseHitPointTexture, resources.hitPointBuffer);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._ColorPyramidTexture, resources.colorPyramid);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._HistoryDepthTexture, resources.historyDepth);
|
|
cmd.SetComputeBufferParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._DepthPyramidMipLevelOffsets, parameters.offsetBuffer);
|
|
|
|
// Bind the output texture
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._IndirectDiffuseTexture0RW, resources.outputBuffer0);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.projectKernel, HDShaderIDs._IndirectDiffuseTexture1RW, resources.outputBuffer1);
|
|
|
|
// Do the reprojection
|
|
cmd.DispatchCompute(parameters.ssGICS, parameters.projectKernel, numTilesXHR, numTilesYHR, parameters.viewCount);
|
|
}
|
|
|
|
struct SSGIConvertParameters
|
|
{
|
|
// Camera parameters
|
|
public int texWidth;
|
|
public int texHeight;
|
|
public int viewCount;
|
|
|
|
// Compute Shader
|
|
public ComputeShader ssGICS;
|
|
public int convertKernel;
|
|
public ComputeBuffer offsetBuffer;
|
|
}
|
|
|
|
SSGIConvertParameters PrepareSSGIConvertParameters(HDCamera hdCamera, bool halfResolution)
|
|
{
|
|
SSGIConvertParameters parameters = new SSGIConvertParameters();
|
|
|
|
// Set the camera parameters
|
|
if (!halfResolution)
|
|
{
|
|
parameters.texWidth = hdCamera.actualWidth;
|
|
parameters.texHeight = hdCamera.actualHeight;
|
|
}
|
|
else
|
|
{
|
|
parameters.texWidth = hdCamera.actualWidth / 2;
|
|
parameters.texHeight = hdCamera.actualHeight / 2;
|
|
}
|
|
parameters.viewCount = hdCamera.viewCount;
|
|
|
|
// Grab the right kernel
|
|
parameters.ssGICS = m_Asset.renderPipelineResources.shaders.screenSpaceGlobalIlluminationCS;
|
|
parameters.convertKernel = halfResolution ? m_ConvertYCoCgToRGBHalfKernel : m_ConvertYCoCgToRGBKernel;
|
|
|
|
parameters.offsetBuffer = m_DepthBufferMipChainInfo.GetOffsetBufferData(m_DepthPyramidMipLevelOffsetsBuffer);
|
|
|
|
return parameters;
|
|
}
|
|
|
|
struct SSGIConvertResources
|
|
{
|
|
public RTHandle depthTexture;
|
|
public RTHandle stencilBuffer;
|
|
public RTHandle normalBuffer;
|
|
public RTHandle inoutBuffer0;
|
|
public RTHandle inputBufer1;
|
|
}
|
|
|
|
static void ExecuteSSGIConversion(CommandBuffer cmd, SSGIConvertParameters parameters, SSGIConvertResources resources)
|
|
{
|
|
// Re-evaluate the dispatch parameters (we are evaluating the upsample in full resolution)
|
|
int ssgiTileSize = 8;
|
|
int numTilesXHR = (parameters.texWidth + (ssgiTileSize - 1)) / ssgiTileSize;
|
|
int numTilesYHR = (parameters.texHeight + (ssgiTileSize - 1)) / ssgiTileSize;
|
|
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.convertKernel, HDShaderIDs._DepthTexture, resources.depthTexture);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.convertKernel, HDShaderIDs._NormalBufferTexture, resources.normalBuffer);
|
|
cmd.SetComputeBufferParam(parameters.ssGICS, parameters.convertKernel, HDShaderIDs._DepthPyramidMipLevelOffsets, parameters.offsetBuffer);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.convertKernel, HDShaderIDs._IndirectDiffuseTexture0RW, resources.inoutBuffer0);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.convertKernel, HDShaderIDs._IndirectDiffuseTexture1, resources.inputBufer1);
|
|
cmd.SetComputeTextureParam(parameters.ssGICS, parameters.convertKernel, HDShaderIDs._StencilTexture, resources.stencilBuffer, 0, RenderTextureSubElement.Stencil);
|
|
cmd.SetComputeIntParams(parameters.ssGICS, HDShaderIDs._SsrStencilBit, (int)StencilUsage.TraceReflectionRay);
|
|
cmd.DispatchCompute(parameters.ssGICS, parameters.convertKernel, numTilesXHR, numTilesYHR, parameters.viewCount);
|
|
}
|
|
|
|
struct SSGIUpscaleParameters
|
|
{
|
|
// Camera parameters
|
|
public int texWidth;
|
|
public int texHeight;
|
|
public int viewCount;
|
|
public Vector4 halfScreenSize;
|
|
|
|
// Generation parameters
|
|
public Vector2 firstMipOffset;
|
|
|
|
// Compute Shader
|
|
public ComputeShader bilateralUpsampleCS;
|
|
public int upscaleKernel;
|
|
}
|
|
|
|
SSGIUpscaleParameters PrepareSSGIUpscaleParameters(HDCamera hdCamera, GlobalIllumination settings, HDUtils.PackedMipChainInfo info)
|
|
{
|
|
SSGIUpscaleParameters parameters = new SSGIUpscaleParameters();
|
|
|
|
// Set the camera parameters
|
|
parameters.texWidth = hdCamera.actualWidth;
|
|
parameters.texHeight = hdCamera.actualHeight;
|
|
parameters.viewCount = hdCamera.viewCount;
|
|
parameters.halfScreenSize.Set(parameters.texWidth / 2, parameters.texHeight / 2, 1.0f / (parameters.texWidth * 0.5f), 1.0f / (parameters.texHeight * 0.5f));
|
|
|
|
// Set the generation parameters
|
|
parameters.firstMipOffset.Set(HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].x), HDShadowUtils.Asfloat((uint)info.mipLevelOffsets[1].y));
|
|
|
|
// Grab the right kernel
|
|
parameters.bilateralUpsampleCS = m_Asset.renderPipelineResources.shaders.bilateralUpsampleCS;
|
|
parameters.upscaleKernel = m_BilateralUpSampleColorKernel;
|
|
|
|
return parameters;
|
|
}
|
|
|
|
struct SSGIUpscaleResources
|
|
{
|
|
// Input buffers
|
|
public RTHandle depthTexture;
|
|
public RTHandle inputBuffer;
|
|
|
|
// Output buffers
|
|
public RTHandle outputBuffer;
|
|
}
|
|
|
|
static void ExecuteSSGIUpscale(CommandBuffer cmd, SSGIUpscaleParameters parameters, SSGIUpscaleResources resources)
|
|
{
|
|
// Re-evaluate the dispatch parameters (we are evaluating the upsample in full resolution)
|
|
int ssgiTileSize = 8;
|
|
int numTilesXHR = (parameters.texWidth + (ssgiTileSize - 1)) / ssgiTileSize;
|
|
int numTilesYHR = (parameters.texHeight + (ssgiTileSize - 1)) / ssgiTileSize;
|
|
|
|
// Inject the input scalars
|
|
cmd.SetComputeVectorParam(parameters.bilateralUpsampleCS, HDShaderIDs._HalfScreenSize, parameters.halfScreenSize);
|
|
cmd.SetComputeVectorParam(parameters.bilateralUpsampleCS, HDShaderIDs._DepthPyramidFirstMipLevelOffset, parameters.firstMipOffset);
|
|
|
|
// Inject all the input buffers
|
|
cmd.SetComputeTextureParam(parameters.bilateralUpsampleCS, parameters.upscaleKernel, HDShaderIDs._DepthTexture, resources.depthTexture);
|
|
cmd.SetComputeTextureParam(parameters.bilateralUpsampleCS, parameters.upscaleKernel, HDShaderIDs._LowResolutionTexture, resources.inputBuffer);
|
|
|
|
// Inject the output textures
|
|
cmd.SetComputeTextureParam(parameters.bilateralUpsampleCS, parameters.upscaleKernel, HDShaderIDs._OutputUpscaledTexture, resources.outputBuffer);
|
|
|
|
// Upscale the buffer to full resolution
|
|
cmd.DispatchCompute(parameters.bilateralUpsampleCS, parameters.upscaleKernel, numTilesXHR, numTilesYHR, parameters.viewCount);
|
|
}
|
|
|
|
private float EvaluateIndirectDiffuseHistoryValidityCombined(HDCamera hdCamera, bool fullResolution, bool rayTraced)
|
|
{
|
|
// Evaluate the history validity
|
|
float effectHistoryValidity = hdCamera.EffectHistoryValidity(HDCamera.HistoryEffectSlot.GlobalIllumination0, fullResolution, rayTraced)
|
|
&& hdCamera.EffectHistoryValidity(HDCamera.HistoryEffectSlot.GlobalIllumination1, fullResolution, rayTraced) ? 1.0f : 0.0f;
|
|
return EvaluateHistoryValidity(hdCamera) * effectHistoryValidity;
|
|
}
|
|
|
|
private float EvaluateIndirectDiffuseHistoryValidity0(HDCamera hdCamera, bool fullResolution, bool rayTraced)
|
|
{
|
|
// Evaluate the history validity
|
|
float effectHistoryValidity = hdCamera.EffectHistoryValidity(HDCamera.HistoryEffectSlot.GlobalIllumination0, fullResolution, rayTraced) ? 1.0f : 0.0f;
|
|
return EvaluateHistoryValidity(hdCamera) * effectHistoryValidity;
|
|
}
|
|
|
|
private float EvaluateIndirectDiffuseHistoryValidity1(HDCamera hdCamera, bool fullResolution, bool rayTraced)
|
|
{
|
|
// Evaluate the history validity
|
|
float effectHistoryValidity = hdCamera.EffectHistoryValidity(HDCamera.HistoryEffectSlot.GlobalIllumination1, fullResolution, rayTraced) ? 1.0f : 0.0f;
|
|
return EvaluateHistoryValidity(hdCamera) * effectHistoryValidity;
|
|
}
|
|
|
|
private void PropagateIndirectDiffuseHistoryValidityCombined(HDCamera hdCamera, bool fullResolution, bool rayTraced)
|
|
{
|
|
hdCamera.PropagateEffectHistoryValidity(HDCamera.HistoryEffectSlot.GlobalIllumination0, fullResolution, rayTraced);
|
|
hdCamera.PropagateEffectHistoryValidity(HDCamera.HistoryEffectSlot.GlobalIllumination1, fullResolution, rayTraced);
|
|
}
|
|
|
|
private void PropagateIndirectDiffuseHistoryValidity0(HDCamera hdCamera, bool fullResolution, bool rayTraced)
|
|
{
|
|
hdCamera.PropagateEffectHistoryValidity(HDCamera.HistoryEffectSlot.GlobalIllumination0, fullResolution, rayTraced);
|
|
}
|
|
|
|
private void PropagateIndirectDiffuseHistoryValidity1(HDCamera hdCamera, bool fullResolution, bool rayTraced)
|
|
{
|
|
hdCamera.PropagateEffectHistoryValidity(HDCamera.HistoryEffectSlot.GlobalIllumination1, fullResolution, rayTraced);
|
|
}
|
|
}
|
|
}
|