_xiaofang/xiaofang/Assets/Obi/Scripts/Common/Rendering/ObiParticleRenderSystem.cs
杨号敬 bcc74f0465 add
2024-12-18 02:18:45 +08:00

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()
{
}
}
}