浏览代码

[shader graph]optimise for GC

/main
Tim Cooper 9 年前
当前提交
51ceebd2
共有 14 个文件被更改,包括 128 次插入130 次删除
  1. 66
      UnityProject/Assets/GraphFramework/Canvas2D/Editor/Canvas2D.cs
  2. 27
      UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph.cs
  3. 7
      UnityProject/Assets/UnityShaderEditor/Editor/Source/BaseMaterialGraph.cs
  4. 4
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/DrawableMaterialNode.cs
  5. 4
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/MaterialWindow.cs
  6. 11
      UnityProject/Assets/UnityShaderEditor/Editor/Source/MaterialSubGraph.cs
  7. 53
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/BaseMaterialNode.cs
  8. 10
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MandelbrotNode.cs
  9. 10
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PixelShaderNode.cs
  10. 2
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PropertyNode.cs
  11. 9
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SubGraphNode.cs
  12. 12
      UnityProject/Assets/UnityShaderEditor/Editor/Source/PixelGraph.cs
  13. 30
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/NodeUtils.cs
  14. 13
      UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/ShaderGenerator.cs

66
UnityProject/Assets/GraphFramework/Canvas2D/Editor/Canvas2D.cs


rect.xMax = rect.xMin + m_Scale.x;
rect.yMax = rect.yMin + m_Scale.y;
foreach (CanvasElement e in m_Children)
{
Rect childRect = e.boundingRect;
childRect.x += rect.x;
childRect.y += rect.y;
rect = RectUtils.Encompass(rect, childRect);
}
for (int i = 0; i < m_Children.Count; i++)
{
CanvasElement e = m_Children[i];
Rect childRect = e.boundingRect;
childRect.x += rect.x;
childRect.y += rect.y;
rect = RectUtils.Encompass(rect, childRect);
}
return rect;
return rect;
}
}

screenRect.min = parent.MouseToCanvas(parent.clientRect.min);
screenRect.max = parent.MouseToCanvas(new Vector2(Screen.width, Screen.height));
Rect thisRect = boundingRect;
foreach (CanvasElement e in visibleList)
{
if (e.texture != null)
{
float ratio = 1.0f;
Rect r = new Rect(e.translation.x, e.translation.y, e.texture.width, e.texture.height);
if (r.y < screenRect.y)
{
float overlap = (screenRect.y - r.y);
r.y = screenRect.y;
r.height -= overlap;
if (r.height < 0.0f)
{
r.height = 0.0f;
}
ratio = r.height / e.texture.height;
}
for (int i = 0; i < visibleList.Count; i++)
{
CanvasElement e = visibleList[i];
if (e.texture != null)
{
float ratio = 1.0f;
Rect r = new Rect(e.translation.x, e.translation.y, e.texture.width, e.texture.height);
if (r.y < screenRect.y)
{
float overlap = (screenRect.y - r.y);
r.y = screenRect.y;
r.height -= overlap;
if (r.height < 0.0f)
r.height = 0.0f;
ratio = r.height / e.texture.height;
}
Graphics.DrawTexture(r, e.texture, new Rect(0, 0, 1.0f, ratio), 0, 0, 0, 0);
}
else
{
e.Render(thisRect, parent);
}
Graphics.DrawTexture(r, e.texture, new Rect(0, 0, 1.0f, ratio), 0, 0, 0, 0);
}
else
e.Render(thisRect, parent);
e.RenderWidgets(parent);
}
e.RenderWidgets(parent);
}
if (OnWidget != null)
if (OnWidget != null)
OnWidget(this, Event.current, parent);
}

27
UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph.cs


Vector3[] points, tangents;
EdgeConnector<T>.GetTangents(from, to, out points, out tangents);
Handles.DrawBezier(points[0], points[1], tangents[0], tangents[1], edgeColor, null, 5f);
// little widget on the middle of the edge
Vector3[] allPoints = Handles.MakeBezierPoints(points[0], points[1], tangents[0], tangents[1], 20);
Color oldColor = Handles.color;
Handles.color = Color.blue;
Handles.DrawSolidDisc(allPoints[10], new Vector3(0.0f, 0.0f, -1.0f), 6f);
Handles.color = edgeColor;
Handles.DrawWireDisc(allPoints[10], new Vector3(0.0f, 0.0f, -1.0f), 6f);
Handles.DrawWireDisc(allPoints[10], new Vector3(0.0f, 0.0f, -1.0f), 5f);
// dot on top of anchor showing it's connected
Handles.color = new Color(0.3f, 0.4f, 1.0f, 1.0f);
Handles.DrawSolidDisc(from, new Vector3(0.0f, 0.0f, -1.0f), 4f);
Handles.DrawSolidDisc(to, new Vector3(0.0f, 0.0f, -1.0f), 4f);
/*if (EditorApplication.isPlaying)
{
Handles.color = Color.red;
Handles.DrawSolidDisc(allPoints[m_RealtimeFeedbackPointIndex], new Vector3(0.0f, 0.0f, -1.0f), 6f);
m_RealtimeFeedbackPointIndex++;
if (m_RealtimeFeedbackPointIndex >= 20)
{
m_RealtimeFeedbackPointIndex = 0;
}
}*/
Handles.color = oldColor;
}
public override void UpdateModel(UpdateType t)

