Tim Cooper
9 年前
当前提交
404ea34c
共有 136 个文件被更改,包括 155 次插入 和 3093 次删除
-
5UnityProject/Assets/UnityShaderEditor/Editor/Source/AbstractMaterialGraph.cs
-
9UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/DrawableMaterialNode.cs
-
5UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/MaterialGraphDataSource.cs
-
2UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/BaseLightFunction.cs
-
7UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/AbstractMaterialNode.cs
-
1UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Function2Input.cs
-
1UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MaterialSlot.cs
-
5UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PixelShaderNode.cs
-
1UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector4Node.cs
-
5UnityProject/Assets/UnityShaderEditor/Editor/Source/PixelGraph.cs
-
4UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/Edge.cs
-
2UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/GUIModificationType.cs
-
20UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/NodeUtils.cs
-
49UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/SerializableGraph.cs
-
30UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/SerializableNode.cs
-
4UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/SerializableSlot.cs
-
11UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/SlotReference.cs
-
2UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/SlotType.cs
-
2UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/ListPool.cs
-
2UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/Logging.cs
-
2UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/ObjectPool.cs
-
3UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/SerializationHelper.cs
-
3UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/ShaderGenerator.cs
-
1UnityProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/AbstractMaterialGraphTests.cs
-
1UnityProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/SerializedGraphTests.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/IEdge.cs
-
19UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/IGraph.cs
-
24UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/INode.cs
-
10UnityProject/Assets/UnityShaderEditor/Editor/Source/SerializableGraph/ISlot.cs
-
49UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/SimpleSpecularFunction.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/SimpleSpecularFunction.cs.meta
-
48UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/WrapLambertFunction.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/WrapLambertFunction.cs.meta
-
30UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/AbsoluteNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/AbsoluteNode.cs.meta
-
819UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BaseMaterialNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BaseMaterialNode.cs.meta
-
76UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BlendNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BlendNode.cs.meta
-
30UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ClampNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ClampNode.cs.meta
-
74UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ColorNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ColorNode.cs.meta
-
72UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ColorizeNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ColorizeNode.cs.meta
-
124UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/CombineNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/CombineNode.cs.meta
-
30UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/DivNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/DivNode.cs.meta
-
33UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/DotNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/DotNode.cs.meta
-
47UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Extensions.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Extensions.cs.meta
-
31UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/FresnelNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/FresnelNode.cs.meta
-
73UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Function1Input.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Function1Input.cs.meta
-
132UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Function3Input.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Function3Input.cs.meta
-
84UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/FunctionMultiInput.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/FunctionMultiInput.cs.meta
-
96UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/KaleidoscopeNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/KaleidoscopeNode.cs.meta
-
14UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/LengthNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/LengthNode.cs.meta
-
102UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MandelbrotNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MandelbrotNode.cs.meta
-
14UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MaxNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MaxNode.cs.meta
-
14UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MinNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MinNode.cs.meta
-
35UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MultiplyNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MultiplyNode.cs.meta
-
36UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/NormalNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/NormalNode.cs.meta
-
14UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/NormalizeNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/NormalizeNode.cs.meta
-
104UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PerlinNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PerlinNode.cs.meta
-
16UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PowerNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PowerNode.cs.meta
-
30UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/QuantizeNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/QuantizeNode.cs.meta
-
38UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ReflectNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ReflectNode.cs.meta
-
38UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ScreenPosNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ScreenPosNode.cs.meta
-
14UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SinNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SinNode.cs.meta
-
32UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SinTimeNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SinTimeNode.cs.meta
-
30UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SmoothStepNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SmoothStepNode.cs.meta
-
42UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SubGraphIOBaseNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SubGraphIOBaseNode.cs.meta
-
80UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SubGraphInputsNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SubGraphInputsNode.cs.meta
-
208UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SubGraphNode.cs
-
8UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SubGraphNode.cs.meta
-
21UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SubGraphOutputsNode.cs
|
|||
namespace UnityEditor.Graphing |
|||
{ |
|||
public interface IEdge |
|||
{ |
|||
SlotReference outputSlot { get; } |
|||
SlotReference inputSlot { get; } |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace UnityEditor.Graphing |
|||
{ |
|||
public interface IGraph |
|||
{ |
|||
IEnumerable<INode> nodes { get; } |
|||
IEnumerable<IEdge> edges { get; } |
|||
void AddNode(INode node); |
|||
void RemoveNode(INode node); |
|||
IEdge Connect(SlotReference fromSlotRef, SlotReference toSlotRef); |
|||
void RemoveEdge(IEdge e); |
|||
void RemoveElements(IEnumerable<INode> nodes, IEnumerable<IEdge> edges); |
|||
INode GetNodeFromGuid(Guid guid); |
|||
IEnumerable<IEdge> GetEdges(SlotReference s); |
|||
void ValidateGraph(); |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Graphing |
|||
{ |
|||
public interface INode |
|||
{ |
|||
IGraph owner { get; set; } |
|||
Guid guid { get; } |
|||
string name { get; set; } |
|||
bool canDeleteNode { get; } |
|||
Rect position { get; set; } |
|||
IEnumerable<ISlot> inputSlots { get; } |
|||
IEnumerable<ISlot> outputSlots { get; } |
|||
IEnumerable<ISlot> slots { get; } |
|||
void AddSlot(ISlot slot); |
|||
void RemoveSlot(string name); |
|||
SlotReference GetSlotReference(string name); |
|||
ISlot FindSlot(string name); |
|||
ISlot FindInputSlot(string name); |
|||
ISlot FindOutputSlot(string name); |
|||
} |
|||
} |
|
|||
namespace UnityEditor.Graphing |
|||
{ |
|||
public interface ISlot |
|||
{ |
|||
string name { get; } |
|||
string displayName { get; set; } |
|||
bool isInputSlot { get; } |
|||
bool isOutputSlot { get; } |
|||
} |
|||
} |
|
|||
using UnityEditor.Graphs; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
class SimpleSpecularFunction : BaseLightFunction |
|||
{ |
|||
public const string kAlbedoSlotName = "Albedo"; |
|||
public const string kAlphaSlotName = "Alpha"; |
|||
|
|||
public override string GetLightFunctionName() { return "SimpleSpecular"; } |
|||
public override string GetSurfaceOutputStructureName() {return "SurfaceOutput";} |
|||
|
|||
public override void GenerateLightFunctionBody(ShaderGenerator visitor) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
outputString.AddShaderChunk("half4 Lighting" + GetLightFunctionName() + " (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("half3 h = normalize (lightDir + viewDir);", false); |
|||
outputString.AddShaderChunk("half diff = max (0, dot (s.Normal, lightDir));", false); |
|||
outputString.AddShaderChunk("half nh = max (0, dot (s.Normal, h));", false); |
|||
outputString.AddShaderChunk("half spec = pow (nh, 48.0);", false); |
|||
outputString.AddShaderChunk("half4 c; c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2);", false); |
|||
outputString.AddShaderChunk("c.a = s.Alpha;", false); |
|||
outputString.AddShaderChunk("return c;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
|
|||
public override void DoSlotsForConfiguration(PixelShaderNode node) |
|||
{ |
|||
node.AddSlot(new MaterialGraphSlot(new Slot(name: SlotType.InputSlot, slotType: kAlbedoSlotName), SlotValueType.Vector3)); |
|||
node.AddSlot(new MaterialGraphSlot(new Slot(name: SlotType.InputSlot, slotType: kNormalSlotName), SlotValueType.Vector3)); |
|||
node.AddSlot(new MaterialGraphSlot(new Slot(name: SlotType.InputSlot, slotType: kAlphaSlotName), SlotValueType.Vector1)); |
|||
|
|||
// clear out slot names that do not match the slots
|
|||
// we support
|
|||
node.RemoveSlotsNameNotMatching( |
|||
new[] |
|||
{ |
|||
kAlbedoSlotName, |
|||
kNormalSlotName, |
|||
kAlphaSlotName |
|||
}); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 241a90386f89a7f4da1ca187a0dd3eb2 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
class WrapLambertFunction : BaseLightFunction |
|||
{ |
|||
public const string kAlbedoSlotName = "Albedo"; |
|||
public const string kAlphaSlotName = "Alpha"; |
|||
|
|||
public override string GetLightFunctionName() { return "WrapLambert"; } |
|||
|
|||
public override string GetSurfaceOutputStructureName() { return "SurfaceOutput"; } |
|||
|
|||
public override void GenerateLightFunctionBody(ShaderGenerator visitor) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
outputString.AddShaderChunk("half4 Lighting" + GetLightFunctionName() + " (SurfaceOutput s, half3 lightDir, half atten)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("half NdotL = dot (s.Normal, lightDir);", false); |
|||
outputString.AddShaderChunk("half diff = NdotL * 0.5 + 0.5;", false); |
|||
outputString.AddShaderChunk("half4 c;", false); |
|||
outputString.AddShaderChunk("c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);", false); |
|||
outputString.AddShaderChunk("c.a = s.Alpha;", false); |
|||
outputString.AddShaderChunk("return c;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
|
|||
public override void DoSlotsForConfiguration(PixelShaderNode node) |
|||
{ |
|||
node.AddSlot(new MaterialGraphSlot(new Slot(name: SlotType.InputSlot, slotType: kAlbedoSlotName), SlotValueType.Vector3)); |
|||
node.AddSlot(new MaterialGraphSlot(new Slot(name: SlotType.InputSlot, slotType: kNormalSlotName), SlotValueType.Vector3)); |
|||
node.AddSlot(new MaterialGraphSlot(new Slot(name: SlotType.InputSlot, slotType: kAlphaSlotName), SlotValueType.Vector1)); |
|||
|
|||
// clear out slot names that do not match the slots
|
|||
// we support
|
|||
node.RemoveSlotsNameNotMatching(new[] |
|||
{ |
|||
kAlbedoSlotName, |
|||
kNormalSlotName, |
|||
kAlphaSlotName |
|||
}); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 4ed268fcd50cca74489ba39307e33e63 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Absolute Node")] |
|||
class AbsoluteNode : Function1Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "AbsoluteNode"; |
|||
base.OnCreate(); |
|||
} |
|||
|
|||
protected override string GetFunctionName() {return "unity_absolute_" + precision; } |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + outputDimension + " unity_absolute_" + precision + " (" + precision + outputDimension + " arg1)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("return abs(arg1);", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 4b496ffd32c22d94bb525897d152da05 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using UnityEditorInternal; |
|||
using UnityEngine; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Serializable] |
|||
public abstract class BaseMaterialNode : IGenerateProperties, ISerializationCallbackReceiver |
|||
{ |
|||
[Serializable] |
|||
protected class NodeSpecificData |
|||
{ } |
|||
|
|||
public delegate void NeedsRepaint(); |
|||
|
|||
private const int kPreviewWidth = 64; |
|||
private const int kPreviewHeight = 64; |
|||
|
|||
private static readonly Mesh[] s_Meshes = {null, null, null, null}; |
|||
|
|||
[SerializeField] |
|||
private DrawMode m_DrawMode = DrawMode.Full; |
|||
|
|||
protected PreviewMode m_GeneratedShaderMode = PreviewMode.Preview2D; |
|||
|
|||
[NonSerialized] |
|||
private Guid m_GUID; |
|||
|
|||
[SerializeField] |
|||
private string m_GUIDSerialized; |
|||
|
|||
[NonSerialized] |
|||
private bool m_HasError; |
|||
|
|||
[SerializeField] |
|||
private string m_LastShader; |
|||
|
|||
[SerializeField] |
|||
private string m_Name; |
|||
|
|||
[SerializeField] |
|||
private Rect m_Position; |
|||
|
|||
[NonSerialized] |
|||
private Material m_PreviewMaterial; |
|||
|
|||
[NonSerialized] |
|||
private Shader m_PreviewShader; |
|||
|
|||
[SerializeField] |
|||
private List<Slot> m_Slots = new List<Slot>(); |
|||
|
|||
public NeedsRepaint onNeedsRepaint; |
|||
|
|||
protected BaseMaterialNode(BaseMaterialGraph theOwner) |
|||
{ |
|||
owner = theOwner; |
|||
m_GUID = Guid.NewGuid(); |
|||
} |
|||
|
|||
public Guid guid |
|||
{ |
|||
get { return m_GUID; } |
|||
} |
|||
|
|||
public string name |
|||
{ |
|||
get { return m_Name; } |
|||
set { m_Name = value; } |
|||
} |
|||
|
|||
public string precision |
|||
{ |
|||
get { return "half"; } |
|||
} |
|||
|
|||
public string[] m_PrecisionNames = { "half" }; |
|||
|
|||
public BaseMaterialGraph owner { get; set; } |
|||
|
|||
public IEnumerable<Slot> inputSlots |
|||
{ |
|||
get { return m_Slots.Where(x => x.isInputSlot); } |
|||
} |
|||
|
|||
public IEnumerable<Slot> outputSlots |
|||
{ |
|||
get { return m_Slots.Where(x => x.isOutputSlot); } |
|||
} |
|||
|
|||
public IEnumerable<Slot> slots |
|||
{ |
|||
get { return m_Slots; } |
|||
} |
|||
|
|||
// Nodes that want to have a preview area can override this and return true
|
|||
public virtual bool hasPreview |
|||
{ |
|||
get { return false; } |
|||
} |
|||
|
|||
public virtual PreviewMode previewMode |
|||
{ |
|||
get { return PreviewMode.Preview2D; } |
|||
} |
|||
|
|||
public DrawMode drawMode |
|||
{ |
|||
get { return m_DrawMode; } |
|||
set { m_DrawMode = value; } |
|||
} |
|||
|
|||
protected virtual bool generateDefaultInputs |
|||
{ |
|||
get { return true; } |
|||
} |
|||
|
|||
public virtual bool canDeleteNode |
|||
{ |
|||
get { return true; } |
|||
} |
|||
|
|||
public Material previewMaterial |
|||
{ |
|||
get |
|||
{ |
|||
if (m_PreviewMaterial == null) |
|||
{ |
|||
m_PreviewMaterial = new Material(m_PreviewShader) {hideFlags = HideFlags.HideInHierarchy}; |
|||
m_PreviewMaterial.hideFlags = HideFlags.HideInHierarchy; |
|||
} |
|||
return m_PreviewMaterial; |
|||
} |
|||
} |
|||
|
|||
protected virtual int previewWidth |
|||
{ |
|||
get { return kPreviewWidth; } |
|||
} |
|||
|
|||
protected virtual int previewHeight |
|||
{ |
|||
get { return kPreviewHeight; } |
|||
} |
|||
|
|||
public bool hasError |
|||
{ |
|||
get |
|||
{ |
|||
return m_HasError; |
|||
} |
|||
protected set |
|||
{ |
|||
if (m_HasError != value) |
|||
{ |
|||
m_HasError = value; |
|||
ExecuteRepaint(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public Rect position |
|||
{ |
|||
get |
|||
{ |
|||
return m_Position; |
|||
} |
|||
|
|||
set |
|||
{ |
|||
m_Position = value; |
|||
} |
|||
} |
|||
|
|||
public virtual void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode) |
|||
{} |
|||
|
|||
public virtual void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode, ConcreteSlotValueType slotValueType) |
|||
{ |
|||
if (!generateDefaultInputs) |
|||
return; |
|||
|
|||
if (!generationMode.IsPreview()) |
|||
return; |
|||
|
|||
foreach (var inputSlot in inputSlots) |
|||
{ |
|||
var edges = owner.GetEdges(inputSlot); |
|||
if (edges.Any()) |
|||
continue; |
|||
|
|||
inputSlot.GeneratePropertyUsages(visitor, generationMode, inputSlot.concreteValueType, this); |
|||
} |
|||
} |
|||
|
|||
public virtual void OnBeforeSerialize() |
|||
{ |
|||
m_GUIDSerialized = m_GUID.ToString(); |
|||
} |
|||
|
|||
public virtual void OnAfterDeserialize() |
|||
{ |
|||
if (!string.IsNullOrEmpty(m_GUIDSerialized)) |
|||
m_GUID = new Guid(m_GUIDSerialized); |
|||
else |
|||
m_GUID = Guid.NewGuid(); |
|||
|
|||
//patch up the slot owner reference
|
|||
foreach (var slot in slots) |
|||
slot.owner = this; |
|||
} |
|||
|
|||
public virtual float GetNodeUIHeight(float width) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
public virtual GUIModificationType NodeUI(Rect drawArea) |
|||
{ |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
protected virtual void OnPreviewGUI() |
|||
{ |
|||
if (!ShaderUtil.hardwareSupportsRectRenderTexture) |
|||
return; |
|||
|
|||
GUILayout.BeginHorizontal(GUILayout.MinWidth(previewWidth + 10), GUILayout.MinWidth(previewHeight + 10)); |
|||
GUILayout.FlexibleSpace(); |
|||
var rect = GUILayoutUtility.GetRect(previewWidth, previewHeight, GUILayout.ExpandWidth(false)); |
|||
var preview = RenderPreview(rect); |
|||
GUILayout.FlexibleSpace(); |
|||
GUILayout.EndHorizontal(); |
|||
GL.sRGBWrite = QualitySettings.activeColorSpace == ColorSpace.Linear; |
|||
GUI.DrawTexture(rect, preview, ScaleMode.StretchToFill, false); |
|||
GL.sRGBWrite = false; |
|||
} |
|||
|
|||
public Slot FindInputSlot(string name) |
|||
{ |
|||
var slot = m_Slots.FirstOrDefault(x => x.isInputSlot && x.name == name); |
|||
if (slot == null) |
|||
Debug.LogError("Input slot: " + name + " could be found on node " + GetOutputVariableNameForNode()); |
|||
return slot; |
|||
} |
|||
|
|||
public Slot FindOutputSlot(string name) |
|||
{ |
|||
var slot = m_Slots.FirstOrDefault(x => x.isOutputSlot && x.name == name); |
|||
if (slot == null) |
|||
Debug.LogError("Output slot: " + name + " could be found on node " + GetOutputVariableNameForNode()); |
|||
return slot; |
|||
} |
|||
|
|||
protected string GetSlotValue(Slot inputSlot, GenerationMode generationMode) |
|||
{ |
|||
var edges = owner.GetEdges(inputSlot).ToArray(); |
|||
|
|||
if (edges.Length > 0) |
|||
{ |
|||
var fromSocketRef = edges[0].outputSlot; |
|||
var fromNode = owner.GetNodeFromGUID(fromSocketRef.nodeGuid); |
|||
var slot = fromNode.FindOutputSlot(fromSocketRef.slotName); |
|||
|
|||
return ShaderGenerator.AdaptNodeOutput(this, slot, generationMode, inputSlot.concreteValueType); |
|||
} |
|||
|
|||
return inputSlot.GetDefaultValue(generationMode, inputSlot.concreteValueType, this); |
|||
} |
|||
|
|||
public void RemoveSlotsNameNotMatching(string[] slotNames) |
|||
{ |
|||
var invalidSlots = m_Slots.Select(x => x.name).Except(slotNames); |
|||
|
|||
foreach (var invalidSlot in invalidSlots.ToList()) |
|||
{ |
|||
Debug.LogWarningFormat("Removing Invalid Slot: {0}", invalidSlot); |
|||
RemoveSlot(invalidSlot); |
|||
} |
|||
} |
|||
|
|||
private ConcreteSlotValueType FindCommonChannelType(ConcreteSlotValueType @from, ConcreteSlotValueType to) |
|||
{ |
|||
if (ImplicitConversionExists(@from, to)) |
|||
return to; |
|||
|
|||
return ConcreteSlotValueType.Error; |
|||
} |
|||
|
|||
private static ConcreteSlotValueType ToConcreteType(SlotValueType svt) |
|||
{ |
|||
switch (svt) |
|||
{ |
|||
case SlotValueType.Vector1: |
|||
return ConcreteSlotValueType.Vector1; |
|||
case SlotValueType.Vector2: |
|||
return ConcreteSlotValueType.Vector2; |
|||
case SlotValueType.Vector3: |
|||
return ConcreteSlotValueType.Vector3; |
|||
case SlotValueType.Vector4: |
|||
return ConcreteSlotValueType.Vector4; |
|||
} |
|||
return ConcreteSlotValueType.Error; |
|||
} |
|||
|
|||
private static bool ImplicitConversionExists(ConcreteSlotValueType from, ConcreteSlotValueType to) |
|||
{ |
|||
return from >= to || from == ConcreteSlotValueType.Vector1; |
|||
} |
|||
|
|||
protected virtual ConcreteSlotValueType ConvertDynamicInputTypeToConcrete(IEnumerable<ConcreteSlotValueType> inputTypes) |
|||
{ |
|||
var concreteSlotValueTypes = inputTypes as IList<ConcreteSlotValueType> ?? inputTypes.ToList(); |
|||
if (concreteSlotValueTypes.Any(x => x == ConcreteSlotValueType.Error)) |
|||
return ConcreteSlotValueType.Error; |
|||
|
|||
var inputTypesDistinct = concreteSlotValueTypes.Distinct().ToList(); |
|||
switch (inputTypesDistinct.Count) |
|||
{ |
|||
case 0: |
|||
return ConcreteSlotValueType.Vector1; |
|||
case 1: |
|||
return inputTypesDistinct.FirstOrDefault(); |
|||
default: |
|||
// find the 'minumum' channel width excluding 1 as it can promote
|
|||
inputTypesDistinct.RemoveAll(x => x == ConcreteSlotValueType.Vector1); |
|||
var ordered = inputTypesDistinct.OrderBy(x => x); |
|||
if (ordered.Any()) |
|||
return ordered.FirstOrDefault(); |
|||
break; |
|||
} |
|||
return ConcreteSlotValueType.Error; |
|||
} |
|||
|
|||
public void ValidateNode() |
|||
{ |
|||
var isInError = false; |
|||
|
|||
// all children nodes needs to be updated first
|
|||
// so do that here
|
|||
foreach (var inputSlot in inputSlots) |
|||
{ |
|||
var edges = owner.GetEdges(inputSlot); |
|||
foreach (var edge in edges) |
|||
{ |
|||
var fromSocketRef = edge.outputSlot; |
|||
var outputNode = owner.GetNodeFromGUID(fromSocketRef.nodeGuid); |
|||
|
|||
outputNode.ValidateNode(); |
|||
if (outputNode.hasError) |
|||
isInError = true; |
|||
} |
|||
} |
|||
|
|||
var dynamicInputSlotsToCompare = new Dictionary<Slot, ConcreteSlotValueType>(); |
|||
var skippedDynamicSlots = new List<Slot>(); |
|||
|
|||
// iterate the input slots
|
|||
foreach (var inputSlot in inputSlots) |
|||
{ |
|||
var inputType = inputSlot.valueType; |
|||
// if there is a connection
|
|||
var edges = owner.GetEdges(inputSlot).ToList(); |
|||
if (!edges.Any()) |
|||
{ |
|||
if (inputType != SlotValueType.Dynamic) |
|||
inputSlot.concreteValueType = ToConcreteType(inputType); |
|||
else |
|||
skippedDynamicSlots.Add(inputSlot); |
|||
continue; |
|||
} |
|||
|
|||
// get the output details
|
|||
var outputSlotRef = edges[0].outputSlot; |
|||
var outputNode = owner.GetNodeFromGUID(outputSlotRef.nodeGuid); |
|||
var outputSlot = outputNode.FindOutputSlot(outputSlotRef.slotName); |
|||
var outputConcreteType = outputSlot.concreteValueType; |
|||
|
|||
// if we have a standard connection... just check the types work!
|
|||
if (inputType != SlotValueType.Dynamic) |
|||
{ |
|||
var inputConcreteType = ToConcreteType(inputType); |
|||
inputSlot.concreteValueType = FindCommonChannelType(outputConcreteType, inputConcreteType); |
|||
continue; |
|||
} |
|||
|
|||
// dynamic input... depends on output from other node.
|
|||
// we need to compare ALL dynamic inputs to make sure they
|
|||
// are compatable.
|
|||
dynamicInputSlotsToCompare.Add(inputSlot, outputConcreteType); |
|||
} |
|||
|
|||
// we can now figure out the dynamic slotType
|
|||
// from here set all the
|
|||
var dynamicType = ConvertDynamicInputTypeToConcrete(dynamicInputSlotsToCompare.Values); |
|||
foreach (var dynamicKvP in dynamicInputSlotsToCompare) |
|||
dynamicKvP.Key.concreteValueType= dynamicType; |
|||
foreach (var skippedSlot in skippedDynamicSlots) |
|||
skippedSlot.concreteValueType = dynamicType; |
|||
|
|||
var inputError = inputSlots.Any(x => x.concreteValueType == ConcreteSlotValueType.Error); |
|||
|
|||
// configure the output slots now
|
|||
// their slotType will either be the default output slotType
|
|||
// or the above dynanic slotType for dynamic nodes
|
|||
// or error if there is an input error
|
|||
foreach (var outputSlot in outputSlots) |
|||
{ |
|||
if (inputError) |
|||
{ |
|||
outputSlot.concreteValueType = ConcreteSlotValueType.Error; |
|||
continue; |
|||
} |
|||
|
|||
if (outputSlot.valueType == SlotValueType.Dynamic) |
|||
{ |
|||
outputSlot.concreteValueType = dynamicType; |
|||
continue; |
|||
} |
|||
outputSlot.concreteValueType = ToConcreteType(outputSlot.valueType); |
|||
} |
|||
|
|||
isInError |= inputError; |
|||
isInError |= outputSlots.Any(x => x.concreteValueType == ConcreteSlotValueType.Error); |
|||
isInError |= CalculateNodeHasError(); |
|||
hasError = isInError; |
|||
|
|||
if (!hasError) |
|||
{ |
|||
previewShaderNeedsUpdate = true; |
|||
} |
|||
} |
|||
|
|||
public bool previewShaderNeedsUpdate { get; set; } |
|||
|
|||
//True if error
|
|||
protected virtual bool CalculateNodeHasError() |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public static string ConvertConcreteSlotValueTypeToString(ConcreteSlotValueType slotValue) |
|||
{ |
|||
switch (slotValue) |
|||
{ |
|||
case ConcreteSlotValueType.Vector1: |
|||
return string.Empty; |
|||
case ConcreteSlotValueType.Vector2: |
|||
return "2"; |
|||
case ConcreteSlotValueType.Vector3: |
|||
return "3"; |
|||
case ConcreteSlotValueType.Vector4: |
|||
return "4"; |
|||
default: |
|||
return "Error"; |
|||
} |
|||
} |
|||
|
|||
public virtual bool OnGUI() |
|||
{ |
|||
GUILayout.Label("Slot Defaults", EditorStyles.boldLabel); |
|||
var modified = false; |
|||
foreach (var slot in inputSlots) |
|||
{ |
|||
if (!owner.GetEdges(slot).Any()) |
|||
modified |= DoSlotUI(this, slot); |
|||
} |
|||
|
|||
return modified; |
|||
} |
|||
|
|||
public static bool DoSlotUI(BaseMaterialNode node, Slot slot) |
|||
{ |
|||
GUILayout.BeginHorizontal( /*EditorStyles.inspectorBig*/); |
|||
GUILayout.BeginVertical(); |
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Label("Slot " + slot.name, EditorStyles.largeLabel); |
|||
GUILayout.FlexibleSpace(); |
|||
GUILayout.EndHorizontal(); |
|||
GUILayout.EndVertical(); |
|||
GUILayout.EndHorizontal(); |
|||
|
|||
return slot.OnGUI(); |
|||
} |
|||
|
|||
public virtual bool DrawSlotDefaultInput(Rect rect, Slot inputSlot) |
|||
{ |
|||
var inputSlotType = inputSlot.concreteValueType; |
|||
return inputSlot.OnGUI(rect, inputSlotType); |
|||
} |
|||
|
|||
public virtual IEnumerable<Slot> GetDrawableInputProxies() |
|||
{ |
|||
return inputSlots.Where(x => !owner.GetEdges(x).Any()); |
|||
} |
|||
|
|||
public void ExecuteRepaint() |
|||
{ |
|||
if (onNeedsRepaint != null) |
|||
onNeedsRepaint(); |
|||
} |
|||
|
|||
|
|||
// CollectDependentNodes looks at the current node and calculates
|
|||
// which nodes further up the tree (parents) would be effected if this node was changed
|
|||
// it also includes itself in this list
|
|||
public IEnumerable<BaseMaterialNode> CollectDependentNodes() |
|||
{ |
|||
var nodeList = new List<BaseMaterialNode>(); |
|||
NodeUtils.CollectDependentNodes(nodeList, this); |
|||
return nodeList; |
|||
} |
|||
|
|||
// CollectDependentNodes looks at the current node and calculates
|
|||
// which child nodes it depends on for it's calculation.
|
|||
// Results are returned depth first so by processing each node in
|
|||
// order you can generate a valid code block.
|
|||
public List<BaseMaterialNode> CollectChildNodesByExecutionOrder(List<BaseMaterialNode> nodeList, Slot slotToUse = null, bool includeSelf = true) |
|||
{ |
|||
if (slotToUse != null && !m_Slots.Contains(slotToUse)) |
|||
{ |
|||
Debug.LogError("Attempting to collect nodes by execution order with an invalid slot on: " + name); |
|||
return nodeList; |
|||
} |
|||
|
|||
NodeUtils.CollectChildNodesByExecutionOrder(nodeList, this, slotToUse); |
|||
|
|||
if (!includeSelf) |
|||
nodeList.Remove(this); |
|||
|
|||
return nodeList; |
|||
} |
|||
|
|||
protected virtual bool UpdatePreviewShader() |
|||
{ |
|||
if (hasError) |
|||
return false; |
|||
|
|||
var resultShader = ShaderGenerator.GeneratePreviewShader(this, out m_GeneratedShaderMode); |
|||
return InternalUpdatePreviewShader(resultShader); |
|||
} |
|||
|
|||
private static bool ShaderHasError(Shader shader) |
|||
{ |
|||
var hasErrorsCall = typeof(ShaderUtil).GetMethod("GetShaderErrorCount", BindingFlags.Static | BindingFlags.NonPublic); |
|||
var result = hasErrorsCall.Invoke(null, new object[] {shader}); |
|||
return (int) result != 0; |
|||
} |
|||
|
|||
protected bool InternalUpdatePreviewShader(string resultShader) |
|||
{ |
|||
MaterialWindow.DebugMaterialGraph("RecreateShaderAndMaterial : " + name + "_" + guid.ToString().Replace("-","_") + "\n" + resultShader); |
|||
|
|||
// workaround for some internal shader compiler weirdness
|
|||
// if we are in error we sometimes to not properly clean
|
|||
// clean out the error flags and will stay in error, even
|
|||
// if we are now valid
|
|||
if (m_PreviewShader && ShaderHasError(m_PreviewShader)) |
|||
{ |
|||
Object.DestroyImmediate(m_PreviewShader, true); |
|||
Object.DestroyImmediate(m_PreviewMaterial, true); |
|||
m_PreviewShader = null; |
|||
m_PreviewMaterial = null; |
|||
} |
|||
|
|||
if (m_PreviewShader == null) |
|||
{ |
|||
m_PreviewShader = ShaderUtil.CreateShaderAsset(resultShader); |
|||
m_PreviewShader.hideFlags = HideFlags.HideInHierarchy; |
|||
m_LastShader = resultShader; |
|||
} |
|||
else |
|||
{ |
|||
if (string.CompareOrdinal(resultShader, m_LastShader) != 0) |
|||
{ |
|||
ShaderUtil.UpdateShaderAsset(m_PreviewShader, resultShader); |
|||
m_LastShader = resultShader; |
|||
} |
|||
} |
|||
|
|||
return !ShaderHasError(m_PreviewShader); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// RenderPreview gets called in OnPreviewGUI. Nodes can override
|
|||
/// RenderPreview and do their own rendering to the render texture
|
|||
/// </summary>
|
|||
public Texture RenderPreview(Rect targetSize) |
|||
{ |
|||
if (hasError) |
|||
return null; |
|||
|
|||
if (previewShaderNeedsUpdate) |
|||
{ |
|||
UpdatePreviewShader(); |
|||
previewShaderNeedsUpdate = false; |
|||
} |
|||
|
|||
UpdatePreviewProperties(); |
|||
|
|||
if (s_Meshes[0] == null) |
|||
{ |
|||
var handleGo = (GameObject) EditorGUIUtility.LoadRequired("Previews/PreviewMaterials.fbx"); |
|||
// @TODO: temp workaround to make it not render in the scene
|
|||
handleGo.SetActive(false); |
|||
foreach (Transform t in handleGo.transform) |
|||
{ |
|||
switch (t.name) |
|||
{ |
|||
case "sphere": |
|||
s_Meshes[0] = ((MeshFilter) t.GetComponent("MeshFilter")).sharedMesh; |
|||
break; |
|||
case "cube": |
|||
s_Meshes[1] = ((MeshFilter) t.GetComponent("MeshFilter")).sharedMesh; |
|||
break; |
|||
case "cylinder": |
|||
s_Meshes[2] = ((MeshFilter) t.GetComponent("MeshFilter")).sharedMesh; |
|||
break; |
|||
case "torus": |
|||
s_Meshes[3] = ((MeshFilter) t.GetComponent("MeshFilter")).sharedMesh; |
|||
break; |
|||
default: |
|||
Debug.Log("Something is wrong, weird object found: " + t.name); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
var previewUtil = owner.previewUtility; |
|||
previewUtil.BeginPreview(targetSize, GUIStyle.none); |
|||
|
|||
if (m_GeneratedShaderMode == PreviewMode.Preview3D) |
|||
{ |
|||
previewUtil.m_Camera.transform.position = -Vector3.forward * 5; |
|||
previewUtil.m_Camera.transform.rotation = Quaternion.identity; |
|||
EditorUtility.SetCameraAnimateMaterialsTime(previewUtil.m_Camera, Time.realtimeSinceStartup); |
|||
var amb = new Color(.2f, .2f, .2f, 0); |
|||
previewUtil.m_Light[0].intensity = 1.0f; |
|||
previewUtil.m_Light[0].transform.rotation = Quaternion.Euler(50f, 50f, 0); |
|||
previewUtil.m_Light[1].intensity = 1.0f; |
|||
|
|||
InternalEditorUtility.SetCustomLighting(previewUtil.m_Light, amb); |
|||
previewUtil.DrawMesh(s_Meshes[0], Vector3.zero, Quaternion.Euler(-20, 0, 0) * Quaternion.Euler(0, 0, 0), previewMaterial, 0); |
|||
var oldFog = RenderSettings.fog; |
|||
Unsupported.SetRenderSettingsUseFogNoDirty(false); |
|||
previewUtil.m_Camera.Render(); |
|||
Unsupported.SetRenderSettingsUseFogNoDirty(oldFog); |
|||
InternalEditorUtility.RemoveCustomLighting(); |
|||
} |
|||
else |
|||
{ |
|||
EditorUtility.UpdateGlobalShaderProperties(Time.realtimeSinceStartup); |
|||
Graphics.Blit(null, previewMaterial); |
|||
} |
|||
return previewUtil.EndPreview(); |
|||
} |
|||
|
|||
private static void SetPreviewMaterialProperty(PreviewProperty previewProperty, Material mat) |
|||
{ |
|||
switch (previewProperty.m_PropType) |
|||
{ |
|||
case PropertyType.Texture2D: |
|||
mat.SetTexture(previewProperty.m_Name, previewProperty.m_Texture); |
|||
break; |
|||
case PropertyType.Color: |
|||
mat.SetColor(previewProperty.m_Name, previewProperty.m_Color); |
|||
break; |
|||
case PropertyType.Vector2: |
|||
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4); |
|||
break; |
|||
case PropertyType.Vector3: |
|||
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4); |
|||
break; |
|||
case PropertyType.Vector4: |
|||
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4); |
|||
break; |
|||
case PropertyType.Float: |
|||
mat.SetFloat(previewProperty.m_Name, previewProperty.m_Float); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
protected virtual void CollectPreviewMaterialProperties(List<PreviewProperty> properties) |
|||
{ |
|||
var validSlots = inputSlots.ToArray(); |
|||
|
|||
for (var index = 0; index < validSlots.Length; index++) |
|||
{ |
|||
var s = validSlots[index]; |
|||
var edges = owner.GetEdges(s); |
|||
if (edges.Any()) |
|||
continue; |
|||
|
|||
var pp = new PreviewProperty |
|||
{ |
|||
m_Name = s.GetInputName(this), |
|||
m_PropType = PropertyType.Vector4, |
|||
m_Vector4 = s.currentValue |
|||
}; |
|||
properties.Add(pp); |
|||
} |
|||
} |
|||
|
|||
public static void UpdateMaterialProperties(BaseMaterialNode target, Material material) |
|||
{ |
|||
var childNodes = ListPool<BaseMaterialNode>.Get(); |
|||
target.CollectChildNodesByExecutionOrder(childNodes); |
|||
|
|||
var pList = ListPool<PreviewProperty>.Get(); |
|||
for (var index = 0; index < childNodes.Count; index++) |
|||
{ |
|||
var node = childNodes[index]; |
|||
node.CollectPreviewMaterialProperties(pList); |
|||
} |
|||
|
|||
foreach (var prop in pList) |
|||
SetPreviewMaterialProperty(prop, material); |
|||
|
|||
ListPool<BaseMaterialNode>.Release(childNodes); |
|||
ListPool<PreviewProperty>.Release(pList); |
|||
} |
|||
|
|||
public void UpdatePreviewProperties() |
|||
{ |
|||
if (!hasPreview) |
|||
return; |
|||
|
|||
UpdateMaterialProperties(this, previewMaterial); |
|||
} |
|||
|
|||
|
|||
public virtual string GetOutputVariableNameForSlot(Slot s, GenerationMode generationMode) |
|||
{ |
|||
if (s.isInputSlot) Debug.LogError("Attempting to use input slot (" + s + ") for output!"); |
|||
if (!m_Slots.Contains(s)) Debug.LogError("Attempting to use slot (" + s + ") for output on a node that does not have this slot!"); |
|||
|
|||
return GetOutputVariableNameForNode() + "_" + s.name; |
|||
} |
|||
|
|||
public virtual string GetOutputVariableNameForNode() |
|||
{ |
|||
return name + "_" + guid.ToString().Replace("-", "_"); |
|||
} |
|||
|
|||
public virtual Vector4 GetNewSlotDefaultValue(SlotValueType type) |
|||
{ |
|||
return Vector4.one; |
|||
} |
|||
|
|||
public void AddSlot(Slot slot) |
|||
{ |
|||
if (slot == null) |
|||
return; |
|||
|
|||
// new slot, just add it, we cool
|
|||
if (!m_Slots.Contains(slot)) |
|||
{ |
|||
m_Slots.Add(slot); |
|||
return; |
|||
} |
|||
|
|||
// old slot found
|
|||
// update the default value, and the slotType!
|
|||
var foundSlots = m_Slots.FindAll(x => x.name == slot.name); |
|||
|
|||
// if we are in a bad state (> 1 slot with same name, just reset).
|
|||
if (foundSlots.Count > 1) |
|||
{ |
|||
Debug.LogWarningFormat("Node {0} has more than one slot with the same name, removing."); |
|||
foundSlots.ForEach(x => m_Slots.Remove(x)); |
|||
m_Slots.Add(slot); |
|||
return; |
|||
} |
|||
|
|||
var foundSlot = foundSlots[0]; |
|||
|
|||
// if the defualt and current are the same, change the current
|
|||
// to the new default.
|
|||
if (foundSlot.defaultValue == foundSlot.currentValue) |
|||
foundSlot.currentValue = slot.defaultValue; |
|||
|
|||
foundSlot.defaultValue = slot.defaultValue; |
|||
foundSlot.valueType = slot.valueType; |
|||
} |
|||
|
|||
public void RemoveSlot(string name) |
|||
{ |
|||
m_Slots.RemoveAll(x => x.name == name); |
|||
} |
|||
|
|||
public string GenerateSlotName(Slot.SlotType type) |
|||
{ |
|||
var slotsToCheck = type == Slot.SlotType.Input ? inputSlots.ToArray() : outputSlots.ToArray(); |
|||
var format = type == Slot.SlotType.Input ? "I{0:00}" : "O{0:00}"; |
|||
var index = slotsToCheck.Count(); |
|||
var slotName = string.Format(format, index); |
|||
if (slotsToCheck.All(x => x.name != slotName)) |
|||
return slotName; |
|||
index = 0; |
|||
do |
|||
{ |
|||
slotName = string.Format(format, index++); |
|||
} while (slotsToCheck.Any(x => x.name == slotName)); |
|||
|
|||
return slotName; |
|||
} |
|||
} |
|||
|
|||
public enum GUIModificationType |
|||
{ |
|||
None, |
|||
Repaint, |
|||
ModelChanged |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a4da4d7c02dcbdd4f9ef2d3b1106879a |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Art/Blend Node")] |
|||
class BlendNode : Function2Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "BlendNode"; |
|||
base.OnCreate(); |
|||
} |
|||
|
|||
public enum Operation |
|||
{ |
|||
Normal, |
|||
Additive, |
|||
} |
|||
|
|||
[SerializeField] |
|||
private Operation m_Operation; |
|||
[SerializeField] |
|||
private float m_Blend = 0.5f; |
|||
|
|||
private static readonly string[] kOpNames = { |
|||
"normal", |
|||
"add" |
|||
}; |
|||
|
|||
protected override string GetFunctionName() { return "unity_blend_" + kOpNames[(int)m_Operation] + "_" + precision; } |
|||
protected override string GetFunctionCallBody(string input1Value, string input2Value) |
|||
{ |
|||
return GetFunctionName() + "(" + input1Value + ", " + input2Value + ", " + m_Blend + ")"; |
|||
} |
|||
|
|||
protected void AddOperationBody(ShaderGenerator visitor, string name, string body, string precision) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
outputString.AddShaderChunk("inline " + precision + outputDimension +" unity_blend_" + name + "_" + precision + " (" + precision + outputDimension + " arg1, " + precision + outputDimension + " arg2, " + precision + " blend)", false); |
|||
outputString.AddShaderChunk("{", false); outputString.Indent(); |
|||
outputString.AddShaderChunk(body, false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
public override float GetNodeUIHeight(float width) |
|||
{ |
|||
return 2.0f * EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public override GUIModificationType NodeUI(Rect drawArea) |
|||
{ |
|||
base.NodeUI(drawArea); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Blend = GUI.HorizontalSlider(new Rect(drawArea.x, drawArea.y, drawArea.width, EditorGUIUtility.singleLineHeight), m_Blend, 0f, 1f); |
|||
m_Operation = (Operation) EditorGUI.EnumPopup(new Rect(drawArea.x, drawArea.y + EditorGUIUtility.singleLineHeight, drawArea.width, EditorGUIUtility.singleLineHeight), m_Operation); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
pixelGraph.RevalidateGraph(); |
|||
return GUIModificationType.Repaint; |
|||
} |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Normal], "return lerp(arg1, arg2, blend);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Additive], "return (arg1 + arg2) * blend;", precision); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 909ffbb62e82bfb4abbeeb93022c6e9b |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Clamp Node")] |
|||
class ClampNode : Function3Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "ClampNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() {return "unity_clamp_" + precision; } |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_clamp_" + precision + " (" + precision + "4 arg1, " + precision + "4 minval, " + precision + "4 maxval)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("return clamp(arg1, minval, maxval);", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b58e88ce87f05b241b7dc5d9a31bac69 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Input/Color Node")] |
|||
class ColorNode : PropertyNode, IGeneratesBodyCode |
|||
{ |
|||
[SerializeField] |
|||
private Color m_Color; |
|||
|
|||
private const string kOutputSlotName = "Color"; |
|||
|
|||
public override void OnCreate() |
|||
{ |
|||
base.OnCreate(); |
|||
name = "ColorNode"; |
|||
} |
|||
|
|||
public override void OnEnable() |
|||
{ |
|||
base.OnEnable(); |
|||
AddSlot(new MaterialGraphSlot(new Slot(SlotType.OutputSlot, kOutputSlotName), SlotValueType.Vector4)); |
|||
} |
|||
|
|||
public override PropertyType propertyType |
|||
{ |
|||
get { return PropertyType.Color; } |
|||
} |
|||
|
|||
public override string GetOutputVariableNameForSlot(Slot s, GenerationMode generationMode) |
|||
{ |
|||
return propertyName; |
|||
} |
|||
|
|||
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode, ConcreteSlotValueType slotValueType) |
|||
{ |
|||
if (exposed || generationMode.IsPreview()) |
|||
visitor.AddShaderChunk("float4 " + propertyName + ";", true); |
|||
} |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
// we only need to generate node code if we are using a constant... otherwise we can just refer to the property :)
|
|||
if (exposed || generationMode.IsPreview()) |
|||
return; |
|||
|
|||
visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + precision + "4 (" + m_Color.r + ", " + m_Color.g + ", " + m_Color.b + ", " + m_Color.a + ");", true); |
|||
} |
|||
|
|||
|
|||
public override GUIModificationType NodeUI(Rect drawArea) |
|||
{ |
|||
base.NodeUI(drawArea); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Color = EditorGUI.ColorField(new Rect(drawArea.x, drawArea.y, drawArea.width, EditorGUIUtility.singleLineHeight), m_Color); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
return GUIModificationType.Repaint; |
|||
|
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
public override PreviewProperty GetPreviewProperty() |
|||
{ |
|||
return new PreviewProperty |
|||
{ |
|||
m_Name = propertyName, |
|||
m_PropType = PropertyType.Color, |
|||
m_Color = m_Color |
|||
}; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 325c0e24c20746345a5f90dc201973f8 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Art/Colorize Node")] |
|||
class ColorizeNode : Function1Input, IGeneratesFunction |
|||
{ |
|||
[SerializeField] |
|||
private Color m_Color = Color.blue; |
|||
[SerializeField] |
|||
private float m_Colorization = 0.0f; |
|||
[SerializeField] |
|||
private float m_Brightness = 1.0f; |
|||
[SerializeField] |
|||
private float m_Contrast = 1.0f; |
|||
|
|||
public override void OnCreate() |
|||
{ |
|||
name = "ColorizeNode"; |
|||
base.OnCreate(); |
|||
} |
|||
|
|||
protected override string GetFunctionName() {return ""; } |
|||
|
|||
protected override string GetFunctionCallBody(string inputValue) |
|||
{ |
|||
return "unity_colorize_" + precision + "(" + inputValue + ", " + precision + "4(" + m_Color.r + ", " + m_Color.g + ", " + m_Color.b + ", " + m_Color.a + "), " + m_Colorization + ", " + m_Brightness + ", " + m_Contrast + ")"; |
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
|
|||
foreach (var thePrecisision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + thePrecisision + "4 unity_colorize_" + thePrecisision + " (" + thePrecisision + "4 arg1, " + thePrecisision + "4 color, " + thePrecisision + " amount, " + thePrecisision + " brightness, " + thePrecisision + " contrast)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk(thePrecisision + "4 x = lerp(arg1, arg1 * color, amount);", false); |
|||
outputString.AddShaderChunk("x *= brightness;", false); |
|||
outputString.AddShaderChunk("x = pow(x, contrast);", false); |
|||
outputString.AddShaderChunk("return x;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
|
|||
static float Slider(string title, float value, float from, float to) |
|||
{ |
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Label(title); |
|||
value = GUILayout.HorizontalSlider(value, from, to, GUILayout.Width(64)); |
|||
GUILayout.EndHorizontal(); |
|||
return value; |
|||
} |
|||
|
|||
/*public override void NodeUI() |
|||
{ |
|||
base.NodeUI(); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Color = EditorGUILayout.ColorField("Tint", m_Color); |
|||
m_Colorization = Slider("Colorization", m_Colorization, 0f, 1f); |
|||
m_Brightness = Slider("Brightness", m_Brightness, 0f, 2f); |
|||
m_Contrast = Slider("Contrast", m_Contrast, 0.3f, 4f); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
RegeneratePreviewShaders(); |
|||
}*/ |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: eb2553e0542079a4b86f8abe5ad4045e |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Art/Combine Node")] |
|||
class CombineNode : Function2Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "CombineNode"; |
|||
base.OnCreate(); |
|||
} |
|||
|
|||
// Based on information from:
|
|||
// http://photoblogstop.com/photoshop/photoshop-blend-modes-explained
|
|||
// http://www.venture-ware.com/kevin/coding/lets-learn-math-photoshop-blend-modes/
|
|||
// http://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/
|
|||
// http://dunnbypaul.net/blends/
|
|||
public enum Operation |
|||
{ |
|||
Darken, |
|||
Multiply, |
|||
ColorBurn, |
|||
LinearBurn, |
|||
// TODO: DarkerColor (Darken, but based on luminosity)
|
|||
Lighten, |
|||
Screen, |
|||
ColorDodge, |
|||
LinearDodge, |
|||
// TODO: LighterColor (Lighten, but based on luminosity)
|
|||
Overlay, |
|||
SoftLight, |
|||
HardLight, |
|||
VividLight, |
|||
LinearLight, |
|||
PinLight, |
|||
HardMix, |
|||
Difference, |
|||
Exclusion, |
|||
Subtract, |
|||
Divide, |
|||
} |
|||
|
|||
[SerializeField] |
|||
private Operation m_Operation; |
|||
|
|||
private static readonly string[] kOpNames = { |
|||
"darken", "mul", "cburn", "lburn", |
|||
"lighten", "screen", "cdodge", "ldodge", |
|||
"overlay", "softl", "hardl", "vividl", "linearl", "pinl", "hardmix", |
|||
"diff", "excl", "sub", "div" |
|||
}; |
|||
|
|||
protected override string GetFunctionName() { return "unity_combine_" + kOpNames[(int)m_Operation] + "_" + precision; } |
|||
|
|||
|
|||
protected void AddOperationBody(ShaderGenerator visitor, string combineName, string body, string combinePrecision) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
outputString.AddShaderChunk("inline " + combinePrecision + "4 unity_combine_" + combineName + "_" + combinePrecision + " (" + combinePrecision + "4 arg1, " + combinePrecision + "4 arg2)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk(body, false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
|
|||
public override float GetNodeUIHeight(float width) |
|||
{ |
|||
return EditorGUIUtility.singleLineHeight * 1; |
|||
} |
|||
|
|||
public override GUIModificationType NodeUI(Rect drawArea) |
|||
{ |
|||
base.NodeUI(drawArea); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Operation = (Operation)EditorGUI.EnumPopup(drawArea, m_Operation); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
pixelGraph.RevalidateGraph(); |
|||
return GUIModificationType.Repaint; |
|||
} |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
// Darken group
|
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Darken], "return min(arg1, arg2);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Multiply], "return arg1 * arg2;", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.ColorBurn], "return 1 - (1-arg1)/(arg2+1e-5);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.LinearBurn], "return arg1 + arg2 - 1;", precision); |
|||
|
|||
// Lighten group
|
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Lighten], "return max(arg1, arg2);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Screen], "return 1- (1-arg1) * (1-arg2);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.ColorDodge], "return arg1/(1-arg2+1e-5);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.LinearDodge], "return arg1 + arg2;", precision); |
|||
|
|||
// Contrast group
|
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Overlay], "return (arg1 < 0.5)? arg1*arg2*2: 1-(1-arg1)*(1-arg2)*2;", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.SoftLight], |
|||
"return (1-arg1)*arg1*arg2 + arg1*(1- (1-arg1)*(1-arg2));", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.HardLight], "return (arg2 < 0.5)? arg1*arg2*2: 1-(1-arg1)*(1-arg2)*2;", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.VividLight], |
|||
"return (arg2 < 0.5)? 1- (1-arg1)/(2*arg2+1e-5): arg1/(1-2*(arg2-0.5)+1e-5);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.LinearLight], "return (arg2 < 0.5)? arg1+(2*arg2)-1: arg1+2*(arg2-0.5);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.PinLight], "return (arg2 < 0.5)? min(arg1, 2*arg2): max(arg1, 2*(arg2-0.5));", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.HardMix], "return (arg2 < 1-arg1)? " + precision + "(0):" + precision + "(1);", precision); |
|||
|
|||
// Inversion group
|
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Difference], "return abs(arg2-arg1);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Exclusion], "return arg1 + arg2 - arg1*arg2*2;", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Subtract], "return max(arg2-arg1, 0.0);", precision); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Divide], "return arg1 / (arg2+1e-5);", precision); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3738e97908dea1f4bbc5e5a7cf562ecc |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Div Node")] |
|||
class DivNode : Function2Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "DivNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() {return "unity_div_" + precision; } |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_div_" + precision + " (" + precision + "4 arg1, " + precision + "4 arg2)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("return arg1 / arg2;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 8e9d13e64300d6942ad51651d39f9ac6 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Dot Node")] |
|||
class DotNode : Function2Input |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "DotNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() { return "dot"; } |
|||
protected override MaterialGraphSlot GetInputSlot1() |
|||
{ |
|||
var slot = new Slot(SlotType.InputSlot, GetInputSlot1Name()); |
|||
return new MaterialGraphSlot(slot, SlotValueType.Vector3); |
|||
} |
|||
|
|||
protected override MaterialGraphSlot GetInputSlot2() |
|||
{ |
|||
var slot = new Slot(SlotType.InputSlot, GetInputSlot2Name()); |
|||
return new MaterialGraphSlot(slot, SlotValueType.Vector3); |
|||
} |
|||
|
|||
protected override MaterialGraphSlot GetOutputSlot() |
|||
{ |
|||
var slot = new Slot(SlotType.OutputSlot, GetOutputSlotName()); |
|||
return new MaterialGraphSlot(slot, SlotValueType.Vector1); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 97e1d998eea5d644095671979ecf2e54 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
internal static class Extensions |
|||
{ |
|||
public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, |
|||
IEnumerable<TSource> second , Func<TSource, TSource, bool> comparer) |
|||
{ |
|||
return first.Except(second, new LambdaComparer<TSource>(comparer)); |
|||
} |
|||
|
|||
public class LambdaComparer<T> : IEqualityComparer<T> |
|||
{ |
|||
private readonly Func<T, T, bool> _lambdaComparer; |
|||
private readonly Func<T, int> _lambdaHash; |
|||
|
|||
public LambdaComparer(Func<T, T, bool> lambdaComparer) : |
|||
this(lambdaComparer, o => 0) |
|||
{ |
|||
} |
|||
|
|||
public LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash) |
|||
{ |
|||
if (lambdaComparer == null) |
|||
throw new ArgumentNullException("lambdaComparer"); |
|||
if (lambdaHash == null) |
|||
throw new ArgumentNullException("lambdaHash"); |
|||
|
|||
_lambdaComparer = lambdaComparer; |
|||
_lambdaHash = lambdaHash; |
|||
} |
|||
|
|||
public bool Equals(T x, T y) |
|||
{ |
|||
return _lambdaComparer(x, y); |
|||
} |
|||
|
|||
public int GetHashCode(T obj) |
|||
{ |
|||
return _lambdaHash(obj); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: adf5c8d21f606c848a855790481093b2 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Fresnel Node")] |
|||
class FresnelNode : Function2Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "FresnelNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() { return "unity_fresnel_" + precision; } |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
|
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_fresnel_" + precision + " (" + precision + "4 arg1, " + precision + "4 arg2)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("return (1.0 - dot (normalize (arg1.xyz), normalize (arg2.xyz))).xxxx;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 06ab35c1dfe05414787df3ea2772d507 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
abstract class Function1Input : BaseMaterialNode, IGeneratesBodyCode |
|||
{ |
|||
public override bool hasPreview |
|||
{ |
|||
get { return true; } |
|||
} |
|||
|
|||
public override void OnEnable() |
|||
{ |
|||
base.OnEnable(); |
|||
AddSlot(GetInputSlot()); |
|||
AddSlot(GetOutputSlot()); |
|||
RemoveSlotsNameNotMatching(validSlots); |
|||
} |
|||
|
|||
protected string[] validSlots |
|||
{ |
|||
get { return new[] {GetInputSlotName(), GetOutputSlotName()}; } |
|||
} |
|||
|
|||
protected virtual MaterialGraphSlot GetInputSlot() |
|||
{ |
|||
var slot = new Slot(SlotType.InputSlot, GetInputSlotName()); |
|||
return new MaterialGraphSlot(slot, SlotValueType.Dynamic); |
|||
} |
|||
|
|||
protected virtual MaterialGraphSlot GetOutputSlot() |
|||
{ |
|||
var slot = new Slot(SlotType.OutputSlot, GetOutputSlotName()); |
|||
return new MaterialGraphSlot(slot, SlotValueType.Dynamic); |
|||
} |
|||
|
|||
protected virtual string GetInputSlotName() {return "Input"; } |
|||
protected virtual string GetOutputSlotName() {return "Output"; } |
|||
|
|||
protected abstract string GetFunctionName(); |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputSlot = FindOutputSlot(GetOutputSlotName()); |
|||
var inputSlot = FindInputSlot(GetInputSlotName()); |
|||
|
|||
if (inputSlot == null || outputSlot == null) |
|||
{ |
|||
Debug.LogError("Invalid slot configuration on node: " + name); |
|||
return; |
|||
} |
|||
|
|||
var inputValue = GetSlotValue(inputSlot, generationMode); |
|||
visitor.AddShaderChunk(precision + outputDimension + " " + GetOutputVariableNameForSlot(outputSlot, generationMode) + " = " + GetFunctionCallBody(inputValue) + ";", true); |
|||
} |
|||
|
|||
protected virtual string GetFunctionCallBody(string inputValue) |
|||
{ |
|||
return GetFunctionName() + " (" + inputValue + ")"; |
|||
} |
|||
|
|||
public string outputDimension |
|||
{ |
|||
get { return ConvertConcreteSlotValueTypeToString(concreteOutputSlotValueTypes[GetOutputSlotName()]); } |
|||
} |
|||
|
|||
public string input1Dimension |
|||
{ |
|||
get { return ConvertConcreteSlotValueTypeToString(concreteInputSlotValueTypes[GetInputSlotName()]); } |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9e8ba3e80e4d9e947a9377e9e73fdca9 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
internal abstract class Function3Input : BaseMaterialNode, IGeneratesBodyCode |
|||
{ |
|||
public override bool hasPreview |
|||
{ |
|||
get { return true; } |
|||
} |
|||
|
|||
public override void OnEnable() |
|||
{ |
|||
base.OnEnable(); |
|||
AddSlot(GetInputSlot1()); |
|||
AddSlot(GetInputSlot2()); |
|||
AddSlot(GetInputSlot3()); |
|||
AddSlot(GetOutputSlot()); |
|||
RemoveSlotsNameNotMatching(validSlots); |
|||
} |
|||
|
|||
protected string[] validSlots |
|||
{ |
|||
get { return new[] {GetInputSlot1Name(), GetInputSlot2Name(), GetInputSlot3Name(), GetOutputSlotName()}; } |
|||
} |
|||
|
|||
protected virtual MaterialGraphSlot GetInputSlot1() |
|||
{ |
|||
var slot = new Slot(SlotType.InputSlot, GetInputSlot1Name()); |
|||
return new MaterialGraphSlot(slot, SlotValueType.Dynamic); |
|||
} |
|||
|
|||
protected virtual MaterialGraphSlot GetInputSlot2() |
|||
{ |
|||
var slot = new Slot(SlotType.InputSlot, GetInputSlot2Name()); |
|||
return new MaterialGraphSlot(slot, SlotValueType.Dynamic); |
|||
} |
|||
|
|||
protected virtual MaterialGraphSlot GetInputSlot3() |
|||
{ |
|||
var slot = new Slot(SlotType.InputSlot, GetInputSlot3Name()); |
|||
return new MaterialGraphSlot(slot, SlotValueType.Dynamic); |
|||
} |
|||
|
|||
protected virtual MaterialGraphSlot GetOutputSlot() |
|||
{ |
|||
var slot = new Slot(SlotType.OutputSlot, GetOutputSlotName()); |
|||
return new MaterialGraphSlot(slot, SlotValueType.Dynamic); |
|||
} |
|||
|
|||
protected virtual string GetInputSlot1Name() |
|||
{ |
|||
return "Input1"; |
|||
} |
|||
|
|||
protected virtual string GetInputSlot2Name() |
|||
{ |
|||
return "Input2"; |
|||
} |
|||
|
|||
protected virtual string GetInputSlot3Name() |
|||
{ |
|||
return "Input3"; |
|||
} |
|||
|
|||
protected virtual string GetOutputSlotName() |
|||
{ |
|||
return "Output"; |
|||
} |
|||
|
|||
protected abstract string GetFunctionName(); |
|||
|
|||
protected virtual string GetFunctionPrototype(string arg1Name, string arg2Name, string arg3Name) |
|||
{ |
|||
return "inline " + precision + outputDimension + " " + GetFunctionName() + " (" |
|||
+ precision + input1Dimension + " " + arg1Name + ", " |
|||
+ precision + input2Dimension + " " + arg2Name + ", " |
|||
+ precision + input3Dimension + " " + arg3Name + ")"; |
|||
} |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputSlot = FindOutputSlot(GetOutputSlotName()); |
|||
var inputSlot1 = FindInputSlot(GetInputSlot1Name()); |
|||
var inputSlot2 = FindInputSlot(GetInputSlot2Name()); |
|||
var inputSlot3 = FindInputSlot(GetInputSlot3Name()); |
|||
|
|||
if (inputSlot1 == null || inputSlot2 == null || inputSlot3 == null || outputSlot == null) |
|||
{ |
|||
Debug.LogError("Invalid slot configuration on node: " + name); |
|||
return; |
|||
} |
|||
|
|||
string input1Value = GetSlotValue(inputSlot1, generationMode); |
|||
string input2Value = GetSlotValue(inputSlot2, generationMode); |
|||
string input3Value = GetSlotValue(inputSlot3, generationMode); |
|||
|
|||
visitor.AddShaderChunk(precision + outputDimension + " " + GetOutputVariableNameForSlot(outputSlot, generationMode) + " = " + GetFunctionCallBody(input1Value, input2Value, input3Value) + ";", true); |
|||
} |
|||
|
|||
protected virtual string GetFunctionCallBody(string inputValue1, string inputValue2, string inputValue3) |
|||
{ |
|||
return GetFunctionName() + " (" + inputValue1 + ", " + inputValue2 + ", " + inputValue3 + ")"; |
|||
} |
|||
|
|||
protected virtual string GetFunctionCallBody(string inputValue) |
|||
{ |
|||
return GetFunctionName() + " (" + inputValue + ")"; |
|||
} |
|||
|
|||
public string outputDimension |
|||
{ |
|||
get { return ConvertConcreteSlotValueTypeToString(concreteOutputSlotValueTypes[GetOutputSlotName()]); } |
|||
} |
|||
|
|||
public string input1Dimension |
|||
{ |
|||
get { return ConvertConcreteSlotValueTypeToString(concreteInputSlotValueTypes[GetInputSlot1Name()]); } |
|||
} |
|||
|
|||
public string input2Dimension |
|||
{ |
|||
get { return ConvertConcreteSlotValueTypeToString(concreteInputSlotValueTypes[GetInputSlot2Name()]); } |
|||
} |
|||
|
|||
public string input3Dimension |
|||
{ |
|||
get { return ConvertConcreteSlotValueTypeToString(concreteInputSlotValueTypes[GetInputSlot3Name()]); } |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e7d8fb926f570fb48b10d7d068d54123 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using System.Linq; |
|||
using UnityEngine; |
|||
using System.Collections.Generic; |
|||
using UnityEditor.Graphs; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
/*public 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 " + GetOutputVariableNameForSlot(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; |
|||
} |
|||
}*/ |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 323a0eb1930dff241b4547716c8eb21f |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using System; |
|||
using System.Linq; |
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Fractal/Kaleidoscope Node")] |
|||
class KaleidoscopeNode : BaseMaterialNode, IGeneratesFunction, IGeneratesBodyCode |
|||
{ |
|||
[SerializeField] |
|||
private int m_Iterations = 6; |
|||
|
|||
private const string kPointInputName = "Point"; |
|||
private const string kConstant1InputName = "Constant1"; |
|||
private const string kConstant2InputName = "Constant2"; |
|||
private const string kOutputSlotName = "Output"; |
|||
|
|||
public override bool hasPreview { get { return true; } } |
|||
|
|||
public override void OnCreate() |
|||
{ |
|||
name = "KaleidoscopeNode"; |
|||
base.OnCreate(); |
|||
// AddSlot(new Slot(SlotType.InputSlot, kPointInputName));
|
|||
//AddSlot(new Slot(SlotType.InputSlot, kConstant1InputName));
|
|||
//AddSlot(new Slot(SlotType.InputSlot, kConstant2InputName));
|
|||
//AddSlot(new Slot(SlotType.OutputSlot, kOutputSlotName));
|
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_kaleidoscope_" + precision + " (" + precision + "2 p, " + precision + "4 c1, " + precision + "4 c2, int iterations)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("c1 = c1 * 2 - 1;", false); |
|||
outputString.AddShaderChunk("c2 = c2 * 2 - 1;", false); |
|||
outputString.AddShaderChunk("for (int n = 0; n < iterations; n++)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("p = c1.xy + p * c1.zw + " + precision + "2(dot(p, c2.xy), dot(p, c2.zw));", false); |
|||
outputString.AddShaderChunk("if(p.x < p.y) p.xy = -p.yx;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
outputString.AddShaderChunk("return " + precision + "4(p, 1, 1);", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputSlot = FindOutputSlot(kOutputSlotName); |
|||
var pointInput = FindInputSlot(kPointInputName); |
|||
var constant1Input = FindInputSlot(kConstant1InputName); |
|||
var constant2Input = FindInputSlot(kConstant2InputName); |
|||
|
|||
if (outputSlot == null || pointInput == null || constant1Input == null || constant2Input == null) |
|||
{ |
|||
Debug.LogError("Invalid slot configuration on node: " + name); |
|||
return; |
|||
} |
|||
|
|||
string pointInputValue = GetSlotValue(pointInput, generationMode); |
|||
string constant1InputValue = GetSlotValue(constant1Input, generationMode); |
|||
string constant2InputValue = GetSlotValue(constant2Input, generationMode); |
|||
|
|||
string outName = GetOutputVariableNameForSlot(outputSlot, generationMode); |
|||
visitor.AddShaderChunk(precision + "4 " + outName + " = unity_kaleidoscope_" + precision + "(" + pointInputValue + ".xy, " + constant1InputValue + ", " + constant2InputValue + ", " + m_Iterations + ");", false); |
|||
} |
|||
|
|||
static float Slider(string title, float value, float from, float to) |
|||
{ |
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Label(title); |
|||
value = GUILayout.HorizontalSlider(value, from, to, GUILayout.Width(64)); |
|||
GUILayout.EndHorizontal(); |
|||
return value; |
|||
} |
|||
|
|||
/*public override void NodeUI() |
|||
{ |
|||
base.NodeUI(); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Iterations = (int)Slider("Iterations", (float)m_Iterations, 1, 50); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
RegeneratePreviewShaders(); |
|||
}*/ |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: dfc00afcda39bfa4fbd9bd6176f53477 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Length Node")] |
|||
class LengthNode : Function1Input |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "LengthNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() { return "length"; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 52afae1b1271e864c9c6965dc738c2dd |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using System; |
|||
using System.Linq; |
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Fractal/Mandelbrot Node")] |
|||
class MandelbrotNode : BaseMaterialNode, IGeneratesFunction, IGeneratesBodyCode |
|||
{ |
|||
[SerializeField] |
|||
private int m_Iterations = 6; |
|||
|
|||
private const string kPointInputName = "Point"; |
|||
private const string kConstantInputName = "Constant"; |
|||
private const string kOutputSlotName = "Output"; |
|||
|
|||
public override bool hasPreview { get { return true; } } |
|||
|
|||
public override void OnCreate() |
|||
{ |
|||
name = "MandelbrotNode"; |
|||
base.OnCreate(); |
|||
//AddSlot(new Slot(SlotType.InputSlot, kPointInputName));
|
|||
//AddSlot(new Slot(SlotType.InputSlot, kConstantInputName));
|
|||
//AddSlot(new Slot(SlotType.OutputSlot, kOutputSlotName));
|
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_mandelbrot_" + precision + " (" + precision + "2 p, " + precision + "2 c, float limit, float scale, int iterations)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk(precision + " zr = p.x * 4 - 2, zi = p.y * 4 - 2, dzr = 1, dzi = 0, r = 0, len2;", false); |
|||
outputString.AddShaderChunk("for (int n = 0; n < iterations; n++)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk(precision + " tmp1 = 2 * zr * zi + c.y; zr = zr * zr - zi * zi + c.x; zi = tmp1;", false); |
|||
outputString.AddShaderChunk(precision + " tmp2 = 2 * (dzr * zi + dzi * zr); dzr = 2 * (dzr * zr - dzi * zi) + 1; dzi = tmp2;", false); |
|||
outputString.AddShaderChunk("len2 = zr * zr + zi * zi;", false); |
|||
outputString.AddShaderChunk("if (len2 > 1000000 * limit) { r = n; break; }", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
outputString.AddShaderChunk("return scale * sqrt(len2 / (dzr * dzr + dzi * dzi)) * log(len2);", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var validSlots = ListPool<Slot>.Get(); |
|||
GetValidInputSlots(validSlots); |
|||
|
|||
var outputSlot = outputSlots.FirstOrDefault(x => x.name == kOutputSlotName); |
|||
var pointInput = validSlots.FirstOrDefault(x => x.name == kPointInputName); |
|||
var constantInput = validSlots.FirstOrDefault(x => x.name == kConstantInputName); |
|||
|
|||
ListPool<Slot>.Release(validSlots); |
|||
|
|||
if (outputSlot == null || pointInput == null || constantInput == null) |
|||
{ |
|||
Debug.LogError("Invalid slot configuration on node: " + name); |
|||
return; |
|||
} |
|||
|
|||
//TODO: This will break if there is NO input connected, use default in that case
|
|||
var pointProvider = pointInput.edges[0].fromSlot.node as BaseMaterialNode; |
|||
var pointName = pointProvider.GetOutputVariableNameForSlot(pointInput.edges[0].fromSlot, generationMode); |
|||
|
|||
var constantProvider = constantInput.edges[0].fromSlot.node as BaseMaterialNode; |
|||
var constantName = constantProvider.GetOutputVariableNameForSlot(constantInput.edges[0].fromSlot, generationMode); |
|||
|
|||
string outName = GetOutputVariableNameForSlot(outputSlot, generationMode); |
|||
visitor.AddShaderChunk(precision + "4 " + outName + " = unity_mandelbrot_" + precision + "(" + pointName + ".xy, " + constantName + ".xy, " + constantName + ".z, " + constantName + ".w, " + m_Iterations + ");", false); |
|||
} |
|||
|
|||
static float Slider(string title, float value, float from, float to) |
|||
{ |
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Label(title); |
|||
value = GUILayout.HorizontalSlider(value, from, to, GUILayout.Width(64)); |
|||
GUILayout.EndHorizontal(); |
|||
return value; |
|||
} |
|||
|
|||
/*public override void NodeUI() |
|||
{ |
|||
base.NodeUI(); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Iterations = (int)Slider("Iterations", (float)m_Iterations, 1, 50); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
RegeneratePreviewShaders(); |
|||
}*/ |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 45896ba83118f8548bd9d2f9263bcde5 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Maximum Node")] |
|||
class MaximumNode : Function2Input |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "MaximumNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() { return "max"; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1de46e012f3608843978529b36704c2b |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Minimum Node")] |
|||
class MinimumNode : Function2Input |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "MinimumNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() { return "min"; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 79ffed9a70f191f4c966a6eb3ae10d07 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Multiply Node")] |
|||
internal class MultiplyNode : Function2Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "MultiplyNode"; |
|||
base.OnCreate(); |
|||
} |
|||
|
|||
protected override string GetFunctionName() |
|||
{ |
|||
return "unity_multiply_" + precision; |
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + outputDimension + " " + GetFunctionName() + " (" + precision + input1Dimension + " arg1, " + precision + input2Dimension + " arg2)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("return arg1 * arg2;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 088fb5bde3ece0f4190136b3ab43f7c4 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Input/Normal Node")] |
|||
public class NormalNode : BaseMaterialNode |
|||
{ |
|||
private const string kOutputSlotName = "Normal"; |
|||
|
|||
public override bool hasPreview { get { return true; } } |
|||
public override PreviewMode previewMode |
|||
{ |
|||
get { return PreviewMode.Preview3D; } } |
|||
|
|||
public override void OnCreate() |
|||
{ |
|||
base.OnCreate(); |
|||
name = "Normal"; |
|||
} |
|||
|
|||
public override void OnEnable() |
|||
{ |
|||
base.OnEnable(); |
|||
AddSlot(new MaterialGraphSlot(new Slot(SlotType.OutputSlot, kOutputSlotName), SlotValueType.Vector3)); |
|||
} |
|||
|
|||
public override string GetOutputVariableNameForSlot(Slot slot, GenerationMode generationMode) |
|||
{ |
|||
if (generationMode == GenerationMode.Preview2D) |
|||
Debug.LogError("Trying to generate 2D preview on a node that does not support it!"); |
|||
|
|||
return generationMode.Is2DPreview() ? "IN.Normal" : "o.Normal"; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 5b34601661908b3499c4c5e2ecd61f75 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Normalize Node")] |
|||
class NormalizeNode : Function1Input |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "NormalizeNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() { return "normalize"; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7eb73d726827e2c41ae4d68018bc97e1 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Fractal/Perlin Node")] |
|||
class PerlinNode : TextureNode, IGeneratesFunction, IGeneratesBodyCode |
|||
{ |
|||
public override bool hasPreview { get { return true; } } |
|||
|
|||
[SerializeField] |
|||
private int m_Iterations = 4; |
|||
|
|||
[SerializeField] |
|||
private float m_Decay = 0.5f; |
|||
|
|||
[SerializeField] |
|||
private float m_Frequency = 2.0f; |
|||
|
|||
public override void OnCreate() |
|||
{ |
|||
name = "Perlin"; |
|||
base.OnCreate(); |
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_perlin_" + precision + " (" |
|||
+ "sampler2D textureID, " |
|||
+ "int iterations, " |
|||
+ precision + " decay, " |
|||
+ precision + " frequency, " |
|||
+ precision + "2 p" |
|||
+ ")", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk(precision + "4 sum = " + precision + "4(0, 0, 0, 0);", false); |
|||
outputString.AddShaderChunk(precision + " amp = 0.5;", false); |
|||
outputString.AddShaderChunk("for(int n = 0; n < iterations; n++)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("sum += amp * tex2D (textureID, p);", false); |
|||
outputString.AddShaderChunk("p *= frequency;", false); |
|||
outputString.AddShaderChunk("amp *= decay;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
outputString.AddShaderChunk("return sum;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
|
|||
/* public override void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputSlot = FindOutputSlot(kOutputSlotName); |
|||
if (outputSlot == null) |
|||
return; |
|||
|
|||
var uvSlot = FindInputSlot(kUVSlotName); |
|||
if (uvSlot == null) |
|||
return; |
|||
|
|||
var uvName = "IN.meshUV0"; |
|||
if (uvSlot.edges.Count > 0) |
|||
{ |
|||
var fromNode = uvSlot.edges[0].fromSlot.node as BaseMaterialNode; |
|||
uvName = fromNode.GetOutputVariableNameForSlot(uvSlot.edges[0].fromSlot, generationMode); |
|||
} |
|||
|
|||
string body = "unity_perlin_" + precision + "(" + GetPropertyName() + ", " + m_Iterations + ", " + m_Decay + ", " + m_Frequency + ", " + uvName + ".xy)"; |
|||
visitor.AddShaderChunk("float4 " + GetOutputVariableNameForSlot(outputSlot, generationMode) + " = " + body + ";", true); |
|||
} |
|||
*/ |
|||
static float Slider(string title, float value, float from, float to) |
|||
{ |
|||
GUILayout.BeginHorizontal(); |
|||
GUILayout.Label(title); |
|||
value = GUILayout.HorizontalSlider(value, from, to, GUILayout.Width(64)); |
|||
GUILayout.EndHorizontal(); |
|||
return value; |
|||
} |
|||
/* |
|||
public override float GetNodeUIHeight() |
|||
{ |
|||
return EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public override bool NodeUI(Rect drawArea) |
|||
{ |
|||
base.NodeUI(drawArea); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Iterations = (int)Slider("Iterations", (float)m_Iterations, 1, 8); |
|||
m_Decay = Slider("Decay", m_Decay, -1f, 1f); |
|||
m_Frequency = Slider("Frequency", m_Frequency, 0f, 5f); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
RegeneratePreviewShaders(); |
|||
}*/ |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6388ec78711fae240b4d5c60bd70d36d |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Power Node")] |
|||
class PowerNode : Function2Input |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "PowerNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() { return "pow"; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b2957c4e08e061444a7444a1a03fb584 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Quantize Node")] |
|||
class QuantizeNode : Function2Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "QuantizeNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() {return "unity_quantize_" + precision; } |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_quantize_" + precision + " (" + precision + "4 input, " + precision + "4 stepsize)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("return floor(input / stepsize) * stepsize;", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 4322ad8d0cd83df47afd741a6b97d57b |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using System; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Reflect Node")] |
|||
class ReflectNode : Function2Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "ReflectNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetInputSlot1Name() {return "Normal"; } |
|||
protected override string GetInputSlot2Name() {return "Direction"; } |
|||
protected override string GetOutputSlotName() {return "Reflection"; } |
|||
|
|||
protected override string GetFunctionName() {return "unity_reflect_" + precision; } |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_reflect_" + precision + " (" + precision + "4 normal, " + precision + "4 direction)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk(precision + "3 vn = normalize(normal.xyz);", false); |
|||
outputString.AddShaderChunk(precision + "3 vd = normalize(direction.xyz);", false); |
|||
outputString.AddShaderChunk("return half4 (2 * dot(vn, vd) * vn - vd, 1.0);", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6af2205640e32994db6fd7de8aebf1de |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Input/Screen Pos Node")] |
|||
public class ScreenPosNode : BaseMaterialNode, IGeneratesVertexToFragmentBlock |
|||
{ |
|||
private const string kOutputSlotName = "ScreenPos"; |
|||
|
|||
public override bool hasPreview { get { return true; } } |
|||
|
|||
public override void OnCreate() |
|||
{ |
|||
name = "ScreenPos"; |
|||
base.OnCreate(); |
|||
} |
|||
|
|||
public override void OnEnable() |
|||
{ |
|||
base.OnEnable(); |
|||
AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kOutputSlotName), SlotValueType.Vector4)); |
|||
} |
|||
|
|||
public override string GetOutputVariableNameForSlot(Slot slot, GenerationMode generationMode) |
|||
{ |
|||
return "IN.screenPos"; |
|||
} |
|||
|
|||
public void GenerateVertexToFragmentBlock(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
string temp = precision + "4 screenPos"; |
|||
if (generationMode == GenerationMode.Preview2D) |
|||
temp += " : TEXCOORD1"; |
|||
temp += ";"; |
|||
visitor.AddShaderChunk(temp, true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e204c7999bfa0ee42a18d8a560a36244 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/Sin Node")] |
|||
class SinNode : Function1Input |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "SinNode"; |
|||
base.OnCreate();; |
|||
} |
|||
|
|||
protected override string GetFunctionName() {return "sin"; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2b10d839969f5484cad9632519dc7324 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Input/Sine Time Node")] |
|||
public class SinTimeNode : BaseMaterialNode, IRequiresTime |
|||
{ |
|||
private const string kOutputSlotName = "SinTime"; |
|||
|
|||
public override void OnCreate() |
|||
{ |
|||
base.OnCreate(); |
|||
name = "Sine Time"; |
|||
} |
|||
|
|||
public override void OnEnable() |
|||
{ |
|||
base.OnEnable(); |
|||
AddSlot(new MaterialGraphSlot(new Slot(SlotType.OutputSlot, kOutputSlotName), SlotValueType.Vector4)); |
|||
} |
|||
|
|||
public override bool hasPreview |
|||
{ |
|||
get { return true; } |
|||
} |
|||
|
|||
public override string GetOutputVariableNameForSlot(Slot s, GenerationMode generationMode) |
|||
{ |
|||
return "_SinTime"; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f80af444cd4235c419b356216d784b57 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[Title("Math/SmoothStep Node")] |
|||
class SmoothStepNode : Function3Input, IGeneratesFunction |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
base.OnCreate();; |
|||
name = "SmoothStepNode"; |
|||
} |
|||
|
|||
protected override string GetFunctionName() {return "unity_smoothstep_" + precision; } |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
foreach (var precision in m_PrecisionNames) |
|||
{ |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_smoothstep_" + precision + " (" + precision + "4 input, " + precision + "4 edge1, " + precision + "4 edge2)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk("return smoothstep(edge1, edge2, input);", false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
} |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a9ced96a233d64541b3c5d374a057d6b |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
public class SubGraphIOBaseNode : BaseMaterialNode |
|||
{ |
|||
GUIContent kTempContent = new GUIContent("+"); |
|||
|
|||
public virtual void AddSlot() |
|||
{ |
|||
} |
|||
|
|||
public void FooterUI(GraphGUI host) |
|||
{ |
|||
// TODO: make it pretty
|
|||
GUIStyle style = this is SubGraphOutputsNode ? |
|||
Styles.GetNodeStyle("shader in", Styles.Color.Aqua, false) : |
|||
Styles.GetNodeStyle("shader out", Styles.Color.Aqua, false); |
|||
var pos = GUILayoutUtility.GetRect(kTempContent, style); |
|||
int id = GUIUtility.GetControlID(FocusType.Passive); |
|||
|
|||
Event evt = Event.current; |
|||
if (evt.type == EventType.Layout || evt.type == EventType.Used) |
|||
return; |
|||
|
|||
switch (evt.GetTypeForControl(id)) |
|||
{ |
|||
case EventType.MouseUp: |
|||
if (pos.Contains(evt.mousePosition) && evt.button == 0) |
|||
{ |
|||
AddSlot(); |
|||
evt.Use(); |
|||
} |
|||
break; |
|||
case EventType.Repaint: |
|||
style.Draw(pos, kTempContent, id); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 329dc46f2903e364da6c6d6500b0cfee |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEngine; |
|||
using System.Collections.Generic; |
|||
using UnityEditor.Graphs; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
public class SubGraphInputsNode : SubGraphIOBaseNode, IGenerateProperties |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
name = "SubGraphInputs"; |
|||
title = "Inputs"; |
|||
// position = new Rect(BaseMaterialGraphGUI.kDefaultNodeWidth * 4, BaseMaterialGraphGUI.kDefaultNodeHeight * 2, Mathf.Max(300, position.width), position.height);
|
|||
base.OnCreate(); |
|||
} |
|||
|
|||
public override void AddSlot() |
|||
{ |
|||
//AddSlot(new Slot(SlotType.OutputSlot, GenerateSlotName(SlotType.OutputSlot)));
|
|||
} |
|||
|
|||
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
base.GeneratePropertyBlock(visitor, generationMode); |
|||
|
|||
if (!generationMode.IsPreview()) |
|||
return; |
|||
|
|||
foreach (var slot in outputSlots) |
|||
{ |
|||
if (slot.edges.Count == 0) |
|||
continue; |
|||
|
|||
var defaultValue = GetSlotDefaultValue(slot.name); |
|||
if (defaultValue != null) |
|||
defaultValue.GeneratePropertyBlock(visitor, generationMode); |
|||
} |
|||
} |
|||
|
|||
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode, ConcreteSlotValueType slotValueType) |
|||
{ |
|||
base.GeneratePropertyUsages(visitor, generationMode, slotValueType); |
|||
|
|||
if (!generationMode.IsPreview()) |
|||
return; |
|||
|
|||
foreach (var slot in outputSlots) |
|||
{ |
|||
if (slot.edges.Count == 0) |
|||
continue; |
|||
|
|||
var defaultValue = GetSlotDefaultValue(slot.name); |
|||
if (defaultValue != null) |
|||
defaultValue.GeneratePropertyUsages(visitor, generationMode, slotValueType); |
|||
} |
|||
} |
|||
|
|||
protected override void CollectPreviewMaterialProperties (List<PreviewProperty> properties) |
|||
{ |
|||
base.CollectPreviewMaterialProperties(properties); |
|||
foreach (var slot in outputSlots) |
|||
{ |
|||
if (slot.edges.Count == 0) |
|||
continue; |
|||
|
|||
var defaultOutput = GetSlotDefaultValue(slot.name); |
|||
if (defaultOutput == null) |
|||
continue; |
|||
|
|||
var pp = new PreviewProperty |
|||
{ |
|||
m_Name = defaultOutput.inputName, |
|||
m_PropType = PropertyType.Vector4, |
|||
m_Vector4 = defaultOutput.defaultValue |
|||
}; |
|||
properties.Add (pp); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: af738716871e4a345ac8edc429a3b665 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
//[Title("Sub-graph/Sub-graph Node")]
|
|||
public class SubGraphNode : BaseMaterialNode, IGeneratesBodyCode, IGeneratesVertexToFragmentBlock, IGeneratesFunction, IGeneratesVertexShaderBlock |
|||
{ |
|||
[SerializeField] |
|||
private MaterialSubGraph m_SubGraphAsset; |
|||
|
|||
public MaterialSubGraph subGraphAsset { get { return m_SubGraphAsset; } } |
|||
|
|||
public override PreviewMode previewMode |
|||
{ |
|||
get |
|||
{ |
|||
if (subGraphAsset == null) |
|||
return PreviewMode.Preview2D; |
|||
var nodes = ListPool<BaseMaterialNode>.Get(); |
|||
var preview3D = subGraphAsset.outputsNode.CollectChildNodesByExecutionOrder(nodes).Any(x => x.previewMode == PreviewMode.Preview3D); |
|||
ListPool <BaseMaterialNode >.Release(nodes); |
|||
return preview3D ? PreviewMode.Preview3D : PreviewMode.Preview2D; |
|||
} |
|||
} |
|||
|
|||
public const int kMaxSlots = 16; |
|||
|
|||
public override void OnCreate() |
|||
{ |
|||
base.OnCreate(); |
|||
name = "SubGraph"; |
|||
position = new Rect(position.x, position.y, Mathf.Max(300, position.width), position.height); |
|||
} |
|||
|
|||
static string GetInputSlotName(int n) |
|||
{ |
|||
return string.Format("I{0:00}", n); |
|||
} |
|||
|
|||
static string GetOutputSlotName(int n) |
|||
{ |
|||
return string.Format("O{0:00}", n); |
|||
} |
|||
|
|||
/* public override IEnumerable<Slot> GetValidInputSlots() |
|||
{ |
|||
// We only want to return the input slots that are internally wired to an output slot
|
|||
return base.GetValidInputSlots().Where(slot => m_SubGraphAsset.InputInternallyWired(slot.name, this)).ToList(); |
|||
}*/ |
|||
|
|||
public override void NodeUI(GraphGUI host) |
|||
{ |
|||
EditorGUI.BeginChangeCheck(); |
|||
m_SubGraphAsset = (MaterialSubGraph)EditorGUILayout.ObjectField(GUIContent.none, m_SubGraphAsset, typeof(MaterialSubGraph), false); |
|||
if (EditorGUI.EndChangeCheck() && m_SubGraphAsset != null) |
|||
{ |
|||
SubGraphChanged(m_SubGraphAsset); |
|||
} |
|||
} |
|||
|
|||
private void SubGraphChanged(MaterialSubGraph sender) |
|||
{ |
|||
RefreshSlots(SlotType.InputSlot, inputSlots.ToList(), sender.inputsNode.slots, (s) => true); |
|||
RefreshSlots(SlotType.OutputSlot, outputSlots.ToList(), sender.outputsNode.slots, sender.OutputInternallyWired); |
|||
pixelGraph.RevalidateGraph(); |
|||
} |
|||
|
|||
private void RefreshSlots(SlotType type, IEnumerable<Slot> current, IEnumerable<Slot> updated, Func<string, bool> slotFilter) |
|||
{ |
|||
var innerOutputSlots = updated.Where(n => slotFilter(n.name)).ToArray(); |
|||
foreach (var slot in innerOutputSlots) |
|||
{ |
|||
var s = current.FirstOrDefault(n => n.name == slot.name); |
|||
if (s != null) |
|||
s.title = slot.title; |
|||
// else
|
|||
// AddSlot(new Slot(type, slot.name, slot.title));
|
|||
} |
|||
|
|||
var danglingSlots = current.Except(innerOutputSlots, (ls, rs) => ls.name == rs.name).ToArray(); |
|||
foreach (var slot in danglingSlots) |
|||
RemoveSlot(slot); |
|||
} |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator shaderBodyVisitor, GenerationMode generationMode) |
|||
{ |
|||
if (m_SubGraphAsset == null) |
|||
return; |
|||
|
|||
var outputString = new ShaderGenerator(); |
|||
outputString.AddShaderChunk("// Subgraph for node " + GetOutputVariableNameForNode(), false); |
|||
|
|||
// Step 1...
|
|||
// find out which output slots are actually used
|
|||
//TODO: Be smarter about this and only output ones that are actually USED, not just connected
|
|||
//var validOutputSlots = NodeUtils.GetSlotsThatOutputToNodeRecurse(this, (graph as BaseMaterialGraph).masterNode);
|
|||
var validOutputSlots = outputSlots.Where(x => x.edges.Count > 0); |
|||
foreach (var slot in validOutputSlots) |
|||
{ |
|||
outputString.AddShaderChunk( |
|||
"float4 " |
|||
+ GetOutputVariableNameForSlot(slot, generationMode) |
|||
+ " = float4(0, 0, 0, 0);", false); |
|||
} |
|||
|
|||
// Step 2...
|
|||
// Go into the subgraph
|
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
|
|||
// Step 3...
|
|||
// For each input that is used and connects through we want to generate code.
|
|||
// First we assign the input variables to the subgraph
|
|||
foreach (var slot in slots) |
|||
{ |
|||
if (!slot.isInputSlot) |
|||
continue; |
|||
|
|||
// see if the input connects all the way though to the output
|
|||
// if it does allow generation
|
|||
var inputWired = m_SubGraphAsset.InputInternallyWired(slot.name, this); |
|||
if (!inputWired) |
|||
continue; |
|||
|
|||
var varName = m_SubGraphAsset.GetInputVariableNameForSlotByName(slot.name, this, generationMode); |
|||
var varValue = "float4(0, 0, 0, 0);"; |
|||
var slotDefaultValue = GetSlotDefaultValue(slot.name); |
|||
if (slotDefaultValue != null) |
|||
{ |
|||
varValue = slotDefaultValue.GetDefaultValue(generationMode, concreteInputSlotValueTypes[slot.name]); |
|||
} |
|||
bool externallyWired = slot.edges.Count > 0; |
|||
if (externallyWired) |
|||
{ |
|||
var fromSlot = slot.edges[0].fromSlot; |
|||
var fromNode = slot.edges[0].fromSlot.node as BaseMaterialNode; |
|||
varValue = fromNode.GetOutputVariableNameForSlot(fromSlot, generationMode); |
|||
} |
|||
|
|||
outputString.AddShaderChunk("float4 " + varName + " = " + varValue + ";", false); |
|||
} |
|||
|
|||
// Step 4...
|
|||
// Using the inputs we can now generate the shader body :)
|
|||
var bodyGenerator = new ShaderGenerator(); |
|||
m_SubGraphAsset.GenerateNodeCode(bodyGenerator, this); |
|||
outputString.AddShaderChunk(bodyGenerator.GetShaderString(0), false); |
|||
|
|||
// Step 5...
|
|||
// Copy the outputs to the parent context name);
|
|||
foreach (var slot in validOutputSlots) |
|||
{ |
|||
bool internallyWired = m_SubGraphAsset.OutputInternallyWired(slot.name); |
|||
if (internallyWired) |
|||
{ |
|||
outputString.AddShaderChunk( |
|||
GetOutputVariableNameForSlot(slot, generationMode) |
|||
+ " = " |
|||
+ m_SubGraphAsset.GetOutputVariableNameForSlotByName(slot.name, this, generationMode) |
|||
+ ";", false); |
|||
} |
|||
} |
|||
|
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
outputString.AddShaderChunk("// Subgraph ends", false); |
|||
|
|||
shaderBodyVisitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
|
|||
public void GenerateVertexToFragmentBlock(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
m_SubGraphAsset.GenerateVertexToFragmentBlock(visitor, GenerationMode.SurfaceShader); |
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
m_SubGraphAsset.GenerateNodeFunction(visitor, GenerationMode.SurfaceShader); |
|||
} |
|||
|
|||
public void GenerateVertexShaderBlock(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
m_SubGraphAsset.GenerateVertexShaderBlock(visitor, GenerationMode.SurfaceShader); |
|||
} |
|||
|
|||
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
base.GeneratePropertyBlock(visitor, generationMode); |
|||
m_SubGraphAsset.GeneratePropertyBlock(visitor, GenerationMode.SurfaceShader); |
|||
} |
|||
|
|||
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode, ConcreteSlotValueType slotValueType) |
|||
{ |
|||
base.GeneratePropertyUsages(visitor, generationMode, slotValueType); |
|||
m_SubGraphAsset.GeneratePropertyUsages(visitor, GenerationMode.SurfaceShader, slotValueType); |
|||
} |
|||
|
|||
protected override void CollectPreviewMaterialProperties (List<PreviewProperty> properties) |
|||
{ |
|||
base.CollectPreviewMaterialProperties(properties); |
|||
properties.AddRange(m_SubGraphAsset.GetPreviewProperties()); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 047e0841c1476e041935baac6d7bb652 |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
public class SubGraphOutputsNode : SubGraphIOBaseNode |
|||
{ |
|||
public override void OnCreate() |
|||
{ |
|||
base.OnCreate(); |
|||
name = "SubGraphOutputs"; |
|||
title = "Outputs"; |
|||
//position = new Rect(BaseMaterialGraphGUI.kDefaultNodeWidth * 8, BaseMaterialGraphGUI.kDefaultNodeHeight * 2, Mathf.Max(300, position.width), position.height);
|
|||
} |
|||
|
|||
public override void AddSlot() |
|||
{ |
|||
//AddSlot(new Slot(SlotType.InputSlot, GenerateSlotName(SlotType.InputSlot)));
|
|||
} |
|||
} |
|||
} |
部分文件因为文件数量过多而无法显示
撰写
预览
正在加载...
取消
保存
Reference in new issue