浏览代码

[shader graph]

*Allow drawn nodes to invaludate the model in OnGUI for the node (if for example the slots change)
*Lighting functions now determine what is available on master pixel node
/main
Tim Cooper 9 年前
当前提交
f93f8c6b
共有 15 个文件被更改,包括 185 次插入128 次删除
  1. 9
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/DrawableMaterialNode.cs
  2. 101
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/BaseLightFunction.cs
  3. 25
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/SimpleSpecularFunction.cs
  4. 25
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/WrapLambertFunction.cs
  5. 28
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BaseMaterialNode.cs
  6. 6
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BlendNode.cs
  7. 6
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ColorNode.cs
  8. 67
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PixelShaderNode.cs
  9. 6
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SwizzleNode.cs
  10. 8
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/TextureNode.cs
  11. 6
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector1Node.cs
  12. 6
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector2Node.cs
  13. 6
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector3Node.cs
  14. 6
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector4Node.cs
  15. 8
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/ShaderGenerator.cs

9
UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/DrawableMaterialNode.cs


return;
}
if (m_Node.NodeUI(m_NodeUIRect))
var modificationType = m_Node.NodeUI(m_NodeUIRect);
if (modificationType== GUIModificationType.Repaint)
}
else if (modificationType == GUIModificationType.ModelChanged)
{
ParentCanvas().ReloadData();
ParentCanvas().Repaint();
return;
}
if (m_Node.hasPreview

101
UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/BaseLightFunction.cs


using System.Collections.Generic;
using UnityEditor.Graphs;
namespace UnityEditor.MaterialGraph

public const string kNormalSlotName = "Normal";
public virtual string GetLightFunctionName() { return ""; }
public virtual string GetSurfaceOutputStructureName() { return ""; }
public virtual void GenerateLightFunctionBody(ShaderGenerator visitor) {}

visitor.AddPragmaChunk(GetSurfaceOutputStructureName());
}
public virtual IEnumerable<Slot> FilterSlots(List<Slot> slots)
public abstract void DoSlotsForConfiguration(PixelShaderNode node);
public virtual string GetFirstPassSlotName()
return new List<Slot>();
return kNormalSlotName;
public const string kAlbedoSlotName = "Albedo";
public const string kEmissionSlotName = "Emission";
public const string kMetallicSlotName = "Metallic";
public const string kSmoothnessSlotName = "Smoothness";
public const string kOcclusion = "Occlusion";
public const string kAlphaSlotName = "Alpha";
public override void DoSlotsForConfiguration(PixelShaderNode node)
{
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlbedoSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kNormalSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kEmissionSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kMetallicSlotName), SlotValueType.Vector1));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kSmoothnessSlotName), SlotValueType.Vector1));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kOcclusion), SlotValueType.Vector1));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlphaSlotName), SlotValueType.Vector1));
public override IEnumerable<Slot> FilterSlots(List<Slot> slots)
{
var rSlots = new List<Slot>();
foreach (var slot in slots)
{
switch (slot.name)
// clear out slot names that do not match the slots
// we support
node.RemoveSlotsNameNotMatching(
new[]
case PixelShaderNode.kAlbedoSlotName:
case PixelShaderNode.kNormalSlotName:
case PixelShaderNode.kEmissionSlotName:
case PixelShaderNode.kMetallicSlotName:
case PixelShaderNode.kSmoothnessSlotName:
case PixelShaderNode.kOcclusion:
case PixelShaderNode.kAlphaSlotName:
rSlots.Add(slot);
break;
}
}
return rSlots;
kAlbedoSlotName,
kNormalSlotName,
kEmissionSlotName,
kMetallicSlotName,
kSmoothnessSlotName,
kOcclusion,
kAlphaSlotName
});
public const string kAlbedoSlotName = "Albedo";
public const string kSpecularSlotName = "Specular";
public const string kEmissionSlotName = "Emission";
public const string kSmoothnessSlotName = "Smoothness";
public const string kOcclusion = "Occlusion";
public const string kAlphaSlotName = "Alpha";
public override IEnumerable<Slot> FilterSlots(List<Slot> slots)
public override void DoSlotsForConfiguration(PixelShaderNode node)
var rSlots = new List<Slot>();
foreach (var slot in slots)
{
switch (slot.name)
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlbedoSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kNormalSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kSpecularSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kEmissionSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kSmoothnessSlotName), SlotValueType.Vector1));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kOcclusion), SlotValueType.Vector1));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlphaSlotName), SlotValueType.Vector1));
// clear out slot names that do not match the slots
// we support
node.RemoveSlotsNameNotMatching(
new[]
case PixelShaderNode.kAlbedoSlotName:
case PixelShaderNode.kSpecularSlotName:
case PixelShaderNode.kNormalSlotName:
case PixelShaderNode.kEmissionSlotName:
case PixelShaderNode.kSmoothnessSlotName:
case PixelShaderNode.kOcclusion:
case PixelShaderNode.kAlphaSlotName:
rSlots.Add(slot);
break;
}
}
return rSlots;
kAlbedoSlotName,
kNormalSlotName,
kSpecularSlotName,
kEmissionSlotName,
kSmoothnessSlotName,
kOcclusion,
kAlphaSlotName
});
}
}
}

