浏览代码

Major shader generation refactor part 1

/main
Peter Bay Bastian 6 年前
当前提交
a107a23e
共有 6 个文件被更改,包括 560 次插入452 次删除
  1. 296
      ShaderGraph/HDPipeline/HDUnlitSubShader.cs
  2. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/MasterNode.cs
  3. 50
      ShaderGraph/com.unity.shadergraph/Editor/Data/SurfaceModel/SurfaceMaterialOptions.cs
  4. 384
      ShaderGraph/com.unity.shadergraph/Editor/Data/Util/GraphUtil.cs
  5. 233
      ShaderGraph/com.unity.shadergraph/Editor/Data/Util/ShaderGenerator.cs
  6. 47
      ShaderGraph/com.unity.shadergraph/Editor/Templates/HDUnlitPassForward.template

296
ShaderGraph/HDPipeline/HDUnlitSubShader.cs


[Serializable]
public class HDUnlitSubShader
{
static NeededCoordinateSpace m_VertexCoordinateSpace = NeededCoordinateSpace.Object;
static NeededCoordinateSpace m_PixelCoordinateSpace = NeededCoordinateSpace.World;
struct Pass
{
public string Name;

PixelShaderSlots = new List<int>()
{
UnlitMasterNode.ColorSlotId,
UnlitMasterNode.AlphaSlotId
UnlitMasterNode.AlphaSlotId,
UnlitMasterNode.AlphaThresholdSlotId
}
};

PixelShaderSlots = new List<int>()
{
UnlitMasterNode.ColorSlotId,
UnlitMasterNode.AlphaSlotId
UnlitMasterNode.AlphaSlotId,
UnlitMasterNode.AlphaThresholdSlotId
private static string GetShaderPassFromTemplate(UnlitMasterNode masterNode, Pass pass, GenerationMode mode)
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
var builder = new ShaderStringBuilder();
builder.IncreaseIndent();
builder.IncreaseIndent();
var templatePath = GetTemplatePath("HDUnlitPassForward.template");
if (!File.Exists(templatePath))
return string.Empty;
string passTemplate = File.ReadAllText(templatePath);
var masterNode = inMasterNode as UnlitMasterNode;
var subShader = new ShaderStringBuilder();
subShader.AppendLine("SubShader");
using(subShader.BlockScope())
{
subShader.AppendLine("Tags{ \"RenderPipeline\" = \"HDRenderPipeline\"}");
subShader.AppendLine("Tags{ \"RenderType\" = \"Opaque\" }");
var surfaceDescriptionFunction = new ShaderGenerator();
var surfaceDescriptionStruct = new ShaderGenerator();
var surfaceInputs = new ShaderGenerator();
var functionRegistry = new FunctionRegistry(builder);
subShader.AppendLines(
GetShaderPassFromTemplate(
passTemplate,
masterNode,
m_UnlitPassForwardDepthOnly,
mode));
subShader.AppendLines(
GetShaderPassFromTemplate(
passTemplate,
masterNode,
m_UnlitPassForwardOnly,
mode));
}
return subShader.ToString();
}
static string GetTemplatePath(string templateName)
{
var templatePath = ShaderGenerator.GetTemplatePath(templateName);
if (File.Exists(templatePath))
return templatePath;
throw new FileNotFoundException(string.Format(@"Cannot find a template with name ""{0}"".", templateName));
}
private static string GetShaderPassFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode)
{
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// -------------------------------------
// String builders
var functionBuilder = new ShaderStringBuilder(1);
var functionRegistry = new FunctionRegistry(functionBuilder);
surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
var defines = new ShaderStringBuilder(1);
var graph = new ShaderStringBuilder(0);
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
var surfaceDescriptionInputStruct = new ShaderStringBuilder(1);
var surfaceDescriptionFunction = new ShaderStringBuilder(1);
var surfaceDescriptionStruct = new ShaderStringBuilder(1);
var pixelShader = new ShaderStringBuilder(2);
var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
var pixelShaderSurfaceRemap = new ShaderStringBuilder(2);
// -------------------------------------
// Get Slot and Node lists per stage
var requirements = ShaderGraphRequirements.FromNodes(activeNodeList);
var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var pixelNodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
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);
// -------------------------------------
// Get Requirements
ShaderGenerator defines = new ShaderGenerator();
defines.AddShaderChunk(string.Format("#define SHADERPASS {0}", pass.ShaderPassName), true);
var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes);
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
// ----------------------------------------------------- //
// START SHADER GENERATION //
// ----------------------------------------------------- //
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
// -------------------------------------
// Calculate material options
foreach (var channel in requirements.requiresMeshUVs.Distinct())
var tagsBuilder = new ShaderStringBuilder(1);
var blendingBuilder = new ShaderStringBuilder(1);
var cullingBuilder = new ShaderStringBuilder(1);
var zTestBuilder = new ShaderStringBuilder(1);
var zWriteBuilder = new ShaderStringBuilder(1);
var materialOptions = new SurfaceMaterialOptions();
materialOptions.GetTags(tagsBuilder);
materialOptions.GetBlend(blendingBuilder);
materialOptions.GetCull(cullingBuilder);
materialOptions.GetDepthTest(zTestBuilder);
materialOptions.GetDepthWrite(zWriteBuilder);
// -------------------------------------
// Generate defines
defines.AppendLine("#define SHADERPASS {0}", pass.ShaderPassName);
foreach (var channel in pixelRequirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
defines.AddShaderChunk(string.Format("#define ATTRIBUTES_NEED_TEXCOORD{0}", (int)channel), true);
defines.AddShaderChunk(string.Format("#define VARYINGS_NEED_TEXCOORD{0}", (int)channel), true);
defines.AppendLine("#define ATTRIBUTES_NEED_TEXCOORD{0}", (int)channel);
defines.AppendLine("#define VARYINGS_NEED_TEXCOORD{0}", (int)channel);
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
defines.AppendLine("#define _ALPHATEST_ON");
var slots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
// ----------------------------------------------------- //
// START SURFACE DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Surface Description function
// Surface Description Input requirements are needed to exclude intermediate translation spaces
surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs", false);
using(surfaceDescriptionInputStruct.BlockSemicolonScope())
var slot = masterNode.FindSlot<MaterialSlot>(id);
if (slot != null)
slots.Add(slot);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(pixelRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);
if (pixelRequirements.requiresVertexColor)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (pixelRequirements.requiresScreenPosition)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in pixelRequirements.requiresMeshUVs.Distinct())
{
surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
}
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, true);
// -------------------------------------
// Generate Output structure for Surface Description function
var usedSlots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
usedSlots.Add(masterNode.FindSlot<MaterialSlot>(id));
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots, true);
// -------------------------------------
// Generate Surface Description function
GraphUtil.GenerateSurfaceDescription(
activeNodeList,
GraphUtil.GenerateSurfaceDescriptionFunction(
pixelNodes,
requirements,
pixelRequirements,
usedSlots);
var graph = new ShaderGenerator();
graph.AddShaderChunk(shaderProperties.GetPropertiesDeclaration(2), false);
graph.AddShaderChunk(surfaceInputs.GetShaderString(2), false);
graph.AddShaderChunk(builder.ToString(), false);
graph.AddShaderChunk(surfaceDescriptionStruct.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionFunction.GetShaderString(2), false);
pixelSlots);
var tagsVisitor = new ShaderGenerator();
var blendingVisitor = new ShaderGenerator();
var cullingVisitor = new ShaderGenerator();
var zTestVisitor = new ShaderGenerator();
var zWriteVisitor = new ShaderGenerator();
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
var materialOptions = new SurfaceMaterialOptions();
materialOptions.GetTags(tagsVisitor);
materialOptions.GetBlend(blendingVisitor);
materialOptions.GetCull(cullingVisitor);
materialOptions.GetDepthTest(zTestVisitor);
materialOptions.GetDepthWrite(zWriteVisitor);
// -------------------------------------
// TODO - Why is this not a full generation?
// Generate standard transformations
var localPixelShader = new ShaderGenerator();
var localSurfaceInputs = new ShaderGenerator();
var surfaceOutputRemap = new ShaderGenerator();
foreach (var channel in requirements.requiresMeshUVs.Distinct())
localSurfaceInputs.AddShaderChunk(string.Format("surfaceInput.{0} = {1};", channel.GetUVName(), string.Format("half4(input.texCoord{0}, 0, 0)", (int)channel)), false);
foreach (var channel in pixelRequirements.requiresMeshUVs.Distinct())
pixelShaderSurfaceInputs.AppendLine("surfaceInput.{0} = {1};", channel.GetUVName(), string.Format("half4(input.texCoord{0}, 0, 0)", (int)channel));
var templateLocation = ShaderGenerator.GetTemplatePath("HDUnlitPassForward.template");
// -------------------------------------
// Generate pixel shader surface remap
foreach (var slot in usedSlots)
foreach (var slot in pixelSlots)
surfaceOutputRemap.AddShaderChunk(slot.shaderOutputName
+ " = surf."
+ slot.shaderOutputName + ";", true);
pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName);
if (!File.Exists(templateLocation))
return string.Empty;
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
var subShaderTemplate = File.ReadAllText(templateLocation);
var resultPass = subShaderTemplate.Replace("${Defines}", defines.GetShaderString(3));
resultPass = resultPass.Replace("${Graph}", graph.GetShaderString(3));
resultPass = resultPass.Replace("${LocalPixelShader}", localPixelShader.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceInputs}", localSurfaceInputs.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceOutputRemap}", surfaceOutputRemap.GetShaderString(3));
resultPass = resultPass.Replace("${LightMode}", pass.Name);
resultPass = resultPass.Replace("${ShaderPassInclude}", pass.ShaderPassInclude);
// -------------------------------------
// Combine Graph sections
graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));
resultPass = resultPass.Replace("${Tags}", tagsVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${Blending}", blendingVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${Culling}", cullingVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${ZTest}", zTestVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${ZWrite}", zWriteVisitor.GetShaderString(2));
resultPass = resultPass.Replace("${LOD}", "" + materialOptions.lod);
return resultPass;
}
graph.AppendLine(functionBuilder.ToString());
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
{
var masterNode = inMasterNode as UnlitMasterNode;
var subShader = new ShaderGenerator();
subShader.AddShaderChunk("SubShader", true);
subShader.AddShaderChunk("{", true);
subShader.Indent();
subShader.AddShaderChunk("Tags{ \"RenderPipeline\" = \"HDRenderPipeline\"}", true);
subShader.AddShaderChunk("Tags{ \"RenderType\" = \"Opaque\" }", true);
graph.AppendLine(surfaceDescriptionInputStruct.ToString());
graph.AppendLine(surfaceDescriptionStruct.ToString());
graph.AppendLine(surfaceDescriptionFunction.ToString());
subShader.AddShaderChunk(
GetShaderPassFromTemplate(
masterNode,
m_UnlitPassForwardDepthOnly,
mode),
true);
// -------------------------------------
// Generate final subshader
subShader.AddShaderChunk(
GetShaderPassFromTemplate(
masterNode,
m_UnlitPassForwardOnly,
mode),
true);
var resultPass = template.Replace("${Tags}", tagsBuilder.ToString());
resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString());
resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString());
resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString());
resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString());
resultPass = resultPass.Replace("${Defines}", defines.ToString());
resultPass = resultPass.Replace("${LOD}", "" + materialOptions.lod);
subShader.Deindent();
subShader.AddShaderChunk("}", true);
resultPass = resultPass.Replace("${LightMode}", pass.Name);
resultPass = resultPass.Replace("${ShaderPassInclude}", pass.ShaderPassInclude);
resultPass = resultPass.Replace("${Graph}", graph.ToString());
return subShader.GetShaderString(0);
resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString());
return resultPass;
}
}
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/MasterNode.cs


