ThomagicRenderer/Runtime/DrawCall.cs

98 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
namespace Assets.ThoMagic.Renderer
{
public class DrawCall
{
public readonly Mesh Mesh;
public readonly Material[] Materials;
public readonly RenderParams[] RenderParams;
private readonly Matrix4x4 _localToWorldMatrix;
private readonly uint baseIndirectArgsIndex;
private readonly int lodNr;
public DrawCall(
int lodNr,
Mesh mesh,
Material[] materials,
Matrix4x4 localToWorldMatrix,
uint baseIndirectArgsIndex,
List<GraphicsBuffer.IndirectDrawIndexedArgs> indirectDrawIndexedArgs,
in RenderParams renderParams)
{
if (mesh == null)
throw new ArgumentNullException(nameof(mesh));
if (materials == null)
throw new ArgumentNullException(nameof(materials));
if (materials.Length != mesh.subMeshCount)
throw new IndexOutOfRangeException(nameof(materials));
this.baseIndirectArgsIndex = baseIndirectArgsIndex;
_localToWorldMatrix = localToWorldMatrix;
Mesh = mesh;
Materials = materials;
RenderParams = new RenderParams[mesh.subMeshCount];
this.lodNr = lodNr;
for (int index = 0; index < mesh.subMeshCount; ++index)
{
RenderParams[index] = renderParams;
RenderParams[index].material = materials[index];
RenderParams[index].matProps = new MaterialPropertyBlock();
RenderParams[index].matProps.SetMatrix("trInstanceMatrix", _localToWorldMatrix);
RenderParams[index].matProps.SetInteger("trLodNr", lodNr + 1);
RenderParams[index].worldBounds = new Bounds(Vector3.zero, 1000f * Vector3.one);
indirectDrawIndexedArgs.Add(new GraphicsBuffer.IndirectDrawIndexedArgs
{
indexCountPerInstance = mesh.GetIndexCount(index),
baseVertexIndex = mesh.GetBaseVertex(index),
startIndex = mesh.GetIndexStart(index),
startInstance = 0,
instanceCount = 0
});
}
}
public virtual void SetInstances(ComputeBuffer instances, ComputeBuffer visibleIndexBuffer, ComputeBuffer metaBuffer)
{
for (int index = 0; index < this.RenderParams.Length; ++index)
{
RenderParams[index].matProps.SetBuffer("trInstances", instances);
RenderParams[index].matProps.SetBuffer("trPerCamVisibleIndexesBuffer", visibleIndexBuffer);
RenderParams[index].matProps.SetBuffer("trPerCamMeta", metaBuffer);
}
}
public virtual void Draw(Camera camera, ObjectData obj, GraphicsBuffer indirectDrawIndexedArgs)
{
if (Materials == null)
throw new ObjectDisposedException("Materials");
if (Mesh == null)
throw new ObjectDisposedException("Mesh");
var bounds = new Bounds(camera.transform.position, Vector3.one * 1000f);
for (int index = 0; index < RenderParams.Length; ++index)
{
var renderParam = RenderParams[index];
if (renderParam.material != null)
{
renderParam.camera = camera;
renderParam.worldBounds = bounds;
Graphics.RenderMeshIndirect(in renderParam, Mesh, indirectDrawIndexedArgs, 1, obj.indirectArgsPerSubmeshOffsets[(int)baseIndirectArgsIndex + index]);
}
}
}
internal virtual void Dispose()
{
}
}
}