25
UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/SimpleSpecularFunction.cs


using System;
using UnityEngine;
using UnityEditor.Graphs;
public const string kAlbedoSlotName = "Albedo";
public const string kAlphaSlotName = "Alpha";
public override string GetSurfaceOutputStructureName() {return "SurfaceOutput";}
public override void GenerateLightFunctionBody(ShaderGenerator visitor)
{
var outputString = new ShaderGenerator();

outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
public override void DoSlotsForConfiguration(PixelShaderNode node)
{
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlbedoSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kNormalSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlphaSlotName), SlotValueType.Vector1));
// clear out slot names that do not match the slots
// we support
node.RemoveSlotsNameNotMatching(
new[]
{
kAlbedoSlotName,
kNormalSlotName,
kAlphaSlotName
});
}
}
}

25
UnityProject/Assets/UnityShaderEditor/Editor/Source/Light/WrapLambertFunction.cs


using System;
using UnityEngine;
using UnityEditor.Graphs;
public const string kAlbedoSlotName = "Albedo";
public const string kAlphaSlotName = "Alpha";
public override string GetSurfaceOutputStructureName() { return "SurfaceOutput"; }
public override void GenerateLightFunctionBody(ShaderGenerator visitor)
{
var outputString = new ShaderGenerator();

outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
public override void DoSlotsForConfiguration(PixelShaderNode node)
{
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlbedoSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kNormalSlotName), SlotValueType.Vector3));
node.AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlphaSlotName), SlotValueType.Vector1));
// clear out slot names that do not match the slots
// we support
node.RemoveSlotsNameNotMatching(new[]
{
kAlbedoSlotName,
kNormalSlotName,
kAlphaSlotName
});
}
}
}

28
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BaseMaterialNode.cs


if (string.IsNullOrEmpty(slot))
return;
m_SlotValueTypes.Add(slot, slotType);
if (m_SlotValueTypes.ContainsKey(slot))
m_SlotValueTypes[slot] = slotType;
else
m_SlotValueTypes.Add(slot, slotType);
}
public string precision

return 0;
}
public virtual bool NodeUI(Rect drawArea)
public virtual GUIModificationType NodeUI(Rect drawArea)
return false;
return GUIModificationType.None;
}
protected virtual void OnPreviewGUI()

return inputValue;
}
protected void RemoveSlotsNameNotMatching(string[] slotNames)
public void RemoveSlotsNameNotMatching(string[] slotNames)
{
var invalidSlots = slots.Select(x => x.name).Except(slotNames);

public ConcreteSlotValueType GetConcreteOutputSlotValueType(Slot slot)
{
return concreteOutputSlotValueTypes[slot.name];
if (concreteOutputSlotValueTypes.ContainsKey(slot.name))
return concreteOutputSlotValueTypes[slot.name];
return ConcreteSlotValueType.Error;
return concreteInputSlotValueTypes[slot.name];
if (concreteInputSlotValueTypes.ContainsKey(slot.name))
return concreteInputSlotValueTypes[slot.name];
return ConcreteSlotValueType.Error;
}
private ConcreteSlotValueType FindCommonChannelType(ConcreteSlotValueType @from, ConcreteSlotValueType to)

}
}
public enum GUIModificationType
{
None,
Repaint,
ModelChanged
}
}

6
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BlendNode.cs


return 2.0f * EditorGUIUtility.singleLineHeight;
}
public override bool NodeUI(Rect drawArea)
public override GUIModificationType NodeUI(Rect drawArea)
{
base.NodeUI(drawArea);

if (EditorGUI.EndChangeCheck())
{
pixelGraph.RevalidateGraph();
return true;
return GUIModificationType.Repaint;
return false;
return GUIModificationType.None;
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)

6
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/ColorNode.cs


}
public override bool NodeUI(Rect drawArea)
public override GUIModificationType NodeUI(Rect drawArea)
{
base.NodeUI(drawArea);

return true;
return GUIModificationType.Repaint;
return false;
return GUIModificationType.None;
}
public override PreviewProperty GetPreviewProperty()

