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( "Packages/com.unity.render-pipelines.core/Runtime/PathTracing/Shaders/Lightmapping/ChartRasterizerSoftware.shader"); hardwareRasterizationShader = UnityEditor.AssetDatabase.LoadAssetAtPath( "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); } } } }