7
UnityProject/Assets/UnityShaderEditor/Editor/Source/BaseMaterialGraph.cs


public void GeneratePreviewShaders()
{
MaterialWindow.DebugMaterialGraph("Generating preview shaders on: " + name);
// 2 passes...
// 1 create the shaders
foreach (var node in nodes)

{
}
}
// 2 set the properties

if (pNode != null && pNode.hasPreview)
{
MaterialWindow.DebugMaterialGraph("Updating preview Properties on Node: " + pNode);
}
}
}
}

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


private bool MarkDirtyIfNeedsTime(CanvasElement element, Event e, Canvas2D parent)
{
var childrenNodes = m_Node.CollectChildNodesByExecutionOrder();
var childrenNodes = ListPool<BaseMaterialNode>.Get();
m_Node.CollectChildNodesByExecutionOrder(childrenNodes);
ListPool<BaseMaterialNode>.Release(childrenNodes);
return true;
}

4
UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/MaterialWindow.cs


void OnSelectionChange()
{
DebugMaterialGraph("Got OnSelection Change: " + Selection.activeObject);
if (Selection.activeObject == null || !EditorUtility.IsPersistent(Selection.activeObject))
return;

DebugMaterialGraph("Selection: " + selection);
DebugMaterialGraph("Existing: " + m_MaterialGraph);
if (selection != m_MaterialGraph)
{
m_MaterialGraph = selection;

11
UnityProject/Assets/UnityShaderEditor/Editor/Source/MaterialSubGraph.cs


{
if (edge.toSlot.node == toNode && !foundUsedInputSlots.Contains(edge.toSlot))
{
var validInputSlotsAtTarget = (edge.toSlot.node as BaseMaterialNode).GetValidInputSlots();
if (validInputSlotsAtTarget.Contains(edge.toSlot))
var validSlots = ListPool<Slot>.Get();
(edge.toSlot.node as BaseMaterialNode).GetValidInputSlots(validSlots);
if (validSlots.Contains(edge.toSlot))
ListPool<Slot>.Release(validSlots);
}
else
FindValidInputsToNodeFromNode(toNode, edge.toSlot.node, foundUsedInputSlots);

private IEnumerable<BaseMaterialNode> GetCollectedNodes()
{
return outputsNode.CollectChildNodesByExecutionOrder();
return null;
//return outputsNode.CollectChildNodesByExecutionOrder();
}
public void GenerateNodeCode(ShaderGenerator visitor, SubGraphNode generatingFor)

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


// 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 IEnumerable<BaseMaterialNode> CollectChildNodesByExecutionOrder(Slot slotToUse = null, bool includeSelf = true)
{
var nodeList = new List<BaseMaterialNode>();
CollectChildNodesByExecutionOrder(nodeList, slotToUse, includeSelf);
return nodeList;
}
public IEnumerable<BaseMaterialNode> CollectChildNodesByExecutionOrder(List<BaseMaterialNode> nodeList, Slot slotToUse = null, bool includeSelf = true)
public List<BaseMaterialNode> CollectChildNodesByExecutionOrder(List<BaseMaterialNode> nodeList, Slot slotToUse = null, bool includeSelf = true)
{
if (slotToUse != null && !slots.Contains(slotToUse))
{

protected void InternalUpdatePreviewShader(string resultShader)
{
MaterialWindow.DebugMaterialGraph("RecreateShaderAndMaterial : " + name + "_" + GetInstanceID());
MaterialWindow.DebugMaterialGraph(resultShader);
MaterialWindow.DebugMaterialGraph("RecreateShaderAndMaterial : " + name + "_" + GetInstanceID() + "\n" + resultShader);
if (previewMaterial.shader != defaultPreviewShader)
DestroyImmediate(previewMaterial.shader, true);
previewMaterial.shader = ShaderUtil.CreateShaderAsset(resultShader);

protected virtual void CollectPreviewMaterialProperties (List<PreviewProperty> properties)
{
foreach (var s in inputSlots)
var validSlots = ListPool<Slot>.Get();
GetValidInputSlots(validSlots);
for (int index = 0; index < validSlots.Count; index++)
var s = validSlots[index];
if (s.edges.Count > 0)
continue;

m_PropType = PropertyType.Vector4,
m_Vector4 = defaultInput.defaultValue
};
properties.Add (pp);
properties.Add(pp);
ListPool<Slot>.Release(validSlots);
}
// this function looks at all the nodes that have a

public static void UpdateMaterialProperties(BaseMaterialNode target, Material material)
{
var childrenNodes = target.CollectChildNodesByExecutionOrder();
var pList = new List<PreviewProperty>();
foreach (var node in childrenNodes)
var childNodes = ListPool<BaseMaterialNode>.Get();
target.CollectChildNodesByExecutionOrder(childNodes);
var pList = ListPool<PreviewProperty>.Get();
for (int index = 0; index < childNodes.Count; index++)
{
var node = childNodes[index];
}
ListPool<BaseMaterialNode>.Release(childNodes);
ListPool<PreviewProperty>.Release(pList);
}
public void UpdatePreviewProperties()

#region Slots
public virtual IEnumerable<Slot> GetValidInputSlots()
public virtual void GetValidInputSlots(List<Slot> slotsToFill)
return inputSlots;
for (int i = 0; i < slots.Count; ++i)
{
var slot = slots[i];
if (slot != null && slot.isInputSlot)
slotsToFill.Add(slot);
}
}
public virtual string GetOutputVariableNameForSlot(Slot s, GenerationMode generationMode)

SetSlotDefaultValue(slot.name, new SlotValue(this, slot.name, GetNewSlotDefaultValue(mgSlot.valueType)));
SetSlotDefaultValueType(slot.name, mgSlot.valueType);
// slots are not serialzied but the default values are
// because of this we need to see if the default has
// already been set
// if it has... do nothing.
MaterialWindow.DebugMaterialGraph("Node ID: " + GetInstanceID());
MaterialWindow.DebugMaterialGraph("Node Name: " + GetOutputVariableNameForNode());
}
public override void RemoveSlot(Slot slot)

10
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/MandelbrotNode.cs


public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var validSlots = ListPool<Slot>.Get();
GetValidInputSlots(validSlots);
var pointInput = GetValidInputSlots().FirstOrDefault(x => x.name == kPointInputName);
var constantInput = GetValidInputSlots().FirstOrDefault(x => x.name == kConstantInputName);
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);

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


{
// do the normal slot first so that it can be used later in the shader :)
var normal = FindInputSlot(kNormalSlotName);
var nodes = new List<BaseMaterialNode>();
var nodes = ListPool<BaseMaterialNode>.Get();
foreach (var node in nodes)
for (int index = 0; index < nodes.Count; index++)
var node = nodes[index];
foreach (var edge in normal.edges)
for (int index = 0; index < normal.edges.Count; index++)
var edge = normal.edges[index];
var node = edge.fromSlot.node as BaseMaterialNode;
shaderBody.AddShaderChunk("o." + normal.name + " = " + node.GetOutputVariableNameForSlot(edge.fromSlot, generationMode) + ";", true);
}

if (node is IGeneratesBodyCode)
(node as IGeneratesBodyCode).GenerateNodeCode(shaderBody, generationMode);
}
ListPool<BaseMaterialNode>.Release(nodes);
foreach (var slot in FilterSlotsForLightFunction())
{

2
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/PropertyNode.cs


{
// var validExposedName = !string.IsNullOrEmpty(m_Name);
//if (!validExposedName)
return name + "_" + Math.Abs(GetInstanceID()) + "_Uniform";
return string.Format("{0}_{1}_Uniform", name, Math.Abs(GetInstanceID()));
// return m_Name + "_Uniform";
}

9
UnityProject/Assets/UnityShaderEditor/Editor/Source/Nodes/SubGraphNode.cs


{
if (subGraphAsset == null)
return PreviewMode.Preview2D;
var preview3D = subGraphAsset.outputsNode.CollectChildNodesByExecutionOrder().Any(x => x.previewMode == PreviewMode.Preview3D);
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;
}
}

return string.Format("O{0:00}", n);
}
public override IEnumerable<Slot> GetValidInputSlots()
/* public override IEnumerable<Slot> GetValidInputSlots()
}
}*/
public override void NodeUI(GraphGUI host)
{

12
UnityProject/Assets/UnityShaderEditor/Editor/Source/PixelGraph.cs


}
}
private IEnumerable<BaseMaterialNode> m_ActiveNodes;
private List<BaseMaterialNode> m_ActiveNodes;
if (m_ActiveNodes == null)
m_ActiveNodes = pixelMasterNode.CollectChildNodesByExecutionOrder();
if (m_ActiveNodes == null)
{
m_ActiveNodes = new List<BaseMaterialNode>();
pixelMasterNode.CollectChildNodesByExecutionOrder(m_ActiveNodes);
}
return m_ActiveNodes;
}
}