67
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PixelShaderNode.cs


namespace UnityEditor.MaterialGraph
{
[Title("Output/Pixel Shader")]
class PixelShaderNode : BaseMaterialNode, IGeneratesBodyCode
public class PixelShaderNode : BaseMaterialNode, IGeneratesBodyCode
public const string kAlbedoSlotName = "Albedo";
public const string kSpecularSlotName = "Specular";
public const string kNormalSlotName = "Normal";
public const string kEmissionSlotName = "Emission";
public const string kMetallicSlotName = "Metallic";
public const string kSmoothnessSlotName = "Smoothness";
public const string kOcclusion = "Occlusion";
public const string kAlphaSlotName = "Alpha";
[SerializeField]
private string m_LightFunctionClassName;

{
base.OnEnable();
AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlbedoSlotName), SlotValueType.Vector3));
AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kNormalSlotName), SlotValueType.Vector3));
AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kSpecularSlotName), SlotValueType.Vector3));
AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kEmissionSlotName), SlotValueType.Vector3));
AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kMetallicSlotName), SlotValueType.Vector1));
AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kSmoothnessSlotName), SlotValueType.Vector1));
AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kOcclusion), SlotValueType.Vector1));
AddSlot(new MaterialGraphSlot(new Slot(SlotType.InputSlot, kAlphaSlotName), SlotValueType.Vector1));
// clear out slot names that do not match the slots
// we support
RemoveSlotsNameNotMatching(
new[]
{
kAlbedoSlotName,
kNormalSlotName,
kSpecularSlotName,
kEmissionSlotName,
kMetallicSlotName,
kSmoothnessSlotName,
kOcclusion,
kAlphaSlotName
});
var lightFunction = GetLightFunction();
lightFunction.DoSlotsForConfiguration(this);
}
public override void OnCreate()

var lightFunction = GetLightFunction();
lightFunction.GenerateSurfaceOutputStructureName(visitor);
}
public virtual IEnumerable<Slot> FilterSlotsForLightFunction()
{
var lightFunction = GetLightFunction();
return lightFunction.FilterSlots(slots);
}
var lightFunction = GetLightFunction();
var firstPassSlotName = lightFunction.GetFirstPassSlotName();
var normal = FindInputSlot(kNormalSlotName);
var firstPassSlot = FindInputSlot(firstPassSlotName);
CollectChildNodesByExecutionOrder(nodes, normal, false);
CollectChildNodesByExecutionOrder(nodes, firstPassSlot, false);
for (int index = 0; index < nodes.Count; index++)
{

}
for (int index = 0; index < normal.edges.Count; index++)
for (int index = 0; index < firstPassSlot.edges.Count; index++)
var edge = normal.edges[index];
var edge = firstPassSlot.edges[index];
shaderBody.AddShaderChunk("o." + normal.name + " = " + node.GetOutputVariableNameForSlot(edge.fromSlot, generationMode) + ";", true);
shaderBody.AddShaderChunk("o." + firstPassSlot.name + " = " + node.GetOutputVariableNameForSlot(edge.fromSlot, generationMode) + ";", true);
}
// track the last index of nodes... they have already been processed :)

ListPool<BaseMaterialNode>.Release(nodes);
foreach (var slot in FilterSlotsForLightFunction())
foreach (var slot in inputSlots)
if (slot == normal)
if (slot == firstPassSlot)
continue;
foreach (var edge in slot.edges)

