浏览代码

Prepare shader generation for uber shader

/main
Peter Bay Bastian 7 年前
当前提交
b63c4c28
共有 3 个文件被更改,包括 185 次插入160 次删除
  1. 12
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Implementation/NodeUtils.cs
  2. 108
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/AbstractMaterialGraph.cs
  3. 225
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/SubGraph/LayeredShaderGraph.cs

12
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Implementation/NodeUtils.cs


nodeList.Add(node);
}
static Stack<INode> s_NodeStack = new Stack<INode>();
var nodeStack = new Stack<INode>();
nodeStack.Push(initialNode);
while (nodeStack.Any() && shaderStage == ShaderStage.Dynamic)
s_NodeStack.Clear();
s_NodeStack.Push(initialNode);
while (s_NodeStack.Any() && shaderStage == ShaderStage.Dynamic)
var node = nodeStack.Pop();
var node = s_NodeStack.Pop();
foreach (var slot in goingBackwards ? node.GetInputSlots<MaterialSlot>() : node.GetOutputSlots<MaterialSlot>())
{
if (shaderStage != ShaderStage.Dynamic)

var connectedNode = node.owner.GetNodeFromGuid(goingBackwards ? edge.outputSlot.nodeGuid : edge.inputSlot.nodeGuid);
var connectedSlot = goingBackwards ? connectedNode.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId) : connectedNode.FindInputSlot<MaterialSlot>(edge.inputSlot.slotId);
if (connectedSlot.shaderStage == ShaderStage.Dynamic)
nodeStack.Push(connectedNode);
s_NodeStack.Push(connectedNode);
else
{
shaderStage = connectedSlot.shaderStage;

108
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/AbstractMaterialGraph.cs


using System.Linq;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.Graphing.Util;
namespace UnityEditor.ShaderGraph
{

return GetShader(node, GenerationMode.Preview, string.Format("hidden/preview/{0}", node.GetVariableNameForNode()), out configuredTextures, out previewMode);
}
protected static void GenerateSurfaceDescriptionStruct(ShaderGenerator surfaceDescriptionStruct, AbstractMaterialNode node, bool isMasterNode)
protected static void GenerateSurfaceDescriptionStruct(ShaderGenerator surfaceDescriptionStruct, List<MaterialSlot> slots)
if (isMasterNode)
foreach (var slot in slots)
foreach (var slot in node.GetInputSlots<MaterialSlot>())
if (slot.isInputSlot)
}
else
{
foreach (var slot in node.GetOutputSlots<MaterialSlot>())
surfaceDescriptionStruct.AddShaderChunk(string.Format("{0} {1};", AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType), node.GetVariableNameForSlot(slot.id)), false);
else
surfaceDescriptionStruct.AddShaderChunk(string.Format("{0} {1};", AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType), ((AbstractMaterialNode) slot.owner).GetVariableNameForSlot(slot.id)), false);
}
surfaceDescriptionStruct.Deindent();
surfaceDescriptionStruct.AddShaderChunk("};", false);

if (isMasterNode)
foreach (var slot in slots)
foreach (var slot in node.GetInputSlots<MaterialSlot>())
surfaceDescriptionStruct.AddShaderChunk( string.Format("surface.{0} = scale * surface.{0};", slot.shaderOutputName), false);
}
else
{
foreach (var slot in node.GetOutputSlots<MaterialSlot>())
surfaceDescriptionStruct.AddShaderChunk(string.Format("surface.{0} = scale * surface.{0};", node.GetVariableNameForSlot(slot.id)), false);
if (slot.isInputSlot)
surfaceDescriptionStruct.AddShaderChunk(string.Format("surface.{0} = scale * surface.{0};", slot.shaderOutputName), false);
else
surfaceDescriptionStruct.AddShaderChunk(string.Format("surface.{0} = scale * surface.{0};", ((AbstractMaterialNode) slot.owner).GetVariableNameForSlot(slot.id)), false);
}
surfaceDescriptionStruct.Deindent();
surfaceDescriptionStruct.AddShaderChunk("};", false);

if (isMasterNode)
foreach (var slot in slots)
foreach (var slot in node.GetInputSlots<MaterialSlot>())
{
var str = string.Format("base.{0} = base.{0} + add.{0};", slot.shaderOutputName);
surfaceDescriptionStruct.AddShaderChunk(str, false);
}
}
else
{
foreach (var slot in node.GetOutputSlots<MaterialSlot>())
{
var str = string.Format("base.{0} = base.{0} + add.{0};", node.GetVariableNameForSlot(slot.id));
surfaceDescriptionStruct.AddShaderChunk(str, false);
}
if (slot.isInputSlot)
surfaceDescriptionStruct.AddShaderChunk(string.Format("base.{0} = base.{0} + add.{0};", slot.shaderOutputName), false);
else
surfaceDescriptionStruct.AddShaderChunk(string.Format("base.{0} = base.{0} + add.{0};", ((AbstractMaterialNode) slot.owner).GetVariableNameForSlot(slot.id)), false);
}
surfaceDescriptionStruct.Deindent();
surfaceDescriptionStruct.AddShaderChunk("};", false);