protected override void RecacheActiveNodes()
{
m_ActiveNodes = pixelMasterNode.CollectChildNodesByExecutionOrder();
m_ActiveNodes.Clear();
pixelMasterNode.CollectChildNodesByExecutionOrder(m_ActiveNodes);
}
public Material GetMaterial()

30
UnityProject/Assets/UnityShaderEditor/Editor/Source/Util/NodeUtils.cs


if (bmn == null)
return;
foreach (var inputSlot in bmn.GetValidInputSlots())
var validSlots = ListPool<Slot>.Get();
bmn.GetValidInputSlots(validSlots);
for (int index = 0; index < validSlots.Count; index++)
foreach (var edge in inputSlot.edges)
var inputSlot = validSlots[index];
for (int i = 0; i < inputSlot.edges.Count; i++)
var edge = inputSlot.edges[i];
if (edge.fromSlot.node == fromNode && !foundUsedOutputSlots.Contains(edge.fromSlot))
foundUsedOutputSlots.Add(edge.fromSlot);
else

ListPool<Slot>.Release(validSlots);
}
public static void CollectChildNodesByExecutionOrder(ICollection<BaseMaterialNode> nodeList, BaseMaterialNode node, Slot slotToUse)

if (nodeList.Contains(node))
return;
var validSlots = node.GetValidInputSlots().ToList();
var validSlots = ListPool<Slot>.Get();
node.GetValidInputSlots(validSlots);
{
ListPool<Slot>.Release(validSlots);
var slotsToUse = slotToUse == null ? validSlots : new List<Slot> {slotToUse};
}
foreach (var slot in slotsToUse)
if (slotToUse != null)
{
validSlots.Clear();
validSlots.Add(slotToUse);
}
for (int index = 0; index < validSlots.Count; index++)
foreach (var edge in slot.edges)
var slot = validSlots[index];
for (int i = 0; i < slot.edges.Count; i++)
var edge = slot.edges[i];
var inputNode = edge.fromSlot.node as BaseMaterialNode;
CollectChildNodesByExecutionOrder(nodeList, inputNode, null);
}

