using System;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Rendering;
namespace UnityEngine.PathTracing.Lightmapping
{
internal class ChartRasterizer : IDisposable
{
// Buffers required to execute chart rasterization
public struct Buffers
{
public GraphicsBuffer vertex; // Only used in software path
public GraphicsBuffer vertexToOriginalVertex; // Only used in software path
public GraphicsBuffer vertexToChartID;
}
private readonly Material _softwareRasterizationMaterial;
private readonly Material _hardwareRasterizationMaterial;
private static class ShaderProperties
{
public static readonly int VertexBuffer = Shader.PropertyToID("g_VertexBuffer");
public static readonly int VertexToOriginalVertex = Shader.PropertyToID("g_VertexToOriginalVertex");
public static readonly int VertexToChartID = Shader.PropertyToID("g_VertexToChartID");
public static readonly int ScaleAndOffset = Shader.PropertyToID("g_ScaleAndOffset");
public static readonly int ChartIndexOffset = Shader.PropertyToID("g_ChartIndexOffset");
public static readonly int Width = Shader.PropertyToID("g_Width");
public static readonly int Height = Shader.PropertyToID("g_Height");
}
public ChartRasterizer(Shader softwareRasterizationShader, Shader hardwareRasterizationShader)
{
_softwareRasterizationMaterial = new Material(softwareRasterizationShader);
_hardwareRasterizationMaterial = new Material(hardwareRasterizationShader);
}
public void Dispose()
{
CoreUtils.Destroy(_softwareRasterizationMaterial);
CoreUtils.Destroy(_hardwareRasterizationMaterial);
}
#if UNITY_EDITOR
public static void LoadShaders(out Shader softwareRasterizationShader, out Shader hardwareRasterizationShader)
{
softwareRasterizationShader = UnityEditor.AssetDatabase.LoadAssetAtPath<Shader>(
"Packages/com.unity.render-pipelines.core/Runtime/PathTracing/Shaders/Lightmapping/ChartRasterizerSoftware.shader");
hardwareRasterizationShader = UnityEditor.AssetDatabase.LoadAssetAtPath<Shader>(
"Packages/com.unity.render-pipelines.core/Runtime/PathTracing/Shaders/Lightmapping/ChartRasterizerHardware.shader");
}
#endif
private static Vector2[] SelectUVBuffer(Mesh from)
{
var uv2 = from.uv2;
if (uv2 != null && uv2.Length > 0)
return uv2;
else
return from.uv;
}
public static void PrepareRasterizeSoftware(CommandBuffer cmd, Mesh from, GraphicsBuffer vertexBuffer, GraphicsBuffer vertexToOriginalVertexBuffer)
{
var originalUVs = from.vertices;
var originalIndices = from.triangles;
var uvs = new Vector2[originalIndices.Length];
var vertexIds = new uint[originalIndices.Length];
for (int i = 0; i < originalIndices.Length; i++)
{
uint originalVertexIdx = (uint)originalIndices[i];
uvs[i] = originalUVs[originalVertexIdx];
vertexIds[i] = originalVertexIdx;
}
cmd.SetBufferData(vertexBuffer, uvs);
cmd.SetBufferData(vertexToOriginalVertexBuffer, vertexIds);
}
public void RasterizeSoftware(CommandBuffer cmd, GraphicsBuffer vertexBuffer, GraphicsBuffer vertexToOriginalVertexBuffer, GraphicsBuffer vertexToChartIdBuffer, uint indexCount, Vector4 scaleAndOffset, uint chartIndexOffset, RenderTexture destination)
{
cmd.SetGlobalBuffer(ShaderProperties.VertexBuffer, vertexBuffer);
cmd.SetGlobalBuffer(ShaderProperties.VertexToOriginalVertex, vertexToOriginalVertexBuffer);
cmd.SetGlobalBuffer(ShaderProperties.VertexToChartID, vertexToChartIdBuffer);
cmd.SetGlobalVector(ShaderProperties.ScaleAndOffset, scaleAndOffset);
cmd.SetGlobalInt(ShaderProperties.ChartIndexOffset, (int)chartIndexOffset);
cmd.SetGlobalInteger(ShaderProperties.Width, destination.width);
cmd.SetGlobalInteger(ShaderProperties.Height, destination.height);
cmd.SetRenderTarget(destination);
cmd.DrawProcedural(Matrix4x4.identity, _softwareRasterizationMaterial, 0, MeshTopology.Triangles, (int)indexCount);
}
public void RasterizeHardware(CommandBuffer cmd, Mesh mesh, GraphicsBuffer vertexToChartIdBuffer, Vector4 scaleAndOffset, uint chartIndexOffset, RenderTexture destination)
{
Debug.Assert(SystemInfo.supportsConservativeRaster, "Conservative rasterization is not supported on the current platform.");
cmd.SetGlobalBuffer(ShaderProperties.VertexToChartID, vertexToChartIdBuffer);
cmd.SetGlobalVector(ShaderProperties.ScaleAndOffset, scaleAndOffset);
cmd.SetGlobalInt(ShaderProperties.ChartIndexOffset, (int)chartIndexOffset);
cmd.SetRenderTarget(destination);
for (int i = 0; i < mesh.subMeshCount; i++)
{
cmd.DrawMesh(mesh, Matrix4x4.identity, _hardwareRasterizationMaterial, i, 0);
}
}
}
}