return EditorGUIUtility.singleLineHeight;
}
public override bool NodeUI(Rect drawArea)
public override GUIModificationType NodeUI(Rect drawArea)
{
var lightFunctions = GetLightFunctions();
var lightFunction = GetLightFunction();

m_LightFunctionClassName = lightFunctions[lightFuncIndex].GetType().ToString();
if (EditorGUI.EndChangeCheck())
{
var function = GetLightFunction();
function.DoSlotsForConfiguration(this);
return true;
return GUIModificationType.ModelChanged;
return false;
return GUIModificationType.None;
}
public override IEnumerable<Slot> GetDrawableInputProxies()
{

6
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SwizzleNode.cs


return EditorGUIUtility.singleLineHeight;
}
public override bool NodeUI(Rect drawArea)
public override GUIModificationType NodeUI(Rect drawArea)
{
base.NodeUI(drawArea);
string[] channelNames = {"X", "Y", "Z", "W"};

if (EditorGUI.EndChangeCheck())
{
pixelGraph.RevalidateGraph();
return true;
return GUIModificationType.Repaint;
return false;
return GUIModificationType.None;
}
protected override string GetFunctionName()

8
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/TextureNode.cs


var uvName = "IN.meshUV0.xy";
if (uvSlot.edges.Count > 0)
uvName = ShaderGenerator.AdaptNodeOutput(uvSlot.edges[0].fromSlot, generationMode, ConcreteSlotValueType.Vector2);
uvName = ShaderGenerator.AdaptNodeOutput(uvSlot.edges[0].fromSlot, generationMode, ConcreteSlotValueType.Vector2, true);
string body = "tex2D (" + propertyName + ", " + uvName + ")";
if (m_TextureType == TextureType.Bump)

return EditorGUIUtility.singleLineHeight * 2;
}
public override bool NodeUI(Rect drawArea)
public override GUIModificationType NodeUI(Rect drawArea)
{
LoadTextureTypes();

if (typeChanged)
{
pixelGraph.RevalidateGraph();
return true;
return GUIModificationType.Repaint;
return texureChanged;
return texureChanged ? GUIModificationType.Repaint : GUIModificationType.None;
}
public override PreviewProperty GetPreviewProperty()

6
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector1Node.cs


visitor.AddShaderChunk(precision + " " + propertyName + " = " + m_Value + ";", true);
}
public override bool NodeUI(Rect drawArea)
public override GUIModificationType NodeUI(Rect drawArea)
{
base.NodeUI(drawArea);

{
return true;
return GUIModificationType.Repaint;
return false;
return GUIModificationType.None;
}
public override PreviewProperty GetPreviewProperty()

6
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector2Node.cs


visitor.AddShaderChunk(precision + "2 " + propertyName + " = " + precision + "2 (" + m_Value.x + ", " + m_Value.y + ");", true);
}
public override bool NodeUI(Rect drawArea)
public override GUIModificationType NodeUI(Rect drawArea)
{
base.NodeUI(drawArea);

{
return true;
return GUIModificationType.Repaint;
return false;
return GUIModificationType.None;
}
public override PreviewProperty GetPreviewProperty()

6
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector3Node.cs


visitor.AddShaderChunk(precision + "3 " + propertyName + " = " + precision + "3 (" + m_Value.x + ", " + m_Value.y + ", " + m_Value.z + ");", true);
}
public override bool NodeUI(Rect drawArea)
public override GUIModificationType NodeUI(Rect drawArea)
{
base.NodeUI(drawArea);

return true;
return false;
return GUIModificationType.Repaint;
return GUIModificationType.None;
}
public override PreviewProperty GetPreviewProperty()

6
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/Vector4Node.cs


visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + precision + "4 (" + m_Value.x + ", " + m_Value.y + ", " + m_Value.z + ", " + m_Value.w + ");", true);
}
public override bool NodeUI(Rect drawArea)
public override GUIModificationType NodeUI(Rect drawArea)
{
base.NodeUI(drawArea);

return true;
return false;
return GUIModificationType.Repaint;
return GUIModificationType.None;
}
public override PreviewProperty GetPreviewProperty()

8
UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/ShaderGenerator.cs


}
private const string kErrorString = @"ERROR!";
public static string AdaptNodeOutput(Slot outputSlot, GenerationMode mode, ConcreteSlotValueType convertToType)
public static string AdaptNodeOutput(Slot outputSlot, GenerationMode mode, ConcreteSlotValueType convertToType, bool textureSampleUVHack = false)
{
if (outputSlot == null)
return kErrorString;

switch (convertFromType)
{
case ConcreteSlotValueType.Vector1:
return string.Format("({0}.xx)", rawOutput);
return string.Format("({0}{1})", rawOutput, textureSampleUVHack ? ".xx" : string.Empty);
case ConcreteSlotValueType.Vector3:
case ConcreteSlotValueType.Vector4:
return string.Format("({0}.xy)", rawOutput);

switch (convertFromType)
{
case ConcreteSlotValueType.Vector1:
return string.Format("({0}.xxx)", rawOutput);
return string.Format("({0}{1})", rawOutput, textureSampleUVHack ? ".xxx" : string.Empty);
case ConcreteSlotValueType.Vector4:
return string.Format("({0}.xyz)", rawOutput);
default:

switch (convertFromType)
{
case ConcreteSlotValueType.Vector1:
return string.Format("({0}.xxxx)", rawOutput);
return string.Format("({0}{1})", rawOutput, textureSampleUVHack ? ".xxxx" : string.Empty);
default:
return kErrorString;
}

正在加载...
取消
保存