ListPool<Slot>.Release(validSlots);
}
public static void CollectDependentNodes(ICollection<BaseMaterialNode> nodeList, BaseMaterialNode node)

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


public static string GeneratePreviewShader(BaseMaterialNode node, out PreviewMode generatedShaderMode)
{
// figure out what kind of preview we want!
var childNodes = node.CollectChildNodesByExecutionOrder();
var activeNodeList = ListPool<BaseMaterialNode>.Get();
node.CollectChildNodesByExecutionOrder(activeNodeList);
if (childNodes.Any(x => x.previewMode == PreviewMode.Preview3D))
if (activeNodeList.Any(x => x.previewMode == PreviewMode.Preview3D))
{
generationMode = GenerationMode.Preview3D;
generatedShaderMode = PreviewMode.Preview3D;

var vertexShaderBlock = new ShaderGenerator();
var shaderName = "Hidden/PreviewShader/" + node.GetOutputVariableNameForSlot(node.outputSlots.First(), generationMode);
var activeNodeList = node.CollectChildNodesByExecutionOrder();
foreach (var activeNode in activeNodeList)
{
if (activeNode is IGeneratesFunction)

resultShader = resultShader.Replace("${VertexShaderDecl}", "");
resultShader = resultShader.Replace("${VertexShaderBody}", "");
}
MaterialWindow.DebugMaterialGraph("----------Shader-----------");
MaterialWindow.DebugMaterialGraph(resultShader);
configuredTxtures = shaderPropertiesVisitor.GetConfiguredTexutres();
return resultShader;
}

正在加载...
取消
保存