finalShader.AddShaderChunk("Properties", false);
finalShader.AddShaderChunk("{", false);
finalShader.Indent();
finalShader.AddShaderChunk(shaderProperties.GetPropertiesBlock(2), false);
finalShader.AddShaderChunk(shaderProperties.GetPropertiesBlock(0), false);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);

50
ShaderGraph/com.unity.shadergraph/Editor/Data/SurfaceModel/SurfaceMaterialOptions.cs


lod = 200;
}
public void GetTags(ShaderGenerator visitor)
public void GetTags(ShaderStringBuilder builder)
visitor.AddShaderChunk("Tags", false);
visitor.AddShaderChunk("{", false);
visitor.Indent();
visitor.AddShaderChunk("\"RenderType\"=\"" + renderType + "\"", false);
visitor.AddShaderChunk("\"Queue\"=\"" + renderQueue + "\"", false);
visitor.Deindent();
visitor.AddShaderChunk("}", false);
builder.AppendLine("Tags");
using (builder.BlockScope())
{
builder.AppendLine("\"RenderType\"=\"{0}\"", renderType);
builder.AppendLine("\"Queue\"=\"{0}\"", renderQueue);
}
public void GetBlend(ShaderGenerator visitor)
public void GetBlend(ShaderStringBuilder builder)
visitor.AddShaderChunk("Blend " + srcBlend + " " + dstBlend, false);
builder.AppendLine("Blend {0} {1}", srcBlend, dstBlend);
public void GetCull(ShaderGenerator visitor)
public void GetCull(ShaderStringBuilder builder)
visitor.AddShaderChunk("Cull " + cullMode, false);
builder.AppendLine("Cull {0}", cullMode);
public void GetDepthWrite(ShaderGenerator visitor)
public void GetDepthWrite(ShaderStringBuilder builder)
visitor.AddShaderChunk("ZWrite " + zWrite, false);
builder.AppendLine("ZWrite {0}", zWrite);
public void GetDepthTest(ShaderGenerator visitor)
public void GetDepthTest(ShaderStringBuilder builder)
visitor.AddShaderChunk("ZTest " + zTest, false);
builder.AppendLine("ZTest {0}", zTest);
/*private Vector2 m_ScrollPos;
public void DoGUI()
{
GUILayout.BeginVertical();
m_Expanded = MaterialGraphStyles.Header("Options", m_Expanded);
if (m_Expanded)
{
srcBlend = (BlendMode) EditorGUILayout.EnumPopup("Src Blend", srcBlend);
dstBlend = (BlendMode) EditorGUILayout.EnumPopup("Dst Blend", dstBlend);
cullMode = (CullMode) EditorGUILayout.EnumPopup("Cull Mode", cullMode);
zTest = (ZTest) EditorGUILayout.EnumPopup("Z Test", zTest);
zWrite = (ZWrite) EditorGUILayout.EnumPopup("Z Write", zWrite);
renderQueue = (RenderQueue) EditorGUILayout.EnumPopup("Render Queue", renderQueue);
renderType = (RenderType) EditorGUILayout.EnumPopup("Render Type", renderType);
}
GUILayout.EndVertical();
}*/
public BlendMode srcBlend { get { return m_SrcBlend; } set { m_SrcBlend = value; } }
public BlendMode dstBlend { get { return m_DstBlend; } set { m_DstBlend = value; } }

