|
|
|
|
|
|
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(); |
|
|
|