List<INode> activeNodeList,
AbstractMaterialNode node,
ShaderGenerator surfaceDescriptionFunction,
ShaderGenerator shaderFunctionVisitor,

graph.CollectShaderProperties(shaderProperties, mode);
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);
foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
{
if (activeNode is IGeneratesFunction)

surfaceDescriptionFunction.AddShaderChunk("return surface;", false);
surfaceDescriptionFunction.Deindent();
surfaceDescriptionFunction.AddShaderChunk("}", false);
ListPool<INode>.Release(activeNodeList);
}
static void Visit(List<INode> outputList, Dictionary<Guid, INode> unmarkedNodes, INode node)
{
if (!unmarkedNodes.ContainsKey(node.guid))
return;
foreach (var slot in node.GetInputSlots<ISlot>())
{
foreach (var edge in node.owner.GetEdges(slot.slotReference))
{
var inputNode = node.owner.GetNodeFromGuid(edge.outputSlot.nodeGuid);
Visit(outputList, unmarkedNodes, inputNode);
}
}
unmarkedNodes.Remove(node.guid);
outputList.Add(node);
public string GetShader(AbstractMaterialNode node, GenerationMode mode, string name, out List<PropertyCollector.TextureInfo> configuredTextures, out PreviewMode previewMode)
public string GetShader(AbstractMaterialNode node, GenerationMode mode, string name, out List<PropertyCollector.TextureInfo> configuredTextures, out PreviewMode previewMode, bool isUber = false)
{
if (node == null)
throw new ArgumentNullException("node");

surfaceInputs.Indent();
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);
if (isUber)
{
var unmarkedNodes = node.owner.GetNodes<INode>().ToDictionary(x => x.guid);
while (unmarkedNodes.Any())
{
var unmarkedNode = unmarkedNodes.FirstOrDefault();
Visit(activeNodeList, unmarkedNodes, unmarkedNode.Value);
}
}
else
{
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);
}
var requirements = GetRequirements(activeNodeList);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);

if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
previewMode = PreviewMode.Preview2D;
foreach (var pNode in activeNodeList.OfType<AbstractMaterialNode>())
previewMode = PreviewMode.Preview3D;
if (!isUber)
if (pNode.previewMode == PreviewMode.Preview3D)
foreach (var pNode in activeNodeList.OfType<AbstractMaterialNode>())
previewMode = PreviewMode.Preview3D;
break;
if (pNode.previewMode == PreviewMode.Preview3D)
{
previewMode = PreviewMode.Preview3D;
break;
}
ListPool<INode>.Release(activeNodeList);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);

vertexShader.Deindent();
vertexShader.AddShaderChunk("}", false);
GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, node, node is IMasterNode);
var slots = new List<MaterialSlot>();
foreach (var activeNode in isUber ? activeNodeList.Where(n => ((AbstractMaterialNode)n).hasPreview) : ((INode)node).ToEnumerable())
{
if (activeNode is IMasterNode)
slots.AddRange(activeNode.GetInputSlots<MaterialSlot>());
else
slots.AddRange(activeNode.GetOutputSlots<MaterialSlot>());
}
GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots);
activeNodeList,
node,
surfaceDescriptionFunction,
shaderFunctionVisitor,

node is IMasterNode);
ListPool<INode>.Release(activeNodeList);
var finalShader = new ShaderGenerator();
finalShader.AddShaderChunk(string.Format(@"Shader ""{0}""", name), false);

225
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/SubGraph/LayeredShaderGraph.cs


[SerializeField]
private Shader m_Shader;
public Layer()
{}
public Layer() { }
public Guid guid
{

if (outputNode != null)
outputNode.onModified(outputNode, ModificationScope.Graph);
}
}
public override void OnBeforeSerialize()

