778 lines
46 KiB
C#
778 lines
46 KiB
C#
|
|
using Unity.Mathematics;
|
||
|
|
using UnityEngine.PathTracing.Core;
|
||
|
|
using UnityEngine.PathTracing.Lightmapping;
|
||
|
|
using UnityEngine.Rendering;
|
||
|
|
using UnityEngine.Rendering.Sampling;
|
||
|
|
using UnityEngine.Rendering.UnifiedRayTracing;
|
||
|
|
|
||
|
|
namespace UnityEngine.PathTracing.Integration
|
||
|
|
{
|
||
|
|
internal enum AntiAliasingType { Stochastic, SuperSampling };
|
||
|
|
|
||
|
|
internal static class LightmapIntegratorShaderIDs
|
||
|
|
{
|
||
|
|
public static readonly int LightmapInOut = Shader.PropertyToID("g_LightmapInOut");
|
||
|
|
public static readonly int DirectionalInOut = Shader.PropertyToID("g_DirectionalInOut");
|
||
|
|
public static readonly int AdaptiveInOut = Shader.PropertyToID("g_AdaptiveInOut");
|
||
|
|
public static readonly int AdaptiveSampling = Shader.PropertyToID("g_AdaptiveSampling");
|
||
|
|
public static readonly int AdaptiveStopSamples = Shader.PropertyToID("g_AdaptiveStopSamples");
|
||
|
|
public static readonly int AdaptiveCheckIfFullyConverged = Shader.PropertyToID("g_AdaptiveCheckIfFullyConverged");
|
||
|
|
public static readonly int AdaptiveThreshold = Shader.PropertyToID("g_AdaptiveThreshold");
|
||
|
|
public static readonly int AccumulateDirectional = Shader.PropertyToID("g_AccumulateDirectional");
|
||
|
|
public static readonly int SampleCountInOut = Shader.PropertyToID("g_SampleCountInOut");
|
||
|
|
public static readonly int SampleCountIn = Shader.PropertyToID("g_SampleCountIn");
|
||
|
|
public static readonly int ShaderLocalToWorld = Shader.PropertyToID("g_ShaderLocalToWorld");
|
||
|
|
public static readonly int ShaderLocalToWorldNormals = Shader.PropertyToID("g_ShaderLocalToWorldNormals");
|
||
|
|
public static readonly int InstanceGeometryIndex = Shader.PropertyToID("g_InstanceGeometryIndex");
|
||
|
|
public static readonly int GISampleCount = Shader.PropertyToID("g_GISampleCount");
|
||
|
|
public static readonly int AOMaxDistance = Shader.PropertyToID("g_AOMaxDistance");
|
||
|
|
public static readonly int InputSampleCountInW = Shader.PropertyToID("g_InputSampleCountInW");
|
||
|
|
public static readonly int Normals = Shader.PropertyToID("g_Normals");
|
||
|
|
public static readonly int TextureWidth = Shader.PropertyToID("g_TextureWidth");
|
||
|
|
public static readonly int TextureHeight = Shader.PropertyToID("g_TextureHeight");
|
||
|
|
public static readonly int ReceiveShadows = Shader.PropertyToID("g_ReceiveShadows");
|
||
|
|
public static readonly int PushOff = Shader.PropertyToID("g_PushOff");
|
||
|
|
public static readonly int IndirectDispatchDimensions = Shader.PropertyToID("g_IndirectDispatchDimensions");
|
||
|
|
public static readonly int IndirectDispatchoriginalDimensions = Shader.PropertyToID("g_IndirectDispatchOriginalDimensions");
|
||
|
|
public static readonly int InputBufferSelector = Shader.PropertyToID("g_InputBufferSelector");
|
||
|
|
public static readonly int InputBufferLength = Shader.PropertyToID("g_InputBufferLength");
|
||
|
|
public static readonly int InputBuffer0 = Shader.PropertyToID("g_InputBuffer0");
|
||
|
|
public static readonly int InputBuffer1 = Shader.PropertyToID("g_InputBuffer1");
|
||
|
|
public static readonly int SelectionOutput = Shader.PropertyToID("g_SelectionOutput");
|
||
|
|
public static readonly int GBuffer = Shader.PropertyToID("g_GBuffer");
|
||
|
|
public static readonly int SampleOffset = Shader.PropertyToID("g_SampleOffset");
|
||
|
|
public static readonly int StochasticAntialiasing = Shader.PropertyToID("g_StochasticAntialiasing");
|
||
|
|
public static readonly int SuperSampleWidth = Shader.PropertyToID("g_SuperSampleWidth");
|
||
|
|
public static readonly int Float3Buffer = Shader.PropertyToID("g_Float3Buffer");
|
||
|
|
public static readonly int DestinationTexture = Shader.PropertyToID("g_DestinationTexture");
|
||
|
|
public static readonly int SourceTexture = Shader.PropertyToID("g_SourceTexture");
|
||
|
|
public static readonly int SourceX = Shader.PropertyToID("g_SourceX");
|
||
|
|
public static readonly int SourceY = Shader.PropertyToID("g_SourceY");
|
||
|
|
public static readonly int SourceWidth = Shader.PropertyToID("g_SourceWidth");
|
||
|
|
public static readonly int SourceHeight = Shader.PropertyToID("g_SourceHeight");
|
||
|
|
public static readonly int DestinationX = Shader.PropertyToID("g_DestinationX");
|
||
|
|
public static readonly int DestinationY = Shader.PropertyToID("g_DestinationY");
|
||
|
|
public static readonly int TextureInOut = Shader.PropertyToID("g_TextureInOut");
|
||
|
|
public static readonly int ExpandedOutput = Shader.PropertyToID("g_ExpandedOutput");
|
||
|
|
public static readonly int ExpandedDirectional = Shader.PropertyToID("g_ExpandedDirectional");
|
||
|
|
public static readonly int ExpandedSampleCountInW = Shader.PropertyToID("g_ExpandedSampleCountInW");
|
||
|
|
public static readonly int ExpandedTexelSampleWidth = Shader.PropertyToID("g_ExpandedTexelSampleWidth");
|
||
|
|
public static readonly int MaxLocalSampleCount = Shader.PropertyToID("g_MaxLocalSampleCount");
|
||
|
|
public static readonly int SourceBuffer = Shader.PropertyToID("g_SourceBuffer");
|
||
|
|
public static readonly int SourceLength = Shader.PropertyToID("g_SourceLength");
|
||
|
|
public static readonly int SourceStride = Shader.PropertyToID("g_SourceStride");
|
||
|
|
public static readonly int GBufferLength = Shader.PropertyToID("g_GBufferLength");
|
||
|
|
public static readonly int CompactedGBuffer = Shader.PropertyToID("g_CompactedGBuffer");
|
||
|
|
public static readonly int InstanceWidth = Shader.PropertyToID("g_InstanceWidth");
|
||
|
|
public static readonly int ChunkOffsetX = Shader.PropertyToID("g_ChunkOffsetX");
|
||
|
|
public static readonly int ChunkOffsetY = Shader.PropertyToID("g_ChunkOffsetY");
|
||
|
|
public static readonly int LightmapSamplesExpanded = Shader.PropertyToID("g_LightmapSamplesExpanded");
|
||
|
|
}
|
||
|
|
|
||
|
|
internal class LightmapOccupancyIntegrator
|
||
|
|
{
|
||
|
|
private ComputeShader _occupancyShader;
|
||
|
|
private int _occupancyKernel;
|
||
|
|
|
||
|
|
public void Prepare(ComputeShader occupancyShader)
|
||
|
|
{
|
||
|
|
_occupancyShader = occupancyShader;
|
||
|
|
Debug.Assert(_occupancyShader != null);
|
||
|
|
_occupancyKernel = _occupancyShader.FindKernel("BlitOccupancy");
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Accumulate(
|
||
|
|
CommandBuffer cmd,
|
||
|
|
Vector2Int instanceTexelSize,
|
||
|
|
Vector2Int instanceTexelOffset,
|
||
|
|
UVFallbackBuffer uvFallbackBuffer,
|
||
|
|
RenderTexture output)
|
||
|
|
{
|
||
|
|
uvFallbackBuffer.Bind(cmd, _occupancyShader, _occupancyKernel, instanceTexelOffset);
|
||
|
|
cmd.SetComputeTextureParam(_occupancyShader, _occupancyKernel, LightmapIntegratorShaderIDs.LightmapInOut, output);
|
||
|
|
_occupancyShader.GetKernelThreadGroupSizes(_occupancyKernel, out uint x, out uint y, out _);
|
||
|
|
cmd.DispatchCompute(_occupancyShader, _occupancyKernel, GraphicsHelpers.DivUp(instanceTexelSize.x, x), GraphicsHelpers.DivUp(instanceTexelSize.y, y), 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal class LightmapDirectIntegrator : System.IDisposable
|
||
|
|
{
|
||
|
|
private IRayTracingShader _accumulationShader;
|
||
|
|
private ComputeShader _normalizationShader;
|
||
|
|
private int _normalizationKernel;
|
||
|
|
private int _directionalNormalizationKernel;
|
||
|
|
private SamplingResources _samplingResources;
|
||
|
|
private RTHandle _emptyTexture;
|
||
|
|
private GraphicsBuffer _accumulationDispatchBuffer;
|
||
|
|
private ComputeShader _expansionHelpers;
|
||
|
|
private int _populateAccumulationDispatchKernel;
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
_accumulationDispatchBuffer?.Dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
public LightmapDirectIntegrator()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Prepare(IRayTracingShader accumulationShader, ComputeShader normalizationShader, ComputeShader expansionHelpers, SamplingResources samplingResources, RTHandle emptyExposureTexture)
|
||
|
|
{
|
||
|
|
_accumulationShader = accumulationShader;
|
||
|
|
Debug.Assert(_accumulationShader != null);
|
||
|
|
|
||
|
|
_normalizationShader = normalizationShader;
|
||
|
|
Debug.Assert(_normalizationShader != null);
|
||
|
|
_normalizationKernel = _normalizationShader.FindKernel("NormalizeRadiance");
|
||
|
|
_directionalNormalizationKernel = _normalizationShader.FindKernel("NormalizeDirection");
|
||
|
|
|
||
|
|
_samplingResources = samplingResources;
|
||
|
|
_emptyTexture = emptyExposureTexture;
|
||
|
|
|
||
|
|
_expansionHelpers = expansionHelpers;
|
||
|
|
_populateAccumulationDispatchKernel = _expansionHelpers.FindKernel("PopulateAccumulationDispatch");
|
||
|
|
_accumulationDispatchBuffer = RayTracingHelper.CreateDispatchIndirectBuffer();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Accumulate(
|
||
|
|
CommandBuffer cmd,
|
||
|
|
uint sampleCountToTakePerTexel,
|
||
|
|
uint currentSampleCountPerTexel,
|
||
|
|
Matrix4x4 shaderLocalToWorld,
|
||
|
|
Matrix4x4 shaderLocalToWorldNormals,
|
||
|
|
int instanceGeometryIndex,
|
||
|
|
Vector2Int instanceTexelSize,
|
||
|
|
uint2 chunkOffset,
|
||
|
|
World world,
|
||
|
|
GraphicsBuffer traceScratchBuffer,
|
||
|
|
GraphicsBuffer gBuffer,
|
||
|
|
uint expandedSampleWidth,
|
||
|
|
GraphicsBuffer expandedOutput,
|
||
|
|
GraphicsBuffer expandedDirectional,
|
||
|
|
GraphicsBuffer compactedTexelIndices,
|
||
|
|
GraphicsBuffer compactedGbufferLength,
|
||
|
|
bool receiveShadows,
|
||
|
|
float pushOff,
|
||
|
|
uint lightEvaluationsPerBounce,
|
||
|
|
bool newChunkStarted)
|
||
|
|
{
|
||
|
|
bool doDirectional = expandedDirectional != null;
|
||
|
|
int instanceWidth = instanceTexelSize.x;
|
||
|
|
int instanceHeight = instanceTexelSize.y;
|
||
|
|
Debug.Assert(math.ispow2(expandedSampleWidth));
|
||
|
|
Debug.Assert(gBuffer.count == expandedOutput.count);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel <= expandedSampleWidth);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel > 0);
|
||
|
|
|
||
|
|
// path tracing inputs
|
||
|
|
bool preExpose = false;
|
||
|
|
float environmentIntensityMultiplier = 1.0f;
|
||
|
|
Util.BindPathTracingInputs(cmd, _accumulationShader, false, lightEvaluationsPerBounce, preExpose, 0, environmentIntensityMultiplier, RenderedGameObjectsFilter.OnlyStatic, _samplingResources, _emptyTexture);
|
||
|
|
Util.BindWorld(cmd, _accumulationShader, world, 1024);
|
||
|
|
|
||
|
|
var requiredSizeInBytes = _accumulationShader.GetTraceScratchBufferRequiredSizeInBytes((uint)expandedOutput.count, 1, 1);
|
||
|
|
if (requiredSizeInBytes > 0)
|
||
|
|
{
|
||
|
|
var actualScratchBufferSize = (ulong)(traceScratchBuffer.count * traceScratchBuffer.stride);
|
||
|
|
Debug.Assert(traceScratchBuffer.stride == sizeof(uint));
|
||
|
|
Debug.Assert(requiredSizeInBytes <= actualScratchBufferSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorld, shaderLocalToWorld);
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorldNormals, shaderLocalToWorldNormals);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceGeometryIndex, instanceGeometryIndex);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ReceiveShadows, receiveShadows ? 1 : 0);
|
||
|
|
_accumulationShader.SetFloatParam(cmd, LightmapIntegratorShaderIDs.PushOff, pushOff);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceWidth, instanceWidth);
|
||
|
|
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.AccumulateDirectional, doDirectional ? 1 : 0);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.GBuffer, gBuffer);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.CompactedGBuffer, compactedTexelIndices);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.ExpandedOutput, expandedOutput);
|
||
|
|
if (doDirectional)
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.ExpandedDirectional, expandedDirectional);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ExpandedTexelSampleWidth, (int)expandedSampleWidth);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetX, (int)chunkOffset.x);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetY, (int)chunkOffset.y);
|
||
|
|
|
||
|
|
if (newChunkStarted)
|
||
|
|
{
|
||
|
|
// Its time to repopulate the indirect dispatch buffers (as a new instance has started). Use the compacted size for this.
|
||
|
|
ExpansionHelpers.PopulateAccumulationIndirectDispatch(cmd, _accumulationShader, _expansionHelpers, _populateAccumulationDispatchKernel, expandedSampleWidth, compactedGbufferLength, _accumulationDispatchBuffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
// accumulate (expanded)
|
||
|
|
{
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.SampleOffset, (int)currentSampleCountPerTexel);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.MaxLocalSampleCount, (int)sampleCountToTakePerTexel);
|
||
|
|
cmd.BeginSample("Accumulation (Expanded)");
|
||
|
|
_accumulationShader.Dispatch(cmd, traceScratchBuffer, _accumulationDispatchBuffer);
|
||
|
|
cmd.EndSample("Accumulation (Expanded)");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Normalize(CommandBuffer cmd, RenderTexture lightmapInOut)
|
||
|
|
{
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _normalizationKernel, LightmapIntegratorShaderIDs.LightmapInOut, lightmapInOut);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureWidth, lightmapInOut.width);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureHeight, lightmapInOut.height);
|
||
|
|
_normalizationShader.GetKernelThreadGroupSizes(_normalizationKernel, out uint x, out uint y, out _);
|
||
|
|
cmd.DispatchCompute(_normalizationShader, _normalizationKernel, GraphicsHelpers.DivUp(lightmapInOut.width, x), GraphicsHelpers.DivUp(lightmapInOut.height, y), 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void NormalizeDirectional(CommandBuffer cmd, RenderTexture directionalInOut, RenderTexture sampleCountInW, RenderTexture normals)
|
||
|
|
{
|
||
|
|
Debug.Assert(directionalInOut.width == sampleCountInW.width && directionalInOut.height == sampleCountInW.height);
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _directionalNormalizationKernel, LightmapIntegratorShaderIDs.DirectionalInOut, directionalInOut);
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _directionalNormalizationKernel, LightmapIntegratorShaderIDs.InputSampleCountInW, sampleCountInW);
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _directionalNormalizationKernel, LightmapIntegratorShaderIDs.Normals, normals);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureWidth, directionalInOut.width);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureHeight, directionalInOut.height);
|
||
|
|
_normalizationShader.GetKernelThreadGroupSizes(_directionalNormalizationKernel, out uint x, out uint y, out uint _);
|
||
|
|
cmd.DispatchCompute(_normalizationShader, _directionalNormalizationKernel, GraphicsHelpers.DivUp(directionalInOut.width, x), GraphicsHelpers.DivUp(directionalInOut.height, y), 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal class LightmapIndirectIntegrator : System.IDisposable
|
||
|
|
{
|
||
|
|
private IRayTracingShader _accumulationShader;
|
||
|
|
private ComputeShader _normalizationShader;
|
||
|
|
private int _normalizationKernel;
|
||
|
|
private int _directionalNormalizationKernel;
|
||
|
|
private SamplingResources _samplingResources;
|
||
|
|
private RTHandle _emptyTexture;
|
||
|
|
private bool _countNEERayAsPathSegment;
|
||
|
|
private GraphicsBuffer _accumulationDispatchBuffer;
|
||
|
|
private ComputeShader _expansionHelpers;
|
||
|
|
private int _populateAccumulationDispatchKernel;
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
_accumulationDispatchBuffer?.Dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
public LightmapIndirectIntegrator(bool countNEERayAsPathSegment)
|
||
|
|
{
|
||
|
|
_countNEERayAsPathSegment = countNEERayAsPathSegment;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Prepare(IRayTracingShader accumulationShader, ComputeShader normalizationShader, ComputeShader expansionHelpers, SamplingResources samplingResources, RTHandle emptyExposureTexture)
|
||
|
|
{
|
||
|
|
_accumulationShader = accumulationShader;
|
||
|
|
Debug.Assert(_accumulationShader != null);
|
||
|
|
|
||
|
|
_normalizationShader = normalizationShader;
|
||
|
|
Debug.Assert(_normalizationShader != null);
|
||
|
|
_normalizationKernel = _normalizationShader.FindKernel("NormalizeRadiance");
|
||
|
|
_directionalNormalizationKernel = _normalizationShader.FindKernel("NormalizeDirection");
|
||
|
|
|
||
|
|
_samplingResources = samplingResources;
|
||
|
|
_emptyTexture = emptyExposureTexture;
|
||
|
|
|
||
|
|
_expansionHelpers = expansionHelpers;
|
||
|
|
_populateAccumulationDispatchKernel = _expansionHelpers.FindKernel("PopulateAccumulationDispatch");
|
||
|
|
_accumulationDispatchBuffer = RayTracingHelper.CreateDispatchIndirectBuffer();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Accumulate(
|
||
|
|
CommandBuffer cmd,
|
||
|
|
uint sampleCountToTakePerTexel,
|
||
|
|
uint currentSampleCountPerTexel,
|
||
|
|
uint bounceCount,
|
||
|
|
Matrix4x4 shaderLocalToWorld,
|
||
|
|
Matrix4x4 shaderLocalToWorldNormals,
|
||
|
|
int instanceGeometryIndex,
|
||
|
|
Vector2Int instanceTexelSize,
|
||
|
|
uint2 chunkOffset,
|
||
|
|
World world,
|
||
|
|
GraphicsBuffer traceScratchBuffer,
|
||
|
|
GraphicsBuffer gBuffer,
|
||
|
|
uint expandedSampleWidth,
|
||
|
|
GraphicsBuffer expandedOutput,
|
||
|
|
GraphicsBuffer expandedDirectional,
|
||
|
|
GraphicsBuffer compactedTexelIndices,
|
||
|
|
GraphicsBuffer compactedGbufferLength,
|
||
|
|
float pushOff,
|
||
|
|
uint lightEvaluationsPerBounce,
|
||
|
|
bool newChunkStarted)
|
||
|
|
{
|
||
|
|
bool doDirectional = expandedDirectional != null;
|
||
|
|
int instanceWidth = instanceTexelSize.x;
|
||
|
|
int instanceHeight = instanceTexelSize.y;
|
||
|
|
Debug.Assert(math.ispow2(expandedSampleWidth));
|
||
|
|
Debug.Assert(gBuffer.count == expandedOutput.count);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel <= expandedSampleWidth);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel > 0);
|
||
|
|
|
||
|
|
// path tracing inputs
|
||
|
|
bool preExpose = false;
|
||
|
|
float environmentIntensityMultiplier = 1.0f;
|
||
|
|
Util.BindPathTracingInputs(cmd, _accumulationShader, _countNEERayAsPathSegment, lightEvaluationsPerBounce, preExpose, (int)bounceCount, environmentIntensityMultiplier, RenderedGameObjectsFilter.OnlyStatic, _samplingResources, _emptyTexture);
|
||
|
|
Util.BindWorld(cmd, _accumulationShader, world, 1024);
|
||
|
|
|
||
|
|
var requiredSizeInBytes = _accumulationShader.GetTraceScratchBufferRequiredSizeInBytes((uint)expandedOutput.count, 1, 1);
|
||
|
|
if (requiredSizeInBytes > 0)
|
||
|
|
{
|
||
|
|
var actualScratchBufferSize = (ulong)(traceScratchBuffer.count * traceScratchBuffer.stride);
|
||
|
|
Debug.Assert(traceScratchBuffer.stride == sizeof(uint));
|
||
|
|
Debug.Assert(requiredSizeInBytes <= actualScratchBufferSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorld, shaderLocalToWorld);
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorldNormals, shaderLocalToWorldNormals);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceGeometryIndex, instanceGeometryIndex);
|
||
|
|
_accumulationShader.SetFloatParam(cmd, LightmapIntegratorShaderIDs.PushOff, pushOff);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceWidth, instanceWidth);
|
||
|
|
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.AccumulateDirectional, doDirectional ? 1 : 0);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.GBuffer, gBuffer);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.CompactedGBuffer, compactedTexelIndices);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.ExpandedOutput, expandedOutput);
|
||
|
|
if (doDirectional)
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.ExpandedDirectional, expandedDirectional);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ExpandedTexelSampleWidth, (int)expandedSampleWidth);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetX, (int)chunkOffset.x);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetY, (int)chunkOffset.y);
|
||
|
|
|
||
|
|
if (newChunkStarted)
|
||
|
|
{
|
||
|
|
// Its time to repopulate the indirect dispatch buffers (as a new instance has started). Use the compacted size for this.
|
||
|
|
ExpansionHelpers.PopulateAccumulationIndirectDispatch(cmd, _accumulationShader, _expansionHelpers, _populateAccumulationDispatchKernel, expandedSampleWidth, compactedGbufferLength, _accumulationDispatchBuffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
// accumulate (expanded)
|
||
|
|
{
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.SampleOffset, (int)currentSampleCountPerTexel);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.MaxLocalSampleCount, (int)sampleCountToTakePerTexel);
|
||
|
|
cmd.BeginSample("Accumulation (Expanded)");
|
||
|
|
_accumulationShader.Dispatch(cmd, traceScratchBuffer, _accumulationDispatchBuffer);
|
||
|
|
cmd.EndSample("Accumulation (Expanded)");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Normalize(CommandBuffer cmd, RenderTexture lightmapInOut)
|
||
|
|
{
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _normalizationKernel, LightmapIntegratorShaderIDs.LightmapInOut, lightmapInOut);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureWidth, lightmapInOut.width);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureHeight, lightmapInOut.height);
|
||
|
|
_normalizationShader.GetKernelThreadGroupSizes(_normalizationKernel, out uint x, out uint y, out _);
|
||
|
|
cmd.DispatchCompute(_normalizationShader, _normalizationKernel, GraphicsHelpers.DivUp(lightmapInOut.width, x), GraphicsHelpers.DivUp(lightmapInOut.height, y), 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void NormalizeDirectional(CommandBuffer cmd, RenderTexture directionalInOut, RenderTexture sampleCountInW, RenderTexture normals)
|
||
|
|
{
|
||
|
|
Debug.Assert(directionalInOut.width == sampleCountInW.width && directionalInOut.height == sampleCountInW.height);
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _directionalNormalizationKernel, LightmapIntegratorShaderIDs.DirectionalInOut, directionalInOut);
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _directionalNormalizationKernel, LightmapIntegratorShaderIDs.InputSampleCountInW, sampleCountInW);
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _directionalNormalizationKernel, LightmapIntegratorShaderIDs.Normals, normals);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureWidth, directionalInOut.width);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureHeight, directionalInOut.height);
|
||
|
|
_normalizationShader.GetKernelThreadGroupSizes(_directionalNormalizationKernel, out uint x, out uint y, out _);
|
||
|
|
cmd.DispatchCompute(_normalizationShader, _directionalNormalizationKernel, GraphicsHelpers.DivUp(directionalInOut.width, x), GraphicsHelpers.DivUp(directionalInOut.height, y), 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal class LightmapAOIntegrator : System.IDisposable
|
||
|
|
{
|
||
|
|
private IRayTracingShader _accumulationShader;
|
||
|
|
private ComputeShader _normalizationShader;
|
||
|
|
private int _normalizationKernel;
|
||
|
|
private SamplingResources _samplingResources;
|
||
|
|
private RTHandle _emptyTexture;
|
||
|
|
private GraphicsBuffer _accumulationDispatchBuffer;
|
||
|
|
private ComputeShader _expansionHelpers;
|
||
|
|
private int _populateAccumulationDispatchKernel;
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
_accumulationDispatchBuffer?.Dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Prepare(IRayTracingShader accumulationShader, ComputeShader normalizationShader, ComputeShader expansionHelpers, SamplingResources samplingResources, RTHandle emptyExposureTexture)
|
||
|
|
{
|
||
|
|
_accumulationShader = accumulationShader;
|
||
|
|
Debug.Assert(_accumulationShader != null);
|
||
|
|
|
||
|
|
_normalizationShader = normalizationShader;
|
||
|
|
Debug.Assert(_normalizationShader != null);
|
||
|
|
_normalizationKernel = _normalizationShader.FindKernel("NormalizeAO");
|
||
|
|
|
||
|
|
_samplingResources = samplingResources;
|
||
|
|
_emptyTexture = emptyExposureTexture;
|
||
|
|
|
||
|
|
_expansionHelpers = expansionHelpers;
|
||
|
|
_populateAccumulationDispatchKernel = _expansionHelpers.FindKernel("PopulateAccumulationDispatch");
|
||
|
|
_accumulationDispatchBuffer = RayTracingHelper.CreateDispatchIndirectBuffer();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Accumulate(
|
||
|
|
CommandBuffer cmd,
|
||
|
|
uint sampleCountToTakePerTexel,
|
||
|
|
uint currentSampleCountPerTexel,
|
||
|
|
Matrix4x4 shaderLocalToWorld,
|
||
|
|
Matrix4x4 shaderLocalToWorldNormals,
|
||
|
|
int instanceGeometryIndex,
|
||
|
|
Vector2Int instanceTexelSize,
|
||
|
|
uint2 chunkOffset,
|
||
|
|
World world,
|
||
|
|
GraphicsBuffer traceScratchBuffer,
|
||
|
|
GraphicsBuffer gBuffer,
|
||
|
|
uint expandedSampleWidth,
|
||
|
|
GraphicsBuffer expandedOutput,
|
||
|
|
GraphicsBuffer compactedTexelIndices,
|
||
|
|
GraphicsBuffer compactedGbufferLength,
|
||
|
|
float pushOff,
|
||
|
|
float aoMaxDistance,
|
||
|
|
bool newChunkStarted)
|
||
|
|
{
|
||
|
|
int instanceWidth = instanceTexelSize.x;
|
||
|
|
int instanceHeight = instanceTexelSize.y;
|
||
|
|
Debug.Assert(math.ispow2(expandedSampleWidth));
|
||
|
|
Debug.Assert(gBuffer.count == expandedOutput.count);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel <= expandedSampleWidth);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel > 0);
|
||
|
|
|
||
|
|
// path tracing inputs
|
||
|
|
uint lightEvaluationsPerBounce = 1;
|
||
|
|
bool preExpose = false;
|
||
|
|
float environmentIntensityMultipler = 1.0f;
|
||
|
|
Util.BindPathTracingInputs(cmd, _accumulationShader, false, lightEvaluationsPerBounce, preExpose, 0, environmentIntensityMultipler, RenderedGameObjectsFilter.OnlyStatic, _samplingResources, _emptyTexture);
|
||
|
|
Util.BindWorld(cmd, _accumulationShader, world, 1024);
|
||
|
|
|
||
|
|
var requiredSizeInBytes = _accumulationShader.GetTraceScratchBufferRequiredSizeInBytes((uint)expandedOutput.count, 1, 1);
|
||
|
|
if (requiredSizeInBytes > 0)
|
||
|
|
{
|
||
|
|
var actualScratchBufferSize = (ulong)(traceScratchBuffer.count * traceScratchBuffer.stride);
|
||
|
|
Debug.Assert(traceScratchBuffer.stride == sizeof(uint));
|
||
|
|
Debug.Assert(requiredSizeInBytes <= actualScratchBufferSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorld, shaderLocalToWorld);
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorldNormals, shaderLocalToWorldNormals);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceGeometryIndex, instanceGeometryIndex);
|
||
|
|
_accumulationShader.SetFloatParam(cmd, LightmapIntegratorShaderIDs.PushOff, pushOff);
|
||
|
|
_accumulationShader.SetFloatParam(cmd, LightmapIntegratorShaderIDs.AOMaxDistance, aoMaxDistance);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceWidth, instanceWidth);
|
||
|
|
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.GBuffer, gBuffer);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.CompactedGBuffer, compactedTexelIndices);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.ExpandedOutput, expandedOutput);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ExpandedTexelSampleWidth, (int)expandedSampleWidth);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetX, (int)chunkOffset.x);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetY, (int)chunkOffset.y);
|
||
|
|
|
||
|
|
if (newChunkStarted)
|
||
|
|
{
|
||
|
|
// Its time to repopulate the indirect dispatch buffers (as a new instance has started). Use the compacted size for this.
|
||
|
|
ExpansionHelpers.PopulateAccumulationIndirectDispatch(cmd, _accumulationShader, _expansionHelpers, _populateAccumulationDispatchKernel, expandedSampleWidth, compactedGbufferLength, _accumulationDispatchBuffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
// accumulate (expanded)
|
||
|
|
{
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.SampleOffset, (int)currentSampleCountPerTexel);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.MaxLocalSampleCount, (int)sampleCountToTakePerTexel);
|
||
|
|
cmd.BeginSample("Accumulation (Expanded)");
|
||
|
|
_accumulationShader.Dispatch(cmd, traceScratchBuffer, _accumulationDispatchBuffer);
|
||
|
|
cmd.EndSample("Accumulation (Expanded)");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Normalize(CommandBuffer cmd, RenderTexture lightmap)
|
||
|
|
{
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _normalizationKernel, LightmapIntegratorShaderIDs.LightmapInOut, lightmap);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureWidth, lightmap.width);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureHeight, lightmap.height);
|
||
|
|
_normalizationShader.GetKernelThreadGroupSizes(_normalizationKernel, out uint x, out uint y, out _);
|
||
|
|
cmd.DispatchCompute(_normalizationShader, _normalizationKernel, GraphicsHelpers.DivUp(lightmap.width, x), GraphicsHelpers.DivUp(lightmap.height, y), 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal class LightmapValidityIntegrator : System.IDisposable
|
||
|
|
{
|
||
|
|
IRayTracingShader _accumulationShader;
|
||
|
|
ComputeShader _normalizationShader;
|
||
|
|
int _normalizationKernel;
|
||
|
|
SamplingResources _samplingResources;
|
||
|
|
RTHandle _emptyTexture;
|
||
|
|
private GraphicsBuffer _accumulationDispatchBuffer;
|
||
|
|
private ComputeShader _expansionHelpers;
|
||
|
|
private int _populateAccumulationDispatchKernel;
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
_accumulationDispatchBuffer?.Dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Prepare(IRayTracingShader accumulationShader, ComputeShader normalizationShader, ComputeShader expansionHelpers, SamplingResources samplingResources, RTHandle emptyExposureTexture)
|
||
|
|
{
|
||
|
|
_accumulationShader = accumulationShader;
|
||
|
|
Debug.Assert(_accumulationShader != null);
|
||
|
|
|
||
|
|
_normalizationShader = normalizationShader;
|
||
|
|
Debug.Assert(_normalizationShader != null);
|
||
|
|
_normalizationKernel = _normalizationShader.FindKernel("NormalizeValidity");
|
||
|
|
|
||
|
|
_samplingResources = samplingResources;
|
||
|
|
_emptyTexture = emptyExposureTexture;
|
||
|
|
|
||
|
|
_expansionHelpers = expansionHelpers;
|
||
|
|
_populateAccumulationDispatchKernel = _expansionHelpers.FindKernel("PopulateAccumulationDispatch");
|
||
|
|
_accumulationDispatchBuffer = RayTracingHelper.CreateDispatchIndirectBuffer();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Accumulate(
|
||
|
|
CommandBuffer cmd,
|
||
|
|
uint sampleCountToTakePerTexel,
|
||
|
|
uint currentSampleCountPerTexel,
|
||
|
|
Matrix4x4 shaderLocalToWorld,
|
||
|
|
Matrix4x4 shaderLocalToWorldNormals,
|
||
|
|
int instanceGeometryIndex,
|
||
|
|
Vector2Int instanceTexelSize,
|
||
|
|
uint2 chunkOffset,
|
||
|
|
World world,
|
||
|
|
GraphicsBuffer traceScratchBuffer,
|
||
|
|
GraphicsBuffer gBuffer,
|
||
|
|
uint expandedSampleWidth,
|
||
|
|
GraphicsBuffer expandedOutput,
|
||
|
|
GraphicsBuffer compactedTexelIndices,
|
||
|
|
GraphicsBuffer compactedGbufferLength,
|
||
|
|
float pushOff,
|
||
|
|
bool newChunkStarted)
|
||
|
|
{
|
||
|
|
int instanceWidth = instanceTexelSize.x;
|
||
|
|
int instanceHeight = instanceTexelSize.y;
|
||
|
|
Debug.Assert(math.ispow2(expandedSampleWidth));
|
||
|
|
Debug.Assert(gBuffer.count == expandedOutput.count);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel <= expandedSampleWidth);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel > 0);
|
||
|
|
|
||
|
|
// path tracing inputs
|
||
|
|
uint lightEvaluationsPerBounce = 1;
|
||
|
|
bool preExpose = false;
|
||
|
|
float environmentIntensityMultiplier = 1.0f;
|
||
|
|
Util.BindPathTracingInputs(cmd, _accumulationShader, false, lightEvaluationsPerBounce, preExpose, 0, environmentIntensityMultiplier, RenderedGameObjectsFilter.OnlyStatic, _samplingResources, _emptyTexture);
|
||
|
|
Util.BindWorld(cmd, _accumulationShader, world, 1024);
|
||
|
|
|
||
|
|
var requiredSizeInBytes = _accumulationShader.GetTraceScratchBufferRequiredSizeInBytes((uint)expandedOutput.count, 1, 1);
|
||
|
|
if (requiredSizeInBytes > 0)
|
||
|
|
{
|
||
|
|
var actualScratchBufferSize = (ulong)(traceScratchBuffer.count * traceScratchBuffer.stride);
|
||
|
|
Debug.Assert(traceScratchBuffer.stride == sizeof(uint));
|
||
|
|
Debug.Assert(requiredSizeInBytes <= actualScratchBufferSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorld, shaderLocalToWorld);
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorldNormals, shaderLocalToWorldNormals);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceGeometryIndex, instanceGeometryIndex);
|
||
|
|
_accumulationShader.SetFloatParam(cmd, LightmapIntegratorShaderIDs.PushOff, pushOff);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceWidth, instanceWidth);
|
||
|
|
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.GBuffer, gBuffer);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.CompactedGBuffer, compactedTexelIndices);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.ExpandedOutput, expandedOutput);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ExpandedTexelSampleWidth, (int)expandedSampleWidth);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetX, (int)chunkOffset.x);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetY, (int)chunkOffset.y);
|
||
|
|
|
||
|
|
if (newChunkStarted)
|
||
|
|
{
|
||
|
|
// Its time to repopulate the indirect dispatch buffers (as a new instance has started). Use the compacted size for this.
|
||
|
|
ExpansionHelpers.PopulateAccumulationIndirectDispatch(cmd, _accumulationShader, _expansionHelpers, _populateAccumulationDispatchKernel, expandedSampleWidth, compactedGbufferLength, _accumulationDispatchBuffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
// accumulate (expanded)
|
||
|
|
{
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.SampleOffset, (int)currentSampleCountPerTexel);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.MaxLocalSampleCount, (int)sampleCountToTakePerTexel);
|
||
|
|
cmd.BeginSample("Accumulation (Expanded)");
|
||
|
|
_accumulationShader.Dispatch(cmd, traceScratchBuffer, _accumulationDispatchBuffer);
|
||
|
|
cmd.EndSample("Accumulation (Expanded)");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Normalize(CommandBuffer cmd, RenderTexture lightmapInOut)
|
||
|
|
{
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _normalizationKernel, LightmapIntegratorShaderIDs.LightmapInOut, lightmapInOut);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureWidth, lightmapInOut.width);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureHeight, lightmapInOut.height);
|
||
|
|
_normalizationShader.GetKernelThreadGroupSizes(_normalizationKernel, out uint x, out uint y, out _);
|
||
|
|
cmd.DispatchCompute(_normalizationShader, _normalizationKernel, GraphicsHelpers.DivUp(lightmapInOut.width, x), GraphicsHelpers.DivUp(lightmapInOut.height, y), 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal class LightmapShadowMaskIntegrator : System.IDisposable
|
||
|
|
{
|
||
|
|
IRayTracingShader _accumulationShader;
|
||
|
|
ComputeShader _normalizationShader;
|
||
|
|
int _normalizationKernel;
|
||
|
|
SamplingResources _samplingResources;
|
||
|
|
RTHandle _emptyTexture;
|
||
|
|
private GraphicsBuffer _accumulationDispatchBuffer;
|
||
|
|
private ComputeShader _expansionHelpers;
|
||
|
|
private int _populateAccumulationDispatchKernel;
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
_accumulationDispatchBuffer?.Dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Prepare(IRayTracingShader accumulationShader, ComputeShader normalizationShader, ComputeShader expansionHelpers, SamplingResources samplingResources, RTHandle emptyExposureTexture)
|
||
|
|
{
|
||
|
|
_accumulationShader = accumulationShader;
|
||
|
|
Debug.Assert(_accumulationShader != null);
|
||
|
|
|
||
|
|
_normalizationShader = normalizationShader;
|
||
|
|
Debug.Assert(_normalizationShader != null);
|
||
|
|
_normalizationKernel = _normalizationShader.FindKernel("NormalizeShadowMask");
|
||
|
|
|
||
|
|
_samplingResources = samplingResources;
|
||
|
|
_emptyTexture = emptyExposureTexture;
|
||
|
|
|
||
|
|
_expansionHelpers = expansionHelpers;
|
||
|
|
_populateAccumulationDispatchKernel = _expansionHelpers.FindKernel("PopulateAccumulationDispatch");
|
||
|
|
_accumulationDispatchBuffer = RayTracingHelper.CreateDispatchIndirectBuffer();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Accumulate(
|
||
|
|
CommandBuffer cmd,
|
||
|
|
uint sampleCountToTakePerTexel,
|
||
|
|
uint currentSampleCountPerTexel,
|
||
|
|
Matrix4x4 shaderLocalToWorld,
|
||
|
|
Matrix4x4 shaderLocalToWorldNormals,
|
||
|
|
int instanceGeometryIndex,
|
||
|
|
Vector2Int instanceTexelSize,
|
||
|
|
uint2 chunkOffset,
|
||
|
|
World world,
|
||
|
|
GraphicsBuffer traceScratchBuffer,
|
||
|
|
GraphicsBuffer gBuffer,
|
||
|
|
uint expandedSampleWidth,
|
||
|
|
GraphicsBuffer expandedOutput,
|
||
|
|
GraphicsBuffer expandedSampleCountInW,
|
||
|
|
GraphicsBuffer compactedTexelIndices,
|
||
|
|
GraphicsBuffer compactedGbufferLength,
|
||
|
|
bool receiveShadows,
|
||
|
|
float pushOff,
|
||
|
|
uint lightEvaluationsPerBounce,
|
||
|
|
bool newChunkStarted)
|
||
|
|
{
|
||
|
|
int instanceWidth = instanceTexelSize.x;
|
||
|
|
int instanceHeight = instanceTexelSize.y;
|
||
|
|
Debug.Assert(math.ispow2(expandedSampleWidth));
|
||
|
|
Debug.Assert(gBuffer.count == expandedOutput.count);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel <= expandedSampleWidth);
|
||
|
|
Debug.Assert(sampleCountToTakePerTexel > 0);
|
||
|
|
|
||
|
|
// path tracing inputs
|
||
|
|
bool preExpose = false;
|
||
|
|
float environmentIntensityMultiplier = 1.0f;
|
||
|
|
Util.BindPathTracingInputs(cmd, _accumulationShader, false, lightEvaluationsPerBounce, preExpose, 0, environmentIntensityMultiplier, RenderedGameObjectsFilter.OnlyStatic, _samplingResources, _emptyTexture);
|
||
|
|
Util.BindWorld(cmd, _accumulationShader, world, 1024);
|
||
|
|
|
||
|
|
var requiredSizeInBytes = _accumulationShader.GetTraceScratchBufferRequiredSizeInBytes((uint)expandedOutput.count, 1, 1);
|
||
|
|
if (requiredSizeInBytes > 0)
|
||
|
|
{
|
||
|
|
var actualScratchBufferSize = (ulong)(traceScratchBuffer.count * traceScratchBuffer.stride);
|
||
|
|
Debug.Assert(traceScratchBuffer.stride == sizeof(uint));
|
||
|
|
Debug.Assert(requiredSizeInBytes <= actualScratchBufferSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorld, shaderLocalToWorld);
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorldNormals, shaderLocalToWorldNormals);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceGeometryIndex, instanceGeometryIndex);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ReceiveShadows, receiveShadows ? 1 : 0);
|
||
|
|
_accumulationShader.SetFloatParam(cmd, LightmapIntegratorShaderIDs.PushOff, pushOff);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceWidth, instanceWidth);
|
||
|
|
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.GBuffer, gBuffer);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.CompactedGBuffer, compactedTexelIndices);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.ExpandedOutput, expandedOutput);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.ExpandedSampleCountInW, expandedSampleCountInW);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ExpandedTexelSampleWidth, (int)expandedSampleWidth);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetX, (int)chunkOffset.x);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.ChunkOffsetY, (int)chunkOffset.y);
|
||
|
|
|
||
|
|
if (newChunkStarted)
|
||
|
|
{
|
||
|
|
// Its time to repopulate the indirect dispatch buffers (as a new instance has started). Use the compacted size for this.
|
||
|
|
ExpansionHelpers.PopulateAccumulationIndirectDispatch(cmd, _accumulationShader, _expansionHelpers, _populateAccumulationDispatchKernel, expandedSampleWidth, compactedGbufferLength, _accumulationDispatchBuffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
// accumulate (expanded)
|
||
|
|
{
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.SampleOffset, (int)currentSampleCountPerTexel);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.MaxLocalSampleCount, (int)sampleCountToTakePerTexel);
|
||
|
|
cmd.BeginSample("Accumulation (Expanded)");
|
||
|
|
_accumulationShader.Dispatch(cmd, traceScratchBuffer, _accumulationDispatchBuffer);
|
||
|
|
cmd.EndSample("Accumulation (Expanded)");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Normalize(CommandBuffer cmd, RenderTexture lightmap, RenderTexture sampleCountInW)
|
||
|
|
{
|
||
|
|
Debug.Assert(lightmap.width == sampleCountInW.width && lightmap.height == sampleCountInW.height);
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _normalizationKernel, LightmapIntegratorShaderIDs.LightmapInOut, lightmap);
|
||
|
|
cmd.SetComputeTextureParam(_normalizationShader, _normalizationKernel, LightmapIntegratorShaderIDs.InputSampleCountInW, sampleCountInW);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureWidth, lightmap.width);
|
||
|
|
cmd.SetComputeIntParam(_normalizationShader, LightmapIntegratorShaderIDs.TextureHeight, lightmap.height);
|
||
|
|
_normalizationShader.GetKernelThreadGroupSizes(_normalizationKernel, out uint x, out uint y, out _);
|
||
|
|
cmd.DispatchCompute(_normalizationShader, _normalizationKernel, GraphicsHelpers.DivUp(lightmap.width, x), GraphicsHelpers.DivUp(lightmap.height, y), 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal class GBufferDebug : System.IDisposable
|
||
|
|
{
|
||
|
|
private IRayTracingShader _accumulationShader;
|
||
|
|
private GraphicsBuffer _accumulationDispatchBuffer;
|
||
|
|
private ComputeShader _expansionHelpers;
|
||
|
|
private int _populateAccumulationDispatchKernel;
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
_accumulationDispatchBuffer?.Dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
public GBufferDebug()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Prepare(IRayTracingShader accumulationShader, ComputeShader expansionHelpers)
|
||
|
|
{
|
||
|
|
_accumulationShader = accumulationShader;
|
||
|
|
Debug.Assert(_accumulationShader != null);
|
||
|
|
|
||
|
|
_expansionHelpers = expansionHelpers;
|
||
|
|
_populateAccumulationDispatchKernel = _expansionHelpers.FindKernel("PopulateAccumulationDispatch");
|
||
|
|
_accumulationDispatchBuffer = RayTracingHelper.CreateDispatchIndirectBuffer();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Accumulate(
|
||
|
|
CommandBuffer cmd,
|
||
|
|
Matrix4x4 shaderLocalToWorld,
|
||
|
|
Matrix4x4 shaderLocalToWorldNormals,
|
||
|
|
int instanceGeometryIndex,
|
||
|
|
World world,
|
||
|
|
GraphicsBuffer gBuffer,
|
||
|
|
uint expandedSampleWidth,
|
||
|
|
GraphicsBuffer lightmapSamplesExpanded,
|
||
|
|
GraphicsBuffer compactedGbufferLength)
|
||
|
|
{
|
||
|
|
Debug.Assert(math.ispow2(expandedSampleWidth));
|
||
|
|
Debug.Assert(lightmapSamplesExpanded.count <= gBuffer.count);
|
||
|
|
Debug.Assert(lightmapSamplesExpanded.count % expandedSampleWidth == 0);
|
||
|
|
Util.BindWorld(cmd, _accumulationShader, world, 1024);
|
||
|
|
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorld, shaderLocalToWorld);
|
||
|
|
_accumulationShader.SetMatrixParam(cmd, LightmapIntegratorShaderIDs.ShaderLocalToWorldNormals, shaderLocalToWorldNormals);
|
||
|
|
_accumulationShader.SetIntParam(cmd, LightmapIntegratorShaderIDs.InstanceGeometryIndex, instanceGeometryIndex);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.GBuffer, gBuffer);
|
||
|
|
_accumulationShader.SetBufferParam(cmd, LightmapIntegratorShaderIDs.LightmapSamplesExpanded, lightmapSamplesExpanded);
|
||
|
|
|
||
|
|
// Its time to repopulate the indirect dispatch buffers. Use the compacted size for this.
|
||
|
|
ExpansionHelpers.PopulateAccumulationIndirectDispatch(cmd, _accumulationShader, _expansionHelpers, _populateAccumulationDispatchKernel, expandedSampleWidth, compactedGbufferLength, _accumulationDispatchBuffer);
|
||
|
|
cmd.BeginSample("GBuffer Debug");
|
||
|
|
_accumulationShader.Dispatch(cmd, null, _accumulationDispatchBuffer);
|
||
|
|
cmd.EndSample("GBuffer Debug");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|