384
ShaderGraph/com.unity.shadergraph/Editor/Data/Util/GraphUtil.cs


return newText.ToString();
}
public static void GenerateApplicationVertexInputs(ShaderGraphRequirements graphRequiements, ShaderGenerator vertexInputs)
{
var builder = new ShaderStringBuilder();
GenerateApplicationVertexInputs(graphRequiements, builder);
vertexInputs.AddShaderChunk(builder.ToString(), false);
}
public static void GenerateApplicationVertexInputs(ShaderGraphRequirements graphRequiements, ShaderStringBuilder vertexInputs)
{
vertexInputs.AppendLine("struct GraphVertexInput");

public static GenerationResults GetShader(this AbstractMaterialGraph graph, AbstractMaterialNode node, GenerationMode mode, string name)
{
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// -------------------------------------
// String builders
var finalShader = new ShaderStringBuilder();
var vertexInputs = new ShaderGenerator();
var vertexShader = new ShaderGenerator();
var surfaceDescriptionFunction = new ShaderGenerator();
var surfaceDescriptionStruct = new ShaderGenerator();
var shaderProperties = new PropertyCollector();
var surfaceInputs = new ShaderGenerator();
surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
var vertexDescriptionFunction = new ShaderStringBuilder(0);
var surfaceDescriptionInputStruct = new ShaderStringBuilder(0);
var surfaceDescriptionStruct = new ShaderStringBuilder(0);
var surfaceDescriptionFunction = new ShaderStringBuilder(0);
var vertexInputs = new ShaderStringBuilder(0);
// -------------------------------------
// Get Slot and Node lists
var activeNodeList = ListPool<INode>.Get();
if (isUber)

NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);
}
var requirements = ShaderGraphRequirements.FromNodes(activeNodeList, ShaderStageCapability.Fragment);
GenerateApplicationVertexInputs(requirements, vertexInputs);
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.requiresScreenPosition)
surfaceInputs.AddShaderChunk(String.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
results.previewMode = PreviewMode.Preview3D;
if (!isUber)
{
foreach (var pNode in activeNodeList.OfType<AbstractMaterialNode>())
{
if (pNode.previewMode == PreviewMode.Preview3D)
{
results.previewMode = PreviewMode.Preview3D;
break;
}
}
}
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(String.Format("half4 {0};", channel.GetUVName()), false);
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
vertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
vertexShader.Indent();
vertexShader.AddShaderChunk("return v;", false);
vertexShader.Deindent();
vertexShader.AddShaderChunk("}", false);
var slots = new List<MaterialSlot>();
foreach (var activeNode in isUber ? activeNodeList.Where(n => ((AbstractMaterialNode)n).hasPreview) : ((INode)node).ToEnumerable())
{

slots.AddRange(activeNode.GetOutputSlots<MaterialSlot>());
}
GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, !isUber);
var shaderProperties = new PropertyCollector();
// -------------------------------------
// Get Requirements
var requirements = ShaderGraphRequirements.FromNodes(activeNodeList, ShaderStageCapability.Fragment);
// -------------------------------------
// Add preview shader output property
results.outputIdProperty = new Vector1ShaderProperty
{
displayName = "OutputId",

if (isUber)
shaderProperties.AddShaderProperty(results.outputIdProperty);
GenerateSurfaceDescription(
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Vertex Description function
vertexDescriptionFunction.AppendLine("GraphVertexInput PopulateVertexData(GraphVertexInput v)");
using(vertexDescriptionFunction.BlockScope())
{
vertexDescriptionFunction.AppendLine("return v;");
}
// ----------------------------------------------------- //
// START SURFACE DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Surface Description function
// Surface Description Input requirements are needed to exclude intermediate translation spaces
surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs");
using(surfaceDescriptionInputStruct.BlockSemicolonScope())
{
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);
if (requirements.requiresVertexColor)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (requirements.requiresScreenPosition)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
results.previewMode = PreviewMode.Preview3D;
if (!isUber)
{
foreach (var pNode in activeNodeList.OfType<AbstractMaterialNode>())
{
if (pNode.previewMode == PreviewMode.Preview3D)
{
results.previewMode = PreviewMode.Preview3D;
break;
}
}
}
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
}
// -------------------------------------
// Generate Output structure for Surface Description function
GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, !isUber);
// -------------------------------------
// Generate Surface Description function
GenerateSurfaceDescriptionFunction(
activeNodeList,
node,
graph,

mode,
outputIdProperty: results.outputIdProperty);
var finalBuilder = new ShaderStringBuilder();
finalBuilder.AppendLine(@"Shader ""{0}""", name);
using (finalBuilder.BlockScope())
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex shader
GenerateApplicationVertexInputs(requirements, vertexInputs);
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
// -------------------------------------
// Build final shader
finalShader.AppendLine(@"Shader ""{0}""", name);
using (finalShader.BlockScope())
finalBuilder.AppendLine("Properties");
using (finalBuilder.BlockScope())
finalShader.AppendLine("Properties");
using (finalShader.BlockScope())
finalBuilder.AppendLines(shaderProperties.GetPropertiesBlock(0));
finalShader.AppendLines(shaderProperties.GetPropertiesBlock(0));
finalShader.AppendNewLine();
finalBuilder.AppendLine(@"HLSLINCLUDE");
finalBuilder.AppendLine("#define USE_LEGACY_UNITY_MATRIX_VARIABLES");
finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/Common.hlsl""");
finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/Packing.hlsl""");
finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/Color.hlsl""");
finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/UnityInstancing.hlsl""");
finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/EntityLighting.hlsl""");
finalBuilder.AppendLine(@"#include ""ShaderGraphLibrary/ShaderVariables.hlsl""");
finalBuilder.AppendLine(@"#include ""ShaderGraphLibrary/ShaderVariablesFunctions.hlsl""");
finalBuilder.AppendLine(@"#include ""ShaderGraphLibrary/Functions.hlsl""");
finalShader.AppendLine(@"HLSLINCLUDE");
finalShader.AppendLine("#define USE_LEGACY_UNITY_MATRIX_VARIABLES");
finalShader.AppendLine(@"#include ""CoreRP/ShaderLibrary/Common.hlsl""");
finalShader.AppendLine(@"#include ""CoreRP/ShaderLibrary/Packing.hlsl""");
finalShader.AppendLine(@"#include ""CoreRP/ShaderLibrary/Color.hlsl""");
finalShader.AppendLine(@"#include ""CoreRP/ShaderLibrary/UnityInstancing.hlsl""");
finalShader.AppendLine(@"#include ""CoreRP/ShaderLibrary/EntityLighting.hlsl""");
finalShader.AppendLine(@"#include ""ShaderGraphLibrary/ShaderVariables.hlsl""");
finalShader.AppendLine(@"#include ""ShaderGraphLibrary/ShaderVariablesFunctions.hlsl""");
finalShader.AppendLine(@"#include ""ShaderGraphLibrary/Functions.hlsl""");
finalShader.AppendNewLine();
finalBuilder.AppendLines(shaderProperties.GetPropertiesDeclaration(0));
finalBuilder.AppendLines(surfaceInputs.GetShaderString(0));
finalBuilder.Concat(functionBuilder);
finalBuilder.AppendLines(vertexInputs.GetShaderString(0));
finalBuilder.AppendLines(surfaceDescriptionStruct.GetShaderString(0));
finalBuilder.AppendLines(vertexShader.GetShaderString(0));
finalBuilder.AppendLines(surfaceDescriptionFunction.GetShaderString(0));
finalBuilder.AppendLine(@"ENDHLSL");
finalShader.AppendLines(shaderProperties.GetPropertiesDeclaration(0));
finalBuilder.AppendLines(ShaderGenerator.GetPreviewSubShader(node, requirements));
finalShader.Concat(functionBuilder);
finalShader.AppendNewLine();
finalShader.AppendLines(surfaceDescriptionInputStruct.ToString());
finalShader.AppendNewLine();
finalShader.AppendLines(surfaceDescriptionStruct.ToString());
finalShader.AppendNewLine();
finalShader.AppendLines(surfaceDescriptionFunction.ToString());
finalShader.AppendNewLine();
finalShader.AppendLines(vertexInputs.ToString());
finalShader.AppendNewLine();
finalShader.AppendLines(vertexDescriptionFunction.ToString());
finalShader.AppendNewLine();
finalShader.AppendLine(@"ENDHLSL");
finalShader.AppendLines(ShaderGenerator.GetPreviewSubShader(node, requirements));
// -------------------------------------
// Finalize
results.shader = finalBuilder.ToString(out sourceMap);
results.shader = finalShader.ToString(out sourceMap);
public static void GenerateSurfaceDescriptionStruct(ShaderGenerator surfaceDescriptionStruct, List<MaterialSlot> slots, bool isMaster)
public static void GenerateSurfaceDescriptionStruct(ShaderStringBuilder surfaceDescriptionStruct, List<MaterialSlot> slots, bool isMaster)
surfaceDescriptionStruct.AddShaderChunk("struct SurfaceDescription{", false);
surfaceDescriptionStruct.Indent();
if (isMaster)
{
foreach (var slot in slots)
surfaceDescriptionStruct.AddShaderChunk(String.Format("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType), NodeUtils.GetHLSLSafeName(slot.shaderOutputName)), false);
surfaceDescriptionStruct.Deindent();
}
else
surfaceDescriptionStruct.AppendLine("struct SurfaceDescription");
using(surfaceDescriptionStruct.BlockSemicolonScope())
surfaceDescriptionStruct.AddShaderChunk("float4 PreviewOutput;", false);
if (isMaster)
{
foreach (var slot in slots)
surfaceDescriptionStruct.AppendLine("{0} {1};",
NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType),
NodeUtils.GetHLSLSafeName(slot.shaderOutputName));
//surfaceDescriptionStruct.Deindent();
}
else
{
surfaceDescriptionStruct.AppendLine("float4 PreviewOutput;");
}
surfaceDescriptionStruct.Deindent();
surfaceDescriptionStruct.AddShaderChunk("};", false);
public static void GenerateSurfaceDescription(
public static void GenerateSurfaceDescriptionFunction(
ShaderGenerator surfaceDescriptionFunction,
ShaderStringBuilder surfaceDescriptionFunction,
FunctionRegistry functionRegistry,
PropertyCollector shaderProperties,
ShaderGraphRequirements requirements,

if (graph == null)
return;
surfaceDescriptionFunction.AddShaderChunk(String.Format("{0} {1}(SurfaceInputs IN) {{", surfaceDescriptionName, functionName), false);
surfaceDescriptionFunction.Indent();
surfaceDescriptionFunction.AddShaderChunk(String.Format("{0} surface = ({0})0;", surfaceDescriptionName), false);
foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
surfaceDescriptionFunction.AppendLine(String.Format("{0} {1}(SurfaceDescriptionInputs IN)", surfaceDescriptionName, functionName), false);
using(surfaceDescriptionFunction.BlockScope())
if (activeNode is IGeneratesFunction)
{
functionRegistry.builder.currentNode = activeNode;
(activeNode as IGeneratesFunction).GenerateNodeFunction(functionRegistry, mode);
}
if (activeNode is IGeneratesBodyCode)
(activeNode as IGeneratesBodyCode).GenerateNodeCode(surfaceDescriptionFunction, mode);
if (masterNode == null && activeNode.hasPreview)
ShaderGenerator sg = new ShaderGenerator();
surfaceDescriptionFunction.AppendLine("{0} surface = ({0})0;", surfaceDescriptionName);
foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
var outputSlot = activeNode.GetOutputSlots<MaterialSlot>().FirstOrDefault();
if (outputSlot != null)
surfaceDescriptionFunction.AddShaderChunk(String.Format("if ({0} == {1}) {{ surface.PreviewOutput = {2}; return surface; }}", outputIdProperty.referenceName, activeNode.tempId.index, ShaderGenerator.AdaptNodeOutputForPreview(activeNode, outputSlot.id, activeNode.GetVariableNameForSlot(outputSlot.id))), false);
}
if (activeNode is IGeneratesFunction)
{
functionRegistry.builder.currentNode = activeNode;
(activeNode as IGeneratesFunction).GenerateNodeFunction(functionRegistry, mode);
}
if (activeNode is IGeneratesBodyCode)
(activeNode as IGeneratesBodyCode).GenerateNodeCode(sg, mode);
if (masterNode == null && activeNode.hasPreview)
{
var outputSlot = activeNode.GetOutputSlots<MaterialSlot>().FirstOrDefault();
if (outputSlot != null)
sg.AddShaderChunk(String.Format("if ({0} == {1}) {{ surface.PreviewOutput = {2}; return surface; }}", outputIdProperty.referenceName, activeNode.tempId.index, ShaderGenerator.AdaptNodeOutputForPreview(activeNode, outputSlot.id, activeNode.GetVariableNameForSlot(outputSlot.id))), false);
}
// In case of the subgraph output node, the preview is generated
// from the first input to the node.
if (activeNode is SubGraphOutputNode)
{
var inputSlot = activeNode.GetInputSlots<MaterialSlot>().FirstOrDefault();
if (inputSlot != null)
// In case of the subgraph output node, the preview is generated
// from the first input to the node.
if (activeNode is SubGraphOutputNode)
var foundEdges = graph.GetEdges(inputSlot.slotReference).ToArray();
string slotValue = foundEdges.Any() ? activeNode.GetSlotValue(inputSlot.id, mode) : inputSlot.GetDefaultValue(mode);
surfaceDescriptionFunction.AddShaderChunk(String.Format("if ({0} == {1}) {{ surface.PreviewOutput = {2}; return surface; }}", outputIdProperty.referenceName, activeNode.tempId.index, slotValue), false);
var inputSlot = activeNode.GetInputSlots<MaterialSlot>().FirstOrDefault();
if (inputSlot != null)
{
var foundEdges = graph.GetEdges(inputSlot.slotReference).ToArray();
string slotValue = foundEdges.Any() ? activeNode.GetSlotValue(inputSlot.id, mode) : inputSlot.GetDefaultValue(mode);
sg.AddShaderChunk(String.Format("if ({0} == {1}) {{ surface.PreviewOutput = {2}; return surface; }}", outputIdProperty.referenceName, activeNode.tempId.index, slotValue), false);
}
}
activeNode.CollectShaderProperties(shaderProperties, mode);
}
functionRegistry.builder.currentNode = null;
activeNode.CollectShaderProperties(shaderProperties, mode);
}
surfaceDescriptionFunction.AppendLines(sg.GetShaderString(0));
functionRegistry.builder.currentNode = null;
if (masterNode != null)
{
if (masterNode is IMasterNode)
if (masterNode != null)
var usedSlots = slots ?? masterNode.GetInputSlots<MaterialSlot>();
foreach (var input in usedSlots)
if (masterNode is IMasterNode)
var foundEdges = graph.GetEdges(input.slotReference).ToArray();
if (foundEdges.Any())
{
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(input.shaderOutputName), masterNode.GetSlotValue(input.id, mode)), true);
}
else
var usedSlots = slots ?? masterNode.GetInputSlots<MaterialSlot>();
foreach (var input in usedSlots)
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(input.shaderOutputName), input.GetDefaultValue(mode)), true);
var foundEdges = graph.GetEdges(input.slotReference).ToArray();
if (foundEdges.Any())
{
surfaceDescriptionFunction.AppendLine("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(input.shaderOutputName), masterNode.GetSlotValue(input.id, mode));
}
else
{
surfaceDescriptionFunction.AppendLine("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(input.shaderOutputName), input.GetDefaultValue(mode));
}
}
else if (masterNode.hasPreview)
{
foreach (var slot in masterNode.GetOutputSlots<MaterialSlot>())
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(slot.shaderOutputName), masterNode.GetSlotValue(slot.id, mode)), true);
else if (masterNode.hasPreview)
{
foreach (var slot in masterNode.GetOutputSlots<MaterialSlot>())
surfaceDescriptionFunction.AppendLine("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(slot.shaderOutputName), masterNode.GetSlotValue(slot.id, mode));
}
}
surfaceDescriptionFunction.AddShaderChunk("return surface;", false);
surfaceDescriptionFunction.Deindent();
surfaceDescriptionFunction.AddShaderChunk("}", false);
surfaceDescriptionFunction.AppendLine("return surface;");
}
}
const string k_VertexDescriptionStructName = "VertexDescription";

}
}
public static void GenerateVertexDescriptionFunction(
AbstractMaterialGraph graph,
GenerationMode generationMode,
GenerationMode mode,
if (graph == null)
return;
graph.CollectShaderProperties(shaderProperties, mode);
ShaderGenerator sg = new ShaderGenerator();
builder.AppendLine("{0} description = ({0})0;", k_VertexDescriptionStructName);
foreach (var node in nodes)
{

functionRegistry.builder.currentNode = node;
generatesFunction.GenerateNodeFunction(functionRegistry, generationMode);
generatesFunction.GenerateNodeFunction(functionRegistry, mode);
var generator = new ShaderGenerator();
generatesBodyCode.GenerateNodeCode(generator, generationMode);
builder.AppendLines(generator.GetShaderString(0));
generatesBodyCode.GenerateNodeCode(sg, mode);
node.CollectShaderProperties(shaderProperties, generationMode);
node.CollectShaderProperties(shaderProperties, mode);
builder.AppendLines(sg.GetShaderString(0));
var slotValue = isSlotConnected ? ((AbstractMaterialNode)slot.owner).GetSlotValue(slot.id, generationMode) : slot.GetDefaultValue(generationMode);
var slotValue = isSlotConnected ? ((AbstractMaterialNode)slot.owner).GetSlotValue(slot.id, mode) : slot.GetDefaultValue(mode);
builder.AppendLine("description.{0} = {1};", slotName, slotValue);
}
builder.AppendLine("return description;");

233
ShaderGraph/com.unity.shadergraph/Editor/Data/Util/ShaderGenerator.cs


public static void GenerateSpaceTranslationSurfaceInputs(
NeededCoordinateSpace neededSpaces,
InterpolatorType interpolatorType,
ShaderGenerator surfaceInputs,
string format = "float3 {0};")
{
var builder = new ShaderStringBuilder();
GenerateSpaceTranslationSurfaceInputs(neededSpaces, interpolatorType, builder, format);
surfaceInputs.AddShaderChunk(builder.ToString(), false);
}
public static void GenerateSpaceTranslationSurfaceInputs(
NeededCoordinateSpace neededSpaces,
InterpolatorType interpolatorType,
ShaderStringBuilder builder,
string format = "float3 {0};")
{

public static void GenerateStandardTransforms(
int interpolatorStartIndex,
int maxInterpolators,
ShaderGenerator interpolators,
ShaderStringBuilder vertexDescriptionInputs,
ShaderGenerator vertexShader,
ShaderGenerator pixelShader,
ShaderGenerator surfaceInputs,
ShaderStringBuilder vertexOutputStruct,
ShaderStringBuilder vertexShader,
ShaderStringBuilder vertexShaderDescriptionInputs,
ShaderStringBuilder vertexShaderOutputs,
ShaderStringBuilder pixelShader,
ShaderStringBuilder pixelShaderSurfaceInputs,
ShaderGraphRequirements pixelRequirements,
ShaderGraphRequirements surfaceRequirements,
ShaderGraphRequirements modelRequiements,

if (combinedRequirements.requiresNormal > 0 || combinedRequirements.requiresBitangent > 0)
{
var name = preferredCoordinateSpace.ToVariableName(InterpolatorType.Normal);
vertexDescriptionInputs.AppendLine("float3 {0} = {1};", name, ConvertBetweenSpace("v.normal", CoordinateSpace.Object, preferredCoordinateSpace, InputType.Normal));
if (vertexRequirements.requiresNormal > 0 || vertexRequirements.requiresBitangent > 0)
vertexDescriptionInputs.AppendLine("vdi.{0} = {0};", name);
vertexShader.AppendLine("float3 {0} = {1};", name, ConvertBetweenSpace("v.normal", CoordinateSpace.Object, preferredCoordinateSpace, InputType.Normal));
//if (vertexRequirements.requiresNormal > 0 || vertexRequirements.requiresBitangent > 0)
// vertexDescriptionInputs.AppendLine("vdi.{0} = {0};", name);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {0};", name), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = normalize(IN.{0});", name), false);
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {0};", name);
pixelShader.AppendLine("float3 {0} = normalize(IN.{0});", name);
interpolatorIndex++;
}
}

var name = preferredCoordinateSpace.ToVariableName(InterpolatorType.Tangent);
vertexDescriptionInputs.AppendLine("float3 {0} = {1};", name, ConvertBetweenSpace("v.tangent.xyz", CoordinateSpace.Object, preferredCoordinateSpace, InputType.Vector));
if (vertexRequirements.requiresTangent > 0 || vertexRequirements.requiresBitangent > 0)
vertexDescriptionInputs.AppendLine("vdi.{0} = {0};", name);
vertexShader.AppendLine("float3 {0} = {1};", name, ConvertBetweenSpace("v.tangent.xyz", CoordinateSpace.Object, preferredCoordinateSpace, InputType.Vector));
//if (vertexRequirements.requiresTangent > 0 || vertexRequirements.requiresBitangent > 0)
// vertexDescriptionInputs.AppendLine("vdi.{0} = {0};", name);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {0};", name), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = IN.{0};", name), false);
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {0};", name);
pixelShader.AppendLine("float3 {0} = IN.{0};", name);
interpolatorIndex++;
}
}

