浏览代码

[MaterialGraph] Compiling (and working) specular / metal setups.

/main
Tim Cooper 9 年前
当前提交
1eaab6d4
共有 9 个文件被更改,包括 152 次插入73 次删除
  1. 79
      UnityProject/Assets/Editor/Material/Light/BaseLightFunction.cs
  2. 6
      UnityProject/Assets/Editor/Material/Light/SimpleSpecularFunction.cs
  3. 6
      UnityProject/Assets/Editor/Material/Light/WrapLambertFunction.cs
  4. 4
      UnityProject/Assets/Editor/Material/MaterialGraph.cs
  5. 75
      UnityProject/Assets/Editor/Material/Nodes/PixelShaderNode.cs
  6. 49
      UnityProject/Assets/Editor/Material/PixelGraph.cs
  7. 3
      UnityProject/Assets/Editor/Material/Util/ShaderGenerator.cs
  8. 1
      UnityProject/Assets/Graphs/FresnelFromSGraph.ShaderGraph
  9. 2
      UnityProject/Assets/MaterialGraph/shader.template

79
UnityProject/Assets/Editor/Material/Light/BaseLightFunction.cs


using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.Graphs.Material

public virtual string GetName () { return ""; }
public virtual void GenerateBody (ShaderGenerator visitor) {}
public virtual string GetLightFunctionName () { return ""; }
public virtual string GetSurfaceOutputStructureName () { return ""; }
public virtual void GenerateLightFunctionBody (ShaderGenerator visitor) {}
public virtual void GenerateLightFunctionName(ShaderGenerator visitor)
{
visitor.AddPragmaChunk(GetLightFunctionName());
}
public virtual void GenerateSurfaceOutputStructureName(ShaderGenerator visitor)
{
visitor.AddPragmaChunk(GetSurfaceOutputStructureName());
}
public virtual IEnumerable<Slot> FilterSlots(List<Slot> slots)
{
return new List<Slot>();
}
class LambertLightFunction : BaseLightFunction
class PBRMetalicLightFunction : BaseLightFunction
public override string GetName () { return "Lambert"; }
public override string GetLightFunctionName () { return "Standard"; }
public override string GetSurfaceOutputStructureName () { return "SurfaceOutputStandard"; }
public override IEnumerable<Slot> FilterSlots(List<Slot> slots)
{
var rSlots = new List<Slot>();
foreach (var slot in slots)
{
switch (slot.name)
{
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;
}
class BlinnPhongLightFunction : BaseLightFunction
class PBRSpecularLightFunction : BaseLightFunction
public override string GetName () { return "BlinnPhong"; }
}
class PBRMetalicLightFunction : BaseLightFunction
{
public override string GetName () { return "Standard"; }
public override string GetLightFunctionName () { return "StandardSpecular"; }
public override string GetSurfaceOutputStructureName () { return "SurfaceOutputStandardSpecular"; }
public override IEnumerable<Slot> FilterSlots(List<Slot> slots)
{
var rSlots = new List<Slot>();
foreach (var slot in slots)
{
switch (slot.name)
{
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;
}
}
}

6
UnityProject/Assets/Editor/Material/Light/SimpleSpecularFunction.cs


{
class SimpleSpecularFunction : BaseLightFunction
{
public override string GetName () { return "SimpleSpecular"; }
public override void GenerateBody(ShaderGenerator visitor)
public override string GetLightFunctionName () { return "SimpleSpecular"; }
public override void GenerateLightFunctionBody(ShaderGenerator visitor)
outputString.AddShaderChunk ("half4 Lighting" + GetName () + " (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)", false);
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);

6
UnityProject/Assets/Editor/Material/Light/WrapLambertFunction.cs


{
class WrapLambertFunction : BaseLightFunction
{
public override string GetName () { return "WrapLambert"; }
public override void GenerateBody(ShaderGenerator visitor)
public override string GetLightFunctionName () { return "WrapLambert"; }
public override void GenerateLightFunctionBody(ShaderGenerator visitor)
outputString.AddShaderChunk ("half4 Lighting" + GetName () + " (SurfaceOutput s, half3 lightDir, half atten)", false);
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);

4
UnityProject/Assets/Editor/Material/MaterialGraph.cs


m_Shader = UnityEditor.ShaderUtil.CreateShaderAsset(shaderSource);
m_Shader.name = name;
//m_Shader.hideFlags = HideFlags.HideInHierarchy;
m_Shader.hideFlags = HideFlags.HideInHierarchy;
m_PixelGraph.AddMasterNodeToAsset ();
}
}
}

75
UnityProject/Assets/Editor/Material/Nodes/PixelShaderNode.cs


[Title("Output/Pixel Shader")]
class PixelShaderNode : BaseMaterialNode, IGeneratesBodyCode
{
private const string kAlbedoSlotName = "Albedo";
private const string kNormalSlotName = "Normal";
private const string kEmissionSlotName = "Emission";
private const string kMetallicSlotName = "Metallic";
private const string kSmoothnessSlotName = "Smoothness";
private const string kOcclusion = "Occlusion";
private const string kAlphaSlotName = "Alpha";
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";
private string m_LightFunction;
private string m_LightFunctionClassName;
private static List<BaseLightFunction> s_LightFunctions;

AddSlot (new Slot(SlotType.InputSlot, kAlbedoSlotName));
AddSlot (new Slot(SlotType.InputSlot, kNormalSlotName));
AddSlot (new Slot(SlotType.InputSlot, kSpecularSlotName));
AddSlot (new Slot(SlotType.InputSlot, kEmissionSlotName));
AddSlot (new Slot(SlotType.InputSlot, kMetallicSlotName));
AddSlot (new Slot(SlotType.InputSlot, kSmoothnessSlotName));

}
return s_LightFunctions;
}
public virtual void GenerateLightFunction (ShaderGenerator visitor)
{
visitor.AddPragmaChunk (m_LightFunction);
private BaseLightFunction GetLightFunction()
{
var lightFunctions = GetLightFunctions();
var lightFunction = lightFunctions.FirstOrDefault(x => x.GetType().ToString() == m_LightFunctionClassName);
if (lightFunction == null && lightFunctions.Count > 0)
lightFunction = lightFunctions[0];
var lightFunction = GetLightFunctions().FirstOrDefault(x => x.GetName() == m_LightFunction);
int lightFuncIndex = 0;
if (lightFunction != null)
lightFuncIndex = GetLightFunctions ().IndexOf (lightFunction);
return lightFunction;
}
if (lightFuncIndex < s_LightFunctions.Count)
{
BaseLightFunction func = s_LightFunctions[lightFuncIndex];
func.GenerateBody (visitor);
}
public virtual void GenerateLightFunction (ShaderGenerator visitor)
{
var lightFunction = GetLightFunction();
lightFunction.GenerateLightFunctionName(visitor);
lightFunction.GenerateLightFunctionBody (visitor);
public void GenerateSurfaceOutput(ShaderGenerator visitor)
{
var lightFunction = GetLightFunction();
lightFunction.GenerateSurfaceOutputStructureName(visitor);
}
public virtual IEnumerable<Slot> FilterSlotsForLightFunction()
{
var lightFunction = GetLightFunction();
return lightFunction.FilterSlots(slots);
}
public void GenerateNodeCode(ShaderGenerator shaderBody, GenerationMode generationMode)
{
// do the normal slot first so that it can be used later in the shader :)

(node as IGeneratesBodyCode).GenerateNodeCode(shaderBody, generationMode);
}
foreach (var slot in slots)
foreach (var slot in FilterSlotsForLightFunction())
{
if (slot == normal)
continue;

public override void NodeUI (Graphs.GraphGUI host)
{
base.NodeUI(host);
var lightFunction = GetLightFunctions ().FirstOrDefault (x => x.GetName () == m_LightFunction);
int lightFuncIndex = 0;
var lightFunctions = GetLightFunctions();
var lightFunction = GetLightFunction();
int lightFuncIndex = 0;
lightFuncIndex = GetLightFunctions ().IndexOf (lightFunction);
lightFuncIndex = EditorGUILayout.Popup (lightFuncIndex, s_LightFunctions.Select(x => x.GetName ()).ToArray (), EditorStyles.popup);
m_LightFunction = GetLightFunctions ()[lightFuncIndex].GetName ();
lightFuncIndex = lightFunctions.IndexOf (lightFunction);
lightFuncIndex = EditorGUILayout.Popup (lightFuncIndex, lightFunctions.Select(x => x.GetLightFunctionName ()).ToArray (), EditorStyles.popup);
m_LightFunctionClassName = lightFunctions[lightFuncIndex].GetType().ToString();
}
}
}

49
UnityProject/Assets/Editor/Material/PixelGraph.cs


{
class PixelGraph : BaseMaterialGraph, IGenerateGraphProperties
{
[SerializeField]
private PixelShaderNode m_MasterNode;
private PixelShaderNode m_PixelMasterNode;
get { return m_MasterNode; }
get { return pixelMasterNode; }
new void OnEnable ()
public PixelShaderNode pixelMasterNode
base.OnEnable ();
if (m_MasterNode == null)
{
m_MasterNode = CreateInstance<PixelShaderNode> ();
m_MasterNode.hideFlags = HideFlags.HideInHierarchy;
m_MasterNode.Init ();
m_MasterNode.position = new Rect(700, m_MasterNode.position.y, m_MasterNode.position.width, m_MasterNode.position.height);
AddMasterNodeNoAddToAsset (m_MasterNode);
}
get
{
if (m_PixelMasterNode == null)
m_PixelMasterNode = nodes.FirstOrDefault(x => x.GetType() == typeof (PixelShaderNode)) as PixelShaderNode;
if (m_PixelMasterNode == null)
{
m_PixelMasterNode = CreateInstance<PixelShaderNode>();
m_PixelMasterNode.hideFlags = HideFlags.HideInHierarchy;
m_PixelMasterNode.Init();
m_PixelMasterNode.position = new Rect(700, pixelMasterNode.position.y, pixelMasterNode.position.width, pixelMasterNode.position.height);
AddNode(m_PixelMasterNode);
}
return m_PixelMasterNode;
}
}
private IEnumerable<BaseMaterialNode> m_ActiveNodes;

{
if (m_ActiveNodes == null)
m_ActiveNodes = m_MasterNode.CollectChildNodesByExecutionOrder();
m_ActiveNodes = pixelMasterNode.CollectChildNodesByExecutionOrder();
return m_ActiveNodes;
}
}

ShaderGenerator shaderBody,
ShaderGenerator inputStruct,
ShaderGenerator lightFunction,
ShaderGenerator surfaceOutput,
m_MasterNode.GenerateLightFunction(lightFunction);
pixelMasterNode.GenerateLightFunction(lightFunction);
pixelMasterNode.GenerateSurfaceOutput(surfaceOutput);
owner.materialProperties.GenerateSharedProperties(shaderProperties, propertyUsages, GenerationMode.SurfaceShader);

}
}
m_MasterNode.GenerateNodeCode(shaderBody, GenerationMode.SurfaceShader);
}
public void AddMasterNodeToAsset ()
{
AssetDatabase.AddObjectToAsset (m_MasterNode, this);
pixelMasterNode.GenerateNodeCode(shaderBody, GenerationMode.SurfaceShader);
m_ActiveNodes = m_MasterNode.CollectChildNodesByExecutionOrder();
m_ActiveNodes = pixelMasterNode.CollectChildNodesByExecutionOrder();
m_ActiveNodes = m_MasterNode.CollectChildNodesByExecutionOrder();
m_ActiveNodes = pixelMasterNode.CollectChildNodesByExecutionOrder();
return ret;
}
}

