146 lines
4.8 KiB
C#
146 lines
4.8 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.Rendering;
|
|
using Unity.Profiling;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Obi
|
|
{
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct ParticleVertex
|
|
{
|
|
public Vector4 pos;
|
|
public Vector3 offset;
|
|
public Vector4 color;
|
|
public Vector4 b1;
|
|
public Vector4 b2;
|
|
public Vector4 b3;
|
|
}
|
|
|
|
public abstract class ObiParticleRenderSystem : RenderSystem<ObiParticleRenderer>
|
|
{
|
|
public Oni.RenderingSystemType typeEnum { get => Oni.RenderingSystemType.Particles; }
|
|
|
|
public RendererSet<ObiParticleRenderer> renderers { get; } = new RendererSet<ObiParticleRenderer>();
|
|
public bool isSetup => activeParticles != null;
|
|
|
|
protected VertexAttributeDescriptor[] layout =
|
|
{
|
|
new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 4),
|
|
new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3),
|
|
new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.Float32, 4),
|
|
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 4),
|
|
new VertexAttributeDescriptor(VertexAttribute.TexCoord1, VertexAttributeFormat.Float32, 4),
|
|
new VertexAttributeDescriptor(VertexAttribute.TexCoord2, VertexAttributeFormat.Float32, 4)
|
|
};
|
|
|
|
static protected ProfilerMarker m_SetupRenderMarker = new ProfilerMarker("SetupParticleRendering");
|
|
static protected ProfilerMarker m_RenderMarker = new ProfilerMarker("ParticleRendering");
|
|
|
|
protected ObiSolver m_Solver;
|
|
|
|
protected List<ProceduralRenderBatch<ParticleVertex>> batchList = new List<ProceduralRenderBatch<ParticleVertex>>();
|
|
|
|
protected ObiNativeList<int> activeParticles;
|
|
protected ObiNativeList<int> rendererIndex;
|
|
protected ObiNativeList<ParticleRendererData> rendererData;
|
|
|
|
public ObiParticleRenderSystem(ObiSolver solver)
|
|
{
|
|
m_Solver = solver;
|
|
|
|
activeParticles = new ObiNativeList<int>();
|
|
rendererIndex = new ObiNativeList<int>();
|
|
rendererData = new ObiNativeList<ParticleRendererData>();
|
|
}
|
|
|
|
public virtual void Dispose()
|
|
{
|
|
for (int i = 0; i < batchList.Count; ++i)
|
|
batchList[i].Dispose();
|
|
batchList.Clear();
|
|
|
|
if (activeParticles != null)
|
|
activeParticles.Dispose();
|
|
if (rendererData != null)
|
|
rendererData.Dispose();
|
|
if (rendererIndex != null)
|
|
rendererIndex.Dispose();
|
|
}
|
|
|
|
protected virtual void Clear()
|
|
{
|
|
for (int i = 0; i < batchList.Count; ++i)
|
|
batchList[i].Dispose();
|
|
batchList.Clear();
|
|
|
|
activeParticles.Clear();
|
|
rendererData.Clear();
|
|
rendererIndex.Clear();
|
|
}
|
|
|
|
protected virtual void CreateBatches()
|
|
{
|
|
// generate batches:
|
|
for (int i = 0; i < renderers.Count; ++i)
|
|
{
|
|
renderers[i].renderParameters.layer = renderers[i].gameObject.layer;
|
|
batchList.Add(new ProceduralRenderBatch<ParticleVertex>(i, renderers[i].material, renderers[i].renderParameters));
|
|
}
|
|
|
|
// sort batches:
|
|
batchList.Sort();
|
|
|
|
int particleCount = 0;
|
|
for (int i = 0; i < batchList.Count; ++i)
|
|
{
|
|
var batch = batchList[i];
|
|
var renderer = renderers[batch.firstRenderer];
|
|
int actorParticleCount = renderer.actor.particleCount;
|
|
|
|
batch.vertexCount += actorParticleCount * 4;
|
|
batch.triangleCount += actorParticleCount * 2;
|
|
|
|
batch.firstParticle = particleCount;
|
|
particleCount += actorParticleCount;
|
|
|
|
// add particles here, respecting batch order:
|
|
activeParticles.AddRange(renderer.actor.solverIndices, actorParticleCount);
|
|
rendererData.Add(new ParticleRendererData(renderer.particleColor, renderer.radiusScale));
|
|
rendererIndex.AddReplicate(i, actorParticleCount);
|
|
}
|
|
}
|
|
|
|
protected virtual void CloseBatches()
|
|
{
|
|
// Initialize each batch:
|
|
for (int i = 0; i < batchList.Count; ++i)
|
|
batchList[i].Initialize(layout);
|
|
}
|
|
|
|
public virtual void Setup()
|
|
{
|
|
using (m_SetupRenderMarker.Auto())
|
|
{
|
|
Clear();
|
|
|
|
CreateBatches();
|
|
|
|
ObiUtils.MergeBatches(batchList);
|
|
|
|
CloseBatches();
|
|
|
|
}
|
|
}
|
|
|
|
public virtual void Step()
|
|
{
|
|
}
|
|
|
|
public virtual void Render()
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|