var name = preferredCoordinateSpace.ToVariableName(InterpolatorType.BiTangent);
vertexDescriptionInputs.AppendLine("float3 {0} = normalize(cross({1}, {2}.xyz) * {3});",
vertexShader.AppendLine("float3 {0} = normalize(cross({1}, {2}.xyz) * {3});",
if (vertexRequirements.requiresBitangent > 0)
vertexDescriptionInputs.AppendLine("vdi.{0} = {0};", name);
//if (vertexRequirements.requiresBitangent > 0)
// vertexDescriptionInputs.AppendLine("vdi.{0} = {0};", name);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {0};", name), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = IN.{0};", name), false);
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {0};", name);
pixelShader.AppendLine("float3 {0} = IN.{0};", name);
interpolatorIndex++;
}
}

const string worldSpaceViewDir = "SafeNormalize(_WorldSpaceCameraPos.xyz - mul(GetObjectToWorldMatrix(), float4(v.vertex.xyz, 1.0)).xyz)";
var preferredSpaceViewDir = ConvertBetweenSpace(worldSpaceViewDir, CoordinateSpace.World, preferredCoordinateSpace, InputType.Vector);
if (vertexRequirements.requiresViewDir > 0)
vertexDescriptionInputs.AppendLine("vdi.{0} = {1};", name, preferredSpaceViewDir);
vertexShaderDescriptionInputs.AppendLine("vdi.{0} = {1};", name, preferredSpaceViewDir);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1};", name, preferredSpaceViewDir), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = normalize(IN.{0});", name), false);
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {1};", name, preferredSpaceViewDir);
pixelShader.AppendLine("float3 {0} = normalize(IN.{0});", name);
interpolatorIndex++;
}
}

