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.
288 lines
10 KiB
288 lines
10 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace UnityEditor.VFX
|
|
{
|
|
abstract class VFXAbstractRenderedOutput : VFXContext
|
|
{
|
|
public enum BlendMode
|
|
{
|
|
Additive,
|
|
Alpha,
|
|
AlphaPremultiplied,
|
|
Opaque,
|
|
}
|
|
public enum ZWriteMode
|
|
{
|
|
Default,
|
|
Off,
|
|
On
|
|
}
|
|
public enum CullMode
|
|
{
|
|
Default,
|
|
Front,
|
|
Back,
|
|
Off
|
|
}
|
|
|
|
public enum ZTestMode
|
|
{
|
|
Default,
|
|
Less,
|
|
Greater,
|
|
LEqual,
|
|
GEqual,
|
|
Equal,
|
|
NotEqual,
|
|
Always
|
|
}
|
|
|
|
[VFXSetting, Header("Render States"), Tooltip("Specifies the transparency and blending method for rendering the particles to the screen.")]
|
|
public BlendMode blendMode = BlendMode.Alpha;
|
|
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.InInspector), SerializeField, Tooltip("Specifies how the particle geometry is culled. This can be used to hide the front or back facing sides or make the mesh double-sided.")]
|
|
protected CullMode cullMode = CullMode.Default;
|
|
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.InInspector), SerializeField, Tooltip("Specifies whether the particle is writing to the depth buffer.")]
|
|
protected ZWriteMode zWriteMode = ZWriteMode.Default;
|
|
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.InInspector), SerializeField, Tooltip("Specifies how the particle rendering is affected by the depth buffer. By default, particles render if they are closer to the camera than solid objects in the scene.")]
|
|
protected ZTestMode zTestMode = ZTestMode.Default;
|
|
|
|
[VFXSetting, Tooltip("When enabled, transparent pixels under the specified alpha threshold will be discarded."), SerializeField]
|
|
protected bool useAlphaClipping = false;
|
|
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.InInspector), SerializeField, Tooltip("When enabled, particles write to the velocity buffer, allowing them to be blurred with the Motion Blur post processing effect.")]
|
|
protected bool generateMotionVector = false;
|
|
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.InInspector), FormerlySerializedAs("excludeFromTAA"), SerializeField, Tooltip("When enabled, particles will not be affected by temporal upscaling and anti-aliasing.")]
|
|
protected bool excludeFromTUAndAA = false;
|
|
|
|
public virtual bool isBlendModeOpaque { get { return blendMode == BlendMode.Opaque; } }
|
|
public bool iszWriting => zWriteMode == ZWriteMode.On || zWriteMode == ZWriteMode.Default && isBlendModeOpaque;
|
|
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.InInspector), Range(-50, 50), FormerlySerializedAs("materialOffset"), Delayed, SerializeField, Tooltip("Specifies an offset applied to the material render queue.")]
|
|
protected int sortingPriority = 0;
|
|
|
|
public virtual int GetMaterialSortingPriority()
|
|
{
|
|
return sortingPriority;
|
|
}
|
|
|
|
public virtual bool hasMotionVector
|
|
{
|
|
get
|
|
{
|
|
return subOutput.supportsMotionVector
|
|
&& implementsMotionVector
|
|
&& generateMotionVector;
|
|
}
|
|
}
|
|
|
|
public virtual bool hasAlphaClipping => useAlphaClipping;
|
|
|
|
public virtual bool implementsMotionVector { get { return false; } }
|
|
|
|
public virtual bool hasExcludeFromTUAndAA => subOutput.supportsExcludeFromTUAndAA && excludeFromTUAndAA;
|
|
|
|
protected VFXAbstractRenderedOutput(VFXDataType dataType) : base(VFXContextType.Output, dataType, VFXDataType.None) { }
|
|
|
|
|
|
public override IEnumerable<int> GetFilteredOutEnumerators(string name)
|
|
{
|
|
return subOutput.GetFilteredOutEnumerators(name);
|
|
}
|
|
|
|
protected override IEnumerable<string> filteredOutSettings
|
|
{
|
|
get
|
|
{
|
|
foreach (var setting in base.filteredOutSettings)
|
|
yield return setting;
|
|
|
|
if (!subOutput.supportsSortingPriority)
|
|
yield return nameof(sortingPriority);
|
|
}
|
|
}
|
|
|
|
public VFXSRPSubOutput subOutput
|
|
{
|
|
get
|
|
{
|
|
if (m_CurrentSubOutput == null)
|
|
m_CurrentSubOutput = GetOrCreateSubOutput();
|
|
return m_CurrentSubOutput;
|
|
}
|
|
}
|
|
|
|
private VFXSRPSubOutput CreateDefaultSubOutput()
|
|
{
|
|
var defaultSubOutput = ScriptableObject.CreateInstance<VFXSRPSubOutput>();
|
|
defaultSubOutput.Init(this);
|
|
return defaultSubOutput;
|
|
}
|
|
|
|
private VFXSRPSubOutput GetOrCreateSubOutput()
|
|
{
|
|
VFXSRPBinder binder = VFXLibrary.currentSRPBinder;
|
|
if (binder == null)
|
|
return CreateDefaultSubOutput();
|
|
|
|
Type outputDataType = binder.SRPOutputDataType;
|
|
if (outputDataType == null)
|
|
return CreateDefaultSubOutput();
|
|
|
|
var outputData = m_SubOutputs.FirstOrDefault(d => d != null && d.GetType() == outputDataType);
|
|
if (outputData == null)
|
|
{
|
|
outputData = (VFXSRPSubOutput)ScriptableObject.CreateInstance(outputDataType);
|
|
m_SubOutputs.Add(outputData);
|
|
}
|
|
|
|
if (outputData.owner != this)
|
|
outputData.Init(this);
|
|
|
|
return outputData;
|
|
}
|
|
|
|
public override void OnEnable()
|
|
{
|
|
InitSubOutputs(m_SubOutputs, false);
|
|
base.OnEnable();
|
|
}
|
|
|
|
public override void OnSRPChanged()
|
|
{
|
|
m_CurrentSubOutput = null;
|
|
}
|
|
|
|
public List<VFXSRPSubOutput> GetSubOutputs()
|
|
{
|
|
return m_SubOutputs;
|
|
}
|
|
|
|
public void InitSubOutputs(List<VFXSRPSubOutput> subOutputs, bool invalidate = true)
|
|
{
|
|
m_SubOutputs = subOutputs;
|
|
SanitizeSubOutputs();
|
|
m_CurrentSubOutput = GetOrCreateSubOutput();
|
|
|
|
if (invalidate)
|
|
Invalidate(InvalidationCause.kSettingChanged);
|
|
}
|
|
|
|
private void SanitizeSubOutputs()
|
|
{
|
|
if (m_SubOutputs == null)
|
|
{
|
|
m_SubOutputs = new List<VFXSRPSubOutput>();
|
|
return;
|
|
}
|
|
|
|
// Reference equals because we only need to remove actual null sub-output, not the ones that cannot be deserialized
|
|
// Because we want to keep reference to unknown SRP outputs. No log because this is internal clean up
|
|
m_SubOutputs.RemoveAll(s => object.ReferenceEquals(s, null));
|
|
|
|
var subOutputsTypes = new HashSet<Type>(); // TODO For some reason constructor that takes a capacity does not exist
|
|
for (int i = 0; i < m_SubOutputs.Count; ++i)
|
|
{
|
|
if (m_SubOutputs[i] == null)
|
|
continue;
|
|
|
|
Type subOutputType = m_SubOutputs[i].GetType();
|
|
if (subOutputsTypes.Contains(subOutputType))
|
|
{
|
|
Debug.LogWarningFormat("Duplicate SRP Sub Output of type {0} found in {1} of type {2}. It is removed", subOutputType, name, GetType());
|
|
m_SubOutputs.RemoveAt(i);
|
|
--i;
|
|
}
|
|
else
|
|
subOutputsTypes.Add(subOutputType);
|
|
}
|
|
}
|
|
|
|
public override void CollectDependencies(HashSet<ScriptableObject> objs, bool ownedOnly)
|
|
{
|
|
base.CollectDependencies(objs, ownedOnly);
|
|
foreach (var data in m_SubOutputs)
|
|
objs.Add(data);
|
|
}
|
|
|
|
public override VFXSetting GetSetting(string name)
|
|
{
|
|
VFXSetting setting = base.GetSetting(name);
|
|
if (!setting.valid)
|
|
setting = subOutput.GetSetting(name);
|
|
return setting;
|
|
}
|
|
|
|
public override IEnumerable<VFXSetting> GetSettings(bool listHidden, VFXSettingAttribute.VisibleFlags flags)
|
|
{
|
|
var settings = base.GetSettings(listHidden, flags);
|
|
settings = settings.Concat(subOutput.GetSettings(listHidden, flags));
|
|
return settings;
|
|
}
|
|
|
|
protected virtual void WriteBlendMode(VFXShaderWriter writer)
|
|
{
|
|
var blendModeStr = subOutput.GetBlendModeStr();
|
|
if (!string.IsNullOrEmpty(blendModeStr))
|
|
writer.WriteLine(blendModeStr);
|
|
if (hasMotionVector && !isBlendModeOpaque)
|
|
writer.WriteLine("Blend 1 SrcAlpha OneMinusSrcAlpha"); //Blend 1 Off, but allow clipping in forward pass for second render target
|
|
}
|
|
|
|
public override void Sanitize(int version)
|
|
{
|
|
if (version < 3) // Fix Blend Modes and useAlphaClipping
|
|
{
|
|
int blendModeValue = (int)blendMode;
|
|
switch (blendModeValue)
|
|
{
|
|
case 0: // No change required for 0 and 1 (Additive and AlphaBlend)
|
|
case 1:
|
|
break;
|
|
case 2: // Masked
|
|
SetSettingValue("useAlphaClipping", true);
|
|
SetSettingValue("blendMode", (int)BlendMode.Opaque);
|
|
break;
|
|
case 3: // Alpha Premultiplied
|
|
SetSettingValue("blendMode", (int)BlendMode.AlphaPremultiplied);
|
|
|
|
break;
|
|
case 4: // Opaque
|
|
SetSettingValue("blendMode", (int)BlendMode.Opaque);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
base.Sanitize(version);
|
|
}
|
|
|
|
public Material FindMaterial()
|
|
{
|
|
var graph = GetGraph();
|
|
if (graph)
|
|
{
|
|
var resource = graph.GetResource();
|
|
if (resource)
|
|
return resource.FindMaterial(this);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
[SerializeField]
|
|
private List<VFXSRPSubOutput> m_SubOutputs;
|
|
|
|
[NonSerialized]
|
|
private VFXSRPSubOutput m_CurrentSubOutput;
|
|
}
|
|
}
|