public string GetShader(string name, GenerationMode mode, out List<PropertyCollector.TextureInfo> configuredTextures)
{
if (outputNode == null)
if (outputNode == null)
throw new InvalidOperationException();
var layerMap = new Dictionary<Guid, MaterialGraph>();

surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
ShaderGraphRequirements requirements;
using (var activeNodesDisposable = ListPool<INode>.GetDisposable())
{
var activeNodes = activeNodesDisposable.value;

}
NodeUtils.DepthFirstCollectNodesFromNode(activeNodes, outputNode);
requirements = GetRequirements(activeNodes);
}
var requirements = GetRequirements(activeNodes);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceInputs);
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
vertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
vertexShader.Indent();
vertexShader.AddShaderChunk("return v;", false);
vertexShader.Deindent();
vertexShader.AddShaderChunk("}", false);
var shaderProperties = new PropertyCollector();
var baseGraph = layerMap.Values.FirstOrDefault();
if (baseGraph == null)
{
configuredTextures = new List<PropertyCollector.TextureInfo>();
return string.Empty;
}
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
var masterNode = baseGraph.masterNode;
GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, ((AbstractMaterialNode) masterNode).GetInputSlots<MaterialSlot>().ToList());
vertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
vertexShader.Indent();
vertexShader.AddShaderChunk("return v;", false);
vertexShader.Deindent();
vertexShader.AddShaderChunk("}", false);
foreach (var layer in layerMap)
{
activeNodes.Clear();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodes, layer.Value.masterNode as AbstractMaterialNode);
GenerateSurfaceDescription(
activeNodes,
layer.Value.masterNode as AbstractMaterialNode,
surfaceDescriptionFunction,
shaderFunctionVisitor,
shaderProperties,
requirements,
mode,
true,
LayerToFunctionName(layer.Key));
}
var shaderProperties = new PropertyCollector();
surfaceDescriptionStruct.AddShaderChunk("struct WeightsSurfaceDescription{", false);
surfaceDescriptionStruct.Indent();
var baseGraph = layerMap.Values.FirstOrDefault();
if (baseGraph == null)
{
configuredTextures = new List<PropertyCollector.TextureInfo>();
return string.Empty;
}
foreach (var slot in outputNode.GetInputSlots<MaterialSlot>())
surfaceDescriptionStruct.AddShaderChunk(AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType) + " " + slot.shaderOutputName + ";", false);
var masterNode = baseGraph.masterNode;
GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, masterNode as AbstractMaterialNode, true);
surfaceDescriptionStruct.Deindent();
surfaceDescriptionStruct.AddShaderChunk("};", false);
foreach (var layer in layerMap)
{
activeNodes.Clear();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodes, outputNode);
layer.Value.masterNode as AbstractMaterialNode,
activeNodes,
outputNode,
surfaceDescriptionFunction,
shaderFunctionVisitor,
shaderProperties,