var name = preferredCoordinateSpace.ToVariableName(InterpolatorType.Position);
var preferredSpacePosition = ConvertBetweenSpace("v.vertex", CoordinateSpace.Object, preferredCoordinateSpace, InputType.Position);
if (vertexRequirements.requiresPosition > 0)
vertexDescriptionInputs.AppendLine("float3 {0} = {1};", name, preferredSpacePosition);
vertexShader.AppendLine("float3 {0} = {1};", name, preferredSpacePosition);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1}.xyz;", name, preferredSpacePosition), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = IN.{0};", name), false);
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {1}.xyz;", name, preferredSpacePosition);
pixelShader.AppendLine("float3 {0} = IN.{0};", name);
interpolatorIndex++;
}
}

var bitangent = preferredCoordinateSpace.ToVariableName(InterpolatorType.BiTangent);
var normal = preferredCoordinateSpace.ToVariableName(InterpolatorType.Normal);
if (vertexRequirements.NeedsTangentSpace())
vertexDescriptionInputs.AppendLine("float3x3 tangentSpaceTransform = float3x3({0},{1},{2});",
vertexShader.AppendLine("float3x3 tangentSpaceTransform = float3x3({0},{1},{2});",
pixelShader.AddShaderChunk(string.Format("float3x3 tangentSpaceTransform = float3x3({0},{1},{2});",
tangent, bitangent, normal), false);
pixelShader.AppendLine("float3x3 tangentSpaceTransform = float3x3({0},{1},{2});",
tangent, bitangent, normal);
var sg = new ShaderGenerator();
//var sg = new ShaderGenerator();
InputType.Normal, sg, Dimension.Three);
InputType.Normal, vertexShader, Dimension.Three);
InputType.Vector, sg, Dimension.Three);
InputType.Vector, vertexShader, Dimension.Three);
InputType.Vector, sg, Dimension.Three);
InputType.Vector, vertexShader, Dimension.Three);
InputType.Vector, sg, Dimension.Three);
InputType.Vector, vertexShader, Dimension.Three);
InputType.Position, sg, Dimension.Three);
vertexDescriptionInputs.AppendLines(sg.GetShaderString(0));
InputType.Position, vertexShader, Dimension.Three);
//vertexShader.AppendLines(sg.GetShaderString(0));
}
// Generate the space translations needed by the surface description and model

