initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
@ -0,0 +1,977 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Colors;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEditor.ShaderGraph.Drawing;
|
||||
using UnityEditor.ShaderGraph.Serialization;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Serializable]
|
||||
abstract class AbstractMaterialNode : JsonObject, IGroupItem, IRectInterface
|
||||
{
|
||||
[SerializeField]
|
||||
JsonRef<GroupData> m_Group = null;
|
||||
|
||||
[SerializeField]
|
||||
private string m_Name;
|
||||
|
||||
[SerializeField]
|
||||
private DrawState m_DrawState;
|
||||
|
||||
[NonSerialized]
|
||||
bool m_HasError;
|
||||
|
||||
[NonSerialized]
|
||||
bool m_IsValid = true;
|
||||
|
||||
[NonSerialized]
|
||||
bool m_IsActive = true;
|
||||
|
||||
[NonSerialized]
|
||||
bool m_WasUsedByGenerator = false;
|
||||
|
||||
[SerializeField]
|
||||
List<JsonData<MaterialSlot>> m_Slots = new List<JsonData<MaterialSlot>>();
|
||||
|
||||
public GraphData owner { get; set; }
|
||||
|
||||
internal virtual bool ExposeToSearcher => true;
|
||||
|
||||
OnNodeModified m_OnModified;
|
||||
|
||||
public GroupData group
|
||||
{
|
||||
get => m_Group;
|
||||
set
|
||||
{
|
||||
if (m_Group == value)
|
||||
return;
|
||||
|
||||
m_Group = value;
|
||||
Dirty(ModificationScope.Topological);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterCallback(OnNodeModified callback)
|
||||
{
|
||||
m_OnModified += callback;
|
||||
}
|
||||
|
||||
public void UnregisterCallback(OnNodeModified callback)
|
||||
{
|
||||
m_OnModified -= callback;
|
||||
}
|
||||
|
||||
public void Dirty(ModificationScope scope)
|
||||
{
|
||||
if (m_OnModified != null)
|
||||
m_OnModified(this, scope);
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return m_Name; }
|
||||
set { m_Name = value; }
|
||||
}
|
||||
|
||||
public string[] synonyms;
|
||||
|
||||
protected virtual string documentationPage => name;
|
||||
public virtual string documentationURL => NodeUtils.GetDocumentationString(documentationPage);
|
||||
|
||||
public virtual bool canDeleteNode => owner != null && owner.outputNode != this;
|
||||
|
||||
public DrawState drawState
|
||||
{
|
||||
get { return m_DrawState; }
|
||||
set
|
||||
{
|
||||
m_DrawState = value;
|
||||
Dirty(ModificationScope.Layout);
|
||||
}
|
||||
}
|
||||
|
||||
Rect IRectInterface.rect
|
||||
{
|
||||
get => drawState.position;
|
||||
set
|
||||
{
|
||||
var state = drawState;
|
||||
state.position = value;
|
||||
drawState = state;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool canSetPrecision
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
// this is the precision after the inherit/automatic behavior has been calculated
|
||||
// it does NOT include fallback to any graph default precision
|
||||
public GraphPrecision graphPrecision { get; set; } = GraphPrecision.Single;
|
||||
|
||||
private ConcretePrecision m_ConcretePrecision = ConcretePrecision.Single;
|
||||
|
||||
public ConcretePrecision concretePrecision
|
||||
{
|
||||
get => m_ConcretePrecision;
|
||||
set => m_ConcretePrecision = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private Precision m_Precision = Precision.Inherit;
|
||||
|
||||
public Precision precision
|
||||
{
|
||||
get => m_Precision;
|
||||
set => m_Precision = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
bool m_PreviewExpanded = true;
|
||||
|
||||
public bool previewExpanded
|
||||
{
|
||||
get { return m_PreviewExpanded; }
|
||||
set
|
||||
{
|
||||
if (previewExpanded == value)
|
||||
return;
|
||||
m_PreviewExpanded = value;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
// by default, if this returns null, the system will allow creation of any previous version
|
||||
public virtual IEnumerable<int> allowedNodeVersions => null;
|
||||
|
||||
// Nodes that want to have a preview area can override this and return true
|
||||
public virtual bool hasPreview
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
internal PreviewMode m_PreviewMode = PreviewMode.Inherit;
|
||||
public virtual PreviewMode previewMode
|
||||
{
|
||||
get { return m_PreviewMode; }
|
||||
}
|
||||
|
||||
public virtual bool allowedInSubGraph
|
||||
{
|
||||
get { return !(this is BlockNode); }
|
||||
}
|
||||
|
||||
public virtual bool allowedInMainGraph
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public virtual bool allowedInLayerGraph
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public virtual bool hasError
|
||||
{
|
||||
get { return m_HasError; }
|
||||
protected set { m_HasError = value; }
|
||||
}
|
||||
|
||||
public virtual bool isActive
|
||||
{
|
||||
get { return m_IsActive; }
|
||||
}
|
||||
|
||||
internal virtual bool wasUsedByGenerator
|
||||
{
|
||||
get { return m_WasUsedByGenerator; }
|
||||
}
|
||||
|
||||
internal void SetUsedByGenerator()
|
||||
{
|
||||
m_WasUsedByGenerator = true;
|
||||
}
|
||||
|
||||
//There are times when isActive needs to be set to a value explicitly, and
|
||||
//not be changed by active forest parsing (what we do when we need to figure out
|
||||
//what nodes should or should not be active, usually from an edit; see NodeUtils).
|
||||
//In this case, we allow for explicit setting of an active value that cant be overriden.
|
||||
//Implicit implies that active forest parsing can edit the nodes isActive property
|
||||
public enum ActiveState
|
||||
{
|
||||
Implicit = 0,
|
||||
ExplicitInactive = 1,
|
||||
ExplicitActive = 2
|
||||
}
|
||||
|
||||
private ActiveState m_ActiveState = ActiveState.Implicit;
|
||||
public ActiveState activeState
|
||||
{
|
||||
get => m_ActiveState;
|
||||
}
|
||||
|
||||
public void SetOverrideActiveState(ActiveState overrideState, bool updateConnections = true)
|
||||
{
|
||||
if (m_ActiveState == overrideState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_ActiveState = overrideState;
|
||||
switch (m_ActiveState)
|
||||
{
|
||||
case ActiveState.Implicit:
|
||||
if (updateConnections)
|
||||
{
|
||||
NodeUtils.ReevaluateActivityOfConnectedNodes(this);
|
||||
}
|
||||
break;
|
||||
case ActiveState.ExplicitInactive:
|
||||
if (m_IsActive == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IsActive = false;
|
||||
Dirty(ModificationScope.Node);
|
||||
if (updateConnections)
|
||||
{
|
||||
NodeUtils.ReevaluateActivityOfConnectedNodes(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ActiveState.ExplicitActive:
|
||||
if (m_IsActive == true)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IsActive = true;
|
||||
Dirty(ModificationScope.Node);
|
||||
if (updateConnections)
|
||||
{
|
||||
NodeUtils.ReevaluateActivityOfConnectedNodes(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetActive(bool value, bool updateConnections = true)
|
||||
{
|
||||
if (m_IsActive == value)
|
||||
return;
|
||||
|
||||
if (m_ActiveState != ActiveState.Implicit)
|
||||
{
|
||||
Debug.LogError($"Cannot set IsActive on Node {this} when value is explicitly overriden by ActiveState {m_ActiveState}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update this node
|
||||
m_IsActive = value;
|
||||
Dirty(ModificationScope.Node);
|
||||
|
||||
if (updateConnections)
|
||||
{
|
||||
NodeUtils.ReevaluateActivityOfConnectedNodes(this);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool isValid
|
||||
{
|
||||
get { return m_IsValid; }
|
||||
set
|
||||
{
|
||||
if (m_IsValid == value)
|
||||
return;
|
||||
|
||||
m_IsValid = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string m_DefaultVariableName;
|
||||
string m_NameForDefaultVariableName;
|
||||
|
||||
string defaultVariableName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_NameForDefaultVariableName != name)
|
||||
{
|
||||
m_DefaultVariableName = string.Format("{0}_{1}", NodeUtils.GetHLSLSafeName(name ?? "node"), objectId);
|
||||
m_NameForDefaultVariableName = name;
|
||||
}
|
||||
return m_DefaultVariableName;
|
||||
}
|
||||
}
|
||||
|
||||
#region Custom Colors
|
||||
|
||||
[SerializeField]
|
||||
CustomColorData m_CustomColors = new CustomColorData();
|
||||
|
||||
public bool TryGetColor(string provider, ref Color color)
|
||||
{
|
||||
return m_CustomColors.TryGetColor(provider, out color);
|
||||
}
|
||||
|
||||
public void ResetColor(string provider)
|
||||
{
|
||||
m_CustomColors.Remove(provider);
|
||||
}
|
||||
|
||||
public void SetColor(string provider, Color color)
|
||||
{
|
||||
m_CustomColors.Set(provider, color);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected AbstractMaterialNode()
|
||||
{
|
||||
m_DrawState.expanded = true;
|
||||
}
|
||||
|
||||
public void GetInputSlots<T>(List<T> foundSlots) where T : MaterialSlot
|
||||
{
|
||||
foreach (var slot in m_Slots.SelectValue())
|
||||
{
|
||||
if (slot.isInputSlot && slot is T)
|
||||
foundSlots.Add((T)slot);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void GetInputSlots<T>(MaterialSlot startingSlot, List<T> foundSlots) where T : MaterialSlot
|
||||
{
|
||||
GetInputSlots(foundSlots);
|
||||
}
|
||||
|
||||
public void GetOutputSlots<T>(List<T> foundSlots) where T : MaterialSlot
|
||||
{
|
||||
foreach (var slot in m_Slots.SelectValue())
|
||||
{
|
||||
if (slot.isOutputSlot && slot is T materialSlot)
|
||||
{
|
||||
foundSlots.Add(materialSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void GetOutputSlots<T>(MaterialSlot startingSlot, List<T> foundSlots) where T : MaterialSlot
|
||||
{
|
||||
GetOutputSlots(foundSlots);
|
||||
}
|
||||
|
||||
public void GetSlots<T>(List<T> foundSlots) where T : MaterialSlot
|
||||
{
|
||||
foreach (var slot in m_Slots.SelectValue())
|
||||
{
|
||||
if (slot is T materialSlot)
|
||||
{
|
||||
foundSlots.Add(materialSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
foreach (var inputSlot in this.GetInputSlots<MaterialSlot>())
|
||||
{
|
||||
var edges = owner.GetEdges(inputSlot.slotReference);
|
||||
if (edges.Any(e => e.outputSlot.node.isActive))
|
||||
continue;
|
||||
|
||||
inputSlot.AddDefaultProperty(properties, generationMode);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetSlotValue(int inputSlotId, GenerationMode generationMode, ConcretePrecision concretePrecision)
|
||||
{
|
||||
string slotValue = GetSlotValue(inputSlotId, generationMode);
|
||||
return slotValue.Replace(PrecisionUtil.Token, concretePrecision.ToShaderString());
|
||||
}
|
||||
|
||||
public string GetSlotValue(int inputSlotId, GenerationMode generationMode)
|
||||
{
|
||||
var inputSlot = FindSlot<MaterialSlot>(inputSlotId);
|
||||
if (inputSlot == null)
|
||||
return string.Empty;
|
||||
|
||||
var edges = owner.GetEdges(inputSlot.slotReference);
|
||||
|
||||
if (edges.Any())
|
||||
{
|
||||
var fromSocketRef = edges.First().outputSlot;
|
||||
var fromNode = fromSocketRef.node;
|
||||
return fromNode.GetOutputForSlot(fromSocketRef, inputSlot.concreteValueType, generationMode);
|
||||
}
|
||||
|
||||
return inputSlot.GetDefaultValue(generationMode);
|
||||
}
|
||||
|
||||
public AbstractShaderProperty GetSlotProperty(int inputSlotId)
|
||||
{
|
||||
if (owner == null)
|
||||
return null;
|
||||
|
||||
var inputSlot = FindSlot<MaterialSlot>(inputSlotId);
|
||||
if (inputSlot?.slotReference.node == null)
|
||||
return null;
|
||||
|
||||
var edges = owner.GetEdges(inputSlot.slotReference);
|
||||
if (edges.Any())
|
||||
{
|
||||
var fromSocketRef = edges.First().outputSlot;
|
||||
var fromNode = fromSocketRef.node;
|
||||
if (fromNode == null)
|
||||
return null; // this is an error condition... we have an edge that connects to a non-existant node?
|
||||
|
||||
if (fromNode is PropertyNode propNode)
|
||||
{
|
||||
return propNode.property;
|
||||
}
|
||||
|
||||
if (fromNode is RedirectNodeData redirectNode)
|
||||
{
|
||||
return redirectNode.GetSlotProperty(RedirectNodeData.kInputSlotID);
|
||||
}
|
||||
|
||||
#if PROCEDURAL_VT_IN_GRAPH
|
||||
if (fromNode is ProceduralVirtualTextureNode pvtNode)
|
||||
{
|
||||
return pvtNode.AsShaderProperty();
|
||||
}
|
||||
#endif // PROCEDURAL_VT_IN_GRAPH
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected internal virtual string GetOutputForSlot(SlotReference fromSocketRef, ConcreteSlotValueType valueType, GenerationMode generationMode)
|
||||
{
|
||||
var slot = FindOutputSlot<MaterialSlot>(fromSocketRef.slotId);
|
||||
if (slot == null)
|
||||
return string.Empty;
|
||||
|
||||
if (fromSocketRef.node.isActive)
|
||||
return GenerationUtils.AdaptNodeOutput(this, slot.id, valueType);
|
||||
else
|
||||
return slot.GetDefaultValue(generationMode);
|
||||
}
|
||||
|
||||
public AbstractMaterialNode GetInputNodeFromSlot(int inputSlotId)
|
||||
{
|
||||
var inputSlot = FindSlot<MaterialSlot>(inputSlotId);
|
||||
if (inputSlot == null)
|
||||
return null;
|
||||
|
||||
var edges = owner.GetEdges(inputSlot.slotReference).ToArray();
|
||||
AbstractMaterialNode fromNode = null;
|
||||
if (edges.Count() > 0)
|
||||
{
|
||||
var fromSocketRef = edges[0].outputSlot;
|
||||
fromNode = fromSocketRef.node;
|
||||
}
|
||||
return fromNode;
|
||||
}
|
||||
|
||||
public static ConcreteSlotValueType ConvertDynamicVectorInputTypeToConcrete(IEnumerable<ConcreteSlotValueType> inputTypes)
|
||||
{
|
||||
var concreteSlotValueTypes = inputTypes as IList<ConcreteSlotValueType> ?? inputTypes.ToList();
|
||||
|
||||
var inputTypesDistinct = concreteSlotValueTypes.Distinct().ToList();
|
||||
switch (inputTypesDistinct.Count)
|
||||
{
|
||||
case 0:
|
||||
return ConcreteSlotValueType.Vector1;
|
||||
case 1:
|
||||
if (SlotValueHelper.AreCompatible(SlotValueType.DynamicVector, inputTypesDistinct.First()))
|
||||
return inputTypesDistinct.First();
|
||||
break;
|
||||
default:
|
||||
// find the 'minumum' channel width excluding 1 as it can promote
|
||||
inputTypesDistinct.RemoveAll(x => x == ConcreteSlotValueType.Vector1);
|
||||
var ordered = inputTypesDistinct.OrderByDescending(x => x);
|
||||
if (ordered.Any())
|
||||
return ordered.FirstOrDefault();
|
||||
break;
|
||||
}
|
||||
return ConcreteSlotValueType.Vector1;
|
||||
}
|
||||
|
||||
public static ConcreteSlotValueType ConvertDynamicMatrixInputTypeToConcrete(IEnumerable<ConcreteSlotValueType> inputTypes)
|
||||
{
|
||||
var concreteSlotValueTypes = inputTypes as IList<ConcreteSlotValueType> ?? inputTypes.ToList();
|
||||
|
||||
var inputTypesDistinct = concreteSlotValueTypes.Distinct().ToList();
|
||||
switch (inputTypesDistinct.Count)
|
||||
{
|
||||
case 0:
|
||||
return ConcreteSlotValueType.Matrix2;
|
||||
case 1:
|
||||
return inputTypesDistinct.FirstOrDefault();
|
||||
default:
|
||||
var ordered = inputTypesDistinct.OrderByDescending(x => x);
|
||||
if (ordered.Any())
|
||||
return ordered.FirstOrDefault();
|
||||
break;
|
||||
}
|
||||
return ConcreteSlotValueType.Matrix2;
|
||||
}
|
||||
|
||||
protected const string k_validationErrorMessage = "Error found during node validation";
|
||||
|
||||
// evaluate ALL the precisions...
|
||||
public virtual void UpdatePrecision(List<MaterialSlot> inputSlots)
|
||||
{
|
||||
// first let's reduce from precision ==> graph precision
|
||||
if (precision == Precision.Inherit)
|
||||
{
|
||||
// inherit means calculate it automatically based on inputs
|
||||
|
||||
// If no inputs were found use the precision of the Graph
|
||||
if (inputSlots.Count == 0)
|
||||
{
|
||||
graphPrecision = GraphPrecision.Graph;
|
||||
}
|
||||
else
|
||||
{
|
||||
int curGraphPrecision = (int)GraphPrecision.Half;
|
||||
foreach (var inputSlot in inputSlots)
|
||||
{
|
||||
// If input port doesn't have an edge use the Graph's precision for that input
|
||||
var edges = owner?.GetEdges(inputSlot.slotReference).ToList();
|
||||
if (!edges.Any())
|
||||
{
|
||||
// disconnected inputs use graph precision
|
||||
curGraphPrecision = Math.Min(curGraphPrecision, (int)GraphPrecision.Graph);
|
||||
}
|
||||
else
|
||||
{
|
||||
var outputSlotRef = edges[0].outputSlot;
|
||||
var outputNode = outputSlotRef.node;
|
||||
curGraphPrecision = Math.Min(curGraphPrecision, (int)outputNode.graphPrecision);
|
||||
}
|
||||
}
|
||||
graphPrecision = (GraphPrecision)curGraphPrecision;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// not inherited, just use the node's selected precision
|
||||
graphPrecision = precision.ToGraphPrecision(GraphPrecision.Graph);
|
||||
}
|
||||
|
||||
// calculate the concrete precision, with fall-back to the graph concrete precision
|
||||
concretePrecision = graphPrecision.ToConcrete(owner.graphDefaultConcretePrecision);
|
||||
}
|
||||
|
||||
public virtual void EvaluateDynamicMaterialSlots(List<MaterialSlot> inputSlots, List<MaterialSlot> outputSlots)
|
||||
{
|
||||
var dynamicInputSlotsToCompare = DictionaryPool<DynamicVectorMaterialSlot, ConcreteSlotValueType>.Get();
|
||||
var skippedDynamicSlots = ListPool<DynamicVectorMaterialSlot>.Get();
|
||||
|
||||
var dynamicMatrixInputSlotsToCompare = DictionaryPool<DynamicMatrixMaterialSlot, ConcreteSlotValueType>.Get();
|
||||
var skippedDynamicMatrixSlots = ListPool<DynamicMatrixMaterialSlot>.Get();
|
||||
|
||||
// iterate the input slots
|
||||
{
|
||||
foreach (var inputSlot in inputSlots)
|
||||
{
|
||||
inputSlot.hasError = false;
|
||||
// if there is a connection
|
||||
var edges = owner.GetEdges(inputSlot.slotReference).ToList();
|
||||
if (!edges.Any())
|
||||
{
|
||||
if (inputSlot is DynamicVectorMaterialSlot)
|
||||
skippedDynamicSlots.Add(inputSlot as DynamicVectorMaterialSlot);
|
||||
if (inputSlot is DynamicMatrixMaterialSlot)
|
||||
skippedDynamicMatrixSlots.Add(inputSlot as DynamicMatrixMaterialSlot);
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the output details
|
||||
var outputSlotRef = edges[0].outputSlot;
|
||||
var outputNode = outputSlotRef.node;
|
||||
if (outputNode == null)
|
||||
continue;
|
||||
|
||||
var outputSlot = outputNode.FindOutputSlot<MaterialSlot>(outputSlotRef.slotId);
|
||||
if (outputSlot == null)
|
||||
continue;
|
||||
|
||||
if (outputSlot.hasError)
|
||||
{
|
||||
inputSlot.hasError = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
var outputConcreteType = outputSlot.concreteValueType;
|
||||
// dynamic input... depends on output from other node.
|
||||
// we need to compare ALL dynamic inputs to make sure they
|
||||
// are compatible.
|
||||
if (inputSlot is DynamicVectorMaterialSlot)
|
||||
{
|
||||
dynamicInputSlotsToCompare.Add((DynamicVectorMaterialSlot)inputSlot, outputConcreteType);
|
||||
continue;
|
||||
}
|
||||
else if (inputSlot is DynamicMatrixMaterialSlot)
|
||||
{
|
||||
dynamicMatrixInputSlotsToCompare.Add((DynamicMatrixMaterialSlot)inputSlot, outputConcreteType);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// we can now figure out the dynamic slotType
|
||||
// from here set all the
|
||||
var dynamicType = ConvertDynamicVectorInputTypeToConcrete(dynamicInputSlotsToCompare.Values);
|
||||
foreach (var dynamicKvP in dynamicInputSlotsToCompare)
|
||||
dynamicKvP.Key.SetConcreteType(dynamicType);
|
||||
foreach (var skippedSlot in skippedDynamicSlots)
|
||||
skippedSlot.SetConcreteType(dynamicType);
|
||||
|
||||
// and now dynamic matrices
|
||||
var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicMatrixInputSlotsToCompare.Values);
|
||||
foreach (var dynamicKvP in dynamicMatrixInputSlotsToCompare)
|
||||
dynamicKvP.Key.SetConcreteType(dynamicMatrixType);
|
||||
foreach (var skippedSlot in skippedDynamicMatrixSlots)
|
||||
skippedSlot.SetConcreteType(dynamicMatrixType);
|
||||
|
||||
bool inputError = inputSlots.Any(x => x.hasError);
|
||||
if (inputError)
|
||||
{
|
||||
owner.AddConcretizationError(objectId, string.Format("Node {0} had input error", objectId));
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
// configure the output slots now
|
||||
// their slotType will either be the default output slotType
|
||||
// or the above dynamic slotType for dynamic nodes
|
||||
// or error if there is an input error
|
||||
foreach (var outputSlot in outputSlots)
|
||||
{
|
||||
outputSlot.hasError = false;
|
||||
|
||||
if (inputError)
|
||||
{
|
||||
outputSlot.hasError = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outputSlot is DynamicVectorMaterialSlot dynamicVectorMaterialSlot)
|
||||
{
|
||||
dynamicVectorMaterialSlot.SetConcreteType(dynamicType);
|
||||
continue;
|
||||
}
|
||||
else if (outputSlot is DynamicMatrixMaterialSlot dynamicMatrixMaterialSlot)
|
||||
{
|
||||
dynamicMatrixMaterialSlot.SetConcreteType(dynamicMatrixType);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (outputSlots.Any(x => x.hasError))
|
||||
{
|
||||
owner.AddConcretizationError(objectId, string.Format("Node {0} had output error", objectId));
|
||||
hasError = true;
|
||||
}
|
||||
CalculateNodeHasError();
|
||||
|
||||
ListPool<DynamicVectorMaterialSlot>.Release(skippedDynamicSlots);
|
||||
DictionaryPool<DynamicVectorMaterialSlot, ConcreteSlotValueType>.Release(dynamicInputSlotsToCompare);
|
||||
|
||||
ListPool<DynamicMatrixMaterialSlot>.Release(skippedDynamicMatrixSlots);
|
||||
DictionaryPool<DynamicMatrixMaterialSlot, ConcreteSlotValueType>.Release(dynamicMatrixInputSlotsToCompare);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Concretize()
|
||||
{
|
||||
hasError = false;
|
||||
owner?.ClearErrorsForNode(this);
|
||||
|
||||
using (var inputSlots = PooledList<MaterialSlot>.Get())
|
||||
using (var outputSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(inputSlots);
|
||||
GetOutputSlots(outputSlots);
|
||||
|
||||
UpdatePrecision(inputSlots);
|
||||
EvaluateDynamicMaterialSlots(inputSlots, outputSlots);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ValidateNode()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool canCutNode => true;
|
||||
public virtual bool canCopyNode => true;
|
||||
|
||||
protected virtual void CalculateNodeHasError()
|
||||
{
|
||||
foreach (var slot in this.GetInputSlots<MaterialSlot>())
|
||||
{
|
||||
if (slot.isConnected)
|
||||
{
|
||||
var edge = owner.GetEdges(slot.slotReference).First();
|
||||
var outputNode = edge.outputSlot.node;
|
||||
var outputSlot = outputNode.GetOutputSlots<MaterialSlot>().First(s => s.id == edge.outputSlot.slotId);
|
||||
if (!slot.IsCompatibleWith(outputSlot))
|
||||
{
|
||||
owner.AddConcretizationError(objectId, $"Slot {slot.RawDisplayName()} cannot accept input of type {outputSlot.concreteValueType}.");
|
||||
hasError = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string GetRayTracingError() => $@"
|
||||
#if defined(SHADER_STAGE_RAY_TRACING)
|
||||
#error '{name}' node is not supported in ray tracing, please provide an alternate implementation, relying for instance on the 'Raytracing Quality' keyword
|
||||
#endif";
|
||||
|
||||
public virtual void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
using (var tempPreviewProperties = PooledList<PreviewProperty>.Get())
|
||||
using (var tempEdges = PooledList<IEdge>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
foreach (var s in tempSlots)
|
||||
{
|
||||
tempPreviewProperties.Clear();
|
||||
tempEdges.Clear();
|
||||
if (owner != null)
|
||||
{
|
||||
owner.GetEdges(s.slotReference, tempEdges);
|
||||
if (tempEdges.Any())
|
||||
continue;
|
||||
}
|
||||
|
||||
s.GetPreviewProperties(tempPreviewProperties, GetVariableNameForSlot(s.id));
|
||||
for (int i = 0; i < tempPreviewProperties.Count; i++)
|
||||
{
|
||||
if (tempPreviewProperties[i].name == null)
|
||||
continue;
|
||||
|
||||
properties.Add(tempPreviewProperties[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
var slot = FindSlot<MaterialSlot>(slotId);
|
||||
if (slot == null)
|
||||
throw new ArgumentException(string.Format("Attempting to use MaterialSlot({0}) on node of type {1} where this slot can not be found", slotId, this), "slotId");
|
||||
return string.Format("_{0}_{1}_{2}", GetVariableNameForNode(), NodeUtils.GetHLSLSafeName(slot.shaderOutputName), unchecked((uint)slotId));
|
||||
}
|
||||
|
||||
public string GetConnnectionStateVariableNameForSlot(int slotId)
|
||||
{
|
||||
return ShaderInput.GetConnectionStateVariableName(GetVariableNameForSlot(slotId));
|
||||
}
|
||||
|
||||
public virtual string GetVariableNameForNode()
|
||||
{
|
||||
return defaultVariableName;
|
||||
}
|
||||
|
||||
public MaterialSlot AddSlot(MaterialSlot slot, bool attemptToModifyExistingInstance = true)
|
||||
{
|
||||
if (slot == null)
|
||||
{
|
||||
throw new ArgumentException($"Trying to add null slot to node {this}");
|
||||
}
|
||||
MaterialSlot foundSlot = FindSlot<MaterialSlot>(slot.id);
|
||||
|
||||
if (slot == foundSlot)
|
||||
return foundSlot;
|
||||
|
||||
// Try to keep the existing instance to avoid unnecessary changes to file
|
||||
if (attemptToModifyExistingInstance && foundSlot != null && slot.GetType() == foundSlot.GetType())
|
||||
{
|
||||
foundSlot.displayName = slot.RawDisplayName();
|
||||
foundSlot.CopyDefaultValue(slot);
|
||||
return foundSlot;
|
||||
}
|
||||
|
||||
// keep the same ordering by replacing the first match, if it exists
|
||||
int firstIndex = m_Slots.FindIndex(s => s.value.id == slot.id);
|
||||
if (firstIndex >= 0)
|
||||
{
|
||||
m_Slots[firstIndex] = slot;
|
||||
|
||||
// remove additional matches to get rid of unused duplicates
|
||||
m_Slots.RemoveAllFromRange(s => s.value.id == slot.id, firstIndex + 1, m_Slots.Count - (firstIndex + 1));
|
||||
}
|
||||
else
|
||||
m_Slots.Add(slot);
|
||||
|
||||
slot.owner = this;
|
||||
|
||||
OnSlotsChanged();
|
||||
|
||||
if (foundSlot == null)
|
||||
return slot;
|
||||
|
||||
// foundSlot is of a different type; try to copy values
|
||||
// I think this is to support casting if implemented in CopyValuesFrom ?
|
||||
slot.CopyValuesFrom(foundSlot);
|
||||
foundSlot.owner = null;
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
public void RemoveSlot(int slotId)
|
||||
{
|
||||
// Remove edges that use this slot
|
||||
// no owner can happen after creation
|
||||
// but before added to graph
|
||||
if (owner != null)
|
||||
{
|
||||
var edges = owner.GetEdges(GetSlotReference(slotId));
|
||||
|
||||
foreach (var edge in edges.ToArray())
|
||||
owner.RemoveEdge(edge);
|
||||
}
|
||||
|
||||
//remove slots
|
||||
m_Slots.RemoveAll(x => x.value.id == slotId);
|
||||
|
||||
OnSlotsChanged();
|
||||
}
|
||||
|
||||
protected virtual void OnSlotsChanged()
|
||||
{
|
||||
Dirty(ModificationScope.Topological);
|
||||
owner?.ClearErrorsForNode(this);
|
||||
}
|
||||
|
||||
public void RemoveSlotsNameNotMatching(IEnumerable<int> slotIds, bool supressWarnings = false)
|
||||
{
|
||||
var invalidSlots = m_Slots.Select(x => x.value.id).Except(slotIds);
|
||||
|
||||
foreach (var invalidSlot in invalidSlots.ToArray())
|
||||
{
|
||||
if (!supressWarnings)
|
||||
Debug.LogWarningFormat("Removing Invalid MaterialSlot: {0}", invalidSlot);
|
||||
RemoveSlot(invalidSlot);
|
||||
}
|
||||
}
|
||||
|
||||
public bool SetSlotOrder(List<int> desiredOrderSlotIds)
|
||||
{
|
||||
bool changed = false;
|
||||
int writeIndex = 0;
|
||||
for (int orderIndex = 0; orderIndex < desiredOrderSlotIds.Count; orderIndex++)
|
||||
{
|
||||
var id = desiredOrderSlotIds[orderIndex];
|
||||
var matchIndex = m_Slots.FindIndex(s => s.value.id == id);
|
||||
if (matchIndex < 0)
|
||||
{
|
||||
// no matching slot with that id.. skip it
|
||||
}
|
||||
else
|
||||
{
|
||||
if (writeIndex != matchIndex)
|
||||
{
|
||||
// swap the matching slot into position
|
||||
var slot = m_Slots[matchIndex];
|
||||
m_Slots[matchIndex] = m_Slots[writeIndex];
|
||||
m_Slots[writeIndex] = slot;
|
||||
changed = true;
|
||||
}
|
||||
writeIndex++;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public SlotReference GetSlotReference(int slotId)
|
||||
{
|
||||
var slot = FindSlot<MaterialSlot>(slotId);
|
||||
if (slot == null)
|
||||
throw new ArgumentException("Slot could not be found", "slotId");
|
||||
return new SlotReference(this, slotId);
|
||||
}
|
||||
|
||||
public T FindSlot<T>(int slotId) where T : MaterialSlot
|
||||
{
|
||||
foreach (var slot in m_Slots.SelectValue())
|
||||
{
|
||||
if (slot.id == slotId && slot is T)
|
||||
return (T)slot;
|
||||
}
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public T FindInputSlot<T>(int slotId) where T : MaterialSlot
|
||||
{
|
||||
foreach (var slot in m_Slots.SelectValue())
|
||||
{
|
||||
if (slot.isInputSlot && slot.id == slotId && slot is T)
|
||||
return (T)slot;
|
||||
}
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public T FindOutputSlot<T>(int slotId) where T : MaterialSlot
|
||||
{
|
||||
foreach (var slot in m_Slots.SelectValue())
|
||||
{
|
||||
if (slot.isOutputSlot && slot.id == slotId && slot is T)
|
||||
return (T)slot;
|
||||
}
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<MaterialSlot> GetInputsWithNoConnection()
|
||||
{
|
||||
return this.GetInputSlots<MaterialSlot>().Where(x => !owner.GetEdges(GetSlotReference(x.id)).Any());
|
||||
}
|
||||
|
||||
public void SetupSlots()
|
||||
{
|
||||
foreach (var s in m_Slots.SelectValue())
|
||||
s.owner = this;
|
||||
}
|
||||
|
||||
public virtual void UpdateNodeAfterDeserialization()
|
||||
{ }
|
||||
|
||||
public bool IsSlotConnected(int slotId)
|
||||
{
|
||||
var slot = FindSlot<MaterialSlot>(slotId);
|
||||
return slot != null && owner.GetEdges(slot.slotReference).Any();
|
||||
}
|
||||
|
||||
public virtual void Setup() { }
|
||||
|
||||
protected void EnqueSlotsForSerialization()
|
||||
{
|
||||
foreach (var slot in m_Slots)
|
||||
{
|
||||
slot.OnBeforeSerialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a4da4d7c02dcbdd4f9ef2d3b1106879a
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8ee6f8ab31f6bf349a63fdd21fc88664
|
||||
folderAsset: yes
|
||||
timeCreated: 1495532491
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 75cc6d701e07fe246ba5377a454f74c4
|
||||
folderAsset: yes
|
||||
timeCreated: 1495532497
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,152 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Adjustment", "Channel Mixer")]
|
||||
class ChannelMixerNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction
|
||||
{
|
||||
public ChannelMixerNode()
|
||||
{
|
||||
name = "Channel Mixer";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
const int InputSlotId = 0;
|
||||
const int OutputSlotId = 1;
|
||||
const string kInputSlotName = "In";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public override bool hasPreview
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
string GetFunctionName()
|
||||
{
|
||||
return "Unity_ChannelMixer_$precision";
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector3MaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector3.zero));
|
||||
AddSlot(new Vector3MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector3.zero));
|
||||
RemoveSlotsNameNotMatching(new[] { InputSlotId, OutputSlotId });
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
ChannelMixer m_ChannelMixer = new ChannelMixer(new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 1));
|
||||
|
||||
[Serializable]
|
||||
public struct ChannelMixer
|
||||
{
|
||||
public Vector3 outRed;
|
||||
public Vector3 outGreen;
|
||||
public Vector3 outBlue;
|
||||
|
||||
public ChannelMixer(Vector3 red, Vector3 green, Vector3 blue)
|
||||
{
|
||||
outRed = red;
|
||||
outGreen = green;
|
||||
outBlue = blue;
|
||||
}
|
||||
}
|
||||
|
||||
[ChannelMixerControl("")]
|
||||
public ChannelMixer channelMixer
|
||||
{
|
||||
get { return m_ChannelMixer; }
|
||||
set
|
||||
{
|
||||
if ((value.outRed == m_ChannelMixer.outRed) && (value.outGreen == m_ChannelMixer.outGreen) && (value.outBlue == m_ChannelMixer.outBlue))
|
||||
return;
|
||||
m_ChannelMixer = value;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var inputValue = GetSlotValue(InputSlotId, generationMode);
|
||||
var outputValue = GetSlotValue(OutputSlotId, generationMode);
|
||||
|
||||
sb.AppendLine("{0} {1};", FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(OutputSlotId));
|
||||
if (!generationMode.IsPreview())
|
||||
{
|
||||
sb.AppendLine("$precision3 _{0}_Red = $precision3 ({1}, {2}, {3});", GetVariableNameForNode(), channelMixer.outRed[0], channelMixer.outRed[1], channelMixer.outRed[2]);
|
||||
sb.AppendLine("$precision3 _{0}_Green = $precision3 ({1}, {2}, {3});", GetVariableNameForNode(), channelMixer.outGreen[0], channelMixer.outGreen[1], channelMixer.outGreen[2]);
|
||||
sb.AppendLine("$precision3 _{0}_Blue = $precision3 ({1}, {2}, {3});", GetVariableNameForNode(), channelMixer.outBlue[0], channelMixer.outBlue[1], channelMixer.outBlue[2]);
|
||||
}
|
||||
sb.AppendLine("{0}({1}, _{2}_Red, _{2}_Green, _{2}_Blue, {3});", GetFunctionName(), inputValue, GetVariableNameForNode(), outputValue);
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
base.CollectPreviewMaterialProperties(properties);
|
||||
|
||||
properties.Add(new PreviewProperty(PropertyType.Vector3)
|
||||
{
|
||||
name = string.Format("_{0}_Red", GetVariableNameForNode()),
|
||||
vector4Value = channelMixer.outRed
|
||||
});
|
||||
|
||||
properties.Add(new PreviewProperty(PropertyType.Vector3)
|
||||
{
|
||||
name = string.Format("_{0}_Green", GetVariableNameForNode()),
|
||||
vector4Value = channelMixer.outGreen
|
||||
});
|
||||
|
||||
properties.Add(new PreviewProperty(PropertyType.Vector3)
|
||||
{
|
||||
name = string.Format("_{0}_Blue", GetVariableNameForNode()),
|
||||
vector4Value = channelMixer.outBlue
|
||||
});
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
if (!generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
base.CollectShaderProperties(properties, generationMode);
|
||||
|
||||
properties.AddShaderProperty(new Vector4ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = string.Format("_{0}_Red", GetVariableNameForNode()),
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
|
||||
properties.AddShaderProperty(new Vector4ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = string.Format("_{0}_Green", GetVariableNameForNode()),
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
|
||||
properties.AddShaderProperty(new Vector4ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = string.Format("_{0}_Blue", GetVariableNameForNode()),
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
registry.ProvideFunction(GetFunctionName(), s =>
|
||||
{
|
||||
s.AppendLine("void {0} ({1} In, $precision3 Red, $precision3 Green, $precision3 Blue, out {2} Out)",
|
||||
GetFunctionName(),
|
||||
FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(),
|
||||
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString());
|
||||
using (s.BlockScope())
|
||||
{
|
||||
s.AppendLine("Out = {0}(dot(In, Red), dot(In, Green), dot(In, Blue));",
|
||||
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d8d3a2d8c96e5994696f30f658efebea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,33 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Adjustment", "Contrast")]
|
||||
class ContrastNode : CodeFunctionNode
|
||||
{
|
||||
public ContrastNode()
|
||||
{
|
||||
name = "Contrast";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_Contrast", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_Contrast(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None, 1, 1, 1, 1)] Vector1 Contrast,
|
||||
[Slot(2, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector2.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision midpoint = pow(0.5, 2.2);
|
||||
Out = (In - midpoint) * Contrast + midpoint;
|
||||
}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 94965bffe51535041a4f0a618263bf7d
|
||||
timeCreated: 1444218016
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,114 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum HueMode
|
||||
{
|
||||
Degrees,
|
||||
Normalized
|
||||
};
|
||||
|
||||
[Title("Artistic", "Adjustment", "Hue")]
|
||||
class HueNode : CodeFunctionNode
|
||||
{
|
||||
public HueNode()
|
||||
{
|
||||
name = "Hue";
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private HueMode m_HueMode = HueMode.Degrees;
|
||||
|
||||
[EnumControl("Range")]
|
||||
public HueMode hueMode
|
||||
{
|
||||
get { return m_HueMode; }
|
||||
set
|
||||
{
|
||||
if (m_HueMode == value)
|
||||
return;
|
||||
|
||||
m_HueMode = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
switch (m_HueMode)
|
||||
{
|
||||
case HueMode.Normalized:
|
||||
return GetType().GetMethod("Unity_Hue_Normalized", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
default:
|
||||
return GetType().GetMethod("Unity_Hue_Degrees", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
}
|
||||
|
||||
static string Unity_Hue_Degrees(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] Vector1 Offset,
|
||||
[Slot(2, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
// RGB to HSV
|
||||
$precision4 K = $precision4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
$precision4 P = lerp($precision4(In.bg, K.wz), $precision4(In.gb, K.xy), step(In.b, In.g));
|
||||
$precision4 Q = lerp($precision4(P.xyw, In.r), $precision4(In.r, P.yzx), step(P.x, In.r));
|
||||
$precision D = Q.x - min(Q.w, Q.y);
|
||||
$precision E = 1e-10;
|
||||
$precision V = (D == 0) ? Q.x : (Q.x + E);
|
||||
$precision3 hsv = $precision3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), V);
|
||||
|
||||
$precision hue = hsv.x + Offset / 360;
|
||||
hsv.x = (hue < 0)
|
||||
? hue + 1
|
||||
: (hue > 1)
|
||||
? hue - 1
|
||||
: hue;
|
||||
|
||||
// HSV to RGB
|
||||
$precision4 K2 = $precision4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
$precision3 P2 = abs(frac(hsv.xxx + K2.xyz) * 6.0 - K2.www);
|
||||
Out = hsv.z * lerp(K2.xxx, saturate(P2 - K2.xxx), hsv.y);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Hue_Normalized(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None, 0.5f, 0.5f, 0.5f, 0.5f)] Vector1 Offset,
|
||||
[Slot(2, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
// RGB to HSV
|
||||
$precision4 K = $precision4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
$precision4 P = lerp($precision4(In.bg, K.wz), $precision4(In.gb, K.xy), step(In.b, In.g));
|
||||
$precision4 Q = lerp($precision4(P.xyw, In.r), $precision4(In.r, P.yzx), step(P.x, In.r));
|
||||
$precision D = Q.x - min(Q.w, Q.y);
|
||||
$precision E = 1e-10;
|
||||
$precision V = (D == 0) ? Q.x : (Q.x + E);
|
||||
$precision3 hsv = $precision3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), V);
|
||||
|
||||
$precision hue = hsv.x + Offset;
|
||||
hsv.x = (hue < 0)
|
||||
? hue + 1
|
||||
: (hue > 1)
|
||||
? hue - 1
|
||||
: hue;
|
||||
|
||||
// HSV to RGB
|
||||
$precision4 K2 = $precision4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
$precision3 P2 = abs(frac(hsv.xxx + K2.xyz) * 6.0 - K2.www);
|
||||
Out = hsv.z * lerp(K2.xxx, saturate(P2 - K2.xxx), hsv.y);
|
||||
}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 083caf0fe7ff62f438e121e934355461
|
||||
timeCreated: 1490973460
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,174 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Adjustment", "Invert Colors")]
|
||||
class InvertColorsNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction
|
||||
{
|
||||
public InvertColorsNode()
|
||||
{
|
||||
name = "Invert Colors";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
const int InputSlotId = 0;
|
||||
const int OutputSlotId = 1;
|
||||
const string kInputSlotName = "In";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public override bool hasPreview
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
string GetFunctionName()
|
||||
{
|
||||
return $"Unity_InvertColors_{FindSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString()}";
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new DynamicVectorMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector4.zero));
|
||||
AddSlot(new DynamicVectorMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
|
||||
RemoveSlotsNameNotMatching(new[] { InputSlotId, OutputSlotId });
|
||||
}
|
||||
|
||||
int channelCount { get { return SlotValueHelper.GetChannelCount(FindSlot<MaterialSlot>(InputSlotId).concreteValueType); } }
|
||||
|
||||
[SerializeField]
|
||||
private bool m_RedChannel;
|
||||
|
||||
[ToggleControl("Red")]
|
||||
public ToggleData redChannel
|
||||
{
|
||||
get { return new ToggleData(m_RedChannel, channelCount > 0); }
|
||||
set
|
||||
{
|
||||
if (m_RedChannel == value.isOn)
|
||||
return;
|
||||
m_RedChannel = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_GreenChannel;
|
||||
|
||||
[ToggleControl("Green")]
|
||||
public ToggleData greenChannel
|
||||
{
|
||||
get { return new ToggleData(m_GreenChannel, channelCount > 1); }
|
||||
set
|
||||
{
|
||||
if (m_GreenChannel == value.isOn)
|
||||
return;
|
||||
m_GreenChannel = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_BlueChannel;
|
||||
|
||||
[ToggleControl("Blue")]
|
||||
public ToggleData blueChannel
|
||||
{
|
||||
get { return new ToggleData(m_BlueChannel, channelCount > 2); }
|
||||
set
|
||||
{
|
||||
if (m_BlueChannel == value.isOn)
|
||||
return;
|
||||
m_BlueChannel = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_AlphaChannel;
|
||||
|
||||
[ToggleControl("Alpha")]
|
||||
public ToggleData alphaChannel
|
||||
{
|
||||
get { return new ToggleData(m_AlphaChannel, channelCount > 3); }
|
||||
set
|
||||
{
|
||||
if (m_AlphaChannel == value.isOn)
|
||||
return;
|
||||
m_AlphaChannel = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var inputValue = GetSlotValue(InputSlotId, generationMode);
|
||||
var outputValue = GetSlotValue(OutputSlotId, generationMode);
|
||||
sb.AppendLine("{0} {1};", FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(OutputSlotId));
|
||||
|
||||
if (!generationMode.IsPreview())
|
||||
{
|
||||
sb.TryAppendIndentation();
|
||||
sb.Append("{0} _{1}_InvertColors = {0} ({2}",
|
||||
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString(),
|
||||
GetVariableNameForNode(),
|
||||
Convert.ToInt32(m_RedChannel));
|
||||
if (channelCount > 1)
|
||||
sb.Append(", {0}", Convert.ToInt32(m_GreenChannel));
|
||||
if (channelCount > 2)
|
||||
sb.Append(", {0}", Convert.ToInt32(m_BlueChannel));
|
||||
if (channelCount > 3)
|
||||
sb.Append(", {0}", Convert.ToInt32(m_AlphaChannel));
|
||||
sb.Append(");");
|
||||
sb.AppendNewLine();
|
||||
}
|
||||
|
||||
sb.AppendLine("{0}({1}, _{2}_InvertColors, {3});", GetFunctionName(), inputValue, GetVariableNameForNode(), outputValue);
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
base.CollectPreviewMaterialProperties(properties);
|
||||
|
||||
properties.Add(new PreviewProperty(PropertyType.Vector4)
|
||||
{
|
||||
name = string.Format("_{0}_InvertColors", GetVariableNameForNode()),
|
||||
vector4Value = new Vector4(Convert.ToInt32(m_RedChannel), Convert.ToInt32(m_GreenChannel), Convert.ToInt32(m_BlueChannel), Convert.ToInt32(m_AlphaChannel)),
|
||||
});
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
if (!generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
base.CollectShaderProperties(properties, generationMode);
|
||||
|
||||
properties.AddShaderProperty(new Vector4ShaderProperty
|
||||
{
|
||||
overrideReferenceName = string.Format("_{0}_InvertColors", GetVariableNameForNode()),
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
registry.ProvideFunction(GetFunctionName(), s =>
|
||||
{
|
||||
s.AppendLine("void {0}({1} In, {2} InvertColors, out {3} Out)",
|
||||
GetFunctionName(),
|
||||
FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(),
|
||||
FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(),
|
||||
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString());
|
||||
|
||||
using (s.BlockScope())
|
||||
{
|
||||
s.AppendLine("Out = abs(InvertColors - In);");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3e16bd8daac9e4e42861472225b22405
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Adjustment", "Replace Color")]
|
||||
class ReplaceColorNode : CodeFunctionNode
|
||||
{
|
||||
public ReplaceColorNode()
|
||||
{
|
||||
name = "Replace Color";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_ReplaceColor", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_ReplaceColor(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] ColorRGB From,
|
||||
[Slot(2, Binding.None)] ColorRGB To,
|
||||
[Slot(3, Binding.None)] Vector1 Range,
|
||||
[Slot(5, Binding.None)] Vector1 Fuzziness,
|
||||
[Slot(4, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision Distance = distance(From, In);
|
||||
Out = lerp(To, In, saturate((Distance - Range) / max(Fuzziness, 1e-5f)));
|
||||
}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a60be5fb80fbbdb449fcc95fa2256cc5
|
||||
timeCreated: 1444218016
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,33 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Adjustment", "Saturation")]
|
||||
class SaturationNode : CodeFunctionNode
|
||||
{
|
||||
public SaturationNode()
|
||||
{
|
||||
name = "Saturation";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_Saturation", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_Saturation(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None, 1, 1, 1, 1)] Vector1 Saturation,
|
||||
[Slot(2, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return @"
|
||||
{
|
||||
$precision luma = dot(In, $precision3(0.2126729, 0.7151522, 0.0721750));
|
||||
Out = luma.xxx + Saturation.xxx * (In - luma.xxx);
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8f3854e9ab30c854b93e88a2e560463e
|
||||
timeCreated: 1444218016
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,71 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Adjustment", "White Balance")]
|
||||
class WhiteBalanceNode : CodeFunctionNode
|
||||
{
|
||||
public WhiteBalanceNode()
|
||||
{
|
||||
name = "White Balance";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_WhiteBalance", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_WhiteBalance(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] Vector1 Temperature,
|
||||
[Slot(2, Binding.None)] Vector1 Tint,
|
||||
[Slot(3, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return @"
|
||||
{
|
||||
// Range ~[-1.67;1.67] works best
|
||||
$precision t1 = Temperature * 10 / 6;
|
||||
$precision t2 = Tint * 10 / 6;
|
||||
|
||||
// Get the CIE xy chromaticity of the reference white point.
|
||||
// Note: 0.31271 = x value on the D65 white point
|
||||
$precision x = 0.31271 - t1 * (t1 < 0 ? 0.1 : 0.05);
|
||||
$precision standardIlluminantY = 2.87 * x - 3 * x * x - 0.27509507;
|
||||
$precision y = standardIlluminantY + t2 * 0.05;
|
||||
|
||||
// Calculate the coefficients in the LMS space.
|
||||
$precision3 w1 = $precision3(0.949237, 1.03542, 1.08728); // D65 white point
|
||||
|
||||
// CIExyToLMS
|
||||
$precision Y = 1;
|
||||
$precision X = Y * x / y;
|
||||
$precision Z = Y * (1 - x - y) / y;
|
||||
$precision L = 0.7328 * X + 0.4296 * Y - 0.1624 * Z;
|
||||
$precision M = -0.7036 * X + 1.6975 * Y + 0.0061 * Z;
|
||||
$precision S = 0.0030 * X + 0.0136 * Y + 0.9834 * Z;
|
||||
$precision3 w2 = $precision3(L, M, S);
|
||||
|
||||
$precision3 balance = $precision3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z);
|
||||
|
||||
$precision3x3 LIN_2_LMS_MAT = {
|
||||
3.90405e-1, 5.49941e-1, 8.92632e-3,
|
||||
7.08416e-2, 9.63172e-1, 1.35775e-3,
|
||||
2.31082e-2, 1.28021e-1, 9.36245e-1
|
||||
};
|
||||
|
||||
$precision3x3 LMS_2_LIN_MAT = {
|
||||
2.85847e+0, -1.62879e+0, -2.48910e-2,
|
||||
-2.10182e-1, 1.15820e+0, 3.24281e-4,
|
||||
-4.18120e-2, -1.18169e-1, 1.06867e+0
|
||||
};
|
||||
|
||||
$precision3 lms = mul(LIN_2_LMS_MAT, In);
|
||||
lms *= balance;
|
||||
Out = mul(LMS_2_LIN_MAT, lms);
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c09bf9b59c16e0d48b9a346376d28640
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f85e7557d4bb9874882ec3fa3044a53e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,28 @@
|
|||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum BlendMode
|
||||
{
|
||||
Burn,
|
||||
Darken,
|
||||
Difference,
|
||||
Dodge,
|
||||
Divide,
|
||||
Exclusion,
|
||||
HardLight,
|
||||
HardMix,
|
||||
Lighten,
|
||||
LinearBurn,
|
||||
LinearDodge,
|
||||
LinearLight,
|
||||
LinearLightAddSub,
|
||||
Multiply,
|
||||
Negation,
|
||||
Overlay,
|
||||
PinLight,
|
||||
Screen,
|
||||
SoftLight,
|
||||
Subtract,
|
||||
VividLight,
|
||||
Overwrite
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e377212826a27da4f9cbf888b0c39bc9
|
||||
timeCreated: 1495455807
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,372 @@
|
|||
using System.Reflection;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Blend", "Blend")]
|
||||
class BlendNode : CodeFunctionNode
|
||||
{
|
||||
public BlendNode()
|
||||
{
|
||||
name = "Blend";
|
||||
synonyms = new string[] { "burn", "darken", "difference", "dodge", "divide", "exclusion", "hard light", "hard mix", "linear burn", "linear dodge", "linear light", "multiply", "negate", "overlay", "pin light", "screen", "soft light", "subtract", "vivid light", "overwrite" };
|
||||
}
|
||||
|
||||
string GetCurrentBlendName()
|
||||
{
|
||||
return System.Enum.GetName(typeof(BlendMode), m_BlendMode);
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
BlendMode m_BlendMode = BlendMode.Overlay;
|
||||
|
||||
[EnumControl("Mode")]
|
||||
public BlendMode blendMode
|
||||
{
|
||||
get { return m_BlendMode; }
|
||||
set
|
||||
{
|
||||
if (m_BlendMode == value)
|
||||
return;
|
||||
|
||||
m_BlendMode = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod(string.Format("Unity_Blend_{0}", GetCurrentBlendName()),
|
||||
BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_Blend_Burn(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = 1.0 - (1.0 - Blend)/(Base + 0.000000000001);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Darken(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = min(Blend, Base);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Difference(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = abs(Blend - Base);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Dodge(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = Base / (1.0 - clamp(Blend, 0.000001, 0.999999));
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Divide(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = Base / (Blend + 0.000000000001);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Exclusion(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = Blend + Base - (2.0 * Blend * Base);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_HardLight(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision{slot2dimension} result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend);
|
||||
$precision{slot2dimension} result2 = 2.0 * Base * Blend;
|
||||
$precision{slot2dimension} zeroOrOne = step(Blend, 0.5);
|
||||
Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_HardMix(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = step(1 - Base, Blend);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Lighten(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = max(Blend, Base);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_LinearBurn(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = Base + Blend - 1.0;
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_LinearDodge(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = Base + Blend;
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_LinearLight(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = Blend < 0.5 ? max(Base + (2 * Blend) - 1, 0) : min(Base + 2 * (Blend - 0.5), 1);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_LinearLightAddSub(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = Blend + 2.0 * Base - 1.0;
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Multiply(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = Base * Blend;
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Negation(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = 1.0 - abs(1.0 - Blend - Base);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Screen(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = 1.0 - (1.0 - Blend) * (1.0 - Base);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Overlay(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision{slot2dimension} result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend);
|
||||
$precision{slot2dimension} result2 = 2.0 * Base * Blend;
|
||||
$precision{slot2dimension} zeroOrOne = step(Base, 0.5);
|
||||
Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_Blend_PinLight(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision{slot2dimension} check = step (0.5, Blend);
|
||||
$precision{slot2dimension} result1 = check * max(2.0 * (Base - 0.5), Blend);
|
||||
Out = result1 + (1.0 - check) * min(2.0 * Base, Blend);
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_Blend_SoftLight(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision{slot2dimension} result1 = 2.0 * Base * Blend + Base * Base * (1.0 - 2.0 * Blend);
|
||||
$precision{slot2dimension} result2 = sqrt(Base) * (2.0 * Blend - 1.0) + 2.0 * Base * (1.0 - Blend);
|
||||
$precision{slot2dimension} zeroOrOne = step(0.5, Blend);
|
||||
Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_Blend_VividLight(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Base = clamp(Base, 0.000001, 0.999999);
|
||||
$precision{slot2dimension} result1 = 1.0 - (1.0 - Blend) / (2.0 * Base);
|
||||
$precision{slot2dimension} result2 = Blend / (2.0 * (1.0 - Base));
|
||||
$precision{slot2dimension} zeroOrOne = step(0.5, Base);
|
||||
Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Subtract(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = Base - Blend;
|
||||
Out = lerp(Base, Out, Opacity);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_Blend_Overwrite(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector Base,
|
||||
[Slot(1, Binding.None)] DynamicDimensionVector Blend,
|
||||
[Slot(3, Binding.None, 1, 1, 1, 1)] Vector1 Opacity,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = lerp(Base, Blend, Opacity);
|
||||
}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1aa4fa75c826d8d409b5033a6ef686eb
|
||||
timeCreated: 1495456651
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e005d19f5315e44bc9f50b3f6f8e50b2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,42 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Filter", "Dither")]
|
||||
class DitherNode : CodeFunctionNode
|
||||
{
|
||||
public DitherNode()
|
||||
{
|
||||
name = "Dither";
|
||||
synonyms = new string[] { "blue noise", "half tone" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_Dither", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_Dither(
|
||||
[Slot(0, Binding.None)] DynamicDimensionVector In,
|
||||
[Slot(1, Binding.ScreenPosition)] Vector2 ScreenPosition,
|
||||
[Slot(2, Binding.None)] out DynamicDimensionVector Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision2 uv = ScreenPosition.xy * _ScreenParams.xy;
|
||||
$precision DITHER_THRESHOLDS[16] =
|
||||
{
|
||||
1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
|
||||
13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
|
||||
4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
|
||||
16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
|
||||
};
|
||||
uint index = (uint(uv.x) % 4) * 4 + uint(uv.y) % 4;
|
||||
Out = In - DITHER_THRESHOLDS[index];
|
||||
}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 40b83fe632985494f96d2211c1963835
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cdb8c403de0823942a95a464c32ad0f0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,153 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum TextureChannel
|
||||
{
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
Alpha
|
||||
}
|
||||
|
||||
[Title("Artistic", "Mask", "Channel Mask")]
|
||||
class ChannelMaskNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction
|
||||
{
|
||||
public ChannelMaskNode()
|
||||
{
|
||||
name = "Channel Mask";
|
||||
synonyms = new string[] { "component mask" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
const int InputSlotId = 0;
|
||||
const int OutputSlotId = 1;
|
||||
const string kInputSlotName = "In";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public override bool hasPreview
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
string GetFunctionName()
|
||||
{
|
||||
string channelSum = "None";
|
||||
if (channelMask != 0)
|
||||
{
|
||||
bool red = (channelMask & 1) != 0;
|
||||
bool green = (channelMask & 2) != 0;
|
||||
bool blue = (channelMask & 4) != 0;
|
||||
bool alpha = (channelMask & 8) != 0;
|
||||
channelSum = string.Format("{0}{1}{2}{3}", red ? "Red" : "", green ? "Green" : "", blue ? "Blue" : "", alpha ? "Alpha" : "");
|
||||
}
|
||||
// NOTE: it's important we use the $precision generic form of the slot type in the name here
|
||||
return $"Unity_ChannelMask_{channelSum}_{FindInputSlot<DynamicVectorMaterialSlot>(InputSlotId).concreteValueType.ToShaderString()}";
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new DynamicVectorMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector3.zero));
|
||||
AddSlot(new DynamicVectorMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector3.zero));
|
||||
RemoveSlotsNameNotMatching(new[] { InputSlotId, OutputSlotId });
|
||||
}
|
||||
|
||||
public TextureChannel channel;
|
||||
|
||||
[SerializeField]
|
||||
private int m_ChannelMask = -1;
|
||||
|
||||
[ChannelEnumMaskControl("Channels")]
|
||||
public int channelMask
|
||||
{
|
||||
get { return m_ChannelMask; }
|
||||
set
|
||||
{
|
||||
if (m_ChannelMask == value)
|
||||
return;
|
||||
|
||||
m_ChannelMask = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateChannelCount()
|
||||
{
|
||||
int channelCount = SlotValueHelper.GetChannelCount(FindSlot<MaterialSlot>(InputSlotId).concreteValueType);
|
||||
if (channelMask >= 1 << channelCount)
|
||||
channelMask = -1;
|
||||
}
|
||||
|
||||
string GetFunctionPrototype(string argIn, string argOut)
|
||||
{
|
||||
return string.Format("void {0} ({1} {2}, out {3} {4})"
|
||||
, GetFunctionName()
|
||||
, FindInputSlot<DynamicVectorMaterialSlot>(InputSlotId).concreteValueType.ToShaderString()
|
||||
, argIn
|
||||
, FindOutputSlot<DynamicVectorMaterialSlot>(OutputSlotId).concreteValueType.ToShaderString()
|
||||
, argOut);
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
ValidateChannelCount();
|
||||
string inputValue = GetSlotValue(InputSlotId, generationMode);
|
||||
string outputValue = GetSlotValue(OutputSlotId, generationMode);
|
||||
sb.AppendLine(string.Format("{0} {1};", FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(OutputSlotId)));
|
||||
sb.AppendLine(GetFunctionCallBody(inputValue, outputValue));
|
||||
}
|
||||
|
||||
string GetFunctionCallBody(string inputValue, string outputValue)
|
||||
{
|
||||
return GetFunctionName() + " (" + inputValue + ", " + outputValue + ");";
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
ValidateChannelCount();
|
||||
registry.ProvideFunction(GetFunctionName(), s =>
|
||||
{
|
||||
int channelCount = SlotValueHelper.GetChannelCount(FindSlot<MaterialSlot>(InputSlotId).concreteValueType);
|
||||
s.AppendLine(GetFunctionPrototype("In", "Out"));
|
||||
using (s.BlockScope())
|
||||
{
|
||||
if (channelMask == 0)
|
||||
s.AppendLine("Out = 0;");
|
||||
else if (channelMask == -1)
|
||||
s.AppendLine("Out = In;");
|
||||
else
|
||||
{
|
||||
bool red = (channelMask & 1) != 0;
|
||||
bool green = (channelMask & 2) != 0;
|
||||
bool blue = (channelMask & 4) != 0;
|
||||
bool alpha = (channelMask & 8) != 0;
|
||||
|
||||
switch (channelCount)
|
||||
{
|
||||
case 1:
|
||||
s.AppendLine("Out = In.r;");
|
||||
break;
|
||||
case 2:
|
||||
s.AppendLine(string.Format("Out = $precision2({0}, {1});",
|
||||
red ? "In.r" : "0", green ? "In.g" : "0"));
|
||||
break;
|
||||
case 3:
|
||||
s.AppendLine(string.Format("Out = $precision3({0}, {1}, {2});",
|
||||
red ? "In.r" : "0", green ? "In.g" : "0", blue ? "In.b" : "0"));
|
||||
break;
|
||||
case 4:
|
||||
s.AppendLine(string.Format("Out = $precision4({0}, {1}, {2}, {3});",
|
||||
red ? "In.r" : "0", green ? "In.g" : "0", blue ? "In.b" : "0", alpha ? "In.a" : "0"));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e3fd76d77a796b641ba3e9149086efc2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,34 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Mask", "Color Mask")]
|
||||
class ColorMaskNode : CodeFunctionNode
|
||||
{
|
||||
public ColorMaskNode()
|
||||
{
|
||||
name = "Color Mask";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_ColorMask", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_ColorMask(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] ColorRGB MaskColor,
|
||||
[Slot(2, Binding.None)] Vector1 Range,
|
||||
[Slot(4, Binding.None)] Vector1 Fuzziness,
|
||||
[Slot(3, Binding.None)] out Vector1 Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision Distance = distance(MaskColor, In);
|
||||
Out = saturate(1 - (Distance - Range) / max(Fuzziness, 1e-5));
|
||||
}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 19255c24842f72c4c94c21b682a3e170
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b7f9e0995756c4a4896912f8873eb63c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,81 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum NormalBlendMode
|
||||
{
|
||||
Default,
|
||||
Reoriented
|
||||
}
|
||||
|
||||
[FormerName("UnityEditor.ShaderGraph.BlendNormalRNM")]
|
||||
[Title("Artistic", "Normal", "Normal Blend")]
|
||||
class NormalBlendNode : CodeFunctionNode
|
||||
{
|
||||
public NormalBlendNode()
|
||||
{
|
||||
name = "Normal Blend";
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private NormalBlendMode m_BlendMode = NormalBlendMode.Default;
|
||||
|
||||
[EnumControl("Mode")]
|
||||
public NormalBlendMode blendMode
|
||||
{
|
||||
get { return m_BlendMode; }
|
||||
set
|
||||
{
|
||||
if (m_BlendMode == value)
|
||||
return;
|
||||
|
||||
m_BlendMode = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
switch (m_BlendMode)
|
||||
{
|
||||
case NormalBlendMode.Reoriented:
|
||||
return GetType().GetMethod("Unity_NormalBlend_Reoriented", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
default:
|
||||
return GetType().GetMethod("Unity_NormalBlend", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
}
|
||||
|
||||
static string Unity_NormalBlend(
|
||||
[Slot(0, Binding.None, 0, 0, 1, 0)] Vector3 A,
|
||||
[Slot(1, Binding.None, 0, 0, 1, 0)] Vector3 B,
|
||||
[Slot(2, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.one;
|
||||
|
||||
return @"
|
||||
{
|
||||
Out = SafeNormalize($precision3(A.rg + B.rg, A.b * B.b));
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_NormalBlend_Reoriented(
|
||||
[Slot(0, Binding.None, 0, 0, 1, 0)] Vector3 A,
|
||||
[Slot(1, Binding.None, 0, 0, 1, 0)] Vector3 B,
|
||||
[Slot(2, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.one;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision3 t = A.xyz + $precision3(0.0, 0.0, 1.0);
|
||||
$precision3 u = B.xyz * $precision3(-1.0, -1.0, 1.0);
|
||||
Out = (t / t.z) * dot(t, u) - u;
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e8d13e9dbb613e04f835b281d7ee9ef1
|
||||
timeCreated: 1490780593
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,131 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum OutputSpace
|
||||
{
|
||||
Tangent,
|
||||
World
|
||||
};
|
||||
|
||||
[Title("Artistic", "Normal", "Normal From Height")]
|
||||
class NormalFromHeightNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction, IMayRequireTangent, IMayRequireBitangent, IMayRequireNormal, IMayRequirePosition
|
||||
{
|
||||
public NormalFromHeightNode()
|
||||
{
|
||||
name = "Normal From Height";
|
||||
synonyms = new string[] { "convert to normal", "bump map" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private OutputSpace m_OutputSpace = OutputSpace.Tangent;
|
||||
|
||||
[EnumControl("Output Space")]
|
||||
public OutputSpace outputSpace
|
||||
{
|
||||
get { return m_OutputSpace; }
|
||||
set
|
||||
{
|
||||
if (m_OutputSpace == value)
|
||||
return;
|
||||
|
||||
m_OutputSpace = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
const int InputSlotId = 0;
|
||||
const int StrengthSlotId = 2;
|
||||
const int OutputSlotId = 1;
|
||||
const string kInputSlotName = "In";
|
||||
const string kStrengthSlotName = "Strength";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public override bool hasPreview
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
string GetFunctionName()
|
||||
{
|
||||
return $"Unity_NormalFromHeight_{outputSpace.ToString()}_$precision";
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, 0));
|
||||
AddSlot(new Vector1MaterialSlot(StrengthSlotId, kStrengthSlotName, kStrengthSlotName, SlotType.Input, 0.01f));
|
||||
AddSlot(new Vector3MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
|
||||
RemoveSlotsNameNotMatching(new[] { InputSlotId, StrengthSlotId, OutputSlotId });
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var inputValue = GetSlotValue(InputSlotId, generationMode);
|
||||
var strengthValue = GetSlotValue(StrengthSlotId, generationMode);
|
||||
var outputValue = GetSlotValue(OutputSlotId, generationMode);
|
||||
sb.AppendLine("{0} {1};", FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(OutputSlotId));
|
||||
sb.AppendLine("$precision3x3 _{0}_TangentMatrix = $precision3x3(IN.{1}SpaceTangent, IN.{1}SpaceBiTangent, IN.{1}SpaceNormal);", GetVariableNameForNode(), NeededCoordinateSpace.World.ToString());
|
||||
sb.AppendLine("$precision3 _{0}_Position = IN.{1}SpacePosition;", GetVariableNameForNode(), NeededCoordinateSpace.World.ToString());
|
||||
sb.AppendLine("{0}({1},{2},_{3}_Position,_{3}_TangentMatrix, {4});", GetFunctionName(), inputValue, strengthValue, GetVariableNameForNode(), outputValue);
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
registry.ProvideFunction(GetFunctionName(), s =>
|
||||
{
|
||||
s.AppendLine("void {0}({1} In, {2} Strength, $precision3 Position, $precision3x3 TangentMatrix, out {3} Out)",
|
||||
GetFunctionName(),
|
||||
FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(),
|
||||
FindInputSlot<MaterialSlot>(StrengthSlotId).concreteValueType.ToShaderString(),
|
||||
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString());
|
||||
using (s.BlockScope())
|
||||
{
|
||||
s.AppendLine(GetRayTracingError());
|
||||
s.AppendLine("$precision3 worldDerivativeX = ddx(Position);");
|
||||
s.AppendLine("$precision3 worldDerivativeY = ddy(Position);");
|
||||
s.AppendNewLine();
|
||||
s.AppendLine("$precision3 crossX = cross(TangentMatrix[2].xyz, worldDerivativeX);");
|
||||
s.AppendLine("$precision3 crossY = cross(worldDerivativeY, TangentMatrix[2].xyz);");
|
||||
s.AppendLine("$precision d = dot(worldDerivativeX, crossY);");
|
||||
s.AppendLine("$precision sgn = d < 0.0 ? (-1.0f) : 1.0f;");
|
||||
s.AppendLine("$precision surface = sgn / max(0.000000000000001192093f, abs(d));");
|
||||
s.AppendNewLine();
|
||||
s.AppendLine("$precision dHdx = ddx(In);");
|
||||
s.AppendLine("$precision dHdy = ddy(In);");
|
||||
s.AppendLine("$precision3 surfGrad = surface * (dHdx*crossY + dHdy*crossX);");
|
||||
s.AppendLine("Out = SafeNormalize(TangentMatrix[2].xyz - (Strength * surfGrad));");
|
||||
|
||||
if (outputSpace == OutputSpace.Tangent)
|
||||
s.AppendLine("Out = TransformWorldToTangent(Out, TangentMatrix);");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
|
||||
{
|
||||
return NeededCoordinateSpace.World;
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
|
||||
{
|
||||
return NeededCoordinateSpace.World;
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
|
||||
{
|
||||
return NeededCoordinateSpace.World;
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
|
||||
{
|
||||
return NeededCoordinateSpace.World;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3bf617c1fe220684696e5bf3850bc423
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,108 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[FormerName("UnityEditor.ShaderGraph.NormalCreateNode")]
|
||||
[Title("Artistic", "Normal", "Normal From Texture")]
|
||||
class NormalFromTextureNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction, IMayRequireMeshUV
|
||||
{
|
||||
public const int TextureInputId = 0;
|
||||
public const int UVInputId = 1;
|
||||
public const int SamplerInputId = 2;
|
||||
public const int OffsetInputId = 3;
|
||||
public const int StrengthInputId = 4;
|
||||
public const int OutputSlotId = 5;
|
||||
|
||||
const string k_TextureInputName = "Texture";
|
||||
const string k_UVInputName = "UV";
|
||||
const string k_SamplerInputName = "Sampler";
|
||||
const string k_OffsetInputName = "Offset";
|
||||
const string k_StrengthInputName = "Strength";
|
||||
const string k_OutputSlotName = "Out";
|
||||
|
||||
public NormalFromTextureNode()
|
||||
{
|
||||
name = "Normal From Texture";
|
||||
synonyms = new string[] { "convert to normal", "bump map" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
string GetFunctionName()
|
||||
{
|
||||
return "Unity_NormalFromTexture_$precision";
|
||||
}
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, k_TextureInputName, k_TextureInputName));
|
||||
AddSlot(new UVMaterialSlot(UVInputId, k_UVInputName, k_UVInputName, UVChannel.UV0));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInputId, k_SamplerInputName, k_SamplerInputName, SlotType.Input));
|
||||
AddSlot(new Vector1MaterialSlot(OffsetInputId, k_OffsetInputName, k_OffsetInputName, SlotType.Input, 0.5f));
|
||||
AddSlot(new Vector1MaterialSlot(StrengthInputId, k_StrengthInputName, k_StrengthInputName, SlotType.Input, 8f));
|
||||
AddSlot(new Vector3MaterialSlot(OutputSlotId, k_OutputSlotName, k_OutputSlotName, SlotType.Output, Vector3.zero, ShaderStageCapability.Fragment));
|
||||
RemoveSlotsNameNotMatching(new[] { TextureInputId, UVInputId, SamplerInputId, OffsetInputId, StrengthInputId, OutputSlotId });
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var textureValue = GetSlotValue(TextureInputId, generationMode);
|
||||
var uvValue = GetSlotValue(UVInputId, generationMode);
|
||||
var offsetValue = GetSlotValue(OffsetInputId, generationMode);
|
||||
var strengthValue = GetSlotValue(StrengthInputId, generationMode);
|
||||
var outputValue = GetSlotValue(OutputSlotId, generationMode);
|
||||
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInputId);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
string samplerValue;
|
||||
if (edgesSampler.Any())
|
||||
samplerValue = GetSlotValue(SamplerInputId, generationMode);
|
||||
else
|
||||
samplerValue = textureValue;
|
||||
|
||||
sb.AppendLine("{0} {1};", FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(OutputSlotId));
|
||||
sb.AppendLine("{0}(TEXTURE2D_ARGS({1}.tex, {2}.samplerstate), {1}.GetTransformedUV({3}), {4}, {5}, {6});", GetFunctionName(), textureValue, samplerValue, uvValue, offsetValue, strengthValue, outputValue);
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
registry.ProvideFunction(GetFunctionName(), s =>
|
||||
{
|
||||
s.AppendLine("void {0}(TEXTURE2D_PARAM(Texture, Sampler), {1} UV, {2} Offset, {3} Strength, out {4} Out)",
|
||||
GetFunctionName(),
|
||||
FindInputSlot<MaterialSlot>(UVInputId).concreteValueType.ToShaderString(),
|
||||
FindInputSlot<MaterialSlot>(OffsetInputId).concreteValueType.ToShaderString(),
|
||||
FindInputSlot<MaterialSlot>(StrengthInputId).concreteValueType.ToShaderString(),
|
||||
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString());
|
||||
using (s.BlockScope())
|
||||
{
|
||||
s.AppendLine("Offset = pow(Offset, 3) * 0.1;");
|
||||
s.AppendLine("$precision2 offsetU = $precision2(UV.x + Offset, UV.y);");
|
||||
s.AppendLine("$precision2 offsetV = $precision2(UV.x, UV.y + Offset);");
|
||||
|
||||
s.AppendLine("$precision normalSample = SAMPLE_TEXTURE2D(Texture, Sampler, UV);");
|
||||
s.AppendLine("$precision uSample = SAMPLE_TEXTURE2D(Texture, Sampler, offsetU);");
|
||||
s.AppendLine("$precision vSample = SAMPLE_TEXTURE2D(Texture, Sampler, offsetV);");
|
||||
|
||||
s.AppendLine("$precision3 va = $precision3(1, 0, (uSample - normalSample) * Strength);");
|
||||
s.AppendLine("$precision3 vb = $precision3(0, 1, (vSample - normalSample) * Strength);");
|
||||
s.AppendLine("Out = normalize(cross(va, vb));");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
foreach (var slot in this.GetInputSlots<MaterialSlot>().OfType<IMayRequireMeshUV>())
|
||||
{
|
||||
if (slot.RequiresMeshUV(channel))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c943843c9c7424a4d9b629c087d93df5
|
||||
timeCreated: 1495565761
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,34 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Normal", "Normal Reconstruct Z")]
|
||||
class NormalReconstructZNode : CodeFunctionNode
|
||||
{
|
||||
public NormalReconstructZNode()
|
||||
{
|
||||
name = "Normal Reconstruct Z";
|
||||
synonyms = new string[] { "derive z" };
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("NormalReconstructZ", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string NormalReconstructZ(
|
||||
[Slot(0, Binding.None)] Vector2 In,
|
||||
[Slot(2, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision reconstructZ = sqrt(1.0 - saturate(dot(In.xy, In.xy)));
|
||||
$precision3 normalVector = $precision3(In.x, In.y, reconstructZ);
|
||||
Out = normalize(normalVector);
|
||||
}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 27615ef3e2e760b45b15895bd39d0954
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,34 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Normal", "Normal Strength")]
|
||||
internal class NormalStrengthNode : CodeFunctionNode
|
||||
{
|
||||
public NormalStrengthNode()
|
||||
{
|
||||
name = "Normal Strength";
|
||||
synonyms = new string[] { "intensity" };
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_NormalStrength", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_NormalStrength(
|
||||
[Slot(0, Binding.None, 0, 0, 1, 0)] Vector3 In,
|
||||
[Slot(1, Binding.None, 1, 1, 1, 1)] Vector1 Strength,
|
||||
[Slot(2, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.up;
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = $precision3(In.rg * Strength, lerp(1, In.b, saturate(Strength)));
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c003a641a03160e478f4ce7ee8ce8da6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,66 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Artistic", "Normal", "Normal Unpack")]
|
||||
internal class NormalUnpackNode : CodeFunctionNode
|
||||
{
|
||||
public NormalUnpackNode()
|
||||
{
|
||||
name = "Normal Unpack";
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private NormalMapSpace m_NormalMapSpace = NormalMapSpace.Tangent;
|
||||
|
||||
[EnumControl("Space")]
|
||||
public NormalMapSpace normalMapSpace
|
||||
{
|
||||
get { return m_NormalMapSpace; }
|
||||
set
|
||||
{
|
||||
if (m_NormalMapSpace == value)
|
||||
return;
|
||||
|
||||
m_NormalMapSpace = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod(normalMapSpace == NormalMapSpace.Tangent ? "Unity_NormalUnpack" : "Unity_NormalUnpackRGB", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_NormalUnpack(
|
||||
[Slot(0, Binding.None)] Vector4 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.up;
|
||||
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = UnpackNormal(In);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_NormalUnpackRGB(
|
||||
[Slot(0, Binding.None)] Vector4 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.up;
|
||||
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = UnpackNormalRGB(In);
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1295ed68a1115a64088fc9298766fde8
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 32bf6e8fcb46ec24a9db465ddec10a34
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,223 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum Colorspace
|
||||
{
|
||||
RGB,
|
||||
Linear,
|
||||
HSV
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
struct ColorspaceConversion : IEnumConversion
|
||||
{
|
||||
public Colorspace from;
|
||||
public Colorspace to;
|
||||
|
||||
public ColorspaceConversion(Colorspace from, Colorspace to)
|
||||
{
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
Enum IEnumConversion.from
|
||||
{
|
||||
get { return from; }
|
||||
set { from = (Colorspace)value; }
|
||||
}
|
||||
|
||||
Enum IEnumConversion.to
|
||||
{
|
||||
get { return to; }
|
||||
set { to = (Colorspace)value; }
|
||||
}
|
||||
}
|
||||
|
||||
[Title("Artistic", "Utility", "Colorspace Conversion")]
|
||||
class ColorspaceConversionNode : CodeFunctionNode
|
||||
{
|
||||
public ColorspaceConversionNode()
|
||||
{
|
||||
name = "Colorspace Conversion";
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
ColorspaceConversion m_Conversion = new ColorspaceConversion(Colorspace.RGB, Colorspace.RGB);
|
||||
|
||||
[EnumConversionControl]
|
||||
ColorspaceConversion conversion
|
||||
{
|
||||
get { return m_Conversion; }
|
||||
set
|
||||
{
|
||||
if (m_Conversion.Equals(value))
|
||||
return;
|
||||
m_Conversion = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
string GetSpaceFrom()
|
||||
{
|
||||
return Enum.GetName(typeof(Colorspace), conversion.from);
|
||||
}
|
||||
|
||||
string GetSpaceTo()
|
||||
{
|
||||
return Enum.GetName(typeof(Colorspace), conversion.to);
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod(string.Format("Unity_ColorspaceConversion_{0}_{1}", GetSpaceFrom(), GetSpaceTo()),
|
||||
BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_ColorspaceConversion_RGB_RGB(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = In;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_ColorspaceConversion_RGB_Linear(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision3 linearRGBLo = In / 12.92;
|
||||
$precision3 linearRGBHi = pow(max(abs((In + 0.055) / 1.055), 1.192092896e-07), $precision3(2.4, 2.4, 2.4));
|
||||
Out = $precision3(In <= 0.04045) ? linearRGBLo : linearRGBHi;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_ColorspaceConversion_RGB_HSV(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision4 K = $precision4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
$precision4 P = lerp($precision4(In.bg, K.wz), $precision4(In.gb, K.xy), step(In.b, In.g));
|
||||
$precision4 Q = lerp($precision4(P.xyw, In.r), $precision4(In.r, P.yzx), step(P.x, In.r));
|
||||
$precision D = Q.x - min(Q.w, Q.y);
|
||||
$precision E = 1e-10;
|
||||
$precision V = (D == 0) ? Q.x : (Q.x + E);
|
||||
Out = $precision3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), V);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_ColorspaceConversion_Linear_RGB(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision3 sRGBLo = In * 12.92;
|
||||
$precision3 sRGBHi = (pow(max(abs(In), 1.192092896e-07), $precision3(1.0 / 2.4, 1.0 / 2.4, 1.0 / 2.4)) * 1.055) - 0.055;
|
||||
Out = $precision3(In <= 0.0031308) ? sRGBLo : sRGBHi;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_ColorspaceConversion_Linear_Linear(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = In;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_ColorspaceConversion_Linear_HSV(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision3 sRGBLo = In * 12.92;
|
||||
$precision3 sRGBHi = (pow(max(abs(In), 1.192092896e-07), $precision3(1.0 / 2.4, 1.0 / 2.4, 1.0 / 2.4)) * 1.055) - 0.055;
|
||||
$precision3 Linear = $precision3(In <= 0.0031308) ? sRGBLo : sRGBHi;
|
||||
$precision4 K = $precision4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
$precision4 P = lerp($precision4(Linear.bg, K.wz), $precision4(Linear.gb, K.xy), step(Linear.b, Linear.g));
|
||||
$precision4 Q = lerp($precision4(P.xyw, Linear.r), $precision4(Linear.r, P.yzx), step(P.x, Linear.r));
|
||||
$precision D = Q.x - min(Q.w, Q.y);
|
||||
$precision E = 1e-10;
|
||||
Out = $precision3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), Q.x);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_ColorspaceConversion_HSV_RGB(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision4 K = $precision4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
$precision3 P = abs(frac(In.xxx + K.xyz) * 6.0 - K.www);
|
||||
Out = In.z * lerp(K.xxx, saturate(P - K.xxx), In.y);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_ColorspaceConversion_HSV_Linear(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision4 K = $precision4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
$precision3 P = abs(frac(In.xxx + K.xyz) * 6.0 - K.www);
|
||||
$precision3 RGB = In.z * lerp(K.xxx, saturate(P - K.xxx), In.y);
|
||||
$precision3 linearRGBLo = RGB / 12.92;
|
||||
$precision3 linearRGBHi = pow(max(abs((RGB + 0.055) / 1.055), 1.192092896e-07), $precision3(2.4, 2.4, 2.4));
|
||||
Out = $precision3(RGB <= 0.04045) ? linearRGBLo : linearRGBHi;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
static string Unity_ColorspaceConversion_HSV_HSV(
|
||||
[Slot(0, Binding.None)] Vector3 In,
|
||||
[Slot(1, Binding.None)] out Vector3 Out)
|
||||
{
|
||||
Out = Vector3.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = In;
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 96dd6bbf093ac3d41a5bdaa467b58e6c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,359 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
class BlockNode : AbstractMaterialNode
|
||||
, IMayRequireNormal
|
||||
, IMayRequireTangent
|
||||
, IMayRequireBitangent
|
||||
, IMayRequireMeshUV
|
||||
, IMayRequireScreenPosition
|
||||
, IMayRequireViewDirection
|
||||
, IMayRequirePosition
|
||||
, IMayRequirePositionPredisplacement
|
||||
, IMayRequireVertexColor
|
||||
{
|
||||
[SerializeField]
|
||||
string m_SerializedDescriptor;
|
||||
|
||||
[NonSerialized]
|
||||
ContextData m_ContextData;
|
||||
|
||||
[NonSerialized]
|
||||
BlockFieldDescriptor m_Descriptor;
|
||||
|
||||
public override bool canCutNode => false;
|
||||
public override bool canCopyNode => false;
|
||||
|
||||
// Because the GraphData is deserialized after its child elements
|
||||
// the descriptor list is not built (and owner is not set)
|
||||
// at the time of node deserialization
|
||||
// Therefore we need to deserialize this element at GraphData.OnAfterDeserialize
|
||||
public string serializedDescriptor => m_SerializedDescriptor;
|
||||
|
||||
public ContextData contextData
|
||||
{
|
||||
get => m_ContextData;
|
||||
set => m_ContextData = value;
|
||||
}
|
||||
|
||||
public int index => contextData.blocks.IndexOf(this);
|
||||
|
||||
public BlockFieldDescriptor descriptor
|
||||
{
|
||||
get => m_Descriptor;
|
||||
set => m_Descriptor = value;
|
||||
}
|
||||
|
||||
const string k_CustomBlockDefaultName = "CustomInterpolator";
|
||||
|
||||
internal enum CustomBlockType { Float = 1, Vector2 = 2, Vector3 = 3, Vector4 = 4 }
|
||||
|
||||
internal bool isCustomBlock { get => m_Descriptor?.isCustom ?? false; }
|
||||
|
||||
internal string customName
|
||||
{
|
||||
get => m_Descriptor.name;
|
||||
set => OnCustomBlockFieldModified(value, customWidth);
|
||||
}
|
||||
|
||||
internal CustomBlockType customWidth
|
||||
{
|
||||
get => (CustomBlockType)ControlToWidth(m_Descriptor.control);
|
||||
set => OnCustomBlockFieldModified(customName, value);
|
||||
}
|
||||
|
||||
public void Init(BlockFieldDescriptor fieldDescriptor)
|
||||
{
|
||||
m_Descriptor = fieldDescriptor;
|
||||
|
||||
// custom blocks can be "copied" via a custom Field Descriptor, we'll use the CI name instead though.
|
||||
name = !isCustomBlock
|
||||
? $"{fieldDescriptor.tag}.{fieldDescriptor.name}"
|
||||
: $"{BlockFields.VertexDescription.name}.{k_CustomBlockDefaultName}";
|
||||
|
||||
|
||||
// TODO: This exposes the MaterialSlot API
|
||||
// TODO: This needs to be removed but is currently required by HDRP for DiffusionProfileInputMaterialSlot
|
||||
if (m_Descriptor is CustomSlotBlockFieldDescriptor customSlotDescriptor)
|
||||
{
|
||||
var newSlot = customSlotDescriptor.createSlot();
|
||||
AddSlot(newSlot);
|
||||
RemoveSlotsNameNotMatching(new int[] { 0 });
|
||||
return;
|
||||
}
|
||||
|
||||
AddSlotFromControlType();
|
||||
}
|
||||
|
||||
internal void InitCustomDefault()
|
||||
{
|
||||
Init(MakeCustomBlockField(k_CustomBlockDefaultName, CustomBlockType.Vector4));
|
||||
}
|
||||
|
||||
private void AddSlotFromControlType(bool attemptToModifyExisting = true)
|
||||
{
|
||||
// TODO: this should really just use callbacks like the CustomSlotBlockFieldDescriptor. then we wouldn't need this switch to make a copy
|
||||
var stageCapability = m_Descriptor.shaderStage.GetShaderStageCapability();
|
||||
switch (descriptor.control)
|
||||
{
|
||||
case PositionControl positionControl:
|
||||
AddSlot(new PositionMaterialSlot(0, descriptor.displayName, descriptor.name, positionControl.space, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
case NormalControl normalControl:
|
||||
AddSlot(new NormalMaterialSlot(0, descriptor.displayName, descriptor.name, normalControl.space, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
case TangentControl tangentControl:
|
||||
AddSlot(new TangentMaterialSlot(0, descriptor.displayName, descriptor.name, tangentControl.space, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
case VertexColorControl vertexColorControl:
|
||||
AddSlot(new VertexColorMaterialSlot(0, descriptor.displayName, descriptor.name, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
case ColorControl colorControl:
|
||||
var colorMode = colorControl.hdr ? ColorMode.HDR : ColorMode.Default;
|
||||
AddSlot(new ColorRGBMaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, colorControl.value, colorMode, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
case ColorRGBAControl colorRGBAControl:
|
||||
AddSlot(new ColorRGBAMaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, colorRGBAControl.value, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
case FloatControl floatControl:
|
||||
AddSlot(new Vector1MaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, floatControl.value, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
case Vector2Control vector2Control:
|
||||
AddSlot(new Vector2MaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, vector2Control.value, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
case Vector3Control vector3Control:
|
||||
AddSlot(new Vector3MaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, vector3Control.value, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
case Vector4Control vector4Control:
|
||||
AddSlot(new Vector4MaterialSlot(0, descriptor.displayName, descriptor.name, SlotType.Input, vector4Control.value, stageCapability), attemptToModifyExisting);
|
||||
break;
|
||||
}
|
||||
RemoveSlotsNameNotMatching(new int[] { 0 });
|
||||
}
|
||||
|
||||
public override string GetVariableNameForNode()
|
||||
{
|
||||
// Temporary block nodes have temporary guids that cannot be used to set preview data
|
||||
// Since each block is unique anyway we just omit the guid
|
||||
return NodeUtils.GetHLSLSafeName(name);
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
if (m_Descriptor.control == null)
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
var requirements = m_Descriptor.control.GetRequirements();
|
||||
return requirements.requiresNormal;
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
if (m_Descriptor.control == null)
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
var requirements = m_Descriptor.control.GetRequirements();
|
||||
return requirements.requiresViewDir;
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
if (m_Descriptor.control == null)
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
var requirements = m_Descriptor.control.GetRequirements();
|
||||
return requirements.requiresPosition;
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresPositionPredisplacement(ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
if (m_Descriptor.control == null)
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
var requirements = m_Descriptor.control.GetRequirements();
|
||||
return requirements.requiresPositionPredisplacement;
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
if (m_Descriptor.control == null)
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
var requirements = m_Descriptor.control.GetRequirements();
|
||||
return requirements.requiresTangent;
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
if (m_Descriptor.control == null)
|
||||
return NeededCoordinateSpace.None;
|
||||
|
||||
var requirements = m_Descriptor.control.GetRequirements();
|
||||
return requirements.requiresBitangent;
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
|
||||
return false;
|
||||
|
||||
if (m_Descriptor.control == null)
|
||||
return false;
|
||||
|
||||
var requirements = m_Descriptor.control.GetRequirements();
|
||||
return requirements.requiresMeshUVs.Contains(channel);
|
||||
}
|
||||
|
||||
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
|
||||
return false;
|
||||
|
||||
if (m_Descriptor.control == null)
|
||||
return false;
|
||||
|
||||
var requirements = m_Descriptor.control.GetRequirements();
|
||||
return requirements.requiresScreenPosition;
|
||||
}
|
||||
|
||||
public bool RequiresVertexColor(ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (stageCapability != m_Descriptor.shaderStage.GetShaderStageCapability())
|
||||
return false;
|
||||
|
||||
if (m_Descriptor.control == null)
|
||||
return false;
|
||||
|
||||
var requirements = m_Descriptor.control.GetRequirements();
|
||||
return requirements.requiresVertexColor;
|
||||
}
|
||||
|
||||
private void OnCustomBlockFieldModified(string name, CustomBlockType width)
|
||||
{
|
||||
if (!isCustomBlock)
|
||||
{
|
||||
Debug.LogWarning(String.Format("{0} is not a custom interpolator.", this.name));
|
||||
return;
|
||||
}
|
||||
|
||||
m_Descriptor = MakeCustomBlockField(name, width);
|
||||
|
||||
// TODO: Preserve the original slot's value and try to reapply after the slot is updated.
|
||||
AddSlotFromControlType(false);
|
||||
|
||||
owner?.ValidateGraph();
|
||||
}
|
||||
|
||||
public override void OnBeforeSerialize()
|
||||
{
|
||||
base.OnBeforeSerialize();
|
||||
if (descriptor != null)
|
||||
{
|
||||
if (isCustomBlock)
|
||||
{
|
||||
int width = ControlToWidth(m_Descriptor.control);
|
||||
m_SerializedDescriptor = $"{m_Descriptor.tag}.{m_Descriptor.name}#{width}";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SerializedDescriptor = $"{m_Descriptor.tag}.{m_Descriptor.name}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAfterDeserialize()
|
||||
{
|
||||
// TODO: Go find someone to tell @esme not to do this.
|
||||
if (m_SerializedDescriptor.Contains("#"))
|
||||
{
|
||||
string descName = k_CustomBlockDefaultName;
|
||||
CustomBlockType descWidth = CustomBlockType.Vector4;
|
||||
var descTag = BlockFields.VertexDescription.name;
|
||||
|
||||
name = $"{descTag}.{descName}";
|
||||
|
||||
var wsplit = m_SerializedDescriptor.Split(new char[] { '#', '.' });
|
||||
|
||||
try
|
||||
{
|
||||
descWidth = (CustomBlockType)int.Parse(wsplit[2]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.LogWarning(String.Format("Bad width found while deserializing custom interpolator {0}, defaulting to 4.", m_SerializedDescriptor));
|
||||
descWidth = CustomBlockType.Vector4;
|
||||
}
|
||||
|
||||
IControl control;
|
||||
try { control = (IControl)FindSlot<MaterialSlot>(0).InstantiateControl(); }
|
||||
catch { control = WidthToControl((int)descWidth); }
|
||||
|
||||
descName = NodeUtils.ConvertToValidHLSLIdentifier(wsplit[1]);
|
||||
m_Descriptor = new BlockFieldDescriptor(descTag, descName, "", control, ShaderStage.Vertex, isCustom: true);
|
||||
}
|
||||
}
|
||||
|
||||
#region CustomInterpolatorHelpers
|
||||
private static BlockFieldDescriptor MakeCustomBlockField(string name, CustomBlockType width)
|
||||
{
|
||||
name = NodeUtils.ConvertToValidHLSLIdentifier(name);
|
||||
var referenceName = name;
|
||||
var define = "";
|
||||
IControl control = WidthToControl((int)width);
|
||||
var tag = BlockFields.VertexDescription.name;
|
||||
|
||||
return new BlockFieldDescriptor(tag, referenceName, define, control, ShaderStage.Vertex, isCustom: true);
|
||||
}
|
||||
|
||||
private static IControl WidthToControl(int width)
|
||||
{
|
||||
switch (width)
|
||||
{
|
||||
case 1: return new FloatControl(default(float));
|
||||
case 2: return new Vector2Control(default(Vector2));
|
||||
case 3: return new Vector3Control(default(Vector3));
|
||||
case 4: return new Vector4Control(default(Vector4));
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static int ControlToWidth(IControl control)
|
||||
{
|
||||
switch (control)
|
||||
{
|
||||
case FloatControl a: return 1;
|
||||
case Vector2Control b: return 2;
|
||||
case Vector3Control c: return 3;
|
||||
case Vector4Control d: return 4;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3c01e026e3d1ea44397e3bcf9a8f5a4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9e3d3d0ce68bbc843b9b8734ab8d4f02
|
||||
folderAsset: yes
|
||||
timeCreated: 1495531110
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Channel", "Combine")]
|
||||
class CombineNode : CodeFunctionNode
|
||||
{
|
||||
public CombineNode()
|
||||
{
|
||||
name = "Combine";
|
||||
synonyms = new string[] { "append" };
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_Combine", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_Combine(
|
||||
[Slot(0, Binding.None)] Vector1 R,
|
||||
[Slot(1, Binding.None)] Vector1 G,
|
||||
[Slot(2, Binding.None)] Vector1 B,
|
||||
[Slot(3, Binding.None)] Vector1 A,
|
||||
[Slot(4, Binding.None)] out Vector4 RGBA,
|
||||
[Slot(5, Binding.None)] out Vector3 RGB,
|
||||
[Slot(6, Binding.None)] out Vector2 RG)
|
||||
{
|
||||
RGBA = Vector4.zero;
|
||||
RGB = Vector3.zero;
|
||||
RG = Vector2.zero;
|
||||
return @"
|
||||
{
|
||||
RGBA = $precision4(R, G, B, A);
|
||||
RGB = $precision3(R, G, B);
|
||||
RG = $precision2(R, G);
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3738e97908dea1f4bbc5e5a7cf562ecc
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
|
@ -0,0 +1,175 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Channel", "Flip")]
|
||||
class FlipNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction
|
||||
{
|
||||
public FlipNode()
|
||||
{
|
||||
name = "Flip";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
const int InputSlotId = 0;
|
||||
const int OutputSlotId = 1;
|
||||
const string kInputSlotName = "In";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public override bool hasPreview
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
string GetFunctionName()
|
||||
{
|
||||
// NOTE: it's important we use the $precision generic form of the slot type in the name here
|
||||
return $"Unity_Flip_{FindSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString()}";
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new DynamicVectorMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector4.zero));
|
||||
AddSlot(new DynamicVectorMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
|
||||
RemoveSlotsNameNotMatching(new[] { InputSlotId, OutputSlotId });
|
||||
}
|
||||
|
||||
int channelCount { get { return SlotValueHelper.GetChannelCount(FindSlot<MaterialSlot>(InputSlotId).concreteValueType); } }
|
||||
|
||||
[SerializeField]
|
||||
private bool m_RedChannel;
|
||||
|
||||
[ToggleControl("Red")]
|
||||
public ToggleData redChannel
|
||||
{
|
||||
get { return new ToggleData(m_RedChannel, channelCount > 0); }
|
||||
set
|
||||
{
|
||||
if (m_RedChannel == value.isOn)
|
||||
return;
|
||||
m_RedChannel = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_GreenChannel;
|
||||
|
||||
[ToggleControl("Green")]
|
||||
public ToggleData greenChannel
|
||||
{
|
||||
get { return new ToggleData(m_GreenChannel, channelCount > 1); }
|
||||
set
|
||||
{
|
||||
if (m_GreenChannel == value.isOn)
|
||||
return;
|
||||
m_GreenChannel = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_BlueChannel;
|
||||
|
||||
[ToggleControl("Blue")]
|
||||
public ToggleData blueChannel
|
||||
{
|
||||
get { return new ToggleData(m_BlueChannel, channelCount > 2); }
|
||||
set
|
||||
{
|
||||
if (m_BlueChannel == value.isOn)
|
||||
return;
|
||||
m_BlueChannel = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_AlphaChannel;
|
||||
|
||||
[ToggleControl("Alpha")]
|
||||
public ToggleData alphaChannel
|
||||
{
|
||||
get { return new ToggleData(m_AlphaChannel, channelCount > 3); }
|
||||
set
|
||||
{
|
||||
if (m_AlphaChannel == value.isOn)
|
||||
return;
|
||||
m_AlphaChannel = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var inputValue = GetSlotValue(InputSlotId, generationMode);
|
||||
var outputValue = GetSlotValue(OutputSlotId, generationMode);
|
||||
sb.AppendLine("{0} {1};", FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(OutputSlotId));
|
||||
|
||||
if (!generationMode.IsPreview())
|
||||
{
|
||||
sb.TryAppendIndentation();
|
||||
sb.Append("{0} _{1}_Flip = {0} ({2}",
|
||||
FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(),
|
||||
GetVariableNameForNode(),
|
||||
Convert.ToInt32(m_RedChannel));
|
||||
if (channelCount > 1)
|
||||
sb.Append(", {0}", Convert.ToInt32(m_GreenChannel));
|
||||
if (channelCount > 2)
|
||||
sb.Append(", {0}", Convert.ToInt32(m_BlueChannel));
|
||||
if (channelCount > 3)
|
||||
sb.Append(", {0}", Convert.ToInt32(m_AlphaChannel));
|
||||
sb.Append(");");
|
||||
sb.AppendNewLine();
|
||||
}
|
||||
|
||||
sb.AppendLine("{0}({1}, _{2}_Flip, {3});", GetFunctionName(), inputValue, GetVariableNameForNode(), outputValue);
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
base.CollectPreviewMaterialProperties(properties);
|
||||
|
||||
properties.Add(new PreviewProperty(PropertyType.Vector4)
|
||||
{
|
||||
name = string.Format("_{0}_Flip", GetVariableNameForNode()),
|
||||
vector4Value = new Vector4(Convert.ToInt32(m_RedChannel), Convert.ToInt32(m_GreenChannel), Convert.ToInt32(m_BlueChannel), Convert.ToInt32(m_AlphaChannel)),
|
||||
});
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
if (!generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
base.CollectShaderProperties(properties, generationMode);
|
||||
|
||||
properties.AddShaderProperty(new Vector4ShaderProperty
|
||||
{
|
||||
overrideReferenceName = string.Format("_{0}_Flip", GetVariableNameForNode()),
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
registry.ProvideFunction(GetFunctionName(), s =>
|
||||
{
|
||||
s.AppendLine("void {0}({1} In, {2} Flip, out {3} Out)",
|
||||
GetFunctionName(),
|
||||
FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(),
|
||||
FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(),
|
||||
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString());
|
||||
using (s.BlockScope())
|
||||
{
|
||||
s.AppendLine("Out = (Flip * -2 + 1) * In;");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fa443691530c547418e195e22597f2af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Channel", "Split")]
|
||||
class SplitNode : AbstractMaterialNode, IGeneratesBodyCode
|
||||
{
|
||||
const string kInputSlotName = "In";
|
||||
const string kOutputSlotRName = "R";
|
||||
const string kOutputSlotGName = "G";
|
||||
const string kOutputSlotBName = "B";
|
||||
const string kOutputSlotAName = "A";
|
||||
|
||||
public const int InputSlotId = 0;
|
||||
public const int OutputSlotRId = 1;
|
||||
public const int OutputSlotGId = 2;
|
||||
public const int OutputSlotBId = 3;
|
||||
public const int OutputSlotAId = 4;
|
||||
|
||||
public SplitNode()
|
||||
{
|
||||
name = "Split";
|
||||
synonyms = new string[] { "separate" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new DynamicVectorMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector4.zero));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0));
|
||||
RemoveSlotsNameNotMatching(new int[] { InputSlotId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId });
|
||||
}
|
||||
|
||||
static int[] s_OutputSlots = { OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId };
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var inputValue = GetSlotValue(InputSlotId, generationMode);
|
||||
|
||||
var inputSlot = FindInputSlot<MaterialSlot>(InputSlotId);
|
||||
var numInputChannels = 0;
|
||||
if (inputSlot != null)
|
||||
{
|
||||
numInputChannels = SlotValueHelper.GetChannelCount(inputSlot.concreteValueType);
|
||||
if (numInputChannels > 4)
|
||||
numInputChannels = 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
var outputFormat = numInputChannels == 1 ? inputValue : string.Format("{0}[{1}]", inputValue, i);
|
||||
var outputValue = i >= numInputChannels ? "0" : outputFormat;
|
||||
sb.AppendLine(string.Format("$precision {0} = {1};", GetVariableNameForSlot(s_OutputSlots[i]), outputValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 892fc353b154d0347854e3bebf1b49e7
|
||||
timeCreated: 1490896965
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,194 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Rendering;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Channel", "Swizzle")]
|
||||
class SwizzleNode : AbstractMaterialNode, IGeneratesBodyCode
|
||||
{
|
||||
public SwizzleNode()
|
||||
{
|
||||
name = "Swizzle";
|
||||
synonyms = new string[] { "swap", "reorder", "component mask" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
const int InputSlotId = 0;
|
||||
const int OutputSlotId = 1;
|
||||
const string kInputSlotName = "In";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public override bool hasPreview
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
string _maskInput = "xyzw";
|
||||
|
||||
[TextControl("Mask:")]
|
||||
public string maskInput
|
||||
{
|
||||
get { return _maskInput; }
|
||||
set
|
||||
{
|
||||
if (_maskInput.Equals(value))
|
||||
return;
|
||||
_maskInput = value;
|
||||
UpdateNodeAfterDeserialization();
|
||||
Dirty(ModificationScope.Topological);
|
||||
}
|
||||
}
|
||||
|
||||
public string convertedMask;
|
||||
|
||||
public bool ValidateMaskInput(int InputValueSize)
|
||||
{
|
||||
convertedMask = _maskInput.ToLower();
|
||||
|
||||
Dictionary<char, char> mask_map = new Dictionary<char, char>
|
||||
{
|
||||
{'r', 'x' },
|
||||
{'g', 'y' },
|
||||
{'b', 'z' },
|
||||
{'a', 'w' },
|
||||
};
|
||||
bool MaskInputIsValid = true;
|
||||
char[] MaskChars = convertedMask.ToCharArray();
|
||||
char[] AllChars = { 'x', 'y', 'z', 'w', 'r', 'g', 'b', 'a' };
|
||||
List<char> CurrentChars = new List<char>();
|
||||
for (int i = 0; i < InputValueSize; i++)
|
||||
{
|
||||
CurrentChars.Add(AllChars[i]);
|
||||
CurrentChars.Add(AllChars[i + 4]);
|
||||
}
|
||||
|
||||
foreach (char c in MaskChars)
|
||||
{
|
||||
if (!CurrentChars.Contains(c))
|
||||
{
|
||||
MaskInputIsValid = false;
|
||||
}
|
||||
}
|
||||
if (MaskChars.Length <= 0 || MaskChars.Length > 4)
|
||||
{
|
||||
MaskInputIsValid = false;
|
||||
}
|
||||
//Convert "rgba" input to "xyzw" to avoid mismathcing
|
||||
if (MaskInputIsValid)
|
||||
{
|
||||
char[] rgba = { 'r', 'g', 'b', 'a' };
|
||||
|
||||
for (int i = 0; i < MaskChars.Length; i++)
|
||||
{
|
||||
if (rgba.Contains(MaskChars[i]))
|
||||
{
|
||||
MaskChars[i] = mask_map[MaskChars[i]];
|
||||
}
|
||||
}
|
||||
convertedMask = new string(MaskChars);
|
||||
}
|
||||
return MaskInputIsValid;
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new DynamicVectorMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector4.zero));
|
||||
switch (_maskInput.Length)
|
||||
{
|
||||
case 1:
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, 0));
|
||||
break;
|
||||
case 2:
|
||||
AddSlot(new Vector2MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector2.zero));
|
||||
break;
|
||||
case 3:
|
||||
AddSlot(new Vector3MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector3.zero));
|
||||
break;
|
||||
default:
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
|
||||
break;
|
||||
}
|
||||
RemoveSlotsNameNotMatching(new[] { InputSlotId, OutputSlotId });
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var outputSlotType = FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString();
|
||||
var outputName = GetVariableNameForSlot(OutputSlotId);
|
||||
var inputValue = GetSlotValue(InputSlotId, generationMode);
|
||||
var inputValueType = FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType;
|
||||
var InputValueSize = SlotValueHelper.GetChannelCount(inputValueType);
|
||||
|
||||
if (!ValidateMaskInput(InputValueSize))
|
||||
{
|
||||
sb.AppendLine(string.Format("{0} {1} = 0;", outputSlotType, outputName));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine("{0} {1} = {2}.{3};", outputSlotType, outputName, inputValue, convertedMask);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ValidateNode()
|
||||
{
|
||||
base.ValidateNode();
|
||||
|
||||
var inputValueType = FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType;
|
||||
var InputValueSize = SlotValueHelper.GetChannelCount(inputValueType);
|
||||
if (!ValidateMaskInput(InputValueSize))
|
||||
{
|
||||
owner.AddValidationError(objectId, "Invalid mask for a Vector" + InputValueSize + " input.", ShaderCompilerMessageSeverity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public override int latestVersion => 1;
|
||||
|
||||
public override void OnAfterMultiDeserialize(string json)
|
||||
{
|
||||
//collect texturechannel properties
|
||||
//get the value
|
||||
//pass it to maskInput
|
||||
if (sgVersion < 1)
|
||||
{
|
||||
LegacySwizzleChannelData.LegacySwizzleChannel(json, this);
|
||||
ChangeVersion(1);
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<int> allowedNodeVersions => new List<int> { 1 };
|
||||
|
||||
class LegacySwizzleChannelData
|
||||
{
|
||||
//collect texturechannel properties
|
||||
[SerializeField]
|
||||
public TextureChannel m_RedChannel;
|
||||
[SerializeField]
|
||||
public TextureChannel m_GreenChannel;
|
||||
[SerializeField]
|
||||
public TextureChannel m_BlueChannel;
|
||||
[SerializeField]
|
||||
public TextureChannel m_AlphaChannel;
|
||||
|
||||
|
||||
public static void LegacySwizzleChannel(string json, SwizzleNode node)
|
||||
{
|
||||
Dictionary<TextureChannel, string> s_ComponentList = new Dictionary<TextureChannel, string>
|
||||
{
|
||||
{TextureChannel.Red, "r" },
|
||||
{TextureChannel.Green, "g" },
|
||||
{TextureChannel.Blue, "b" },
|
||||
{TextureChannel.Alpha, "a" },
|
||||
};
|
||||
var legacySwizzleChannelData = new LegacySwizzleChannelData();
|
||||
JsonUtility.FromJsonOverwrite(json, legacySwizzleChannelData);
|
||||
node._maskInput = s_ComponentList[legacySwizzleChannelData.m_RedChannel] + s_ComponentList[legacySwizzleChannelData.m_GreenChannel] + s_ComponentList[legacySwizzleChannelData.m_BlueChannel] + s_ComponentList[legacySwizzleChannelData.m_AlphaChannel];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 408ee761513fda7449bb3e428095726a
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
|
@ -0,0 +1,588 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using JetBrains.Annotations;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
abstract class CodeFunctionNode : AbstractMaterialNode
|
||||
, IGeneratesBodyCode
|
||||
, IGeneratesFunction
|
||||
, IMayRequireNormal
|
||||
, IMayRequireTangent
|
||||
, IMayRequireBitangent
|
||||
, IMayRequireMeshUV
|
||||
, IMayRequireScreenPosition
|
||||
, IMayRequireViewDirection
|
||||
, IMayRequirePosition
|
||||
, IMayRequirePositionPredisplacement
|
||||
, IMayRequireVertexColor
|
||||
{
|
||||
[NonSerialized]
|
||||
private List<SlotAttribute> m_Slots = new List<SlotAttribute>();
|
||||
|
||||
public override bool hasPreview
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
protected CodeFunctionNode()
|
||||
{
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
protected struct Boolean
|
||||
{ }
|
||||
|
||||
protected struct Vector1
|
||||
{ }
|
||||
|
||||
protected struct Texture2D
|
||||
{ }
|
||||
|
||||
protected struct Texture2DArray
|
||||
{ }
|
||||
|
||||
protected struct Texture3D
|
||||
{ }
|
||||
|
||||
protected struct SamplerState
|
||||
{ }
|
||||
|
||||
protected struct Gradient
|
||||
{ }
|
||||
|
||||
protected struct DynamicDimensionVector
|
||||
{ }
|
||||
|
||||
protected struct ColorRGBA
|
||||
{ }
|
||||
|
||||
protected struct ColorRGB
|
||||
{ }
|
||||
|
||||
protected struct Matrix3x3
|
||||
{ }
|
||||
|
||||
protected struct Matrix2x2
|
||||
{ }
|
||||
|
||||
protected struct DynamicDimensionMatrix
|
||||
{ }
|
||||
|
||||
protected struct PropertyConnectionState
|
||||
{ }
|
||||
|
||||
protected enum Binding
|
||||
{
|
||||
None,
|
||||
ObjectSpaceNormal,
|
||||
ObjectSpaceTangent,
|
||||
ObjectSpaceBitangent,
|
||||
ObjectSpacePosition,
|
||||
ViewSpaceNormal,
|
||||
ViewSpaceTangent,
|
||||
ViewSpaceBitangent,
|
||||
ViewSpacePosition,
|
||||
WorldSpaceNormal,
|
||||
WorldSpaceTangent,
|
||||
WorldSpaceBitangent,
|
||||
WorldSpacePosition,
|
||||
TangentSpaceNormal,
|
||||
TangentSpaceTangent,
|
||||
TangentSpaceBitangent,
|
||||
TangentSpacePosition,
|
||||
MeshUV0,
|
||||
MeshUV1,
|
||||
MeshUV2,
|
||||
MeshUV3,
|
||||
ScreenPosition,
|
||||
ObjectSpaceViewDirection,
|
||||
ViewSpaceViewDirection,
|
||||
WorldSpaceViewDirection,
|
||||
TangentSpaceViewDirection,
|
||||
VertexColor,
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
|
||||
protected class SlotAttribute : Attribute
|
||||
{
|
||||
public int slotId { get; private set; }
|
||||
public Binding binding { get; private set; }
|
||||
public bool hidden { get; private set; }
|
||||
public Vector4? defaultValue { get; private set; }
|
||||
public ShaderStageCapability stageCapability { get; private set; }
|
||||
|
||||
public SlotAttribute(int mSlotId, Binding mImplicitBinding, ShaderStageCapability mStageCapability = ShaderStageCapability.All)
|
||||
{
|
||||
slotId = mSlotId;
|
||||
binding = mImplicitBinding;
|
||||
defaultValue = null;
|
||||
stageCapability = mStageCapability;
|
||||
}
|
||||
|
||||
public SlotAttribute(int mSlotId, Binding mImplicitBinding, bool mHidden, ShaderStageCapability mStageCapability = ShaderStageCapability.All)
|
||||
{
|
||||
slotId = mSlotId;
|
||||
binding = mImplicitBinding;
|
||||
hidden = mHidden;
|
||||
defaultValue = null;
|
||||
stageCapability = mStageCapability;
|
||||
}
|
||||
|
||||
public SlotAttribute(int mSlotId, Binding mImplicitBinding, float defaultX, float defaultY, float defaultZ, float defaultW, ShaderStageCapability mStageCapability = ShaderStageCapability.All)
|
||||
{
|
||||
slotId = mSlotId;
|
||||
binding = mImplicitBinding;
|
||||
defaultValue = new Vector4(defaultX, defaultY, defaultZ, defaultW);
|
||||
stageCapability = mStageCapability;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract MethodInfo GetFunctionToConvert();
|
||||
|
||||
private static SlotValueType ConvertTypeToSlotValueType(ParameterInfo p)
|
||||
{
|
||||
Type t = p.ParameterType;
|
||||
if (p.ParameterType.IsByRef)
|
||||
t = p.ParameterType.GetElementType();
|
||||
|
||||
if (t == typeof(Boolean))
|
||||
{
|
||||
return SlotValueType.Boolean;
|
||||
}
|
||||
if (t == typeof(Vector1))
|
||||
{
|
||||
return SlotValueType.Vector1;
|
||||
}
|
||||
if (t == typeof(Vector2))
|
||||
{
|
||||
return SlotValueType.Vector2;
|
||||
}
|
||||
if (t == typeof(Vector3))
|
||||
{
|
||||
return SlotValueType.Vector3;
|
||||
}
|
||||
if (t == typeof(Vector4))
|
||||
{
|
||||
return SlotValueType.Vector4;
|
||||
}
|
||||
if (t == typeof(Color))
|
||||
{
|
||||
return SlotValueType.Vector4;
|
||||
}
|
||||
if (t == typeof(ColorRGBA))
|
||||
{
|
||||
return SlotValueType.Vector4;
|
||||
}
|
||||
if (t == typeof(ColorRGB))
|
||||
{
|
||||
return SlotValueType.Vector3;
|
||||
}
|
||||
if (t == typeof(Texture2D))
|
||||
{
|
||||
return SlotValueType.Texture2D;
|
||||
}
|
||||
if (t == typeof(Texture2DArray))
|
||||
{
|
||||
return SlotValueType.Texture2DArray;
|
||||
}
|
||||
if (t == typeof(Texture3D))
|
||||
{
|
||||
return SlotValueType.Texture3D;
|
||||
}
|
||||
if (t == typeof(Cubemap))
|
||||
{
|
||||
return SlotValueType.Cubemap;
|
||||
}
|
||||
if (t == typeof(Gradient))
|
||||
{
|
||||
return SlotValueType.Gradient;
|
||||
}
|
||||
if (t == typeof(SamplerState))
|
||||
{
|
||||
return SlotValueType.SamplerState;
|
||||
}
|
||||
if (t == typeof(DynamicDimensionVector))
|
||||
{
|
||||
return SlotValueType.DynamicVector;
|
||||
}
|
||||
if (t == typeof(Matrix4x4))
|
||||
{
|
||||
return SlotValueType.Matrix4;
|
||||
}
|
||||
if (t == typeof(Matrix3x3))
|
||||
{
|
||||
return SlotValueType.Matrix3;
|
||||
}
|
||||
if (t == typeof(Matrix2x2))
|
||||
{
|
||||
return SlotValueType.Matrix2;
|
||||
}
|
||||
if (t == typeof(DynamicDimensionMatrix))
|
||||
{
|
||||
return SlotValueType.DynamicMatrix;
|
||||
}
|
||||
if (t == typeof(PropertyConnectionState))
|
||||
{
|
||||
return SlotValueType.PropertyConnectionState;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unsupported type " + t);
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
var method = GetFunctionToConvert();
|
||||
|
||||
if (method == null)
|
||||
throw new ArgumentException("Mapped method is null on node" + this);
|
||||
|
||||
if (method.ReturnType != typeof(string))
|
||||
throw new ArgumentException("Mapped function should return string");
|
||||
|
||||
// validate no duplicates
|
||||
var slotAtributes = method.GetParameters().Select(GetSlotAttribute).ToList();
|
||||
if (slotAtributes.Any(x => x == null))
|
||||
throw new ArgumentException("Missing SlotAttribute on " + method.Name);
|
||||
|
||||
if (slotAtributes.GroupBy(x => x.slotId).Any(x => x.Count() > 1))
|
||||
throw new ArgumentException("Duplicate SlotAttribute on " + method.Name);
|
||||
|
||||
List<MaterialSlot> slots = new List<MaterialSlot>();
|
||||
foreach (var par in method.GetParameters())
|
||||
{
|
||||
var attribute = GetSlotAttribute(par);
|
||||
var name = GraphUtil.ConvertCamelCase(par.Name, true);
|
||||
|
||||
MaterialSlot s;
|
||||
if (attribute.binding == Binding.None && !par.IsOut && par.ParameterType == typeof(Color))
|
||||
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden);
|
||||
else if (attribute.binding == Binding.None && !par.IsOut && par.ParameterType == typeof(ColorRGBA))
|
||||
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden);
|
||||
else if (attribute.binding == Binding.None && !par.IsOut && par.ParameterType == typeof(ColorRGB))
|
||||
s = new ColorRGBMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, ColorMode.Default, stageCapability: attribute.stageCapability, hidden: attribute.hidden);
|
||||
else if (attribute.binding == Binding.None || par.IsOut)
|
||||
s = MaterialSlot.CreateMaterialSlot(
|
||||
ConvertTypeToSlotValueType(par),
|
||||
attribute.slotId,
|
||||
name,
|
||||
par.Name,
|
||||
par.IsOut ? SlotType.Output : SlotType.Input,
|
||||
attribute.defaultValue ?? Vector4.zero,
|
||||
shaderStageCapability: attribute.stageCapability,
|
||||
hidden: attribute.hidden);
|
||||
else
|
||||
s = CreateBoundSlot(attribute.binding, attribute.slotId, name, par.Name, attribute.stageCapability, attribute.hidden);
|
||||
slots.Add(s);
|
||||
|
||||
m_Slots.Add(attribute);
|
||||
}
|
||||
foreach (var slot in slots)
|
||||
{
|
||||
AddSlot(slot);
|
||||
}
|
||||
RemoveSlotsNameNotMatching(slots.Select(x => x.id), true);
|
||||
}
|
||||
|
||||
private static MaterialSlot CreateBoundSlot(Binding attributeBinding, int slotId, string displayName, string shaderOutputName, ShaderStageCapability shaderStageCapability, bool hidden = false)
|
||||
{
|
||||
switch (attributeBinding)
|
||||
{
|
||||
case Binding.ObjectSpaceNormal:
|
||||
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability, hidden);
|
||||
case Binding.ObjectSpaceTangent:
|
||||
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability, hidden);
|
||||
case Binding.ObjectSpaceBitangent:
|
||||
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability, hidden);
|
||||
case Binding.ObjectSpacePosition:
|
||||
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability, hidden);
|
||||
case Binding.ViewSpaceNormal:
|
||||
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability, hidden);
|
||||
case Binding.ViewSpaceTangent:
|
||||
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability, hidden);
|
||||
case Binding.ViewSpaceBitangent:
|
||||
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability, hidden);
|
||||
case Binding.ViewSpacePosition:
|
||||
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability, hidden);
|
||||
case Binding.WorldSpaceNormal:
|
||||
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability, hidden);
|
||||
case Binding.WorldSpaceTangent:
|
||||
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability, hidden);
|
||||
case Binding.WorldSpaceBitangent:
|
||||
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability, hidden);
|
||||
case Binding.WorldSpacePosition:
|
||||
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability, hidden);
|
||||
case Binding.TangentSpaceNormal:
|
||||
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability, hidden);
|
||||
case Binding.TangentSpaceTangent:
|
||||
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability, hidden);
|
||||
case Binding.TangentSpaceBitangent:
|
||||
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability, hidden);
|
||||
case Binding.TangentSpacePosition:
|
||||
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability, hidden);
|
||||
case Binding.MeshUV0:
|
||||
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV0, shaderStageCapability, hidden);
|
||||
case Binding.MeshUV1:
|
||||
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV1, shaderStageCapability, hidden);
|
||||
case Binding.MeshUV2:
|
||||
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV2, shaderStageCapability, hidden);
|
||||
case Binding.MeshUV3:
|
||||
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV3, shaderStageCapability, hidden);
|
||||
case Binding.ScreenPosition:
|
||||
return new ScreenPositionMaterialSlot(slotId, displayName, shaderOutputName, ScreenSpaceType.Default, shaderStageCapability, hidden);
|
||||
case Binding.ObjectSpaceViewDirection:
|
||||
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability, hidden);
|
||||
case Binding.ViewSpaceViewDirection:
|
||||
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability, hidden);
|
||||
case Binding.WorldSpaceViewDirection:
|
||||
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability, hidden);
|
||||
case Binding.TangentSpaceViewDirection:
|
||||
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability, hidden);
|
||||
case Binding.VertexColor:
|
||||
return new VertexColorMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("attributeBinding", attributeBinding, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetOutputSlots(tempSlots);
|
||||
foreach (var outSlot in tempSlots)
|
||||
{
|
||||
sb.AppendLine(outSlot.concreteValueType.ToShaderString(PrecisionUtil.Token) + " " + GetVariableNameForSlot(outSlot.id) + ";");
|
||||
}
|
||||
|
||||
string call = GetFunctionName() + "(";
|
||||
bool first = true;
|
||||
tempSlots.Clear();
|
||||
GetSlots(tempSlots);
|
||||
tempSlots.Sort((slot1, slot2) => slot1.id.CompareTo(slot2.id));
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
call += ", ";
|
||||
}
|
||||
first = false;
|
||||
|
||||
if (slot.isInputSlot)
|
||||
call += GetSlotValue(slot.id, generationMode);
|
||||
else
|
||||
call += GetVariableNameForSlot(slot.id);
|
||||
}
|
||||
call += ");";
|
||||
|
||||
sb.AppendLine(call);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetFunctionName()
|
||||
{
|
||||
var function = GetFunctionToConvert();
|
||||
return function.Name + (function.IsStatic ? string.Empty : "_" + objectId) + "_$precision"
|
||||
+ (this.GetSlots<DynamicVectorMaterialSlot>().Select(s => NodeUtils.GetSlotDimension(s.concreteValueType)).FirstOrDefault() ?? "")
|
||||
+ (this.GetSlots<DynamicMatrixMaterialSlot>().Select(s => NodeUtils.GetSlotDimension(s.concreteValueType)).FirstOrDefault() ?? "");
|
||||
}
|
||||
|
||||
private string GetFunctionHeader()
|
||||
{
|
||||
string header = "void " + GetFunctionName() + "(";
|
||||
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetSlots(tempSlots);
|
||||
tempSlots.Sort((slot1, slot2) => slot1.id.CompareTo(slot2.id));
|
||||
var first = true;
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (!first)
|
||||
header += ", ";
|
||||
|
||||
first = false;
|
||||
|
||||
if (slot.isOutputSlot)
|
||||
header += "out ";
|
||||
|
||||
// always use generic precisions for parameters, they will get concretized by the system
|
||||
header += slot.concreteValueType.ToShaderString(PrecisionUtil.Token) + " " + slot.shaderOutputName;
|
||||
}
|
||||
|
||||
header += ")";
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
private static object GetDefault(Type type)
|
||||
{
|
||||
return type.IsValueType ? Activator.CreateInstance(type) : null;
|
||||
}
|
||||
|
||||
private string GetFunctionBody(MethodInfo info)
|
||||
{
|
||||
var args = new List<object>();
|
||||
foreach (var param in info.GetParameters())
|
||||
args.Add(GetDefault(param.ParameterType));
|
||||
|
||||
var result = info.Invoke(this, args.ToArray()) as string;
|
||||
|
||||
if (string.IsNullOrEmpty(result))
|
||||
return string.Empty;
|
||||
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetSlots(tempSlots);
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
var toReplace = string.Format("{{slot{0}dimension}}", slot.id);
|
||||
var replacement = NodeUtils.GetSlotDimension(slot.concreteValueType);
|
||||
result = result.Replace(toReplace, replacement);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
registry.ProvideFunction(GetFunctionName(), s =>
|
||||
{
|
||||
s.AppendLine(GetFunctionHeader());
|
||||
var functionBody = GetFunctionBody(GetFunctionToConvert());
|
||||
var lines = functionBody.Trim('\r', '\n', '\t', ' ');
|
||||
s.AppendLines(lines);
|
||||
});
|
||||
}
|
||||
|
||||
private static SlotAttribute GetSlotAttribute([NotNull] ParameterInfo info)
|
||||
{
|
||||
var attrs = info.GetCustomAttributes(typeof(SlotAttribute), false).OfType<SlotAttribute>().ToList();
|
||||
return attrs.FirstOrDefault();
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
|
||||
{
|
||||
var binding = NeededCoordinateSpace.None;
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
foreach (var slot in tempSlots)
|
||||
binding |= slot.RequiresNormal();
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
|
||||
{
|
||||
var binding = NeededCoordinateSpace.None;
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
foreach (var slot in tempSlots)
|
||||
binding |= slot.RequiresViewDirection();
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
var binding = NeededCoordinateSpace.None;
|
||||
foreach (var slot in tempSlots)
|
||||
binding |= slot.RequiresPosition();
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresPositionPredisplacement(ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
var binding = NeededCoordinateSpace.None;
|
||||
foreach (var slot in tempSlots)
|
||||
binding |= slot.RequiresPositionPredisplacement();
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
var binding = NeededCoordinateSpace.None;
|
||||
foreach (var slot in tempSlots)
|
||||
binding |= slot.RequiresTangent();
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
var binding = NeededCoordinateSpace.None;
|
||||
foreach (var slot in tempSlots)
|
||||
binding |= slot.RequiresBitangent();
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresMeshUV(channel))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresScreenPosition(stageCapability))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RequiresVertexColor(ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresVertexColor())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3ed144f424a684a25971321011ebb096
|
||||
timeCreated: 1495966736
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
class FormerNameAttribute : Attribute
|
||||
{
|
||||
public string fullName { get; private set; }
|
||||
|
||||
public FormerNameAttribute(string fullName)
|
||||
{
|
||||
this.fullName = fullName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ae5b0289aecc42c2b6f5b5b08b80bdd9
|
||||
timeCreated: 1513592955
|
|
@ -0,0 +1,79 @@
|
|||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
/*abstract class FunctionMultiInput : BaseMaterialNode, IGeneratesBodyCode
|
||||
{
|
||||
private const string kOutputSlotName = "Output";
|
||||
private const string kBaseInputSlotName = "Input";
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public override void OnCreate()
|
||||
{
|
||||
base.OnCreate();
|
||||
AddSlot(new Slot(SlotType.OutputSlot, kOutputSlotName));
|
||||
|
||||
AddSlot(new Slot(SlotType.InputSlot, GetInputSlotName(0)));
|
||||
AddSlot(new Slot(SlotType.InputSlot, GetInputSlotName(1)));
|
||||
}
|
||||
|
||||
protected bool IsInputSlotConnected(int index)
|
||||
{
|
||||
var inputSlot = GetValidInputSlots().FirstOrDefault(x => x.name == GetInputSlotName(index));
|
||||
if (inputSlot == null)
|
||||
{
|
||||
Debug.LogError("Invalid slot configuration on node: " + name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return inputSlot.edges.Count > 0;
|
||||
}
|
||||
|
||||
private static string GetInputSlotName(int index) { return kBaseInputSlotName + (index); }
|
||||
|
||||
public override void InputEdgeChanged(Edge e)
|
||||
{
|
||||
base.InputEdgeChanged(e);
|
||||
|
||||
int inputSlotCount = GetValidInputSlots().Count();
|
||||
|
||||
if (IsInputSlotConnected(inputSlotCount - 1))
|
||||
AddSlot(new Slot(SlotType.InputSlot, GetInputSlotName(inputSlotCount)));
|
||||
else if (inputSlotCount > 2)
|
||||
{
|
||||
var lastSlot = inputSlots.FirstOrDefault(x => x.name == GetInputSlotName(inputSlotCount - 1));
|
||||
if (lastSlot != null)
|
||||
RemoveSlot(lastSlot);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract string GetFunctionName();
|
||||
|
||||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
|
||||
{
|
||||
var outputSlot = outputSlots.FirstOrDefault(x => x.name == kOutputSlotName);
|
||||
|
||||
if (outputSlot == null)
|
||||
{
|
||||
Debug.LogError("Invalid slot configuration on node: " + name);
|
||||
return;
|
||||
}
|
||||
|
||||
var inputSlots = GetValidInputSlots();
|
||||
int inputSlotCount = inputSlots.Count();
|
||||
|
||||
// build up a list of the valid input connections
|
||||
var inputValues = new List<string>(inputSlotCount);
|
||||
MaterialWindow.DebugMaterialGraph("Generating On Node: " + GetOutputVariableNameForNode() + " - Preview is: " + generationMode);
|
||||
inputValues.AddRange(inputSlots.Select(inputSlot => GetSlotValue(inputSlot, generationMode)));
|
||||
visitor.AddShaderChunk(precision + "4 " + GetVariableNameForSlot(outputSlot, generationMode) + " = " + GetFunctionCallBody(inputValues) + ";", true);
|
||||
}
|
||||
|
||||
protected virtual string GetFunctionCallBody(List<string> inputValues)
|
||||
{
|
||||
string functionCall = inputValues[0];
|
||||
for (int q = 1; q < inputValues.Count; ++q)
|
||||
functionCall = GetFunctionName() + " (" + functionCall + ", " + inputValues[q] + ")";
|
||||
return functionCall;
|
||||
}
|
||||
}*/
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 323a0eb1930dff241b4547716c8eb21f
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
abstract class GeometryNode : AbstractMaterialNode
|
||||
{
|
||||
public GeometryNode()
|
||||
{
|
||||
m_PreviewMode = PreviewMode.Preview3D;
|
||||
}
|
||||
|
||||
public virtual List<CoordinateSpace> validSpaces => new List<CoordinateSpace> { CoordinateSpace.Object, CoordinateSpace.View, CoordinateSpace.World, CoordinateSpace.Tangent };
|
||||
|
||||
[SerializeField]
|
||||
private CoordinateSpace m_Space = CoordinateSpace.World;
|
||||
|
||||
[PopupControl("Space")]
|
||||
public PopupList spacePopup
|
||||
{
|
||||
get
|
||||
{
|
||||
var names = validSpaces.Select(cs => cs.ToString().PascalToLabel()).ToArray();
|
||||
return new PopupList(names, (int)m_Space);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_Space == (CoordinateSpace)value.selectedEntry)
|
||||
return;
|
||||
|
||||
m_Space = (CoordinateSpace)value.selectedEntry;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
public CoordinateSpace space => m_Space;
|
||||
|
||||
public override bool hasPreview
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2e30171d4f8dfdc44beee8926ed3a83e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
static class GuidEncoder
|
||||
{
|
||||
public static string Encode(Guid guid)
|
||||
{
|
||||
string enc = Convert.ToBase64String(guid.ToByteArray());
|
||||
return String.Format("{0:X}", enc.GetHashCode());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3cf71f51f0308524080bb4aba2c9bb81
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,10 @@
|
|||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
interface IPropertyFromNode
|
||||
{
|
||||
AbstractShaderProperty AsShaderProperty();
|
||||
int outputSlotId { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 01ab4daa0c099e24e90bbb8623a4198b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0ab9e53346965db4a8ee81a2b978dca5
|
||||
folderAsset: yes
|
||||
timeCreated: 1495526789
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b43ef3944c134a74995e6582de94d21b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,86 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Basic", "Boolean")]
|
||||
class BooleanNode : AbstractMaterialNode, IGeneratesBodyCode, IPropertyFromNode
|
||||
{
|
||||
[SerializeField]
|
||||
private bool m_Value;
|
||||
|
||||
public const int OutputSlotId = 0;
|
||||
private const string kOutputSlotName = "Out";
|
||||
|
||||
public BooleanNode()
|
||||
{
|
||||
name = "Boolean";
|
||||
synonyms = new string[] { "switch", "true", "false", "on", "off" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new BooleanMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, false));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
|
||||
}
|
||||
|
||||
[ToggleControl("")]
|
||||
public ToggleData value
|
||||
{
|
||||
get { return new ToggleData(m_Value); }
|
||||
set
|
||||
{
|
||||
if (m_Value == value.isOn)
|
||||
return;
|
||||
m_Value = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
if (!generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
properties.AddShaderProperty(new BooleanShaderProperty()
|
||||
{
|
||||
overrideReferenceName = GetVariableNameForNode(),
|
||||
generatePropertyBlock = false,
|
||||
value = m_Value
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
if (generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
sb.AppendLine("$precision {0} = {1};", GetVariableNameForNode(), (m_Value ? 1 : 0));
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return GetVariableNameForNode();
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
properties.Add(new PreviewProperty(PropertyType.Boolean)
|
||||
{
|
||||
name = GetVariableNameForNode(),
|
||||
booleanValue = m_Value
|
||||
});
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
return new BooleanShaderProperty { value = m_Value };
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a6bd4d4655c0b9046a14e6ab0caebdc3
|
||||
timeCreated: 1445864587
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,175 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph.Internal
|
||||
{
|
||||
public enum ColorMode
|
||||
{
|
||||
Default,
|
||||
HDR
|
||||
}
|
||||
}
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Basic", "Color")]
|
||||
class ColorNode : AbstractMaterialNode, IGeneratesBodyCode, IPropertyFromNode
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
private const string kOutputSlotName = "Out";
|
||||
|
||||
public override int latestVersion => 1;
|
||||
|
||||
public ColorNode()
|
||||
{
|
||||
name = "Color";
|
||||
synonyms = new string[] { "rgba" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
Color m_Color = new Color(UnityEngine.Color.clear, ColorMode.Default);
|
||||
|
||||
[Serializable]
|
||||
public struct Color
|
||||
{
|
||||
public UnityEngine.Color color;
|
||||
public ColorMode mode;
|
||||
|
||||
public Color(UnityEngine.Color color, ColorMode mode)
|
||||
{
|
||||
this.color = color;
|
||||
this.mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
[ColorControl("")]
|
||||
public Color color
|
||||
{
|
||||
get { return m_Color; }
|
||||
set
|
||||
{
|
||||
if ((value.color == m_Color.color) && (value.mode == m_Color.mode))
|
||||
return;
|
||||
|
||||
if ((value.mode != m_Color.mode) && (value.mode == ColorMode.Default))
|
||||
{
|
||||
float r = Mathf.Clamp(value.color.r, 0, 1);
|
||||
float g = Mathf.Clamp(value.color.g, 0, 1);
|
||||
float b = Mathf.Clamp(value.color.b, 0, 1);
|
||||
float a = Mathf.Clamp(value.color.a, 0, 1);
|
||||
value.color = new UnityEngine.Color(r, g, b, a);
|
||||
}
|
||||
|
||||
m_Color = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
if (!generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
properties.AddShaderProperty(new ColorShaderProperty()
|
||||
{
|
||||
overrideReferenceName = GetVariableNameForNode(),
|
||||
generatePropertyBlock = false,
|
||||
value = color.color,
|
||||
colorMode = color.mode
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
if (generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
switch (sgVersion)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine(@"$precision4 {0} = IsGammaSpace() ? $precision4({1}, {2}, {3}, {4}) : $precision4(SRGBToLinear($precision3({1}, {2}, {3})), {4});"
|
||||
, GetVariableNameForNode()
|
||||
, NodeUtils.FloatToShaderValue(color.color.r)
|
||||
, NodeUtils.FloatToShaderValue(color.color.g)
|
||||
, NodeUtils.FloatToShaderValue(color.color.b)
|
||||
, NodeUtils.FloatToShaderValue(color.color.a));
|
||||
break;
|
||||
case 1:
|
||||
//HDR color picker assumes Linear space, regular color picker assumes SRGB. Handle both cases
|
||||
if (color.mode == ColorMode.Default)
|
||||
{
|
||||
sb.AppendLine(@"$precision4 {0} = IsGammaSpace() ? $precision4({1}, {2}, {3}, {4}) : $precision4(SRGBToLinear($precision3({1}, {2}, {3})), {4});"
|
||||
, GetVariableNameForNode()
|
||||
, NodeUtils.FloatToShaderValue(color.color.r)
|
||||
, NodeUtils.FloatToShaderValue(color.color.g)
|
||||
, NodeUtils.FloatToShaderValue(color.color.b)
|
||||
, NodeUtils.FloatToShaderValue(color.color.a));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(@"$precision4 {0} = IsGammaSpace() ? LinearToSRGB($precision4({1}, {2}, {3}, {4})) : $precision4({1}, {2}, {3}, {4});"
|
||||
, GetVariableNameForNode()
|
||||
, NodeUtils.FloatToShaderValue(color.color.r)
|
||||
, NodeUtils.FloatToShaderValue(color.color.g)
|
||||
, NodeUtils.FloatToShaderValue(color.color.b)
|
||||
, NodeUtils.FloatToShaderValue(color.color.a));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return GetVariableNameForNode();
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
UnityEngine.Color propColor = color.color;
|
||||
if (color.mode == ColorMode.Default)
|
||||
{
|
||||
if (PlayerSettings.colorSpace == ColorSpace.Linear)
|
||||
propColor = propColor.linear;
|
||||
}
|
||||
if (color.mode == ColorMode.HDR)
|
||||
{
|
||||
switch (sgVersion)
|
||||
{
|
||||
case 0:
|
||||
if (PlayerSettings.colorSpace == ColorSpace.Linear)
|
||||
propColor = propColor.linear;
|
||||
break;
|
||||
case 1:
|
||||
if (PlayerSettings.colorSpace == ColorSpace.Gamma)
|
||||
propColor = propColor.gamma;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// we use Vector4 type to avoid all of the automatic color conversions of PropertyType.Color
|
||||
properties.Add(new PreviewProperty(PropertyType.Vector4)
|
||||
{
|
||||
name = GetVariableNameForNode(),
|
||||
vector4Value = propColor
|
||||
});
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
return new ColorShaderProperty() { value = color.color, colorMode = color.mode };
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 325c0e24c20746345a5f90dc201973f8
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
|
@ -0,0 +1,75 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum ConstantType
|
||||
{
|
||||
PI,
|
||||
TAU,
|
||||
PHI,
|
||||
E,
|
||||
SQRT2
|
||||
};
|
||||
|
||||
[Title("Input", "Basic", "Constant")]
|
||||
class ConstantNode : AbstractMaterialNode, IGeneratesBodyCode
|
||||
{
|
||||
static Dictionary<ConstantType, float> m_constantList = new Dictionary<ConstantType, float>
|
||||
{
|
||||
{ConstantType.PI, 3.1415926f },
|
||||
{ConstantType.TAU, 6.28318530f},
|
||||
{ConstantType.PHI, 1.618034f},
|
||||
{ConstantType.E, 2.718282f},
|
||||
{ConstantType.SQRT2, 1.414214f},
|
||||
};
|
||||
|
||||
[SerializeField]
|
||||
private ConstantType m_constant = ConstantType.PI;
|
||||
|
||||
private const int kOutputSlotId = 0;
|
||||
private const string kOutputSlotName = "Out";
|
||||
|
||||
[EnumControl("")]
|
||||
public ConstantType constant
|
||||
{
|
||||
get { return m_constant; }
|
||||
set
|
||||
{
|
||||
if (m_constant == value)
|
||||
return;
|
||||
|
||||
m_constant = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
public ConstantNode()
|
||||
{
|
||||
name = "Constant";
|
||||
synonyms = new string[] { "pi", "tau", "phi" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, 0));
|
||||
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
sb.AppendLine(string.Format("$precision {0} = {1};"
|
||||
, GetVariableNameForNode()
|
||||
, m_constantList[constant].ToString(CultureInfo.InvariantCulture)));
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return GetVariableNameForNode();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f48f68efc30ae334098ff30e88fbf9db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,89 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Basic", "Integer")]
|
||||
class IntegerNode : AbstractMaterialNode, IGeneratesBodyCode, IPropertyFromNode
|
||||
{
|
||||
[SerializeField]
|
||||
private int m_Value;
|
||||
|
||||
public const int OutputSlotId = 0;
|
||||
private const string kOutputSlotName = "Out";
|
||||
|
||||
public IntegerNode()
|
||||
{
|
||||
name = "Integer";
|
||||
synonyms = new string[] { "whole number" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, 0));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
|
||||
}
|
||||
|
||||
[IntegerControl("")]
|
||||
public int value
|
||||
{
|
||||
get { return m_Value; }
|
||||
set
|
||||
{
|
||||
if (m_Value == value)
|
||||
return;
|
||||
|
||||
m_Value = value;
|
||||
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
if (!generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
properties.AddShaderProperty(new Vector1ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = GetVariableNameForNode(),
|
||||
generatePropertyBlock = false,
|
||||
value = value,
|
||||
floatType = FloatType.Integer
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
if (generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
sb.AppendLine(string.Format("$precision {0} = {1};", GetVariableNameForNode(), m_Value));
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return GetVariableNameForNode();
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
properties.Add(new PreviewProperty(PropertyType.Float)
|
||||
{
|
||||
name = GetVariableNameForNode(),
|
||||
floatValue = m_Value
|
||||
});
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
return new Vector1ShaderProperty { value = value, floatType = FloatType.Integer };
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e449bdf3b245898489ebab4f709ded62
|
||||
timeCreated: 1445864587
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,95 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using System.Globalization;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Basic", "Slider")]
|
||||
class SliderNode : AbstractMaterialNode, IGeneratesBodyCode, IPropertyFromNode
|
||||
{
|
||||
[SerializeField]
|
||||
private Vector3 m_Value = new Vector3(0f, 0f, 1f);
|
||||
|
||||
public const int OutputSlotId = 0;
|
||||
private const string kOutputSlotName = "Out";
|
||||
|
||||
public SliderNode()
|
||||
{
|
||||
name = "Slider";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, 0));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
|
||||
}
|
||||
|
||||
[SliderControl("", true)]
|
||||
public Vector3 value
|
||||
{
|
||||
get { return m_Value; }
|
||||
set
|
||||
{
|
||||
if (m_Value == value)
|
||||
return;
|
||||
|
||||
m_Value = value;
|
||||
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
if (!generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
properties.AddShaderProperty(new Vector1ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = GetVariableNameForNode(),
|
||||
generatePropertyBlock = false,
|
||||
value = value.x,
|
||||
rangeValues = new Vector2(value.y, value.z),
|
||||
floatType = FloatType.Slider
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
if (generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "$precision {0} = {1};", GetVariableNameForNode(), m_Value.x));
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return GetVariableNameForNode();
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
properties.Add(new PreviewProperty(PropertyType.Float)
|
||||
{
|
||||
name = GetVariableNameForNode(),
|
||||
floatValue = m_Value.x
|
||||
});
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
return new Vector1ShaderProperty
|
||||
{
|
||||
value = value.x,
|
||||
rangeValues = new Vector2(value.y, value.z),
|
||||
floatType = FloatType.Slider
|
||||
};
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 39d5ba890306e584c9fb4fede8c37f9c
|
||||
timeCreated: 1445864587
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,64 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Basic", "Time")]
|
||||
class TimeNode : AbstractMaterialNode, IMayRequireTime
|
||||
{
|
||||
private const string kOutputSlotName = "Time";
|
||||
private const string kOutputSlot1Name = "Sine Time";
|
||||
private const string kOutputSlot2Name = "Cosine Time";
|
||||
private const string kOutputSlot3Name = "Delta Time";
|
||||
private const string kOutputSlot4Name = "Smooth Delta";
|
||||
|
||||
public const int OutputSlotId = 0;
|
||||
public const int OutputSlot1Id = 1;
|
||||
public const int OutputSlot2Id = 2;
|
||||
public const int OutputSlot3Id = 3;
|
||||
public const int OutputSlot4Id = 4;
|
||||
|
||||
public TimeNode()
|
||||
{
|
||||
name = "Time";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, 0));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlot1Id, kOutputSlot1Name, kOutputSlot1Name, SlotType.Output, 0));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlot2Id, kOutputSlot2Name, kOutputSlot2Name, SlotType.Output, 0));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlot3Id, kOutputSlot3Name, kOutputSlot3Name, SlotType.Output, 0));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlot4Id, kOutputSlot4Name, kOutputSlot4Name, SlotType.Output, 0));
|
||||
RemoveSlotsNameNotMatching(validSlots);
|
||||
}
|
||||
|
||||
protected int[] validSlots
|
||||
{
|
||||
get { return new[] { OutputSlotId, OutputSlot1Id, OutputSlot2Id, OutputSlot3Id, OutputSlot4Id }; }
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
switch (slotId)
|
||||
{
|
||||
case OutputSlot1Id:
|
||||
return "IN.TimeParameters.y";
|
||||
case OutputSlot2Id:
|
||||
return "IN.TimeParameters.z";
|
||||
case OutputSlot3Id:
|
||||
return "unity_DeltaTime.x";
|
||||
case OutputSlot4Id:
|
||||
return "unity_DeltaTime.z";
|
||||
default:
|
||||
return "IN.TimeParameters.x";
|
||||
}
|
||||
}
|
||||
|
||||
public bool RequiresTime()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 66310de0dabd3074aa56ab7714324cc0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,57 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Basic", "Float")]
|
||||
class Vector1Node : AbstractMaterialNode, IGeneratesBodyCode, IPropertyFromNode
|
||||
{
|
||||
[SerializeField]
|
||||
private float m_Value = 0;
|
||||
|
||||
const string kInputSlotXName = "X";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public const int InputSlotXId = 1;
|
||||
public const int OutputSlotId = 0;
|
||||
|
||||
public Vector1Node()
|
||||
{
|
||||
name = "Float";
|
||||
synonyms = new string[] { "Vector 1", "1", "v1", "vec1", "scalar" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotXId, kInputSlotXName, kInputSlotXName, SlotType.Input, m_Value));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, 0));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId, InputSlotXId });
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var inputValue = GetSlotValue(InputSlotXId, generationMode);
|
||||
sb.AppendLine(string.Format("$precision {0} = {1};", GetVariableNameForSlot(OutputSlotId), inputValue));
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
var slot = FindInputSlot<Vector1MaterialSlot>(InputSlotXId);
|
||||
return new Vector1ShaderProperty { value = slot.value };
|
||||
}
|
||||
|
||||
public override void OnAfterDeserialize()
|
||||
{
|
||||
base.OnAfterDeserialize();
|
||||
|
||||
name = "Float";
|
||||
}
|
||||
|
||||
int IPropertyFromNode.outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 87c4299b09d95d64c99884296038ceeb
|
||||
timeCreated: 1445864587
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,62 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Basic", "Vector 2")]
|
||||
class Vector2Node : AbstractMaterialNode, IGeneratesBodyCode, IPropertyFromNode
|
||||
{
|
||||
[SerializeField]
|
||||
private Vector2 m_Value = Vector2.zero;
|
||||
|
||||
const string kInputSlotXName = "X";
|
||||
const string kInputSlotYName = "Y";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public const int OutputSlotId = 0;
|
||||
public const int InputSlotXId = 1;
|
||||
public const int InputSlotYId = 2;
|
||||
|
||||
|
||||
public Vector2Node()
|
||||
{
|
||||
name = "Vector 2";
|
||||
synonyms = new string[] { "2", "v2", "vec2", "float2" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotXId, kInputSlotXName, kInputSlotXName, SlotType.Input, m_Value.x));
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotYId, kInputSlotYName, kInputSlotYName, SlotType.Input, m_Value.y, label1: "Y"));
|
||||
AddSlot(new Vector2MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId, InputSlotXId, InputSlotYId });
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var inputXValue = GetSlotValue(InputSlotXId, generationMode);
|
||||
var inputYValue = GetSlotValue(InputSlotYId, generationMode);
|
||||
var outputName = GetVariableNameForSlot(OutputSlotId);
|
||||
|
||||
var s = string.Format("$precision2 {0} = $precision2({1}, {2});",
|
||||
outputName,
|
||||
inputXValue,
|
||||
inputYValue);
|
||||
sb.AppendLine(s);
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
var slotX = FindInputSlot<Vector1MaterialSlot>(InputSlotXId);
|
||||
var slotY = FindInputSlot<Vector1MaterialSlot>(InputSlotYId);
|
||||
return new Vector2ShaderProperty { value = new Vector2(slotX.value, slotY.value) };
|
||||
}
|
||||
|
||||
int IPropertyFromNode.outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8361d1f9d12a489438c0b1e2e48c8542
|
||||
timeCreated: 1446473341
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,67 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Basic", "Vector 3")]
|
||||
class Vector3Node : AbstractMaterialNode, IGeneratesBodyCode, IPropertyFromNode
|
||||
{
|
||||
[SerializeField]
|
||||
private Vector3 m_Value = Vector3.zero;
|
||||
|
||||
const string kInputSlotXName = "X";
|
||||
const string kInputSlotYName = "Y";
|
||||
const string kInputSlotZName = "Z";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public const int OutputSlotId = 0;
|
||||
public const int InputSlotXId = 1;
|
||||
public const int InputSlotYId = 2;
|
||||
public const int InputSlotZId = 3;
|
||||
|
||||
|
||||
public Vector3Node()
|
||||
{
|
||||
name = "Vector 3";
|
||||
synonyms = new string[] { "3", "v3", "vec3", "float3" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotXId, kInputSlotXName, kInputSlotXName, SlotType.Input, m_Value.x));
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotYId, kInputSlotYName, kInputSlotYName, SlotType.Input, m_Value.y, label1: "Y"));
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotZId, kInputSlotZName, kInputSlotZName, SlotType.Input, m_Value.z, label1: "Z"));
|
||||
AddSlot(new Vector3MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId, InputSlotXId, InputSlotYId, InputSlotZId });
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var inputXValue = GetSlotValue(InputSlotXId, generationMode);
|
||||
var inputYValue = GetSlotValue(InputSlotYId, generationMode);
|
||||
var inputZValue = GetSlotValue(InputSlotZId, generationMode);
|
||||
var outputName = GetVariableNameForSlot(outputSlotId);
|
||||
|
||||
var s = string.Format("$precision3 {0} = $precision3({1}, {2}, {3});",
|
||||
outputName,
|
||||
inputXValue,
|
||||
inputYValue,
|
||||
inputZValue);
|
||||
sb.AppendLine(s);
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
var slotX = FindInputSlot<Vector1MaterialSlot>(InputSlotXId);
|
||||
var slotY = FindInputSlot<Vector1MaterialSlot>(InputSlotYId);
|
||||
var slotZ = FindInputSlot<Vector1MaterialSlot>(InputSlotZId);
|
||||
return new Vector3ShaderProperty { value = new Vector3(slotX.value, slotY.value, slotZ.value) };
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1350e4a38ff5ae44a9d8627d33b48de8
|
||||
timeCreated: 1453378777
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,73 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Basic", "Vector 4")]
|
||||
class Vector4Node : AbstractMaterialNode, IGeneratesBodyCode, IPropertyFromNode
|
||||
{
|
||||
[SerializeField]
|
||||
private Vector4 m_Value = Vector4.zero;
|
||||
|
||||
const string kInputSlotXName = "X";
|
||||
const string kInputSlotYName = "Y";
|
||||
const string kInputSlotZName = "Z";
|
||||
const string kInputSlotWName = "W";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public const int OutputSlotId = 0;
|
||||
public const int InputSlotXId = 1;
|
||||
public const int InputSlotYId = 2;
|
||||
public const int InputSlotZId = 3;
|
||||
public const int InputSlotWId = 4;
|
||||
|
||||
|
||||
public Vector4Node()
|
||||
{
|
||||
name = "Vector 4";
|
||||
synonyms = new string[] { "4", "v4", "vec4", "float4" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotXId, kInputSlotXName, kInputSlotXName, SlotType.Input, m_Value.x));
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotYId, kInputSlotYName, kInputSlotYName, SlotType.Input, m_Value.y, label1: "Y"));
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotZId, kInputSlotZName, kInputSlotZName, SlotType.Input, m_Value.z, label1: "Z"));
|
||||
AddSlot(new Vector1MaterialSlot(InputSlotWId, kInputSlotWName, kInputSlotWName, SlotType.Input, m_Value.w, label1: "W"));
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId, InputSlotXId, InputSlotYId, InputSlotZId, InputSlotWId });
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var inputXValue = GetSlotValue(InputSlotXId, generationMode);
|
||||
var inputYValue = GetSlotValue(InputSlotYId, generationMode);
|
||||
var inputZValue = GetSlotValue(InputSlotZId, generationMode);
|
||||
var inputWValue = GetSlotValue(InputSlotWId, generationMode);
|
||||
var outputName = GetVariableNameForSlot(outputSlotId);
|
||||
|
||||
var s = string.Format("$precision4 {0} = $precision4({1}, {2}, {3}, {4});",
|
||||
outputName,
|
||||
inputXValue,
|
||||
inputYValue,
|
||||
inputZValue,
|
||||
inputWValue);
|
||||
sb.AppendLine(s);
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
var slotX = FindInputSlot<Vector1MaterialSlot>(InputSlotXId);
|
||||
var slotY = FindInputSlot<Vector1MaterialSlot>(InputSlotYId);
|
||||
var slotZ = FindInputSlot<Vector1MaterialSlot>(InputSlotZId);
|
||||
var slotW = FindInputSlot<Vector1MaterialSlot>(InputSlotWId);
|
||||
return new Vector4ShaderProperty { value = new Vector4(slotX.value, slotY.value, slotZ.value, slotW.value) };
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f34a640000e664d4f8b2e0795df7fad9
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
|
@ -0,0 +1,280 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEditor.Rendering;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Serializable]
|
||||
[Title("Custom Interpolators", "Instance")]
|
||||
class CustomInterpolatorNode : AbstractMaterialNode
|
||||
{
|
||||
[SerializeField]
|
||||
internal string customBlockNodeName = "K_INVALID";
|
||||
|
||||
[SerializeField]
|
||||
private BlockNode.CustomBlockType serializedType = BlockNode.CustomBlockType.Vector4;
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
internal override bool ExposeToSearcher { get => false; } // This is exposed in a special way.
|
||||
|
||||
public override bool allowedInSubGraph { get => false; }
|
||||
|
||||
internal BlockNode e_targetBlockNode // weak indirection via customBlockNodeName
|
||||
{
|
||||
get => (owner?.vertexContext.blocks.Find(cib => cib.value.descriptor.name == customBlockNodeName))?.value ?? null;
|
||||
}
|
||||
|
||||
public CustomInterpolatorNode()
|
||||
{
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
internal void ConnectToCustomBlock(BlockNode node)
|
||||
{
|
||||
// if somehow we were already connected, be sure to unregister.
|
||||
if (e_targetBlockNode != null)
|
||||
{
|
||||
e_targetBlockNode.UnregisterCallback(OnCustomBlockModified);
|
||||
}
|
||||
// if a new cib is renamed to match us when we didn't have a target (unusual case, but covering all bases here).
|
||||
if (node?.isCustomBlock ?? false)
|
||||
{
|
||||
name = node.customName + " (Custom Interpolator)";
|
||||
customBlockNodeName = node.customName;
|
||||
serializedType = node.customWidth;
|
||||
BuildSlot();
|
||||
node.RegisterCallback(OnCustomBlockModified);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ConnectToCustomBlockByName(string customBlockName)
|
||||
{
|
||||
// see above
|
||||
if (e_targetBlockNode != null)
|
||||
{
|
||||
e_targetBlockNode.UnregisterCallback(OnCustomBlockModified);
|
||||
}
|
||||
|
||||
name = customBlockName + " (Custom Interpolator)";
|
||||
customBlockNodeName = customBlockName;
|
||||
if (e_targetBlockNode != null)
|
||||
{
|
||||
serializedType = e_targetBlockNode.customWidth;
|
||||
BuildSlot();
|
||||
e_targetBlockNode.RegisterCallback(OnCustomBlockModified);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should get badged in OnValidate.
|
||||
}
|
||||
}
|
||||
|
||||
void OnCustomBlockModified(AbstractMaterialNode node, Graphing.ModificationScope scope)
|
||||
{
|
||||
if (node is BlockNode bnode)
|
||||
{
|
||||
if (bnode?.isCustomBlock ?? false)
|
||||
{
|
||||
name = bnode.customName + " (Custom Interpolator)";
|
||||
customBlockNodeName = bnode.customName;
|
||||
if (e_targetBlockNode != null && e_targetBlockNode.owner != null)
|
||||
{
|
||||
serializedType = e_targetBlockNode.customWidth;
|
||||
BuildSlot();
|
||||
Dirty(ModificationScope.Node);
|
||||
Dirty(ModificationScope.Topological);
|
||||
}
|
||||
}
|
||||
}
|
||||
// bnode information we got is somehow invalid, this is probably case for an exception.
|
||||
}
|
||||
|
||||
public override void ValidateNode()
|
||||
{
|
||||
// Our node was deleted or we had bad deserialization, we need to badge.
|
||||
if (e_targetBlockNode == null || e_targetBlockNode.owner == null)
|
||||
{
|
||||
e_targetBlockNode?.UnregisterCallback(OnCustomBlockModified);
|
||||
owner.AddValidationError(objectId, String.Format("Custom Block Interpolator '{0}' not found.", customBlockNodeName), ShaderCompilerMessageSeverity.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
// our blockNode reference is somehow valid again after it wasn't,
|
||||
// we can reconnect and everything should be restored.
|
||||
ConnectToCustomBlockByName(customBlockNodeName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
// our e_targetBlockNode is unsafe here, so we build w/our serialization info and hope for the best!
|
||||
BuildSlot();
|
||||
base.UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
void BuildSlot()
|
||||
{
|
||||
switch (serializedType)
|
||||
{
|
||||
case BlockNode.CustomBlockType.Float:
|
||||
AddSlot(new Vector1MaterialSlot(0, "Out", "Out", SlotType.Output, default(float), ShaderStageCapability.Fragment));
|
||||
break;
|
||||
case BlockNode.CustomBlockType.Vector2:
|
||||
AddSlot(new Vector2MaterialSlot(0, "Out", "Out", SlotType.Output, default(Vector2), ShaderStageCapability.Fragment));
|
||||
break;
|
||||
case BlockNode.CustomBlockType.Vector3:
|
||||
AddSlot(new Vector3MaterialSlot(0, "Out", "Out", SlotType.Output, default(Vector3), ShaderStageCapability.Fragment));
|
||||
break;
|
||||
case BlockNode.CustomBlockType.Vector4:
|
||||
AddSlot(new Vector4MaterialSlot(0, "Out", "Out", SlotType.Output, default(Vector4), ShaderStageCapability.Fragment));
|
||||
break;
|
||||
}
|
||||
RemoveSlotsNameNotMatching(new[] { 0 });
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotid)
|
||||
{
|
||||
// Awkward case where current preview generation code does not use the Output for the all/isfinite preview for self.
|
||||
// GetOutputForSlot does _not_ make use of GetVariableNameForSlot in any way, so this is just to prevent disrupting
|
||||
// any existing expected behavior in the preview.
|
||||
if (CustomInterpolatorUtils.generatorNodeOnly)
|
||||
{
|
||||
var slotRef = GetSlotReference(0);
|
||||
return GetOutputForSlot(slotRef, slotRef.slot.concreteValueType, GenerationMode.Preview);
|
||||
}
|
||||
return "float4(1,0,1,1)";
|
||||
}
|
||||
|
||||
protected internal override string GetOutputForSlot(SlotReference fromSocketRef, ConcreteSlotValueType valueType, GenerationMode generationMode)
|
||||
{
|
||||
// check to see if we can inline a value.
|
||||
List<PreviewProperty> props = new List<PreviewProperty>();
|
||||
e_targetBlockNode?.CollectPreviewMaterialProperties(props);
|
||||
|
||||
// if the cib is inActive, this node still might be in an active branch.
|
||||
bool isActive = e_targetBlockNode?.isActive ?? false;
|
||||
|
||||
// if the cib has no input node, we can use the input property to inline a magic value.
|
||||
bool canInline = e_targetBlockNode?.GetInputNodeFromSlot(0) == null && props.Count != 0;
|
||||
|
||||
// vector width of target slot
|
||||
int toWidth = SlotTypeToWidth(valueType);
|
||||
|
||||
string finalResult = "";
|
||||
|
||||
// If cib is inactive (or doesn't exist), then we default to black (as is the case for other nodes).
|
||||
if (!isActive || CustomInterpolatorUtils.generatorSkipFlag)
|
||||
{
|
||||
finalResult = ConvertVector("$precision4(0,0,0,0)", 4, toWidth);
|
||||
}
|
||||
// cib has no input; we can directly use the inline value instead.
|
||||
else if (canInline)
|
||||
{
|
||||
Vector4 v = default;
|
||||
if (props[0].propType != PropertyType.Float)
|
||||
v = props[0].vector4Value;
|
||||
|
||||
int outWidth = 4;
|
||||
string result;
|
||||
switch (props[0].propType)
|
||||
{
|
||||
case PropertyType.Float:
|
||||
result = $" $precision1({props[0].floatValue}) ";
|
||||
outWidth = 1;
|
||||
break;
|
||||
default:
|
||||
result = $" $precision4({v.x},{v.y},{v.z},{v.w}) ";
|
||||
outWidth = 4;
|
||||
break;
|
||||
}
|
||||
finalResult = ConvertVector(result, outWidth, toWidth);
|
||||
}
|
||||
// Preview Node doesn't support CI, but we can fake it by asking the cib's source input for it's value instead.
|
||||
else if (CustomInterpolatorUtils.generatorNodeOnly)
|
||||
{
|
||||
var sourceSlot = FindSourceSlot(out var found);
|
||||
// CIB's type needs to constrain the incoming value (eg. vec2(out)->float(cib) | float(cin)->vec2(in))
|
||||
// If we didn't do this next line, we'd get vec2(out)->vec2(in), which would ignore the truncation in the preview.
|
||||
var result = sourceSlot.node.GetOutputForSlot(sourceSlot, FindSlot<MaterialSlot>(0).concreteValueType, GenerationMode.Preview);
|
||||
finalResult = ConvertVector(result, (int)e_targetBlockNode.customWidth, toWidth);
|
||||
}
|
||||
// If we made it this far, then cib is in a valid and meaningful configuration in the SDI struct.
|
||||
else
|
||||
{
|
||||
// pull directly out of the SDI and just use it.
|
||||
var result = string.Format("IN.{0}", customBlockNodeName);
|
||||
finalResult = ConvertVector(result, (int)e_targetBlockNode.customWidth, toWidth);
|
||||
}
|
||||
return finalResult.Replace(PrecisionUtil.Token, concretePrecision.ToShaderString());
|
||||
}
|
||||
|
||||
SlotReference FindSourceSlot(out bool found)
|
||||
{
|
||||
try
|
||||
{
|
||||
found = true;
|
||||
return owner.GetEdges(e_targetBlockNode).First().outputSlot;
|
||||
}
|
||||
catch
|
||||
{
|
||||
found = false;
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
private static int SlotTypeToWidth(ConcreteSlotValueType valueType)
|
||||
{
|
||||
switch (valueType)
|
||||
{
|
||||
case ConcreteSlotValueType.Boolean:
|
||||
case ConcreteSlotValueType.Vector1: return 1;
|
||||
case ConcreteSlotValueType.Vector2: return 2;
|
||||
case ConcreteSlotValueType.Vector3: return 3;
|
||||
default: return 4;
|
||||
}
|
||||
}
|
||||
|
||||
private static string ConvertVector(string name, int fromLen, int toLen)
|
||||
{
|
||||
if (fromLen == toLen)
|
||||
return name;
|
||||
|
||||
var key = new char[] { 'x', 'y', 'z', 'w' };
|
||||
|
||||
string begin = $"$precision{toLen}({name}.";
|
||||
var mid = "";
|
||||
string end = ")";
|
||||
|
||||
if (toLen == 4)
|
||||
{
|
||||
// We assume homogenous coordinates for some reason.
|
||||
end = ", 1.0)";
|
||||
toLen -= 1;
|
||||
}
|
||||
|
||||
if (fromLen == 1)
|
||||
{
|
||||
// we expand floats for each component for some reason.
|
||||
fromLen = toLen;
|
||||
key = new char[] { 'x', 'x', 'x' };
|
||||
}
|
||||
|
||||
// expand the swizzle
|
||||
int swizzLen = Math.Min(fromLen, toLen);
|
||||
for (int i = 0; i < swizzLen; ++i)
|
||||
mid += key[i];
|
||||
|
||||
// fill gaps
|
||||
for (int i = fromLen; i < toLen; ++i)
|
||||
mid += ", 0.0";
|
||||
|
||||
// float<toLen>(<name>.<swizz>, <gap...>, 1.0)"
|
||||
return $"({begin}{mid}{end})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0ccc92de4363bc249858ecefc3a07775
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5e9138df313dc9e4fa20f92625c26b59
|
||||
folderAsset: yes
|
||||
timeCreated: 1495527166
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,36 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Geometry", "Bitangent Vector")]
|
||||
class BitangentVectorNode : GeometryNode, IMayRequireBitangent
|
||||
{
|
||||
public const int kOutputSlotId = 0;
|
||||
public const string kOutputSlotName = "Out";
|
||||
|
||||
public BitangentVectorNode()
|
||||
{
|
||||
name = "Bitangent Vector";
|
||||
synonyms = new string[] { "binormal" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector3MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, new Vector4(0, 0, 1)));
|
||||
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.BiTangent));
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
|
||||
{
|
||||
return space.ToNeededCoordinateSpace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 25ded6c13e7523d48935f8bd1b9afcb6
|
||||
timeCreated: 1481041579
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,34 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Geometry", "Instance ID")]
|
||||
class InstanceIDNode : CodeFunctionNode
|
||||
{
|
||||
public override bool hasPreview { get { return false; } }
|
||||
|
||||
public InstanceIDNode()
|
||||
{
|
||||
name = "Instance ID";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("UnityGetInstanceID", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string UnityGetInstanceID([Slot(0, Binding.None)] out Vector1 Out)
|
||||
{
|
||||
return
|
||||
@"
|
||||
{
|
||||
#if UNITY_ANY_INSTANCING_ENABLED
|
||||
Out = unity_InstanceID;
|
||||
#else
|
||||
Out = 0;
|
||||
#endif
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 215e6221fbd6f9a4bbd14e951c9575d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,37 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[FormerName("UnityEngine.MaterialGraph.NormalNode")]
|
||||
[Title("Input", "Geometry", "Normal Vector")]
|
||||
class NormalVectorNode : GeometryNode, IMayRequireNormal
|
||||
{
|
||||
public const int kOutputSlotId = 0;
|
||||
public const string kOutputSlotName = "Out";
|
||||
|
||||
public NormalVectorNode()
|
||||
{
|
||||
name = "Normal Vector";
|
||||
synonyms = new string[] { "surface direction" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector3MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, new Vector4(0, 0, 1)));
|
||||
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Normal));
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
|
||||
{
|
||||
return space.ToNeededCoordinateSpace();
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue