浏览代码

Implemented uber shader

/main
Peter Bay Bastian 7 年前
当前提交
2fa06117
共有 6 个文件被更改,包括 203 次插入50 次删除
  1. 77
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/AbstractMaterialGraph.cs
  2. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MaterialGraph.cs
  3. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/SubGraph/LayeredShaderGraph.cs
  4. 36
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Util/ShaderGenerator.cs
  5. 130
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/PreviewManager.cs
  6. 3
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/GraphEditorView.cs

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


public string GetPreviewShader(AbstractMaterialNode node, out PreviewMode previewMode)
{
List<PropertyCollector.TextureInfo> configuredTextures;
return GetShader(node, GenerationMode.Preview, string.Format("hidden/preview/{0}", node.GetVariableNameForNode()), out configuredTextures, out previewMode);
FloatShaderProperty outputIdProperty;
return GetShader(node, GenerationMode.Preview, string.Format("hidden/preview/{0}", node.GetVariableNameForNode()), out configuredTextures, out previewMode, out outputIdProperty);
}
public string GetUberPreviewShader(Dictionary<Guid, int> ids, out FloatShaderProperty outputIdProperty)
{
List<PropertyCollector.TextureInfo> configuredTextures;
PreviewMode previewMode;
return GetShader(null, GenerationMode.Preview, "hidden/preview", out configuredTextures, out previewMode, out outputIdProperty, ids);
}
protected static void GenerateSurfaceDescriptionStruct(ShaderGenerator surfaceDescriptionStruct, List<MaterialSlot> slots)

protected static void GenerateSurfaceDescription(
List<INode> activeNodeList,
AbstractMaterialNode node,
AbstractMaterialNode masterNode,
AbstractMaterialGraph graph,
bool isMasterNode,
var graph = node.owner as AbstractMaterialGraph;
if (graph == null)
return;

}
surfaceDescriptionFunction.AddShaderChunk(string.Format("{0} surface = ({0})0;", surfaceDescriptionName), false);
if (isMasterNode)
var surfaceDescriptionNodes = masterNode == null ? activeNodeList.OfType<AbstractMaterialNode>() : masterNode.ToEnumerable();
foreach (var node in surfaceDescriptionNodes)
foreach (var input in node.GetInputSlots<MaterialSlot>())
if (node is IMasterNode)
var foundEdges = graph.GetEdges(input.slotReference).ToArray();
if (foundEdges.Any())
foreach (var input in node.GetInputSlots<MaterialSlot>())
var outputRef = foundEdges[0].outputSlot;
var fromNode = graph.GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", input.shaderOutputName, fromNode.GetVariableNameForSlot(outputRef.slotId)), true);
var foundEdges = graph.GetEdges(input.slotReference).ToArray();
if (foundEdges.Any())
{
var outputRef = foundEdges[0].outputSlot;
var fromNode = graph.GetNodeFromGuid<AbstractMaterialNode>(outputRef.nodeGuid);
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", input.shaderOutputName, fromNode.GetVariableNameForSlot(outputRef.slotId)), true);
}
else
{
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", input.shaderOutputName, input.GetDefaultValue(mode)), true);
}
else
}
else
{
if (node.hasPreview)
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", input.shaderOutputName, input.GetDefaultValue(mode)), true);
foreach (var slot in node.GetOutputSlots<MaterialSlot>())
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {0};", node.GetVariableNameForSlot(slot.id)), true);
else
{
foreach (var slot in node.GetOutputSlots<MaterialSlot>())
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {0};", node.GetVariableNameForSlot(slot.id)), true);
}
surfaceDescriptionFunction.AddShaderChunk("return surface;", false);
surfaceDescriptionFunction.Deindent();

outputList.Add(node);
}
public string GetShader(AbstractMaterialNode node, GenerationMode mode, string name, out List<PropertyCollector.TextureInfo> configuredTextures, out PreviewMode previewMode, bool isUber = false)
public string GetShader(AbstractMaterialNode node, GenerationMode mode, string name, out List<PropertyCollector.TextureInfo> configuredTextures, out PreviewMode previewMode, out FloatShaderProperty outputIdProperty, Dictionary<Guid, int> ids = null)
if (node == null)
throw new ArgumentNullException("node");
bool isUber = node == null;
var vertexShader = new ShaderGenerator();
var surfaceDescriptionFunction = new ShaderGenerator();

var activeNodeList = ListPool<INode>.Get();
if (isUber)
{
var unmarkedNodes = node.owner.GetNodes<INode>().ToDictionary(x => x.guid);
var unmarkedNodes = GetNodes<INode>().Where(x => !(x is IMasterNode)).ToDictionary(x => x.guid);
while (unmarkedNodes.Any())
{
var unmarkedNode = unmarkedNodes.FirstOrDefault();

GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots);
var shaderProperties = new PropertyCollector();
outputIdProperty = new FloatShaderProperty
{
displayName = "OutputId",
generatePropertyBlock = false,
value = -1
};
if (isUber)
shaderProperties.AddShaderProperty(outputIdProperty);
this,
mode,
node is IMasterNode);
ListPool<INode>.Release(activeNodeList);
mode);
var finalShader = new ShaderGenerator();
finalShader.AddShaderChunk(string.Format(@"Shader ""{0}""", name), false);

finalShader.AddShaderChunk("ENDCG", false);
var masterNode = node as IMasterNode;
if (masterNode != null)
if (node != null && masterNode != null)
{
var subShaders = masterNode.GetSubshader(requirements, null);
foreach (var ss in subShaders)

{
finalShader.AddShaderChunk(ShaderGenerator.GetPreviewSubShader(node, requirements), false);
finalShader.AddShaderChunk(ShaderGenerator.GetPreviewSubShader(activeNodeList, node, requirements, outputIdProperty, ids), false);
ListPool<INode>.Release(activeNodeList);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/MaterialGraph.cs


public string GetShader(string name, GenerationMode mode, out List<PropertyCollector.TextureInfo> configuredTextures)
{
PreviewMode pmode;
return GetShader(masterNode as AbstractMaterialNode, mode, name, out configuredTextures, out pmode);
FloatShaderProperty outputIdProperty;
return base.GetShader(masterNode as AbstractMaterialNode, mode, name, out configuredTextures, out pmode, out outputIdProperty);
}
public void LoadedFromDisk()

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


GenerateSurfaceDescription(
activeNodes,
layer.Value.masterNode as AbstractMaterialNode,
this,
true,
LayerToFunctionName(layer.Key));
}

GenerateSurfaceDescription(
activeNodes,
outputNode,
this,
true,
"PopulateWeightsGraph",
"WeightsSurfaceDescription");

36
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Util/ShaderGenerator.cs


{
private static string[] UV = {"uv0", "uv1", "uv2", "uv3"};
public static int UVCount = 4;
public const string ScreenPosition = "screenPosition";
public const string VertexColor = "vertexColor";

ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.Tangent, inputType, from)), false);
}
public static string GetPreviewSubShader(AbstractMaterialNode node, ShaderGraphRequirements shaderGraphRequirements)
public static string GetPreviewSubShader(List<INode> activeNodeList, AbstractMaterialNode node, ShaderGraphRequirements shaderGraphRequirements, FloatShaderProperty outputIdProperty, Dictionary<Guid, int> ids)
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);
var interpolators = new ShaderGenerator();
var vertexShader = new ShaderGenerator();
var pixelShader = new ShaderGenerator();

CoordinateSpace.World);
var outputs = new ShaderGenerator();
var outputSlot = node.GetOutputSlots<MaterialSlot>().FirstOrDefault();
if (outputSlot != null)
var currentId = -1;
if (node != null)
var result = string.Format("surf.{0}", node.GetVariableNameForSlot(outputSlot.id));
outputs.AddShaderChunk(string.Format("return {0};", AdaptNodeOutputForPreview(node, outputSlot.id, result)), true);
var outputSlot = node.GetOutputSlots<MaterialSlot>().FirstOrDefault();
if (outputSlot != null)
{
var result = string.Format("surf.{0}", node.GetVariableNameForSlot(outputSlot.id));
outputs.AddShaderChunk(string.Format("return {0};", AdaptNodeOutputForPreview(node, outputSlot.id, result)), true);
}
else
outputs.AddShaderChunk("return 0;", true);
outputs.AddShaderChunk("return 0;", true);
{
foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
{
var outputSlot = activeNode.GetOutputSlots<MaterialSlot>().FirstOrDefault();
if (activeNode.hasPreview && outputSlot != null)
{
currentId++;
ids[activeNode.guid] = currentId;
var result = string.Format("surf.{0}", activeNode.GetVariableNameForSlot(outputSlot.id));
outputs.AddShaderChunk(string.Format("if ({0} == {1}) return {2}; else ", outputIdProperty.referenceName, currentId, AdaptNodeOutputForPreview(activeNode, outputSlot.id, result)), false);
}
}
outputs.AddShaderChunk("return 0;", false);
}
var res = subShaderTemplate.Replace("${Interpolators}", interpolators.GetShaderString(0));
res = res.Replace("${VertexShader}", vertexShader.GetShaderString(0));

130
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/PreviewManager.cs


PreviewSceneResources m_SceneResources;
Texture2D m_ErrorTexture;
DateTime m_LastUpdate;
const bool k_UberShaderEnabled = true;
Shader m_UberShader;
string m_UberShaderString;
Dictionary<Guid, int> m_UberShaderIds;
FloatShaderProperty m_OutputIdProperty;
public PreviewRate previewRate { get; set; }

m_ErrorTexture.filterMode = FilterMode.Point;
m_ErrorTexture.Apply();
m_SceneResources = new PreviewSceneResources();
m_UberShader = ShaderUtil.CreateShaderAsset(k_EmptyShader);
m_UberShader.hideFlags = HideFlags.HideAndDontSave;
m_UberShaderIds = new Dictionary<Guid, int>();
foreach (var node in m_Graph.GetNodes<INode>())
AddPreview(node);

List<PreviewData> m_RenderList2D = new List<PreviewData>();
List<PreviewData> m_RenderList3D = new List<PreviewData>();
HashSet<Guid> m_NodesWith3DPreview = new HashSet<Guid>();
public void RenderPreviews()
{

if (m_DirtyShaders.Any())
{
m_NodesWith3DPreview.Clear();
foreach (var node in m_Graph.GetNodes<AbstractMaterialNode>())
{
if (node.previewMode == PreviewMode.Preview3D)
m_NodesWith3DPreview.Add(node.guid);
}
PropagateNodeSet(m_NodesWith3DPreview);
var count = m_DirtyShaders.Count;
var masterNodes = new List<INode>();
var uberNodes = new List<INode>();
foreach (var guid in m_DirtyShaders)
{
var node = m_Graph.GetNodeFromGuid(guid);
if (node == null)
continue;
if (!k_UberShaderEnabled || node is IMasterNode)
masterNodes.Add(node);
else
uberNodes.Add(node);
}
var count = Math.Min(uberNodes.Count, 1) + masterNodes.Count;
foreach (var nodeGuid in m_DirtyShaders)
foreach (var node in masterNodes)
{
UpdateShader(node.guid);
i++;
EditorUtility.DisplayProgressBar("Shader Graph", string.Format("Compiling preview shaders ({0}/{1})", i, count), 0f);
}
if (uberNodes.Count > 0)
UpdateShader(nodeGuid);
m_UberShaderIds.Clear();
m_UberShaderString = m_Graph.GetUberPreviewShader(m_UberShaderIds, out m_OutputIdProperty);
ShaderUtil.UpdateShaderAsset(m_UberShader, m_UberShaderString);
File.WriteAllText(Application.dataPath + "/../UberShader.shader", (m_UberShaderString ?? "null").Replace("UnityEngine.MaterialGraph", "Generated"));
var message = "RecreateUberShader: " + Environment.NewLine + m_UberShaderString;
if (MaterialGraphAsset.ShaderHasError(m_UberShader))
{
Debug.LogWarning(message);
ShaderUtil.ClearShaderErrors(m_UberShader);
ShaderUtil.UpdateShaderAsset(m_UberShader, k_EmptyShader);
}
else
{
Debug.Log(message);
}
foreach (var node in uberNodes)
{
PreviewData previewData;
if (!m_Previews.TryGetValue(node.guid, out previewData))
continue;
previewData.previewMode = m_NodesWith3DPreview.Contains(node.guid) ? PreviewMode.Preview3D : PreviewMode.Preview2D;
previewData.shader = m_UberShader;
}
i++;
EditorUtility.DisplayProgressBar("Shader Graph", string.Format("Compiling preview shaders ({0}/{1})", i, count), 0f);
}

m_PreviewProperties.Clear();
}
var outputIdName = m_OutputIdProperty != null ? m_OutputIdProperty.referenceName : null;
foreach (var nodeGuid in m_DirtyPreviews)
{
PreviewData previewData;

previewData.texture = m_ErrorTexture;
continue;
}
if (previewData.previewMode == PreviewMode.Preview2D)
m_RenderList2D.Add(previewData);
else