GenerateSpaceTranslations(graphModelRequirements.requiresPosition, InterpolatorType.Position, preferredCoordinateSpace,
InputType.Position, pixelShader, Dimension.Three);
if (combinedRequirements.requiresVertexColor)
{
vertexDescriptionInputs.AppendLine("vdi.{0} = v.color;", ShaderGeneratorNames.VertexColor);
vertexShaderDescriptionInputs.AppendLine("vdi.{0} = v.color;", ShaderGeneratorNames.VertexColor);
interpolators.AddShaderChunk(string.Format("float4 {0} : COLOR;", ShaderGeneratorNames.VertexColor), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = v.color;", ShaderGeneratorNames.VertexColor), false);
pixelShader.AddShaderChunk(string.Format("float4 {0} = IN.{0};", ShaderGeneratorNames.VertexColor), false);
vertexOutputStruct.AppendLine("float4 {0} : COLOR;", ShaderGeneratorNames.VertexColor);
vertexShaderOutputs.AppendLine("o.{0} = v.color;", ShaderGeneratorNames.VertexColor);
pixelShader.AppendLine("float4 {0} = IN.{0};", ShaderGeneratorNames.VertexColor);
}
if (combinedRequirements.requiresScreenPosition)
/*if (combinedRequirements.requiresScreenPosition)
vertexShader.AddShaderChunk(string.Format("o.{0} = ComputeScreenPos(mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), v.vertex)), _ProjectionParams.x);", ShaderGeneratorNames.ScreenPosition), false);
vertexOutputs.AddShaderChunk(string.Format("o.{0} = ComputeScreenPos(mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), v.vertex)), _ProjectionParams.x);", ShaderGeneratorNames.ScreenPosition), false);
}
}*/
if (combinedRequirements.requiresScreenPosition)
{

vertexDescriptionInputs.AppendLine("float4 {0} = {1};", ShaderGeneratorNames.ScreenPosition, screenPosition);
vertexShader.AppendLine("float4 {0} = {1};", ShaderGeneratorNames.ScreenPosition, screenPosition);
vertexShaderDescriptionInputs.AppendLine("vdi.{0} = {0};", ShaderGeneratorNames.ScreenPosition);
interpolators.AddShaderChunk(string.Format("float4 {0} : TEXCOORD{1};", ShaderGeneratorNames.ScreenPosition, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1};", ShaderGeneratorNames.ScreenPosition, screenPosition), false);
pixelShader.AddShaderChunk(string.Format("float4 {0} = IN.{0};", ShaderGeneratorNames.ScreenPosition), false);
vertexOutputStruct.AppendLine("float4 {0} : TEXCOORD{1};", ShaderGeneratorNames.ScreenPosition, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {1};", ShaderGeneratorNames.ScreenPosition, screenPosition);
pixelShader.AppendLine("float4 {0} = IN.{0};", ShaderGeneratorNames.ScreenPosition);
interpolatorIndex++;
}
}

vertexDescriptionInputs.AppendLine("vdi.{0} = v.texcoord{1};", channel.GetUVName(), (int)channel);
vertexShaderDescriptionInputs.AppendLine("vdi.{0} = v.texcoord{1};", channel.GetUVName(), (int)channel);
interpolators.AddShaderChunk(string.Format("half4 {0} : TEXCOORD{1};", channel.GetUVName(), interpolatorIndex == 0 ? "" : interpolatorIndex.ToString()), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = v.texcoord{1};", channel.GetUVName(), (int)channel), false);
pixelShader.AddShaderChunk(string.Format("float4 {0} = IN.{0};", channel.GetUVName()), false);
vertexOutputStruct.AppendLine("half4 {0} : TEXCOORD{1};", channel.GetUVName(), interpolatorIndex == 0 ? "" : interpolatorIndex.ToString());
vertexShaderOutputs.AppendLine("o.{0} = v.texcoord{1};", channel.GetUVName(), (int)channel);
pixelShader.AppendLine("float4 {0} = IN.{0};", channel.GetUVName());
interpolatorIndex++;
}

// and are not needed in the shader graph
{
var replaceString = "surfaceInput.{0} = {0};";
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceInputs, replaceString);
}
{
var replaceString = "vdi.{0} = {0};";
var sg = new ShaderGenerator();
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, sg, replaceString);
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, sg, replaceString);
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, sg, replaceString);
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, sg, replaceString);
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, sg, replaceString);
vertexDescriptionInputs.AppendLines(sg.GetShaderString(0));
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, pixelShaderSurfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, pixelShaderSurfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, pixelShaderSurfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, pixelShaderSurfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, pixelShaderSurfaceInputs, replaceString);
surfaceInputs.AddShaderChunk(string.Format("surfaceInput.{0} = {0};", ShaderGeneratorNames.VertexColor), false);
pixelShaderSurfaceInputs.AppendLine("surfaceInput.{0} = {0};", ShaderGeneratorNames.VertexColor);
surfaceInputs.AddShaderChunk(string.Format("surfaceInput.{0} = {0};", ShaderGeneratorNames.ScreenPosition), false);
pixelShaderSurfaceInputs.AppendLine("surfaceInput.{0} = {0};", ShaderGeneratorNames.ScreenPosition);
surfaceInputs.AddShaderChunk(string.Format("surfaceInput.{0} = {0};", channel.GetUVName()), false);
pixelShaderSurfaceInputs.AppendLine("surfaceInput.{0} = {0};", ShaderGeneratorNames.GetUVName(channel));
{
var replaceString = "vdi.{0} = {0};";
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexShaderDescriptionInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexShaderDescriptionInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexShaderDescriptionInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexShaderDescriptionInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexShaderDescriptionInputs, replaceString);
}
}
public enum Dimension

