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.
245 lines
7.8 KiB
245 lines
7.8 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using UnityEditor.Graphing; |
|
using UnityEditor.ShaderGraph.Serialization; |
|
using UnityEngine; |
|
using TextureDimension = UnityEngine.Rendering.TextureDimension; |
|
|
|
namespace UnityEditor.ShaderGraph.Internal |
|
{ |
|
[Serializable] |
|
public struct TextureInfo |
|
{ |
|
public TextureInfo(string name, Texture texture, TextureDimension dimension) |
|
{ |
|
this.name = name; |
|
this.texture = texture; |
|
this.dimension = dimension; |
|
Debug.Assert(texture == null || texture.dimension == dimension); |
|
} |
|
|
|
public string name; |
|
public Texture texture; |
|
public TextureDimension dimension; |
|
|
|
public int instanceID => texture != null ? texture.GetInstanceID() : 0; |
|
} |
|
|
|
public sealed class ShaderGraphVfxAsset : ScriptableObject, ISerializationCallbackReceiver |
|
{ |
|
private class ShaderGraphVfxAssetData : JsonObject |
|
{ |
|
public List<JsonData<AbstractShaderProperty>> m_Properties = new List<JsonData<AbstractShaderProperty>>(); |
|
} |
|
|
|
public const int BaseColorSlotId = 1; |
|
public const int MetallicSlotId = 2; |
|
public const int SmoothnessSlotId = 3; |
|
public const int NormalSlotId = 8; |
|
public const int AlphaSlotId = 4; |
|
public const int EmissiveSlotId = 5; |
|
public const int ColorSlotId = 6; |
|
public const int AlphaThresholdSlotId = 7; |
|
|
|
[SerializeField] |
|
public bool generatesWithShaderGraph; |
|
|
|
[SerializeField] |
|
public bool lit; |
|
|
|
[SerializeField] |
|
public bool alphaClipping; |
|
|
|
[SerializeField] |
|
internal ShaderStageCapability[] m_PropertiesStages; |
|
|
|
[SerializeField] |
|
internal GraphCompilationResult compilationResult; |
|
|
|
[SerializeField] |
|
internal ShaderGraphRequirements[] portRequirements; |
|
|
|
[SerializeField] |
|
string m_EvaluationFunctionName; |
|
|
|
[SerializeField] |
|
string m_InputStructName; |
|
|
|
[SerializeField] |
|
string m_OutputStructName; |
|
|
|
[SerializeField] |
|
ConcretePrecision m_ConcretePrecision = ConcretePrecision.Single; |
|
|
|
ShaderGraphVfxAssetData m_Data = new ShaderGraphVfxAssetData(); |
|
|
|
[SerializeField] |
|
private SerializationHelper.JSONSerializedElement m_SerializedVfxAssetData; |
|
|
|
[SerializeField] |
|
internal IntArray[] outputPropertyIndices; |
|
|
|
internal ConcretePrecision concretePrecision |
|
{ |
|
get => m_ConcretePrecision; |
|
set => m_ConcretePrecision = value; |
|
} |
|
|
|
[SerializeField] |
|
OutputMetadata[] m_Outputs; |
|
|
|
[SerializeField] |
|
TextureInfo[] m_TextureInfos; |
|
|
|
public IEnumerable<TextureInfo> textureInfos { get => m_TextureInfos; } |
|
|
|
internal void SetTextureInfos(IList<PropertyCollector.TextureInfo> textures) |
|
{ |
|
m_TextureInfos = textures.Select(t => new TextureInfo(t.name, EditorUtility.InstanceIDToObject(t.textureId) as Texture, t.dimension)).ToArray(); |
|
} |
|
|
|
internal void SetOutputs(OutputMetadata[] outputs) |
|
{ |
|
m_Outputs = outputs; |
|
} |
|
|
|
public OutputMetadata GetOutput(int id) |
|
{ |
|
return m_Outputs.FirstOrDefault(t => t.id == id); |
|
} |
|
|
|
public bool HasOutput(int id) |
|
{ |
|
return m_Outputs.Any(t => t.id == id); |
|
} |
|
|
|
public string evaluationFunctionName |
|
{ |
|
get { return m_EvaluationFunctionName; } |
|
internal set { m_EvaluationFunctionName = value; } |
|
} |
|
|
|
public string inputStructName |
|
{ |
|
get { return m_InputStructName; } |
|
internal set { m_InputStructName = value; } |
|
} |
|
|
|
public string outputStructName |
|
{ |
|
get { return m_OutputStructName; } |
|
internal set { m_OutputStructName = value; } |
|
} |
|
|
|
public List<AbstractShaderProperty> properties |
|
{ |
|
get |
|
{ |
|
EnsureProperties(); |
|
return m_Data.m_Properties.SelectValue().ToList(); |
|
} |
|
} |
|
|
|
public List<AbstractShaderProperty> fragmentProperties |
|
{ |
|
get |
|
{ |
|
EnsureProperties(); |
|
var allProperties = m_Data.m_Properties.SelectValue().ToList(); |
|
var fragProperties = new List<AbstractShaderProperty>(); |
|
for (var i = 0; i < allProperties.Count(); i++) |
|
{ |
|
if ((m_PropertiesStages[i] & ShaderStageCapability.Fragment) != 0) |
|
fragProperties.Add(allProperties[i]); |
|
} |
|
return fragProperties; |
|
} |
|
} |
|
|
|
public List<AbstractShaderProperty> vertexProperties |
|
{ |
|
get |
|
{ |
|
EnsureProperties(); |
|
var allProperties = m_Data.m_Properties.SelectValue().ToList(); |
|
var vertexProperties = new List<AbstractShaderProperty>(); |
|
for (var i = 0; i < allProperties.Count(); i++) |
|
{ |
|
if ((m_PropertiesStages[i] & ShaderStageCapability.Vertex) != 0) |
|
vertexProperties.Add(allProperties[i]); |
|
} |
|
return vertexProperties; |
|
} |
|
} |
|
|
|
internal void SetProperties(List<AbstractShaderProperty> propertiesList) |
|
{ |
|
m_Data.m_Properties.Clear(); |
|
foreach (var property in propertiesList) |
|
{ |
|
m_Data.m_Properties.Add(property); |
|
} |
|
|
|
var json = MultiJson.Serialize(m_Data); |
|
m_SerializedVfxAssetData = new SerializationHelper.JSONSerializedElement() { JSONnodeData = json }; |
|
m_Data = null; |
|
} |
|
|
|
void EnsureProperties() |
|
{ |
|
if ((m_Data == null || m_Data.m_Properties == null || !m_Data.m_Properties.Any()) && !String.IsNullOrEmpty(m_SerializedVfxAssetData.JSONnodeData)) |
|
{ |
|
m_Data = new ShaderGraphVfxAssetData(); |
|
MultiJson.Deserialize(m_Data, m_SerializedVfxAssetData.JSONnodeData); |
|
} |
|
|
|
foreach (var property in m_Data.m_Properties.SelectValue()) |
|
{ |
|
property.SetupConcretePrecision(m_ConcretePrecision); |
|
} |
|
} |
|
|
|
void ISerializationCallbackReceiver.OnAfterDeserialize() |
|
{ |
|
m_Data = null; |
|
} |
|
|
|
void ISerializationCallbackReceiver.OnBeforeSerialize() { } |
|
|
|
public GraphCode GetCode(OutputMetadata[] outputs) |
|
{ |
|
var graphCode = new GraphCode(); |
|
|
|
graphCode.requirements = ShaderGraphRequirements.none; |
|
var outputIndices = new int[outputs.Length]; |
|
for (var i = 0; i < outputs.Length; i++) |
|
{ |
|
if (!outputs[i].isValid) |
|
{ |
|
throw new ArgumentException($"Invalid {nameof(OutputMetadata)} at index {i}.", nameof(outputs)); |
|
} |
|
|
|
outputIndices[i] = outputs[i].index; |
|
graphCode.requirements = graphCode.requirements.Union(portRequirements[outputs[i].index]); |
|
} |
|
|
|
graphCode.code = compilationResult.GenerateCode(outputIndices); |
|
|
|
var propertyIndexSet = new HashSet<int>(); |
|
foreach (var outputIndex in outputIndices) |
|
{ |
|
foreach (var propertyIndex in outputPropertyIndices[outputIndex].array) |
|
{ |
|
propertyIndexSet.Add(propertyIndex); |
|
} |
|
} |
|
var propertyIndices = propertyIndexSet.ToArray(); |
|
Array.Sort(propertyIndices); |
|
var filteredProperties = propertyIndices.Select(i => properties[i]).ToArray(); |
|
graphCode.properties = filteredProperties; |
|
|
|
return graphCode; |
|
} |
|
} |
|
}
|
|
|