m_SceneResources.camera.orthographic = true;
foreach (var previewData in m_RenderList2D)
{
int outputId;
if (m_UberShaderIds.TryGetValue(previewData.node.guid, out outputId))
m_PreviewPropertyBlock.SetFloat(outputIdName, outputId);
m_PreviewMaterial.shader = previewData.shader;
m_SceneResources.camera.targetTexture = previewData.renderTexture;
var previousRenderTexure = RenderTexture.active;

m_SceneResources.camera.orthographic = false;
foreach (var previewData in m_RenderList3D)
{
int outputId;
if (m_UberShaderIds.TryGetValue(previewData.node.guid, out outputId))
m_PreviewPropertyBlock.SetFloat(outputIdName, outputId);
m_PreviewMaterial.shader = previewData.shader;
m_SceneResources.camera.targetTexture = previewData.renderTexture;
var previousRenderTexure = RenderTexture.active;

if (!m_Previews.TryGetValue(nodeGuid, out previewData))
return;
if (!(node is IMasterNode) && (!node.hasPreview || NodeUtils.FindEffectiveShaderStage(node, true) == ShaderStage.Vertex))
previewData.previewMode = m_NodesWith3DPreview.Contains(nodeGuid) ? PreviewMode.Preview3D : PreviewMode.Preview2D;
if (!(node is IMasterNode) && (!node.hasPreview || NodeUtils.FindEffectiveShaderStage(node, true) == ShaderStage.Vertex))
{
previewData.shaderString = null;
}

previewData.shaderString = m_Graph.GetPreviewShader(node, out mode);
previewData.previewMode = mode;
// Debug output
Debug.Log("RecreateShader: " + node.GetVariableNameForNode() + Environment.NewLine + previewData.shaderString);
File.WriteAllText(Application.dataPath + "/../GeneratedShader.shader", (previewData.shaderString ?? "null").Replace("UnityEngine.MaterialGraph", "Generated"));
if (string.IsNullOrEmpty(previewData.shaderString))

ShaderUtil.UpdateShaderAsset(previewData.shader, previewData.shaderString);
}
// Debug output
var message = "RecreateShader: " + node.GetVariableNameForNode() + Environment.NewLine + previewData.shaderString;
Debug.LogWarningFormat("ShaderHasError: {0}\n{1}", node.GetVariableNameForNode(), previewData.shaderString);
Debug.LogWarningFormat(message);
else
Debug.Log(message);
}
void DestroyPreview(Guid nodeGuid, PreviewData previewData)

{
ReleaseUnmanagedResources();
}
const string k_EmptyShader = @"
Shader ""hidden/preview""
{
SubShader
{
Tags { ""RenderType""=""Opaque"" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include ""UnityCG.cginc""
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return 0;
}
ENDCG
}
}
}";
}
public delegate void OnPreviewChanged();

3
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/GraphEditorView.cs


var textureInfo = new List<PropertyCollector.TextureInfo>();
PreviewMode previewMode;
string shader = graph.GetShader(copyFromNode, GenerationMode.ForReals, assetName, out textureInfo, out previewMode);
FloatShaderProperty outputIdProperty;
string shader = graph.GetShader(copyFromNode, GenerationMode.ForReals, assetName, out textureInfo, out previewMode, out outputIdProperty);
GUIUtility.systemCopyBuffer = shader;
}
));

正在加载...
取消
保存