您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
370 行
13 KiB
370 行
13 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
|
|
namespace UnityEditor.Graphs.Material
|
|
{
|
|
|
|
public abstract class PropertyChunk
|
|
{
|
|
protected string m_PropertyName;
|
|
protected string m_PropertyDescription;
|
|
protected bool m_Hidden;
|
|
protected PropertyChunk(string propertyName, string propertyDescription, bool hidden)
|
|
{
|
|
m_PropertyName = propertyName;
|
|
m_PropertyDescription = propertyDescription;
|
|
m_Hidden = hidden;
|
|
}
|
|
|
|
public abstract string GetPropertyString();
|
|
public string propertyName { get { return m_PropertyName; } }
|
|
public string propertyDescription { get { return m_PropertyDescription; } }
|
|
}
|
|
|
|
public class TexturePropertyChunk : PropertyChunk
|
|
{
|
|
private readonly Texture m_DefaultTexture;
|
|
private readonly TextureType m_DefaultTextureType;
|
|
|
|
public TexturePropertyChunk(string propertyName, string propertyDescription, Texture defaultTexture, TextureType defaultTextureType, bool hidden)
|
|
: base(propertyName, propertyDescription, hidden)
|
|
{
|
|
m_DefaultTexture = defaultTexture;
|
|
m_DefaultTextureType = defaultTextureType;
|
|
}
|
|
|
|
public override string GetPropertyString()
|
|
{
|
|
var result = new StringBuilder();
|
|
if (m_Hidden)
|
|
result.Append ("[HideInInspector] ");
|
|
|
|
result.Append(m_PropertyName);
|
|
result.Append("(\"");
|
|
result.Append(m_PropertyDescription);
|
|
result.Append("\", 2D) = \"");
|
|
result.Append(Enum.GetName(typeof(TextureType), m_DefaultTextureType).ToLower());
|
|
result.Append("\" {}");
|
|
return result.ToString();
|
|
}
|
|
|
|
public Texture defaultTexture { get { return m_DefaultTexture; } }
|
|
}
|
|
|
|
public class ColorPropertyChunk : PropertyChunk
|
|
{
|
|
private Color m_DefaultColor;
|
|
|
|
public ColorPropertyChunk(string propertyName, string propertyDescription, Color defaultColor, bool hidden)
|
|
: base(propertyName, propertyDescription, hidden)
|
|
{
|
|
m_DefaultColor = defaultColor;
|
|
}
|
|
|
|
public override string GetPropertyString()
|
|
{
|
|
var result = new StringBuilder();
|
|
result.Append(m_PropertyName);
|
|
result.Append("(\"");
|
|
result.Append(m_PropertyDescription);
|
|
result.Append("\", Color) = (");
|
|
result.Append(m_DefaultColor.r);
|
|
result.Append(",");
|
|
result.Append(m_DefaultColor.g);
|
|
result.Append(",");
|
|
result.Append(m_DefaultColor.b);
|
|
result.Append(",");
|
|
result.Append(m_DefaultColor.a);
|
|
result.Append(")");
|
|
return result.ToString();
|
|
}
|
|
}
|
|
|
|
public class VectorPropertyChunk : PropertyChunk
|
|
{
|
|
private Vector4 m_DefaultVector;
|
|
public VectorPropertyChunk(string propertyName, string propertyDescription, Vector4 defaultVector, bool hidden)
|
|
: base(propertyName, propertyDescription, hidden)
|
|
{
|
|
m_DefaultVector = defaultVector;
|
|
}
|
|
|
|
public override string GetPropertyString()
|
|
{
|
|
var result = new StringBuilder();
|
|
result.Append(m_PropertyName);
|
|
result.Append("(\"");
|
|
result.Append(m_PropertyDescription);
|
|
result.Append("\", Vector) = (");
|
|
result.Append(m_DefaultVector.x);
|
|
result.Append(",");
|
|
result.Append(m_DefaultVector.y);
|
|
result.Append(",");
|
|
result.Append(m_DefaultVector.z);
|
|
result.Append(",");
|
|
result.Append(m_DefaultVector.w);
|
|
result.Append(")");
|
|
return result.ToString();
|
|
}
|
|
}
|
|
|
|
public class PropertyGenerator
|
|
{
|
|
private readonly List<PropertyChunk> m_Properties = new List<PropertyChunk>();
|
|
|
|
public void AddShaderProperty(PropertyChunk chunk)
|
|
{
|
|
m_Properties.Add(chunk);
|
|
}
|
|
|
|
public string GetShaderString(int baseIndentLevel)
|
|
{
|
|
var sb = new StringBuilder();
|
|
foreach (var prop in m_Properties)
|
|
{
|
|
for (var i = 0; i < baseIndentLevel; i++)
|
|
{
|
|
sb.Append("\t");
|
|
}
|
|
sb.Append(prop.GetPropertyString());
|
|
sb.Append("\n");
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
public Dictionary<string, Texture> GetDefaultTexutres()
|
|
{
|
|
var result = new Dictionary<string, Texture>();
|
|
|
|
foreach (var prop in m_Properties.OfType<TexturePropertyChunk>())
|
|
{
|
|
if (prop.propertyName != null)
|
|
result.Add(prop.propertyName, prop.defaultTexture);
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public class ShaderGenerator
|
|
{
|
|
private struct ShaderChunk
|
|
{
|
|
public ShaderChunk(int indentLevel, string shaderChunkString)
|
|
{
|
|
m_IndentLevel = indentLevel;
|
|
m_ShaderChunkString = shaderChunkString;
|
|
}
|
|
private readonly int m_IndentLevel;
|
|
private readonly string m_ShaderChunkString;
|
|
|
|
public int chunkIndentLevel { get { return m_IndentLevel; } }
|
|
public string chunkString { get { return m_ShaderChunkString; } }
|
|
}
|
|
|
|
private readonly List<ShaderChunk> m_ShaderChunks = new List<ShaderChunk>();
|
|
private int m_IndentLevel;
|
|
private string m_Pragma;
|
|
|
|
public void AddPragmaChunk(string s)
|
|
{
|
|
m_Pragma += s;
|
|
}
|
|
|
|
public string GetPragmaString()
|
|
{
|
|
return m_Pragma;
|
|
}
|
|
|
|
public void AddShaderChunk(string s, bool unique)
|
|
{
|
|
if (unique && m_ShaderChunks.Any(x => x.chunkString == s))
|
|
return;
|
|
|
|
m_ShaderChunks.Add(new ShaderChunk(m_IndentLevel, s));
|
|
}
|
|
|
|
public void Indent() { m_IndentLevel++; }
|
|
public void Deindent() { m_IndentLevel = Math.Max(0, m_IndentLevel - 1); }
|
|
|
|
public string GetShaderString(int baseIndentLevel)
|
|
{
|
|
var sb = new StringBuilder();
|
|
foreach (var shaderChunk in m_ShaderChunks)
|
|
{
|
|
|
|
var replaceString = "\n";
|
|
for (var i = 0; i < shaderChunk.chunkIndentLevel + baseIndentLevel; i++)
|
|
{
|
|
sb.Append("\t");
|
|
replaceString += "\t";
|
|
}
|
|
sb.AppendLine(shaderChunk.chunkString.Replace("\n", replaceString));
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static string GeneratePreviewShader(BaseMaterialNode node, out PreviewMode generatedShaderMode)
|
|
{
|
|
// figure out what kind of preview we want!
|
|
var childNodes = node.CollectChildNodesByExecutionOrder();
|
|
var generationMode = GenerationMode.Preview2D;
|
|
generatedShaderMode = PreviewMode.Preview2D;
|
|
if (childNodes.Any(x => x.previewMode == PreviewMode.Preview3D))
|
|
{
|
|
generationMode = GenerationMode.Preview3D;
|
|
generatedShaderMode = PreviewMode.Preview3D;
|
|
}
|
|
|
|
string templateLocation = Path.Combine (Application.dataPath, Path.Combine ("MaterialGraph", generationMode == GenerationMode.Preview2D ? "2DPreview.template" : "3DPreview.template"));
|
|
if (!File.Exists (templateLocation))
|
|
return null;
|
|
|
|
string template = File.ReadAllText (templateLocation);
|
|
|
|
var shaderBodyVisitor = new ShaderGenerator ();
|
|
var shaderInputVisitor = new ShaderGenerator ();
|
|
var shaderFunctionVisitor = new ShaderGenerator ();
|
|
var shaderPropertiesVisitor = new PropertyGenerator ();
|
|
var shaderPropertyUsagesVisitor = new ShaderGenerator ();
|
|
var vertexShaderBlock = new ShaderGenerator ();
|
|
|
|
var shaderName = "Hidden/PreviewShader/" + node.GetOutputVariableNameForSlot(node.outputSlots.First(), generationMode);
|
|
var activeNodeList = node.CollectChildNodesByExecutionOrder ();
|
|
|
|
if (node.graph is IGenerateGraphProperties)
|
|
(node.graph as IGenerateGraphProperties).GenerateSharedProperties (shaderPropertiesVisitor, shaderPropertyUsagesVisitor, generationMode);
|
|
|
|
foreach (var activeNode in activeNodeList)
|
|
{
|
|
if (activeNode is IGeneratesFunction)
|
|
(activeNode as IGeneratesFunction).GenerateNodeFunction (shaderFunctionVisitor, generationMode);
|
|
if (activeNode is IGeneratesVertexToFragmentBlock)
|
|
(activeNode as IGeneratesVertexToFragmentBlock).GenerateVertexToFragmentBlock (shaderInputVisitor, generationMode);
|
|
if (activeNode is IGeneratesBodyCode)
|
|
(activeNode as IGeneratesBodyCode).GenerateNodeCode (shaderBodyVisitor, generationMode);
|
|
if (activeNode is IGeneratesVertexShaderBlock)
|
|
(activeNode as IGeneratesVertexShaderBlock).GenerateVertexShaderBlock (vertexShaderBlock, generationMode);
|
|
|
|
activeNode.GeneratePropertyBlock (shaderPropertiesVisitor, generationMode);
|
|
activeNode.GeneratePropertyUsages (shaderPropertyUsagesVisitor, generationMode);
|
|
}
|
|
|
|
|
|
if (shaderInputVisitor.numberOfChunks == 0)
|
|
{
|
|
shaderInputVisitor.AddShaderChunk("float4 color : COLOR;", true);
|
|
}
|
|
|
|
if (generationMode == GenerationMode.Preview2D)
|
|
shaderBodyVisitor.AddShaderChunk ("return " + node.GetOutputVariableNameForSlot (node.outputSlots.FirstOrDefault (), generationMode) + ";", true);
|
|
else
|
|
shaderBodyVisitor.AddShaderChunk ("o.Emission = " + node.GetOutputVariableNameForSlot (node.outputSlots.FirstOrDefault (), generationMode) + ";", true);
|
|
|
|
template = template.Replace ("${ShaderName}", shaderName);
|
|
template = template.Replace ("${ShaderPropertiesHeader}", shaderPropertiesVisitor.GetShaderString (2));
|
|
template = template.Replace ("${ShaderPropertyUsages}", shaderPropertyUsagesVisitor.GetShaderString (3));
|
|
template = template.Replace ("${ShaderInputs}", shaderInputVisitor.GetShaderString (4));
|
|
template = template.Replace ("${ShaderFunctions}", shaderFunctionVisitor.GetShaderString (3));
|
|
template = template.Replace ("${VertexShaderBody}", vertexShaderBlock.GetShaderString (4));
|
|
template = template.Replace ("${PixelShaderBody}", shaderBodyVisitor.GetShaderString (4));
|
|
|
|
string vertexShaderBody = vertexShaderBlock.GetShaderString (4);
|
|
if (vertexShaderBody.Length > 0)
|
|
{
|
|
template = template.Replace ("${VertexShaderDecl}", "vertex:vert");
|
|
template = template.Replace ("${VertexShaderBody}", vertexShaderBody);
|
|
}
|
|
else
|
|
{
|
|
template = template.Replace ("${VertexShaderDecl}", "");
|
|
template = template.Replace ("${VertexShaderBody}", vertexShaderBody);
|
|
}
|
|
|
|
return template;
|
|
}
|
|
|
|
public static void GenerateSurfaceShader(MaterialGraph graph)
|
|
{
|
|
string templateLocation = Path.Combine(Application.dataPath, Path.Combine("MaterialGraph", "shader.template"));
|
|
if (!File.Exists(templateLocation))
|
|
return;
|
|
|
|
var templateText = File.ReadAllText(templateLocation);
|
|
|
|
var shaderBodyVisitor = new ShaderGenerator();
|
|
var shaderInputVisitor = new ShaderGenerator();
|
|
var shaderLightFunctionVisitor = new ShaderGenerator();
|
|
var shaderFunctionVisitor = new ShaderGenerator();
|
|
var shaderPropertiesVisitor = new PropertyGenerator();
|
|
var shaderPropertyUsagesVisitor = new ShaderGenerator();
|
|
var vertexShaderBlock = new ShaderGenerator();
|
|
|
|
(graph.currentGraph as PixelGraph).GenerateSurfaceShader(
|
|
shaderBodyVisitor,
|
|
shaderInputVisitor,
|
|
shaderLightFunctionVisitor,
|
|
shaderFunctionVisitor,
|
|
shaderPropertiesVisitor,
|
|
shaderPropertyUsagesVisitor,
|
|
vertexShaderBlock);
|
|
|
|
if (shaderInputVisitor.numberOfChunks == 0)
|
|
{
|
|
shaderInputVisitor.AddShaderChunk("float4 color : COLOR;", true);
|
|
}
|
|
|
|
var tagsVisitor = new ShaderGenerator();
|
|
var blendingVisitor = new ShaderGenerator();
|
|
var cullingVisitor = new ShaderGenerator();
|
|
var zTestVisitor = new ShaderGenerator();
|
|
var zWriteVisitor = new ShaderGenerator();
|
|
|
|
var options = graph.materialOptions;
|
|
options.GetTags(tagsVisitor);
|
|
options.GetBlend(blendingVisitor);
|
|
options.GetCull(cullingVisitor);
|
|
options.GetDepthTest(zTestVisitor);
|
|
options.GetDepthWrite(zWriteVisitor);
|
|
|
|
var resultShader = templateText.Replace("${ShaderName}", graph.name);
|
|
resultShader = resultShader.Replace("${ShaderPropertiesHeader}", shaderPropertiesVisitor.GetShaderString(2));
|
|
resultShader = resultShader.Replace("${ShaderPropertyUsages}", shaderPropertyUsagesVisitor.GetShaderString(2));
|
|
resultShader = resultShader.Replace("${LightingFunctionName}", shaderLightFunctionVisitor.GetPragmaString());
|
|
resultShader = resultShader.Replace("${LightingFunction}", shaderLightFunctionVisitor.GetShaderString(2));
|
|
resultShader = resultShader.Replace("${ShaderFunctions}", shaderFunctionVisitor.GetShaderString(2));
|
|
resultShader = resultShader.Replace("${ShaderInputs}", shaderInputVisitor.GetShaderString(3));
|
|
resultShader = resultShader.Replace("${PixelShaderBody}", shaderBodyVisitor.GetShaderString(3));
|
|
resultShader = resultShader.Replace("${Tags}", tagsVisitor.GetShaderString(2));
|
|
resultShader = resultShader.Replace("${Blending}", blendingVisitor.GetShaderString(2));
|
|
resultShader = resultShader.Replace("${Culling}", cullingVisitor.GetShaderString(2));
|
|
resultShader = resultShader.Replace("${ZTest}", zTestVisitor.GetShaderString(2));
|
|
resultShader = resultShader.Replace("${ZWrite}", zWriteVisitor.GetShaderString(2));
|
|
|
|
string vertexShaderBody = vertexShaderBlock.GetShaderString(3);
|
|
if (vertexShaderBody.Length > 0)
|
|
{
|
|
resultShader = resultShader.Replace("${VertexShaderDecl}", "vertex:vert");
|
|
resultShader = resultShader.Replace("${VertexShaderBody}", vertexShaderBody);
|
|
}
|
|
else
|
|
{
|
|
resultShader = resultShader.Replace("${VertexShaderDecl}", "");
|
|
resultShader = resultShader.Replace("${VertexShaderBody}", "");
|
|
}
|
|
|
|
//Build a map of default
|
|
graph.UpdateShaderSource(resultShader, shaderPropertiesVisitor.GetDefaultTexutres());
|
|
MaterialWindow.DebugMaterialGraph("----------Shader-----------");
|
|
MaterialWindow.DebugMaterialGraph(resultShader);
|
|
}
|
|
|
|
public int numberOfChunks
|
|
{
|
|
get { return m_ShaderChunks.Count; }
|
|
}
|
|
}
|
|
}
|