feat: un-limit on the number of mesh instances

pull/120/head
mob-sakai 2020-10-28 00:39:22 +09:00
parent 4be56669fb
commit f1338813ca
4 changed files with 81 additions and 33 deletions

View File

@ -6,12 +6,13 @@ namespace Coffee.UIParticleExtensions
{
internal static class MeshHelper
{
public static long activeMeshIndices { get; private set; }
public static List<bool> activeMeshIndices { get; private set; }
private static readonly List<CombineInstanceEx> s_CachedInstance;
private static int count;
public static void Init()
{
activeMeshIndices = new List<bool>();
}
static MeshHelper()
@ -64,13 +65,13 @@ namespace Coffee.UIParticleExtensions
inst.Push(mesh, transform);
Profiler.EndSample();
activeMeshIndices |= (long) 1 << inst.index;
activeMeshIndices[inst.index] = true;
}
public static void Clear()
{
count = 0;
activeMeshIndices = 0;
activeMeshIndices.Clear();
foreach (var inst in s_CachedInstance)
{
inst.Clear();

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Coffee.UIParticleExtensions;
using UnityEngine;
@ -44,7 +43,7 @@ namespace Coffee.UIExtensions
private Mesh _bakedMesh;
private readonly List<Material> _modifiedMaterials = new List<Material>();
private readonly List<Material> _maskMaterials = new List<Material>();
private long _activeMeshIndices;
private readonly List<bool> _activeMeshIndices = new List<bool>();
private Vector3 _cachedPosition;
private static readonly List<Material> s_TempMaterials = new List<Material>(2);
private static MaterialPropertyBlock s_Mpb;
@ -117,13 +116,14 @@ namespace Coffee.UIExtensions
get { return _modifiedMaterials; }
}
internal long activeMeshIndices
public List<bool> activeMeshIndices
{
get { return _activeMeshIndices; }
set
{
if (_activeMeshIndices == value) return;
_activeMeshIndices = value;
if (_activeMeshIndices.SequenceEqualFast(value)) return;
_activeMeshIndices.Clear();
_activeMeshIndices.AddRange(value);
UpdateMaterial();
}
}
@ -228,9 +228,9 @@ namespace Coffee.UIExtensions
}
// No mesh to render.
if (activeMeshIndices == 0 || !isActiveAndEnabled || particles.Count == 0)
var count = activeMeshIndices.CountFast();
if (count == 0 || !isActiveAndEnabled || particles.Count == 0)
{
_activeMeshIndices = 0;
canvasRenderer.Clear();
foreach (var m in s_PrevMaskMaterials)
@ -242,7 +242,7 @@ namespace Coffee.UIExtensions
}
//
var materialCount = Mathf.Max(8, activeMeshIndices.BitCount());
var materialCount = Mathf.Max(8, count);
canvasRenderer.materialCount = materialCount;
var j = 0;
for (var i = 0; i < particles.Count; i++)
@ -255,8 +255,8 @@ namespace Coffee.UIExtensions
r.GetSharedMaterials(s_TempMaterials);
// Main
var bit = (long) 1 << (i * 2);
if (0 < (activeMeshIndices & bit) && 0 < s_TempMaterials.Count)
var index = i * 2;
if (activeMeshIndices[index] && 0 < s_TempMaterials.Count)
{
var mat = GetModifiedMaterial(s_TempMaterials[0], ps.GetTextureForSprite());
canvasRenderer.SetMaterial(mat, j);
@ -265,9 +265,9 @@ namespace Coffee.UIExtensions
}
// Trails
index++;
if (materialCount <= j) break;
bit <<= 1;
if (0 < (activeMeshIndices & bit) && 1 < s_TempMaterials.Count)
if (activeMeshIndices[index] && 1 < s_TempMaterials.Count)
{
var mat = GetModifiedMaterial(s_TempMaterials[1], null);
canvasRenderer.SetMaterial(mat, j++);
@ -303,7 +303,8 @@ namespace Coffee.UIExtensions
if (m_AnimatableProperties.Length == 0) return;
//
var materialCount = Mathf.Max(8, activeMeshIndices.BitCount());
var count = activeMeshIndices.CountFast();
var materialCount = Mathf.Max(8, count);
canvasRenderer.materialCount = materialCount;
var j = 0;
for (var i = 0; i < particles.Count; i++)
@ -316,8 +317,7 @@ namespace Coffee.UIExtensions
r.GetSharedMaterials(s_TempMaterials);
// Main
var bit = (long) 1 << (i * 2);
if (0 < (activeMeshIndices & bit) && 0 < s_TempMaterials.Count)
if (activeMeshIndices[i * 2] && 0 < s_TempMaterials.Count)
{
UpdateMaterialProperties(r, j);
j++;
@ -350,7 +350,7 @@ namespace Coffee.UIExtensions
protected override void OnEnable()
{
_cachedPosition = transform.localPosition;
_activeMeshIndices = 0;
activeMeshIndices.Clear();
UIParticleUpdater.Register(this);
particles.Exec(p => p.GetComponent<ParticleSystemRenderer>().enabled = false);
@ -418,7 +418,7 @@ namespace Coffee.UIExtensions
return;
}
if (!this || particles.Any(x => x)) return;
if (!this || particles.AnyFast()) return;
// refresh.
#if UNITY_EDITOR

View File

@ -129,8 +129,10 @@ namespace Coffee.UIExtensions
private static void BakeMesh(UIParticle particle)
{
// Clear mesh before bake.
Profiler.BeginSample("[UIParticle] Bake Mesh > Clear mesh before bake");
MeshHelper.Clear();
particle.bakedMesh.Clear(false);
Profiler.EndSample();
// Get camera for baking mesh.
var camera = BakingCamera.GetCamera(particle.canvas);
@ -153,11 +155,17 @@ namespace Coffee.UIExtensions
for (var i = 0; i < particle.particles.Count; i++)
{
Profiler.BeginSample("[UIParticle] Bake Mesh > Push index");
MeshHelper.activeMeshIndices.Add(false);
MeshHelper.activeMeshIndices.Add(false);
Profiler.EndSample();
// No particle to render.
var currentPs = particle.particles[i];
if (!currentPs || !currentPs.IsAlive() || currentPs.particleCount == 0) continue;
// Calc matrix.
Profiler.BeginSample("[UIParticle] Bake Mesh > Calc matrix");
var matrix = rootMatrix;
if (currentPs.transform != root)
{
@ -177,6 +185,7 @@ namespace Coffee.UIExtensions
}
matrix = scaleMatrix * matrix;
Profiler.EndSample();
// Extra world simulation.
if (currentPs.main.simulationSpace == ParticleSystemSimulationSpace.World && 0 < diff.sqrMagnitude)
@ -245,7 +254,9 @@ namespace Coffee.UIExtensions
}
// Set active indices.
Profiler.BeginSample("[UIParticle] Bake Mesh > Set active indices");
particle.activeMeshIndices = MeshHelper.activeMeshIndices;
Profiler.EndSample();
// Combine
Profiler.BeginSample("[UIParticle] Bake Mesh > CombineMesh");

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Coffee.UIParticleExtensions
{
@ -30,13 +31,38 @@ namespace Coffee.UIParticleExtensions
#endif
}
internal static class LongExtensions
internal static class ListExtensions
{
public static int BitCount(this long self)
public static bool SequenceEqualFast(this List<bool> self, List<bool> value)
{
self = self - ((self >> 1) & 0x5555555555555555L);
self = (self & 0x3333333333333333L) + ((self >> 2) & 0x3333333333333333L);
return (int) (unchecked(((self + (self >> 4)) & 0xF0F0F0F0F0F0F0FL) * 0x101010101010101L) >> 56);
if (self.Count != value.Count) return false;
for (var i = 0; i < self.Count; ++i)
{
if (self[i] != value[i]) return false;
}
return true;
}
public static int CountFast(this List<bool> self)
{
var count = 0;
for (var i = 0; i < self.Count; ++i)
{
if (self[i]) count++;
}
return count;
}
public static bool AnyFast<T>(this List<T> self) where T : Object
{
for (var i = 0; i < self.Count; ++i)
{
if (self[i]) return true;
}
return false;
}
}
@ -107,24 +133,28 @@ namespace Coffee.UIParticleExtensions
internal static class CombineInstanceArrayPool
{
private static readonly List<CombineInstance[]> s_Pool;
private static readonly Dictionary<int, CombineInstance[]> s_Pool;
public static void Init()
{
s_Pool.Clear();
}
static CombineInstanceArrayPool()
{
s_Pool = new List<CombineInstance[]>(32);
for (var i = 0; i < 32; i++)
{
s_Pool.Add(new CombineInstance[i]);
}
s_Pool = new Dictionary<int, CombineInstance[]>();
}
public static CombineInstance[] Get(List<CombineInstance> src)
{
var dst = s_Pool[src.Count];
CombineInstance[] dst;
var count = src.Count;
if (!s_Pool.TryGetValue(count, out dst))
{
dst = new CombineInstance[count];
s_Pool.Add(count, dst);
}
for (var i = 0; i < src.Count; i++)
{
dst[i].mesh = src[i].mesh;
@ -136,7 +166,13 @@ namespace Coffee.UIParticleExtensions
public static CombineInstance[] Get(List<CombineInstanceEx> src, int count)
{
var dst = s_Pool[count];
CombineInstance[] dst;
if (!s_Pool.TryGetValue(count, out dst))
{
dst = new CombineInstance[count];
s_Pool.Add(count, dst);
}
for (var i = 0; i < count; i++)
{
dst[i].mesh = src[i].mesh;