3
UnityProject/Assets/Editor/Material/Util/ShaderGenerator.cs


var shaderBodyVisitor = new ShaderGenerator();
var shaderInputVisitor = new ShaderGenerator();
var shaderLightFunctionVisitor = new ShaderGenerator();
var shaderOutputSurfaceVisitor = new ShaderGenerator();
var shaderFunctionVisitor = new ShaderGenerator();
var shaderPropertiesVisitor = new PropertyGenerator();
var shaderPropertyUsagesVisitor = new ShaderGenerator();

shaderBodyVisitor,
shaderInputVisitor,
shaderLightFunctionVisitor,
shaderOutputSurfaceVisitor,
shaderFunctionVisitor,
shaderPropertiesVisitor,
shaderPropertyUsagesVisitor,

resultShader = resultShader.Replace("${ShaderPropertyUsages}", shaderPropertyUsagesVisitor.GetShaderString(2));
resultShader = resultShader.Replace("${LightingFunctionName}", shaderLightFunctionVisitor.GetPragmaString());
resultShader = resultShader.Replace("${LightingFunction}", shaderLightFunctionVisitor.GetShaderString(2));
resultShader = resultShader.Replace("${SurfaceOutputStructureName}", shaderOutputSurfaceVisitor.GetPragmaString());
resultShader = resultShader.Replace("${ShaderFunctions}", shaderFunctionVisitor.GetShaderString(2));
resultShader = resultShader.Replace("${ShaderInputs}", shaderInputVisitor.GetShaderString(3));
resultShader = resultShader.Replace("${PixelShaderBody}", shaderBodyVisitor.GetShaderString(3));

1
UnityProject/Assets/Graphs/FresnelFromSGraph.ShaderGraph


m_ToSlotName: O01
color: {r: 1, g: 1, b: 1, a: 1}
m_InvalidEdges: []
m_MasterNode: {fileID: 0}
--- !u!114 &11400010
MonoBehaviour:
m_ObjectHideFlags: 1

2
UnityProject/Assets/MaterialGraph/shader.template


${VertexShaderBody}
}
void surf (Input IN, inout SurfaceOutputStandard o)
void surf (Input IN, inout ${SurfaceOutputStructureName} o)
{
${PixelShaderBody}
}

正在加载...
取消
保存