290 lines
14 KiB
C#
290 lines
14 KiB
C#
using System;
|
|
using Unity.Mathematics;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.PathTracing.Integration;
|
|
using UnityEngine.PathTracing.Core;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.UnifiedRayTracing;
|
|
using UnityEngine.Rendering.Sampling;
|
|
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
namespace UnityEngine.PathTracing.Lightmapping
|
|
{
|
|
using InstanceHandle = Handle<World.InstanceKey>;
|
|
using MaterialHandle = Handle<MaterialPool.MaterialDescriptor>;
|
|
|
|
internal struct LodInstanceBuildData
|
|
{
|
|
public int LodMask;
|
|
public Mesh Mesh;
|
|
public MaterialHandle[] Materials;
|
|
public uint[] Masks;
|
|
public Matrix4x4 LocalToWorldMatrix;
|
|
public Bounds Bounds;
|
|
public bool IsStatic;
|
|
public RenderedGameObjectsFilter Filter;
|
|
}
|
|
|
|
internal struct LodIdentifier
|
|
{
|
|
public LodIdentifier(Int32 lodGroup, byte lodMask, Int32 lodContributorLevel)
|
|
{
|
|
this.LodGroup = lodGroup;
|
|
this.LodMask = lodMask;
|
|
this.LodContributorLevel = lodContributorLevel;
|
|
}
|
|
|
|
public Int32 LodGroup;
|
|
public byte LodMask;
|
|
Int32 LodContributorLevel;
|
|
|
|
public override int GetHashCode() => HashCode.Combine(LodGroup, LodMask);
|
|
public override bool Equals(object obj) => obj is LodIdentifier other && other.LodGroup == LodGroup && other.LodMask == LodMask;
|
|
public static readonly LodIdentifier Invalid = new LodIdentifier(-1, 0, -1);
|
|
public bool IsValid() => LodGroup != -1;
|
|
public bool IsContributor()
|
|
{
|
|
if (LodContributorLevel == -1) return false;
|
|
return (LodMask & (1 << LodContributorLevel)) != 0;
|
|
}
|
|
public byte MinLodLevelMask() { return (byte)(LodMask & -LodMask); }
|
|
}
|
|
|
|
internal struct ContributorLodInfo
|
|
{
|
|
public InstanceHandle InstanceHandle;
|
|
public uint[] Masks;
|
|
public int LodMask;
|
|
}
|
|
|
|
internal struct FatInstance
|
|
{
|
|
public BoundingSphere BoundingSphere;
|
|
public Mesh Mesh;
|
|
public Vector2 UVBoundsSize;
|
|
public Vector2 UVBoundsOffset;
|
|
public MaterialHandle[] Materials;
|
|
public uint[] SubMeshMasks;
|
|
public Matrix4x4 LocalToWorldMatrix;
|
|
public Bounds Bounds;
|
|
public bool IsStatic;
|
|
public LodIdentifier LodIdentifier;
|
|
public bool ReceiveShadows;
|
|
public RenderedGameObjectsFilter Filter;
|
|
public uint RenderingObjectLayer;
|
|
public bool EnableEmissiveSampling;
|
|
}
|
|
|
|
internal struct BakeInstance
|
|
{
|
|
public Mesh Mesh;
|
|
public Vector4 NormalizedOccupiedST; // Transforms coordinates in [0; 1] range into the occupied rectangle in the lightmap atlas, also in [0; 1] range.
|
|
public Vector4 SourceLightmapST;
|
|
public Vector2Int TexelSize; // Instance size in the lightmap atlas, in pixels.
|
|
public Vector2Int TexelOffset; // Instance offset in the lightmap atlas, in pixels.
|
|
public Matrix4x4 LocalToWorldMatrix;
|
|
public Matrix4x4 LocalToWorldMatrixNormals;
|
|
public bool ReceiveShadows;
|
|
public LodIdentifier LodIdentifier;
|
|
public uint InstanceIndex; // Index of the instance in BakeInput
|
|
|
|
private static float4x4 NormalMatrix(float4x4 m)
|
|
{
|
|
float3x3 t = new float3x3(m);
|
|
return new float4x4(math.inverse(math.transpose(t)), new float3(0.0));
|
|
}
|
|
|
|
public BoundingSphere GetBoundingSphere()
|
|
{
|
|
var boundingSphere = new BoundingSphere();
|
|
boundingSphere.position = LocalToWorldMatrix.MultiplyPoint(Mesh.bounds.center);
|
|
boundingSphere.radius = (LocalToWorldMatrix.MultiplyPoint(Mesh.bounds.extents) - boundingSphere.position).magnitude;
|
|
return boundingSphere;
|
|
}
|
|
|
|
public void Build(Mesh mesh, Vector4 normalizedOccupiedST, Vector4 sourceLightmapST, Vector2Int texelSize, Vector2Int texelOffset, Matrix4x4 localToWorldMatrix, bool receiveShadows, LodIdentifier lodIdentifier, uint instanceIndex)
|
|
{
|
|
Mesh = mesh;
|
|
NormalizedOccupiedST = normalizedOccupiedST;
|
|
SourceLightmapST = sourceLightmapST;
|
|
TexelSize = texelSize;
|
|
TexelOffset = texelOffset;
|
|
LocalToWorldMatrix = localToWorldMatrix;
|
|
ReceiveShadows = receiveShadows;
|
|
LocalToWorldMatrixNormals = NormalMatrix(this.LocalToWorldMatrix);
|
|
LodIdentifier = lodIdentifier;
|
|
InstanceIndex = instanceIndex;
|
|
}
|
|
}
|
|
|
|
internal class LightmapDesc
|
|
{
|
|
public uint Resolution;
|
|
public float PushOff;
|
|
public BakeInstance[] BakeInstances;
|
|
}
|
|
|
|
internal enum IntegratedOutputType
|
|
{
|
|
Direct,
|
|
Indirect,
|
|
AO,
|
|
Validity,
|
|
DirectionalityDirect,
|
|
DirectionalityIndirect,
|
|
ShadowMask
|
|
}
|
|
|
|
internal class LightmapIntegratorContext : IDisposable
|
|
{
|
|
internal UVFallbackBufferBuilder UVFallbackBufferBuilder;
|
|
internal LightmapDirectIntegrator LightmapDirectIntegrator;
|
|
internal LightmapIndirectIntegrator LightmapIndirectIntegrator;
|
|
internal LightmapAOIntegrator LightmapAOIntegrator;
|
|
internal LightmapValidityIntegrator LightmapValidityIntegrator;
|
|
internal LightmapOccupancyIntegrator LightmapOccupancyIntegrator;
|
|
internal LightmapShadowMaskIntegrator LightmapShadowMaskIntegrator;
|
|
internal GBufferDebug GBufferDebugShader;
|
|
internal IRayTracingShader GBufferShader;
|
|
internal ComputeShader ExpansionShaders;
|
|
internal SamplingResources SamplingResources;
|
|
private RTHandle _emptyExposureTexture;
|
|
internal GraphicsBuffer ClearDispatchBuffer;
|
|
internal GraphicsBuffer CopyDispatchBuffer;
|
|
internal GraphicsBuffer ReduceDispatchBuffer;
|
|
internal GraphicsBuffer CompactedGBufferLength;
|
|
internal int CompactGBufferKernel;
|
|
internal int PopulateAccumulationDispatchKernel;
|
|
internal int PopulateClearDispatchKernel;
|
|
internal int PopulateCopyDispatchKernel;
|
|
internal int PopulateReduceDispatchKernel;
|
|
internal int ClearBufferKernel;
|
|
internal int ReductionKernel;
|
|
internal int CopyToLightmapKernel;
|
|
|
|
public void Dispose()
|
|
{
|
|
UVFallbackBufferBuilder?.Dispose();
|
|
UVFallbackBufferBuilder = null;
|
|
LightmapDirectIntegrator?.Dispose();
|
|
LightmapDirectIntegrator = null;
|
|
LightmapIndirectIntegrator?.Dispose();
|
|
LightmapIndirectIntegrator = null;
|
|
LightmapAOIntegrator?.Dispose();
|
|
LightmapAOIntegrator = null;
|
|
LightmapValidityIntegrator?.Dispose();
|
|
LightmapValidityIntegrator = null;
|
|
LightmapOccupancyIntegrator = null;
|
|
LightmapShadowMaskIntegrator?.Dispose();
|
|
LightmapShadowMaskIntegrator = null;
|
|
GBufferDebugShader?.Dispose();
|
|
GBufferDebugShader = null;
|
|
_emptyExposureTexture?.Release();
|
|
_emptyExposureTexture = null;
|
|
|
|
ClearDispatchBuffer?.Dispose();
|
|
CopyDispatchBuffer?.Dispose();
|
|
ReduceDispatchBuffer?.Dispose();
|
|
CompactedGBufferLength?.Dispose();
|
|
}
|
|
|
|
internal void Initialize(SamplingResources samplingResources, LightmapResourceLibrary lightmapResourceLib, bool countNEERayAsPathSegment)
|
|
{
|
|
SamplingResources = samplingResources;
|
|
_emptyExposureTexture = RTHandles.Alloc(1, 1, enableRandomWrite: true, name: "Empty EV100 Exposure", colorFormat: GraphicsFormat.R8G8B8A8_UNorm);
|
|
|
|
UVFallbackBufferBuilder = new UVFallbackBufferBuilder();
|
|
UVFallbackBufferBuilder.Prepare(lightmapResourceLib.UVFallbackBufferGenerationMaterial);
|
|
LightmapDirectIntegrator = new LightmapDirectIntegrator();
|
|
LightmapDirectIntegrator.Prepare(lightmapResourceLib.DirectAccumulationShader, lightmapResourceLib.NormalizationShader, lightmapResourceLib.ExpansionHelpers, SamplingResources, _emptyExposureTexture);
|
|
LightmapIndirectIntegrator = new LightmapIndirectIntegrator(countNEERayAsPathSegment);
|
|
LightmapIndirectIntegrator.Prepare(lightmapResourceLib.IndirectAccumulationShader, lightmapResourceLib.NormalizationShader, lightmapResourceLib.ExpansionHelpers, SamplingResources, _emptyExposureTexture);
|
|
LightmapAOIntegrator = new LightmapAOIntegrator();
|
|
LightmapAOIntegrator.Prepare(lightmapResourceLib.AOAccumulationShader, lightmapResourceLib.NormalizationShader, lightmapResourceLib.ExpansionHelpers, SamplingResources, _emptyExposureTexture);
|
|
LightmapValidityIntegrator = new LightmapValidityIntegrator();
|
|
LightmapValidityIntegrator.Prepare(lightmapResourceLib.ValidityAccumulationShader, lightmapResourceLib.NormalizationShader, lightmapResourceLib.ExpansionHelpers, SamplingResources, _emptyExposureTexture);
|
|
LightmapOccupancyIntegrator = new LightmapOccupancyIntegrator();
|
|
LightmapOccupancyIntegrator.Prepare(lightmapResourceLib.OccupancyShader);
|
|
LightmapShadowMaskIntegrator = new LightmapShadowMaskIntegrator();
|
|
LightmapShadowMaskIntegrator.Prepare(lightmapResourceLib.ShadowMaskAccumulationShader, lightmapResourceLib.NormalizationShader, lightmapResourceLib.ExpansionHelpers, SamplingResources, _emptyExposureTexture);
|
|
GBufferDebugShader = new GBufferDebug();
|
|
GBufferDebugShader.Prepare(lightmapResourceLib.GBufferDebugShader, lightmapResourceLib.ExpansionHelpers);
|
|
GBufferShader = lightmapResourceLib.GBufferShader;
|
|
ExpansionShaders = lightmapResourceLib.ExpansionHelpers;
|
|
|
|
CompactGBufferKernel = ExpansionShaders.FindKernel("CompactGBuffer");
|
|
PopulateAccumulationDispatchKernel = ExpansionShaders.FindKernel("PopulateAccumulationDispatch");
|
|
PopulateClearDispatchKernel = ExpansionShaders.FindKernel("PopulateClearDispatch");
|
|
PopulateCopyDispatchKernel = ExpansionShaders.FindKernel("PopulateCopyDispatch");
|
|
PopulateReduceDispatchKernel = ExpansionShaders.FindKernel("PopulateReduceDispatch");
|
|
ClearBufferKernel = ExpansionShaders.FindKernel("ClearFloat4Buffer");
|
|
ReductionKernel = ExpansionShaders.FindKernel("BinaryGroupSumLeft");
|
|
CopyToLightmapKernel = ExpansionShaders.FindKernel("AdditivelyCopyCompactedTo2D");
|
|
|
|
ClearDispatchBuffer = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments | GraphicsBuffer.Target.Structured | GraphicsBuffer.Target.CopySource | GraphicsBuffer.Target.CopyDestination, 3, sizeof(uint));
|
|
CopyDispatchBuffer = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments | GraphicsBuffer.Target.Structured | GraphicsBuffer.Target.CopySource | GraphicsBuffer.Target.CopyDestination, 3, sizeof(uint));
|
|
ReduceDispatchBuffer = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments | GraphicsBuffer.Target.Structured | GraphicsBuffer.Target.CopySource | GraphicsBuffer.Target.CopyDestination, 3, sizeof(uint));
|
|
CompactedGBufferLength = new GraphicsBuffer(GraphicsBuffer.Target.Structured | GraphicsBuffer.Target.CopySource, 1, sizeof(uint));
|
|
}
|
|
}
|
|
|
|
internal class LightmapResourceLibrary
|
|
{
|
|
internal IRayTracingShader GBufferShader;
|
|
internal ComputeShader NormalizationShader;
|
|
internal IRayTracingShader DirectAccumulationShader;
|
|
internal IRayTracingShader AOAccumulationShader;
|
|
internal IRayTracingShader ValidityAccumulationShader;
|
|
internal IRayTracingShader IndirectAccumulationShader;
|
|
internal IRayTracingShader ShadowMaskAccumulationShader;
|
|
internal IRayTracingShader NormalAccumulationShader;
|
|
internal IRayTracingShader GBufferDebugShader;
|
|
internal Material UVFallbackBufferGenerationMaterial;
|
|
internal ComputeShader OccupancyShader;
|
|
internal LightmapIntegrationHelpers.ComputeHelpers ComputeHelpers;
|
|
internal ComputeShader BoxFilterShader;
|
|
internal ComputeShader SelectGraphicsBufferShader;
|
|
internal ComputeShader CopyTextureAdditiveShader;
|
|
internal ComputeShader ExpansionHelpers;
|
|
internal Shader SoftwareChartRasterizationShader;
|
|
internal Shader HardwareChartRasterizationShader;
|
|
|
|
#if UNITY_EDITOR
|
|
public void Load(RayTracingContext context)
|
|
{
|
|
const string packageFolder = "Packages/com.unity.render-pipelines.core/Runtime/PathTracing/";
|
|
|
|
GBufferShader = context.LoadRayTracingShader(packageFolder + "Shaders/LightmapGBufferIntegration.urtshader");
|
|
|
|
NormalizationShader = AssetDatabase.LoadAssetAtPath<ComputeShader>(packageFolder + "Shaders/ResolveAccumulation.compute");
|
|
DirectAccumulationShader = context.LoadRayTracingShader(packageFolder + "Shaders/LightmapDirectIntegration.urtshader");
|
|
AOAccumulationShader = context.LoadRayTracingShader(packageFolder + "Shaders/LightmapAOIntegration.urtshader");
|
|
ValidityAccumulationShader = context.LoadRayTracingShader(packageFolder + "Shaders/LightmapValidityIntegration.urtshader");
|
|
IndirectAccumulationShader = context.LoadRayTracingShader(packageFolder + "Shaders/LightmapIndirectIntegration.urtshader");
|
|
ShadowMaskAccumulationShader = context.LoadRayTracingShader(packageFolder + "Shaders/LightmapShadowMaskIntegration.urtshader");
|
|
GBufferDebugShader = context.LoadRayTracingShader(packageFolder + "Shaders/LightmapGBufferDebug.urtshader");
|
|
|
|
NormalAccumulationShader = context.LoadRayTracingShader(packageFolder + "Shaders/LightmapNormalIntegration.urtshader");
|
|
|
|
UVFallbackBufferGenerationMaterial = new Material(AssetDatabase.LoadAssetAtPath<Shader>(packageFolder + "Shaders/Lightmapping/UVFallbackBufferGeneration.shader"));
|
|
|
|
OccupancyShader = AssetDatabase.LoadAssetAtPath<ComputeShader>(packageFolder + "Shaders/LightmapOccupancy.compute");
|
|
|
|
ExpansionHelpers = AssetDatabase.LoadAssetAtPath<ComputeShader>(packageFolder + "Shaders/ExpansionHelpers.compute");
|
|
|
|
ComputeHelpers = new LightmapIntegrationHelpers.ComputeHelpers();
|
|
ComputeHelpers.Load();
|
|
|
|
ChartRasterizer.LoadShaders(out SoftwareChartRasterizationShader, out HardwareChartRasterizationShader);
|
|
|
|
BoxFilterShader = ComputeHelpers.ComputeHelperShader;
|
|
SelectGraphicsBufferShader = ComputeHelpers.ComputeHelperShader;
|
|
CopyTextureAdditiveShader = ComputeHelpers.ComputeHelperShader;
|
|
}
|
|
#endif
|
|
}
|
|
}
|