InterpolatorType type,
CoordinateSpace from,
InputType inputType,
ShaderGenerator pixelShader,
ShaderStringBuilder pixelShader,
pixelShader.AddShaderChunk(
string.Format("float{0} {1} = {2};", DimensionToString(dimension),
CoordinateSpace.Object.ToVariableName(type), ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.Object, inputType, from)), false);
pixelShader.AppendLine("float{0} {1} = {2};", DimensionToString(dimension),
CoordinateSpace.Object.ToVariableName(type), ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.Object, inputType, from));
pixelShader.AddShaderChunk(
string.Format("float{0} {1} = {2};", DimensionToString(dimension),
CoordinateSpace.World.ToVariableName(type), ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.World, inputType, from)), false);
pixelShader.AppendLine("float{0} {1} = {2};", DimensionToString(dimension),
CoordinateSpace.World.ToVariableName(type), ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.World, inputType, from));
pixelShader.AddShaderChunk(
string.Format("float{0} {1} = {2};", DimensionToString(dimension),
pixelShader.AppendLine("float{0} {1} = {2};", DimensionToString(dimension),
ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.View, inputType, from)), false);
ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.View, inputType, from));
pixelShader.AddShaderChunk(
string.Format("float{0} {1} = {2};", DimensionToString(dimension),
pixelShader.AppendLine("float{0} {1} = {2};", DimensionToString(dimension),
ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.Tangent, inputType, from)), false);
ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.Tangent, inputType, from));
var interpolators = new ShaderGenerator();
var vertexDescriptionInputs = new ShaderStringBuilder(3);
var vertexShader = new ShaderGenerator();
var pixelShader = new ShaderGenerator();
var surfaceInputs = new ShaderGenerator();
var vertexOutputStruct = new ShaderStringBuilder(2);
var vertexShader = new ShaderStringBuilder(2);
var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
var vertexShaderOutputs = new ShaderStringBuilder(1);
var pixelShader = new ShaderStringBuilder(2);
var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
var pixelShaderSurfaceRemap = new ShaderStringBuilder(2);
interpolators,
vertexDescriptionInputs,
vertexOutputStruct,
vertexShaderDescriptionInputs,
vertexShaderOutputs,
surfaceInputs,
pixelShaderSurfaceInputs,
shaderGraphRequirements,
shaderGraphRequirements,
ShaderGraphRequirements.none,

