164 lines
5.9 KiB
C#
164 lines
5.9 KiB
C#
using UnityEngine;
|
|
using Unity.Profiling;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Obi
|
|
{
|
|
public class ParticleImpostorRendering
|
|
{
|
|
static ProfilerMarker m_ParticlesToMeshPerfMarker = new ProfilerMarker("ParticlesToMesh");
|
|
|
|
private List<Mesh> meshes = new List<Mesh>();
|
|
|
|
private List<Vector3> vertices = new List<Vector3>(4000);
|
|
private List<Vector3> normals = new List<Vector3>(4000);
|
|
private List<Color> colors = new List<Color>(4000);
|
|
private List<int> triangles = new List<int>(6000);
|
|
|
|
private List<Vector4> anisotropy1 = new List<Vector4>(4000);
|
|
private List<Vector4> anisotropy2 = new List<Vector4>(4000);
|
|
private List<Vector4> anisotropy3 = new List<Vector4>(4000);
|
|
|
|
int particlesPerDrawcall = 0;
|
|
int drawcallCount;
|
|
|
|
private Vector3 particleOffset0 = new Vector3(1, 1, 0);
|
|
private Vector3 particleOffset1 = new Vector3(-1, 1, 0);
|
|
private Vector3 particleOffset2 = new Vector3(-1, -1, 0);
|
|
private Vector3 particleOffset3 = new Vector3(1, -1, 0);
|
|
|
|
public IEnumerable<Mesh> Meshes
|
|
{
|
|
get { return meshes.AsReadOnly(); }
|
|
}
|
|
|
|
private void Apply(Mesh mesh)
|
|
{
|
|
mesh.Clear();
|
|
mesh.SetVertices(vertices);
|
|
mesh.SetNormals(normals);
|
|
mesh.SetColors(colors);
|
|
mesh.SetUVs(0, anisotropy1);
|
|
mesh.SetUVs(1, anisotropy2);
|
|
mesh.SetUVs(2, anisotropy3);
|
|
mesh.SetTriangles(triangles, 0, true);
|
|
}
|
|
|
|
public void ClearMeshes()
|
|
{
|
|
foreach (Mesh mesh in meshes)
|
|
GameObject.DestroyImmediate(mesh);
|
|
meshes.Clear();
|
|
}
|
|
|
|
public void UpdateMeshes(IObiParticleCollection collection, bool[] visible = null, Color[] tint = null)
|
|
{
|
|
using (m_ParticlesToMeshPerfMarker.Auto())
|
|
{
|
|
|
|
// figure out the size of our drawcall arrays:
|
|
particlesPerDrawcall = Constants.maxVertsPerMesh / 4;
|
|
drawcallCount = collection.activeParticleCount / particlesPerDrawcall + 1;
|
|
particlesPerDrawcall = Mathf.Min(particlesPerDrawcall, collection.activeParticleCount);
|
|
|
|
// If the amount of meshes we need to draw the particles has changed:
|
|
if (drawcallCount != meshes.Count)
|
|
{
|
|
|
|
// Re-generate meshes:
|
|
ClearMeshes();
|
|
for (int i = 0; i < drawcallCount; i++)
|
|
{
|
|
Mesh mesh = new Mesh();
|
|
mesh.name = "Particle impostors";
|
|
mesh.hideFlags = HideFlags.HideAndDontSave;
|
|
meshes.Add(mesh);
|
|
}
|
|
|
|
}
|
|
|
|
Vector3 position;
|
|
Vector4 basis1 = new Vector4(1, 0, 0, 0);
|
|
Vector4 basis2 = new Vector4(0, 1, 0, 0);
|
|
Vector4 basis3 = new Vector4(0, 0, 1, 0);
|
|
Color color;
|
|
|
|
int visibleLength = visible != null ? visible.Length : 0;
|
|
int tintLength = tint != null ? tint.Length : 0;
|
|
|
|
//Convert particle data to mesh geometry:
|
|
for (int i = 0; i < drawcallCount; i++)
|
|
{
|
|
|
|
// Clear all arrays
|
|
vertices.Clear();
|
|
normals.Clear();
|
|
colors.Clear();
|
|
triangles.Clear();
|
|
anisotropy1.Clear();
|
|
anisotropy2.Clear();
|
|
anisotropy3.Clear();
|
|
|
|
int index = 0;
|
|
int limit = Mathf.Min((i + 1) * particlesPerDrawcall, collection.activeParticleCount);
|
|
|
|
for (int j = i * particlesPerDrawcall; j < limit; ++j)
|
|
{
|
|
if (j < visibleLength && !visible[j])
|
|
continue;
|
|
|
|
int runtimeIndex = collection.GetParticleRuntimeIndex(j);
|
|
position = collection.GetParticlePosition(runtimeIndex);
|
|
collection.GetParticleAnisotropy(runtimeIndex, ref basis1, ref basis2, ref basis3);
|
|
color = collection.GetParticleColor(runtimeIndex);
|
|
|
|
if (j < tintLength)
|
|
color *= tint[j];
|
|
|
|
vertices.Add(position);
|
|
vertices.Add(position);
|
|
vertices.Add(position);
|
|
vertices.Add(position);
|
|
|
|
normals.Add(particleOffset0);
|
|
normals.Add(particleOffset1);
|
|
normals.Add(particleOffset2);
|
|
normals.Add(particleOffset3);
|
|
|
|
colors.Add(color);
|
|
colors.Add(color);
|
|
colors.Add(color);
|
|
colors.Add(color);
|
|
|
|
anisotropy1.Add(basis1);
|
|
anisotropy1.Add(basis1);
|
|
anisotropy1.Add(basis1);
|
|
anisotropy1.Add(basis1);
|
|
|
|
anisotropy2.Add(basis2);
|
|
anisotropy2.Add(basis2);
|
|
anisotropy2.Add(basis2);
|
|
anisotropy2.Add(basis2);
|
|
|
|
anisotropy3.Add(basis3);
|
|
anisotropy3.Add(basis3);
|
|
anisotropy3.Add(basis3);
|
|
anisotropy3.Add(basis3);
|
|
|
|
triangles.Add(index + 2);
|
|
triangles.Add(index + 1);
|
|
triangles.Add(index);
|
|
triangles.Add(index + 3);
|
|
triangles.Add(index + 2);
|
|
triangles.Add(index);
|
|
|
|
index += 4;
|
|
}
|
|
|
|
Apply(meshes[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |