You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
4.9 KiB
115 lines
4.9 KiB
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using UnityEngine;
|
|
|
|
namespace UnityEditor.VFX
|
|
{
|
|
interface IVFXMultiMeshOutput
|
|
{
|
|
uint meshCount { get; }
|
|
}
|
|
|
|
static class VFXMultiMeshHelper
|
|
{
|
|
private const string meshName = "mesh";
|
|
private const string maskName = "subMeshMask";
|
|
private const string indirectIndexName = "indirectIndex";
|
|
public const string lodName = "lodValues";
|
|
private const string bufferName = "indirectBuffer";
|
|
private static readonly Vector4 lodFactors = new Vector4(8.0f, 4.0f, 2.0f, 0.1f);
|
|
|
|
private static string GetId(uint meshCount, int index)
|
|
{
|
|
if (meshCount > 1)
|
|
return index.ToString();
|
|
return string.Empty;
|
|
}
|
|
|
|
public static IEnumerable<VFXPropertyWithValue> GetInputProperties(uint meshCount, VFXOutputUpdate.Features features)
|
|
{
|
|
for (int i = 0; i < meshCount; ++i)
|
|
{
|
|
string id = GetId(meshCount, i);
|
|
|
|
yield return new VFXPropertyWithValue(new VFXProperty(typeof(Mesh), meshName + id, new TooltipAttribute("Specifies the mesh" + id + " used to render the particle.")), VFXResources.defaultResources.mesh);
|
|
yield return new VFXPropertyWithValue(new VFXProperty(typeof(uint), maskName + id, new TooltipAttribute("Defines a bitmask to control which submeshes are rendered for mesh" + id + "."), new BitFieldAttribute()), 0xffffffff);
|
|
}
|
|
|
|
if (VFXOutputUpdate.HasFeature(features, VFXOutputUpdate.Features.LOD))
|
|
yield return new VFXPropertyWithValue(new VFXProperty(typeof(Vector4), lodName, new TooltipAttribute("Specifies the minimum screen ratio for a LOD mesh to be used (e.g. a value of 25 means the mesh has to occupy 25% of the screen on 1 dimension).")), lodFactors);
|
|
|
|
if (VFXOutputUpdate.HasFeature(features, VFXOutputUpdate.Features.LOD)
|
|
|| VFXOutputUpdate.HasFeature(features, VFXOutputUpdate.Features.FrustumCulling))
|
|
yield return new VFXPropertyWithValue(new VFXProperty(typeof(float), "radiusScale", new MinAttribute(0.0f), new TooltipAttribute("Specifies a scale to apply to the radius of the bounding sphere used for LOD and frustum culling. By default the bounding sphere is encompassing a mesh bounding box of side 1.")), 1.0f);
|
|
}
|
|
|
|
public static IEnumerable<string> GetCPUExpressionNames(uint meshCount)
|
|
{
|
|
for (int i = 0; i < meshCount; ++i)
|
|
{
|
|
foreach (var name in GetCPUExpressionNames(meshCount, i))
|
|
{
|
|
yield return name;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static IEnumerable<string> GetCPUExpressionNames(uint meshCount, int meshIndex)
|
|
{
|
|
string id = GetId(meshCount, meshIndex);
|
|
|
|
yield return meshName + id;
|
|
yield return maskName + id;
|
|
}
|
|
|
|
public static IEnumerable<VFXMapping> PatchCPUMapping(IEnumerable<VFXMapping> mappings, uint meshCount, int index)
|
|
{
|
|
string id = GetId(meshCount, index);
|
|
foreach (var m in mappings)
|
|
{
|
|
if (m.name.StartsWith(meshName))
|
|
{
|
|
if (m.name == meshName + id)
|
|
yield return new VFXMapping(meshName, m.index);
|
|
}
|
|
else if (m.name.StartsWith(maskName))
|
|
{
|
|
if (m.name == maskName + id)
|
|
yield return new VFXMapping(maskName, m.index);
|
|
}
|
|
else if (m.name == indirectIndexName)
|
|
yield return new VFXMapping(indirectIndexName, m.index + index);
|
|
else
|
|
yield return m;
|
|
}
|
|
}
|
|
|
|
public static IEnumerable<VFXMapping> PatchBufferMapping(IEnumerable<VFXMapping> mappings, int bufferIndex)
|
|
{
|
|
foreach (var m in mappings)
|
|
{
|
|
if (m.name == bufferName)
|
|
yield return new VFXMapping(bufferName, m.index + bufferIndex);
|
|
else
|
|
yield return m;
|
|
}
|
|
}
|
|
|
|
public static void PatchInstancingSplitValues(List<uint> instancingSplitDescValues, VFXExpressionGraph expressionGraph, ReadOnlyCollection<VFXSlot> inputSlots, uint meshCount, int meshIndex)
|
|
{
|
|
foreach (var name in GetCPUExpressionNames(meshCount, meshIndex))
|
|
{
|
|
var exp = inputSlots.First(s => s.name == name).GetExpression();
|
|
if (exp != null && !exp.IsAny(VFXExpression.Flags.Constant))
|
|
{
|
|
int index = expressionGraph.GetFlattenedIndex(exp);
|
|
if (index >= 0)
|
|
{
|
|
instancingSplitDescValues.Add((uint)index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|