vertexDescriptionInputs.AppendLines(vertexShader.GetShaderString(0));
vertexShader.AppendLines(vertexShaderDescriptionInputs.ToString());
vertexShader.AppendLines(vertexShaderOutputs.ToString());
var outputs = new ShaderGenerator();
if (node != null)
{
var outputSlot = node.GetOutputSlots<MaterialSlot>().FirstOrDefault();

outputs.AddShaderChunk(string.Format("return {0};", AdaptNodeOutputForPreview(node, outputSlot.id, result)), true);
pixelShaderSurfaceRemap.AppendLine("return {0};", AdaptNodeOutputForPreview(node, outputSlot.id, result));
outputs.AddShaderChunk("return 0;", true);
pixelShaderSurfaceRemap.AppendLine("return 0;");
outputs.AddShaderChunk("return surf.PreviewOutput;", false);
pixelShaderSurfaceRemap.AppendLine("return surf.PreviewOutput;");
var res = subShaderTemplate.Replace("${Interpolators}", interpolators.GetShaderString(0));
res = res.Replace("${VertexShader}", vertexDescriptionInputs.ToString());
res = res.Replace("${LocalPixelShader}", pixelShader.GetShaderString(0));
res = res.Replace("${SurfaceInputs}", surfaceInputs.GetShaderString(0));
res = res.Replace("${SurfaceOutputRemap}", outputs.GetShaderString(0));
var res = subShaderTemplate.Replace("${Interpolators}", vertexOutputStruct.ToString());
res = res.Replace("${VertexShader}", vertexShader.ToString());
res = res.Replace("${LocalPixelShader}", pixelShader.ToString());
res = res.Replace("${SurfaceInputs}", pixelShaderSurfaceInputs.ToString());
res = res.Replace("${SurfaceOutputRemap}", pixelShaderSurfaceRemap.ToString());
return res;
}

float4 frag (GraphVertexOutput IN) : SV_Target
{
${LocalPixelShader}
SurfaceInputs surfaceInput = (SurfaceInputs)0;;
SurfaceDescriptionInputs surfaceInput = (SurfaceDescriptionInputs)0;;
SurfaceDescription surf = PopulateSurfaceData(surfaceInput);
${SurfaceOutputRemap}
}

47
ShaderGraph/com.unity.shadergraph/Editor/Templates/HDUnlitPassForward.template


Name "ForwardUnlit"
Tags { "LightMode" = "${LightMode}" }
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
HLSLPROGRAM
// Material options generated by graph
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 vulkan metal // TEMP: until we go further in dev
//#pragma enable_d3d11_debug_symbols

// -------------------------------------
// HD Pipeline keywords
// Defines generated by graph
${Defines}
${Defines}
${Graph}
${Graph}
${LocalPixelShader}
// Pixel transformations performed by graph
${PixelShader}
SurfaceDescriptionInputs surfaceInput;
// Surface description inputs defined by graph
${PixelShaderSurfaceInputs}
SurfaceDescription surf = PopulateSurfaceData(surfaceInput);
SurfaceInputs surfaceInput;
${SurfaceInputs}
SurfaceDescription surf = PopulateSurfaceData(surfaceInput);
float3 Color = 0;
float Alpha = 0;
${SurfaceOutputRemap}
float3 Color = float3(0.5, 0.5, 0.5);
float Alpha = 1;
float AlphaClipThreshold = 0;
// Surface description remap performed by graph
${PixelShaderSurfaceRemap}
DoAlphaTest(Alpha, _AlphaCutoff);
DoAlphaTest(Alpha, AlphaClipThreshold);
#endif
// Builtin Data

正在加载...
取消
保存