215 lines
11 KiB
C#
215 lines
11 KiB
C#
using System;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Experimental.Rendering.RenderGraphModule;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
public partial class HDRenderPipeline
|
|
{
|
|
// String values
|
|
const string m_RayGenShaderName = "RayGenRenderer";
|
|
|
|
// Pass name for the flag pass
|
|
ShaderTagId raytracingPassID = new ShaderTagId("Forward");
|
|
RenderStateBlock m_RaytracingFlagStateBlock;
|
|
|
|
void InitRecursiveRenderer()
|
|
{
|
|
m_RaytracingFlagStateBlock = new RenderStateBlock
|
|
{
|
|
depthState = new DepthState(false, CompareFunction.LessEqual),
|
|
mask = RenderStateMask.Depth
|
|
};
|
|
}
|
|
|
|
internal TextureHandle CreateFlagMaskTexture(RenderGraph renderGraph)
|
|
{
|
|
return renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
|
|
{
|
|
colorFormat = GraphicsFormat.R8_SNorm,
|
|
dimension = TextureXR.dimension,
|
|
enableRandomWrite = true,
|
|
useMipMap = true,
|
|
name = "FlagMaskTexture"
|
|
});
|
|
}
|
|
|
|
struct RecursiveRendererParameters
|
|
{
|
|
// Camera parameters
|
|
public int texWidth;
|
|
public int texHeight;
|
|
public int viewCount;
|
|
|
|
// Effect parameters
|
|
public float rayLength;
|
|
public int maxDepth;
|
|
public float minSmoothness;
|
|
|
|
// Other data
|
|
public RayTracingAccelerationStructure accelerationStructure;
|
|
public HDRaytracingLightCluster lightCluster;
|
|
public RayTracingShader recursiveRenderingRT;
|
|
public Texture skyTexture;
|
|
public ShaderVariablesRaytracing shaderVariablesRayTracingCB;
|
|
public BlueNoise.DitheredTextureSet ditheredTextureSet;
|
|
}
|
|
|
|
RecursiveRendererParameters PrepareRecursiveRendererParameters(HDCamera hdCamera, RecursiveRendering recursiveRendering)
|
|
{
|
|
RecursiveRendererParameters rrParams = new RecursiveRendererParameters();
|
|
|
|
// Camera parameters
|
|
rrParams.texWidth = hdCamera.actualWidth;
|
|
rrParams.texHeight = hdCamera.actualHeight;
|
|
rrParams.viewCount = hdCamera.viewCount;
|
|
|
|
// Effect parameters
|
|
rrParams.rayLength = recursiveRendering.rayLength.value;
|
|
rrParams.maxDepth = recursiveRendering.maxDepth.value;
|
|
rrParams.minSmoothness = recursiveRendering.minSmoothness.value;
|
|
|
|
// Other data
|
|
rrParams.accelerationStructure = RequestAccelerationStructure();
|
|
rrParams.lightCluster = RequestLightCluster();
|
|
rrParams.recursiveRenderingRT = m_Asset.renderPipelineRayTracingResources.forwardRaytracing;
|
|
rrParams.skyTexture = m_SkyManager.GetSkyReflection(hdCamera);
|
|
rrParams.shaderVariablesRayTracingCB = m_ShaderVariablesRayTracingCB;
|
|
BlueNoise blueNoise = GetBlueNoiseManager();
|
|
rrParams.ditheredTextureSet = blueNoise.DitheredTextureSet8SPP();
|
|
|
|
return rrParams;
|
|
}
|
|
|
|
struct RecursiveRendererResources
|
|
{
|
|
// Input buffers
|
|
public RTHandle depthStencilBuffer;
|
|
public RTHandle flagMask;
|
|
|
|
// Debug buffer
|
|
public RTHandle debugBuffer;
|
|
public RTHandle rayCountTexture;
|
|
|
|
// Output buffer
|
|
public RTHandle outputBuffer;
|
|
}
|
|
|
|
// Recursive rendering works as follow:
|
|
// - Shader have a _RayTracing property
|
|
// When this property is setup to true, a RayTracingPrepass pass on the material is enabled (otherwise it is disabled)
|
|
// - Before prepass we render all object with a RayTracingPrepass pass enabled into the depth buffer for performance saving.
|
|
// Note that we will exclude from the rendering of DepthPrepass, GBuffer and Forward pass the raytraced objects but not from
|
|
// motion vector pass, so we can still benefit from motion vector. This is handled in VertMesh.hlsl (see below).
|
|
// However currently when rendering motion vector this will tag the stencil for deferred lighting, and thus could produce overshading.
|
|
// - After Transparent Depth pass we render all object with a RayTracingPrepass pass enabled into output a mask buffer (need to depth test but not to write depth)
|
|
// Note: we render two times: one to save performance and the other to write the mask, otherwise if we write the mask in the first pass it
|
|
// will not take into account the objects which could render on top of the raytracing one (If we want to do that we need to perform the pass after that
|
|
// the depth buffer is ready, which is after the Gbuffer pass, so we can't save performance).
|
|
// - During RaytracingRecursiveRender we perform a RayTracingRendering.raytrace call on all pixel tag in the mask
|
|
// It is require to exclude mesh from regular pass to save performance (for opaque) and get correct result (for transparent)
|
|
// For this we cull the mesh by setuping their position to NaN if _RayTracing is true and _EnableRecursiveRayTracing true.
|
|
// We use this method to avoid to have to deal with RenderQueue and it allow to dynamically disabled Recursive rendering
|
|
// and fallback to classic rasterize transparent this way. The code for the culling is in VertMesh()
|
|
// If raytracing is disable _EnableRecursiveRayTracing is set to false and no culling happen.
|
|
// Objects are still render in shadow and motion vector pass to keep their properties.
|
|
|
|
// We render Recursive render object before transparent, so transparent object can be overlayed on top
|
|
// like lens flare on top of headlight. We write the depth, so it correctly z-test object behind as recursive rendering
|
|
// re-render everything (Mean we should also support fog and sky into it).
|
|
class RecursiveRenderingPassData
|
|
{
|
|
public RecursiveRendererParameters parameters;
|
|
public TextureHandle depthStencilBuffer;
|
|
public TextureHandle flagMask;
|
|
public TextureHandle debugBuffer;
|
|
public TextureHandle rayCountTexture;
|
|
public TextureHandle outputBuffer;
|
|
}
|
|
|
|
TextureHandle RaytracingRecursiveRender(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle colorBuffer, TextureHandle depthPyramid, TextureHandle flagMask, TextureHandle rayCountTexture)
|
|
{
|
|
// If ray tracing is disabled in the frame settings or the effect is not enabled
|
|
RecursiveRendering recursiveSettings = hdCamera.volumeStack.GetComponent<RecursiveRendering>();
|
|
if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) || !recursiveSettings.enable.value)
|
|
return colorBuffer;
|
|
|
|
// Build the parameter structure
|
|
RecursiveRendererParameters rrParams = PrepareRecursiveRendererParameters(hdCamera, recursiveSettings);
|
|
|
|
using (var builder = renderGraph.AddRenderPass<RecursiveRenderingPassData>("Recursive Rendering Evaluation", out var passData, ProfilingSampler.Get(HDProfileId.RayTracingRecursiveRendering)))
|
|
{
|
|
builder.EnableAsyncCompute(false);
|
|
|
|
passData.parameters = rrParams;
|
|
passData.depthStencilBuffer = builder.ReadTexture(depthPyramid);
|
|
passData.flagMask = builder.ReadTexture(flagMask);
|
|
passData.rayCountTexture = builder.ReadWriteTexture(rayCountTexture);
|
|
passData.outputBuffer = builder.ReadWriteTexture(colorBuffer);
|
|
// Right now the debug buffer is written to independently of what is happening. This must be changed
|
|
// TODO RENDERGRAPH
|
|
passData.debugBuffer = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true)
|
|
{ colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Recursive Rendering Debug Texture" }));
|
|
|
|
builder.SetRenderFunc(
|
|
(RecursiveRenderingPassData data, RenderGraphContext ctx) =>
|
|
{
|
|
RecursiveRendererResources rrResources = new RecursiveRendererResources();
|
|
rrResources.depthStencilBuffer = data.depthStencilBuffer;
|
|
rrResources.flagMask = data.flagMask;
|
|
rrResources.debugBuffer = data.debugBuffer;
|
|
rrResources.rayCountTexture = data.rayCountTexture;
|
|
rrResources.outputBuffer = data.outputBuffer;
|
|
ExecuteRecursiveRendering(ctx.cmd, data.parameters, rrResources);
|
|
});
|
|
|
|
PushFullScreenDebugTexture(m_RenderGraph, passData.debugBuffer, FullScreenDebugMode.RecursiveRayTracing);
|
|
|
|
return passData.outputBuffer;
|
|
}
|
|
}
|
|
|
|
static void ExecuteRecursiveRendering(CommandBuffer cmd, RecursiveRendererParameters rrParams, RecursiveRendererResources rrResources)
|
|
{
|
|
// Define the shader pass to use for the reflection pass
|
|
cmd.SetRayTracingShaderPass(rrParams.recursiveRenderingRT, "ForwardDXR");
|
|
|
|
// Set the acceleration structure for the pass
|
|
cmd.SetRayTracingAccelerationStructure(rrParams.recursiveRenderingRT, HDShaderIDs._RaytracingAccelerationStructureName, rrParams.accelerationStructure);
|
|
|
|
// Inject the ray-tracing sampling data
|
|
BlueNoise.BindDitheredTextureSet(cmd, rrParams.ditheredTextureSet);
|
|
|
|
// Update Global Constant Buffer.
|
|
rrParams.shaderVariablesRayTracingCB._RaytracingRayMaxLength = rrParams.rayLength;
|
|
#if NO_RAY_RECURSION
|
|
rrParams.shaderVariablesRayTracingCB._RaytracingMaxRecursion = 1;
|
|
#else
|
|
rrParams.shaderVariablesRayTracingCB._RaytracingMaxRecursion = rrParams.maxDepth;
|
|
#endif
|
|
rrParams.shaderVariablesRayTracingCB._RaytracingReflectionMinSmoothness = rrParams.minSmoothness;
|
|
ConstantBuffer.PushGlobal(cmd, rrParams.shaderVariablesRayTracingCB, HDShaderIDs._ShaderVariablesRaytracing);
|
|
|
|
// Fecth the temporary buffers we shall be using
|
|
cmd.SetRayTracingTextureParam(rrParams.recursiveRenderingRT, HDShaderIDs._RaytracingFlagMask, rrResources.flagMask);
|
|
cmd.SetRayTracingTextureParam(rrParams.recursiveRenderingRT, HDShaderIDs._DepthTexture, rrResources.depthStencilBuffer);
|
|
cmd.SetRayTracingTextureParam(rrParams.recursiveRenderingRT, HDShaderIDs._CameraColorTextureRW, rrResources.outputBuffer);
|
|
|
|
// Set ray count texture
|
|
cmd.SetRayTracingTextureParam(rrParams.recursiveRenderingRT, HDShaderIDs._RayCountTexture, rrResources.rayCountTexture);
|
|
|
|
// LightLoop data
|
|
rrParams.lightCluster.BindLightClusterData(cmd);
|
|
|
|
// Set the data for the ray miss
|
|
cmd.SetRayTracingTextureParam(rrParams.recursiveRenderingRT, HDShaderIDs._SkyTexture, rrParams.skyTexture);
|
|
|
|
// If this is the right debug mode and we have at least one light, write the first shadow to the de-noised texture
|
|
cmd.SetRayTracingTextureParam(rrParams.recursiveRenderingRT, HDShaderIDs._RaytracingPrimaryDebug, rrResources.debugBuffer);
|
|
|
|
// Run the computation
|
|
cmd.DispatchRays(rrParams.recursiveRenderingRT, m_RayGenShaderName, (uint)rrParams.texWidth, (uint)rrParams.texHeight, (uint)rrParams.viewCount);
|
|
}
|
|
}
|
|
}
|