LayerToFunctionName(layer.Key));
}
"PopulateWeightsGraph",
"WeightsSurfaceDescription");
surfaceDescriptionStruct.AddShaderChunk("struct WeightsSurfaceDescription{", false);
surfaceDescriptionStruct.Indent();
string functionName = "PopulateSurfaceData";
string surfaceDescriptionName = "SurfaceDescription";
layerShaders.AddShaderChunk(string.Format("{0} {1}(SurfaceInputs IN) {{", surfaceDescriptionName, functionName), false);
layerShaders.Indent();
foreach (var slot in outputNode.GetInputSlots<MaterialSlot>())
surfaceDescriptionStruct.AddShaderChunk(AbstractMaterialNode.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType) + " " + slot.shaderOutputName + ";", false);
layerShaders.AddShaderChunk("WeightsSurfaceDescription weights = PopulateWeightsGraph(IN);", false);
layerShaders.AddShaderChunk("SurfaceDescription result = (SurfaceDescription)0;", false);
surfaceDescriptionStruct.Deindent();
surfaceDescriptionStruct.AddShaderChunk("};", false);
GenerateSurfaceDescription(
outputNode,
surfaceDescriptionFunction,
shaderFunctionVisitor,
shaderProperties,
requirements,
mode,
true,
"PopulateWeightsGraph",
"WeightsSurfaceDescription");
string functionName = "PopulateSurfaceData";
string surfaceDescriptionName = "SurfaceDescription";
layerShaders.AddShaderChunk(string.Format("{0} {1}(SurfaceInputs IN) {{", surfaceDescriptionName, functionName), false);
layerShaders.Indent();
layerShaders.AddShaderChunk("WeightsSurfaceDescription weights = PopulateWeightsGraph(IN);", false);
layerShaders.AddShaderChunk("SurfaceDescription result = (SurfaceDescription)0;", false);
foreach (var layer in layerMap)
{
layerShaders.AddShaderChunk(
string.Format(
"{0} {1} = {2}({3});",
surfaceDescriptionName,
LayerToFunctionName(layer.Key) + "_surface",
LayerToFunctionName(layer.Key),
"IN"), false);
foreach (var layer in layerMap)
{
layerShaders.AddShaderChunk(
string.Format(
"{0} {1} = {2}({3});",
surfaceDescriptionName,
LayerToFunctionName(layer.Key) + "_surface",
LayerToFunctionName(layer.Key),
"IN"), false);
layerShaders.AddShaderChunk(
string.Format("ScaleSurfaceDescription({0}_surface, weights.{0});", LayerToFunctionName(layer.Key)), false);
layerShaders.AddShaderChunk(
string.Format("ScaleSurfaceDescription({0}_surface, weights.{0});", LayerToFunctionName(layer.Key)), false);
layerShaders.AddShaderChunk(string.Format("AddSurfaceDescription(result, {0}_surface);", LayerToFunctionName(layer.Key)), false);
}
layerShaders.AddShaderChunk("return result;", false);
layerShaders.AddShaderChunk(string.Format("AddSurfaceDescription(result, {0}_surface);", LayerToFunctionName(layer.Key)), false);
}
layerShaders.AddShaderChunk("return result;", false);
layerShaders.Deindent();
layerShaders.AddShaderChunk("}", false);
layerShaders.Deindent();
layerShaders.AddShaderChunk("}", false);
var finalShader = new ShaderGenerator();
finalShader.AddShaderChunk(string.Format(@"Shader ""{0}""", name), false);
finalShader.AddShaderChunk("{", false);
finalShader.Indent();
var finalShader = new ShaderGenerator();
finalShader.AddShaderChunk(string.Format(@"Shader ""{0}""", name), false);
finalShader.AddShaderChunk("{", false);
finalShader.Indent();
finalShader.AddShaderChunk("Properties", false);
finalShader.AddShaderChunk("{", false);
finalShader.Indent();
finalShader.AddShaderChunk(shaderProperties.GetPropertiesBlock(2), false);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);
finalShader.AddShaderChunk("Properties", false);
finalShader.AddShaderChunk("{", false);
finalShader.Indent();
finalShader.AddShaderChunk(shaderProperties.GetPropertiesBlock(2), false);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);
finalShader.AddShaderChunk("CGINCLUDE", false);
finalShader.AddShaderChunk("#include \"UnityCG.cginc\"", false);
finalShader.AddShaderChunk(shaderFunctionVisitor.GetShaderString(2), false);
finalShader.AddShaderChunk(graphVertexInput, false);
finalShader.AddShaderChunk(surfaceInputs.GetShaderString(2), false);
finalShader.AddShaderChunk(surfaceDescriptionStruct.GetShaderString(2), false);
finalShader.AddShaderChunk(shaderProperties.GetPropertiesDeclaration(2), false);
finalShader.AddShaderChunk(vertexShader.GetShaderString(2), false);
finalShader.AddShaderChunk(surfaceDescriptionFunction.GetShaderString(2), false);
finalShader.AddShaderChunk(layerShaders.GetShaderString(2), false);
finalShader.AddShaderChunk("ENDCG", false);
finalShader.AddShaderChunk("CGINCLUDE", false);
finalShader.AddShaderChunk("#include \"UnityCG.cginc\"", false);
finalShader.AddShaderChunk(shaderFunctionVisitor.GetShaderString(2), false);
finalShader.AddShaderChunk(graphVertexInput, false);
finalShader.AddShaderChunk(surfaceInputs.GetShaderString(2), false);
finalShader.AddShaderChunk(surfaceDescriptionStruct.GetShaderString(2), false);
finalShader.AddShaderChunk(shaderProperties.GetPropertiesDeclaration(2), false);
finalShader.AddShaderChunk(vertexShader.GetShaderString(2), false);
finalShader.AddShaderChunk(surfaceDescriptionFunction.GetShaderString(2), false);
finalShader.AddShaderChunk(layerShaders.GetShaderString(2), false);
finalShader.AddShaderChunk("ENDCG", false);
if (masterNode != null)
{
var subShaders = masterNode.GetSubshader(requirements, null);
foreach (var ss in subShaders)
finalShader.AddShaderChunk(ss, false);
}
if (masterNode != null)
{
var subShaders = masterNode.GetSubshader(requirements, null);
foreach (var ss in subShaders)
finalShader.AddShaderChunk(ss, false);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);
configuredTextures = shaderProperties.GetConfiguredTexutres();
return finalShader.GetShaderString(0);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);
configuredTextures = shaderProperties.GetConfiguredTexutres();
return finalShader.GetShaderString(0);
}
public void LoadedFromDisk()

正在加载...
取消
保存