浏览代码

Merge pull request #1358 from Unity-Technologies/sg/vertex-modification

Vertex Modification
/main
GitHub 7 年前
当前提交
ae1dff05
共有 86 个文件被更改,包括 2552 次插入1237 次删除
  1. 573
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/LightWeightPBRSubShader.cs
  2. 582
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/LightWeightUnlitSubShader.cs
  3. 208
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightPBRExtraPasses.template
  4. 94
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightPBRForwardPass.template
  5. 160
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightUnlitExtraPasses.template
  6. 83
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightUnlitPass.template
  7. 295
      ShaderGraph/HDPipeline/HDUnlitSubShader.cs
  8. 8
      ShaderGraph/Testing/Editor/TestSlot.cs
  9. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/BitangentMaterialSlot.cs
  10. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/BooleanMaterialSlot.cs
  11. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ColorMaterialSlot.cs
  12. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ColorRGBMaterialSlot.cs
  13. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/CubemapInputMaterialSlot.cs
  14. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/CubemapMaterialSlot.cs
  15. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicMatrixMaterialSlot.cs
  16. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicValueMaterialSlot.cs
  17. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicVectorMaterialSlot.cs
  18. 12
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/GradientInputMaterialSlot.cs
  19. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/GradientMaterialSlot.cs
  20. 60
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/MaterialSlot.cs
  21. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix2MaterialSlot.cs
  22. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix3MaterialSlot.cs
  23. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix4MaterialSlot.cs
  24. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/NormalMaterialSlot.cs
  25. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/PositionMaterialSlot.cs
  26. 3
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/PreviewMode.cs
  27. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/SamplerStateMaterialSlot.cs
  28. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ScreenPositionMaterialSlot.cs
  29. 30
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ShaderGraphRequirements.cs
  30. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/SpaceMaterialSlot.cs
  31. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/TangentMaterialSlot.cs
  32. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DInputMaterialSlot.cs
  33. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DMaterialSlot.cs
  34. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/UVMaterialSlot.cs
  35. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector1MaterialSlot.cs
  36. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector2MaterialSlot.cs
  37. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector3MaterialSlot.cs
  38. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector4MaterialSlot.cs
  39. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/VertexColorMaterialSlot.cs
  40. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ViewDirectionMaterialSlot.cs
  41. 98
      ShaderGraph/com.unity.shadergraph/Editor/Data/Implementation/NodeUtils.cs
  42. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireBitangent.cs
  43. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireMeshUV.cs
  44. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireNormal.cs
  45. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequirePosition.cs
  46. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireScreenPosition.cs
  47. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireTangent.cs
  48. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireVertexColor.cs
  49. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireViewDirection.cs
  50. 60
      ShaderGraph/com.unity.shadergraph/Editor/Data/MasterNodes/PBRMasterNode.cs
  51. 30
      ShaderGraph/com.unity.shadergraph/Editor/Data/MasterNodes/UnlitMasterNode.cs
  52. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Normal/NormalCreateNode.cs
  53. 89
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/CodeFunctionNode.cs
  54. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/BitangentVectorNode.cs
  55. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/NormalVectorNode.cs
  56. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/PositionNode.cs
  57. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ScreenPositionNode.cs
  58. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/TangentVectorNode.cs
  59. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/UVNode.cs
  60. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/VertexColorNode.cs
  61. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs
  62. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Scene/FogNode.cs
  63. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleCubemapNode.cs
  64. 12
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleTexture2DNode.cs
  65. 34
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/MasterNode.cs
  66. 6
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Math/Vector/TransformNode.cs
  67. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/CheckerboardNode.cs
  68. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Shape/EllipseNode.cs
  69. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Shape/PolygonNode.cs
  70. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Shape/RectangleNode.cs
  71. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Shape/RoundedRectangleNode.cs
  72. 34
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/ShaderStage.cs
  73. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/UV/FlipbookNode.cs
  74. 10
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/UV/TriplanarNode.cs
  75. 36
      ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Utility/SubGraphNode.cs
  76. 2
      ShaderGraph/com.unity.shadergraph/Editor/Data/SubGraph/SubGraph.cs
  77. 50
      ShaderGraph/com.unity.shadergraph/Editor/Data/SurfaceModel/SurfaceMaterialOptions.cs
  78. 436
      ShaderGraph/com.unity.shadergraph/Editor/Data/Util/GraphUtil.cs
  79. 13
      ShaderGraph/com.unity.shadergraph/Editor/Data/Util/PropertyCollector.cs
  80. 411
      ShaderGraph/com.unity.shadergraph/Editor/Data/Util/ShaderGenerator.cs
  81. 4
      ShaderGraph/com.unity.shadergraph/Editor/Data/Util/ShaderGeneratorNames.cs
  82. 33
      ShaderGraph/com.unity.shadergraph/Editor/Data/Util/ShaderStringBuilder.cs
  83. 69
      ShaderGraph/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs
  84. 6
      ShaderGraph/com.unity.shadergraph/Editor/Drawing/SearchWindowProvider.cs
  85. 17
      ShaderGraph/com.unity.shadergraph/Editor/Drawing/Views/MaterialGraphView.cs
  86. 47
      ShaderGraph/com.unity.shadergraph/Editor/Templates/HDUnlitPassForward.template

573
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/LightWeightPBRSubShader.cs


[FormerName("UnityEditor.ShaderGraph.LightWeightPBRSubShader")]
public class LightWeightPBRSubShader : IPBRSubShader
{
static NeededCoordinateSpace m_VertexCoordinateSpace = NeededCoordinateSpace.Object;
static NeededCoordinateSpace m_PixelCoordinateSpace = NeededCoordinateSpace.World;
struct Pass
{
public string Name;

PBRMasterNode.OcclusionSlotId,
PBRMasterNode.AlphaSlotId,
PBRMasterNode.AlphaThresholdSlotId
},
VertexShaderSlots = new List<int>()
{
PBRMasterNode.PositionSlotId
}
};

PBRMasterNode.OcclusionSlotId,
PBRMasterNode.AlphaSlotId,
PBRMasterNode.AlphaThresholdSlotId
},
VertexShaderSlots = new List<int>()
{
PBRMasterNode.PositionSlotId
private static string GetShaderPassFromTemplate(string template, PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
var builder = new ShaderStringBuilder();
builder.IncreaseIndent();
builder.IncreaseIndent();
var vertexInputs = new ShaderGenerator();
var surfaceVertexShader = new ShaderGenerator();
var surfaceDescriptionFunction = new ShaderGenerator();
var surfaceDescriptionStruct = new ShaderGenerator();
var functionRegistry = new FunctionRegistry(builder);
var surfaceInputs = new ShaderGenerator();
var templatePath = GetTemplatePath("lightweightPBRForwardPass.template");
var extraPassesTemplatePath = GetTemplatePath("lightweightPBRExtraPasses.template");
if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath))
return string.Empty;
string forwardTemplate = File.ReadAllText(templatePath);
string extraTemplate = File.ReadAllText(extraPassesTemplatePath);
var masterNode = inMasterNode as PBRMasterNode;
var pass = masterNode.model == PBRMasterNode.Model.Metallic ? m_ForwardPassMetallic : m_ForwardPassSpecular;
var subShader = new ShaderStringBuilder();
subShader.AppendLine("SubShader");
using (subShader.BlockScope())
{
subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}");
var materialOptions = ShaderGenerator.GetMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
var tagsBuilder = new ShaderStringBuilder(0);
materialOptions.GetTags(tagsBuilder);
subShader.AppendLines(tagsBuilder.ToString());
subShader.AppendLines(GetShaderPassFromTemplate(
forwardTemplate,
masterNode,
pass,
mode,
materialOptions));
subShader.AppendLines(GetExtraPassesFromTemplate(extraTemplate, masterNode, pass, mode, materialOptions));
}
return subShader.ToString();
}
static string GetTemplatePath(string templateName)
{
string relativeTemplatePath = Path.Combine("LWRP", Path.Combine("Editor", Path.Combine("ShaderGraph", templateName)));
foreach (var path in LightweightIncludePaths.GetPaths())
{
var templatePath = Path.Combine(path, relativeTemplatePath);
if (File.Exists(templatePath))
return templatePath;
}
throw new FileNotFoundException(string.Format(@"Cannot find a template with name ""{0}"".", templateName));
}
static string GetShaderPassFromTemplate(string template, PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
{
// ----------------------------------------------------- //
// 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 vertexDescriptionInputStruct = new ShaderStringBuilder(1);
var vertexDescriptionStruct = new ShaderStringBuilder(1);
var vertexDescriptionFunction = new ShaderStringBuilder(1);
var requirements = ShaderGraphRequirements.FromNodes(activeNodeList);
var surfaceDescriptionInputStruct = new ShaderStringBuilder(1);
var surfaceDescriptionStruct = new ShaderStringBuilder(1);
var surfaceDescriptionFunction = new ShaderStringBuilder(1);
var vertexInputStruct = new ShaderStringBuilder(1);
var vertexOutputStruct = new ShaderStringBuilder(2);
var vertexShader = new ShaderStringBuilder(2);
var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
var vertexShaderOutputs = new ShaderStringBuilder(2);
var pixelShader = new ShaderStringBuilder(2);
var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
var pixelShaderSurfaceRemap = new ShaderStringBuilder(2);
// -------------------------------------
// Get Slot and Node lists per stage
var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var vertexNodes = ListPool<AbstractMaterialNode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);
var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var pixelNodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
// -------------------------------------
// Get Requirements
var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment);
var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false);
modelRequiements.requiresNormal |= NeededCoordinateSpace.World;
modelRequiements.requiresTangent |= NeededCoordinateSpace.World;
modelRequiements.requiresBitangent |= NeededCoordinateSpace.World;
modelRequiements.requiresPosition |= NeededCoordinateSpace.World;
modelRequiements.requiresViewDir |= NeededCoordinateSpace.World;
modelRequiements.requiresNormal |= m_PixelCoordinateSpace;
modelRequiements.requiresTangent |= m_PixelCoordinateSpace;
modelRequiements.requiresBitangent |= m_PixelCoordinateSpace;
modelRequiements.requiresPosition |= m_PixelCoordinateSpace;
modelRequiements.requiresViewDir |= m_PixelCoordinateSpace;
GraphUtil.GenerateApplicationVertexInputs(requirements.Union(modelRequiements), 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);
// ----------------------------------------------------- //
// START SHADER GENERATION //
// ----------------------------------------------------- //
// -------------------------------------
// Calculate material options
var blendingBuilder = new ShaderStringBuilder(1);
var cullingBuilder = new ShaderStringBuilder(1);
var zTestBuilder = new ShaderStringBuilder(1);
var zWriteBuilder = new ShaderStringBuilder(1);
materialOptions.GetBlend(blendingBuilder);
materialOptions.GetCull(cullingBuilder);
materialOptions.GetDepthTest(zTestBuilder);
materialOptions.GetDepthWrite(zWriteBuilder);
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
// -------------------------------------
// Generate defines
if (masterNode.IsSlotConnected(PBRMasterNode.NormalSlotId))
defines.AppendLine("#define _NORMALMAP 1");
if (masterNode.model == PBRMasterNode.Model.Specular)
defines.AppendLine("#define _SPECULAR_SETUP 1");
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
defines.AppendLine("#define _AlphaClip 1");
if(masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
defines.AppendLine("#define _ALPHAPREMULTIPLY_ON 1");
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex Description function
// TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces
vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
using (vertexDescriptionInputStruct.BlockSemicolonScope())
{
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);
if (vertexRequirements.requiresVertexColor)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (vertexRequirements.requiresScreenPosition)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
}
// -------------------------------------
// Generate Output structure for Vertex Description function
GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);
// -------------------------------------
// Generate Vertex Description function
GraphUtil.GenerateVertexDescriptionFunction(
masterNode.owner as AbstractMaterialGraph,
vertexDescriptionFunction,
functionRegistry,
shaderProperties,
mode,
vertexNodes,
vertexSlots);
// ----------------------------------------------------- //
// 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(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
if (surfaceRequirements.requiresVertexColor)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
if (surfaceRequirements.requiresScreenPosition)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct())
surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
}
surfaceVertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
surfaceVertexShader.Indent();
surfaceVertexShader.AddShaderChunk("return v;", false);
surfaceVertexShader.Deindent();
surfaceVertexShader.AddShaderChunk("}", false);
// -------------------------------------
// Generate Output structure for Surface Description function
var slots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
slots.Add(masterNode.FindSlot<MaterialSlot>(id));
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, true);
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots, true);
var usedSlots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
usedSlots.Add(masterNode.FindSlot<MaterialSlot>(id));
// -------------------------------------
// Generate Surface Description function
GraphUtil.GenerateSurfaceDescription(
activeNodeList,
GraphUtil.GenerateSurfaceDescriptionFunction(
pixelNodes,
requirements,
pixelRequirements,
usedSlots);
pixelSlots);
var graph = new ShaderGenerator();
graph.AddShaderChunk(shaderProperties.GetPropertiesDeclaration(2), false);
graph.AddShaderChunk(surfaceInputs.GetShaderString(2), false);
graph.AddShaderChunk(builder.ToString(), false);
graph.AddShaderChunk(vertexInputs.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionStruct.GetShaderString(2), false);
graph.AddShaderChunk(surfaceVertexShader.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionFunction.GetShaderString(2), false);
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
var blendingVisitor = new ShaderGenerator();
var cullingVisitor = new ShaderGenerator();
var zTestVisitor = new ShaderGenerator();
var zWriteVisitor = new ShaderGenerator();
// -------------------------------------
// Generate Input structure for Vertex shader
materialOptions.GetBlend(blendingVisitor);
materialOptions.GetCull(cullingVisitor);
materialOptions.GetDepthTest(zTestVisitor);
materialOptions.GetDepthWrite(zWriteVisitor);
GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct);
var interpolators = new ShaderGenerator();
var localVertexShader = new ShaderGenerator();
var localPixelShader = new ShaderGenerator();
var localSurfaceInputs = new ShaderGenerator();
var surfaceOutputRemap = new ShaderGenerator();
// -------------------------------------
// Generate standard transformations
// This method ensures all required transform data is available in vertex and pixel stages
interpolators,
localVertexShader,
localPixelShader,
localSurfaceInputs,
requirements,
vertexOutputStruct,
vertexShader,
vertexShaderDescriptionInputs,
vertexShaderOutputs,
pixelShader,
pixelShaderSurfaceInputs,
pixelRequirements,
surfaceRequirements,
vertexRequirements,
ShaderGenerator defines = new ShaderGenerator();
// -------------------------------------
// Generate pixel shader surface remap
if (masterNode.IsSlotConnected(PBRMasterNode.NormalSlotId))
defines.AddShaderChunk("#define _NORMALMAP 1", true);
foreach (var slot in pixelSlots)
{
pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName);
}
if (masterNode.model == PBRMasterNode.Model.Specular)
defines.AddShaderChunk("#define _SPECULAR_SETUP 1", true);
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
defines.AddShaderChunk("#define _AlphaClip 1", true);
// -------------------------------------
// Combine Graph sections
if (masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
defines.AddShaderChunk("#define _ALPHAPREMULTIPLY_ON 1", true);
graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));
var templateLocation = GetTemplatePath(template);
graph.AppendLine(vertexDescriptionInputStruct.ToString());
graph.AppendLine(surfaceDescriptionInputStruct.ToString());
foreach (var slot in usedSlots)
{
surfaceOutputRemap.AddShaderChunk(string.Format("{0} = surf.{0};", slot.shaderOutputName), true);
}
graph.AppendLine(functionBuilder.ToString());
graph.AppendLine(vertexDescriptionStruct.ToString());
graph.AppendLine(vertexDescriptionFunction.ToString());
graph.AppendLine(surfaceDescriptionStruct.ToString());
graph.AppendLine(surfaceDescriptionFunction.ToString());
graph.AppendLine(vertexInputStruct.ToString());
// -------------------------------------
// Generate final subshader
var resultPass = template.Replace("${Tags}", string.Empty);
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("${Graph}", graph.ToString());
resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString());
if (!File.Exists(templateLocation))
return string.Empty;
resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString());
resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString());
var subShaderTemplate = File.ReadAllText(templateLocation);
var resultPass = subShaderTemplate.Replace("${Defines}", defines.GetShaderString(3));
resultPass = resultPass.Replace("${Graph}", graph.GetShaderString(3));
resultPass = resultPass.Replace("${Interpolators}", interpolators.GetShaderString(3));
resultPass = resultPass.Replace("${VertexShader}", localVertexShader.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("${PixelShader}", pixelShader.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString());
resultPass = resultPass.Replace("${Tags}", string.Empty);
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));
static string GetTemplatePath(string templateName)
static string GetExtraPassesFromTemplate(string template, PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
string relativeTemplatePath = Path.Combine("LWRP", Path.Combine("Editor", Path.Combine("ShaderGraph", templateName)));
foreach (var path in LightweightIncludePaths.GetPaths())
{
var templatePath = Path.Combine(path, relativeTemplatePath);
if (File.Exists(templatePath))
return templatePath;
}
throw new FileNotFoundException(string.Format(@"Cannot find a template with name ""{0}"".", templateName));
}
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// -------------------------------------
// String builders
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
{
var masterNode = inMasterNode as PBRMasterNode;
var subShader = new ShaderGenerator();
subShader.AddShaderChunk("SubShader", true);
subShader.AddShaderChunk("{", true);
subShader.Indent();
subShader.AddShaderChunk("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}", true);
var dummyBuilder = new ShaderStringBuilder(0);
var shaderProperties = new PropertyCollector();
var functionBuilder = new ShaderStringBuilder(1);
var functionRegistry = new FunctionRegistry(functionBuilder);
var materialOptions = ShaderGenerator.GetMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
var tagsVisitor = new ShaderGenerator();
materialOptions.GetTags(tagsVisitor);
subShader.AddShaderChunk(tagsVisitor.GetShaderString(0), true);
var defines = new ShaderStringBuilder(2);
var graph = new ShaderStringBuilder(0);
subShader.AddShaderChunk(
GetShaderPassFromTemplate(
"lightweightPBRForwardPass.template",
masterNode,
masterNode.model == PBRMasterNode.Model.Metallic ? m_ForwardPassMetallic : m_ForwardPassSpecular,
mode,
materialOptions),
true);
var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
var vertexDescriptionStruct = new ShaderStringBuilder(1);
var vertexDescriptionFunction = new ShaderStringBuilder(1);
var extraPassesTemplateLocation = GetTemplatePath("lightweightPBRExtraPasses.template");
if (File.Exists(extraPassesTemplateLocation))
var vertexInputStruct = new ShaderStringBuilder(1);
var vertexShader = new ShaderStringBuilder(2);
var vertexDescriptionInputs = new ShaderStringBuilder(2);
// -------------------------------------
// Get Slot and Node lists per stage
var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var vertexNodes = ListPool<AbstractMaterialNode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);
// -------------------------------------
// Get requirements
var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
var modelRequiements = ShaderGraphRequirements.none;
modelRequiements.requiresNormal |= m_VertexCoordinateSpace;
modelRequiements.requiresPosition |= m_VertexCoordinateSpace;
modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);
// ----------------------------------------------------- //
// START SHADER GENERATION //
// ----------------------------------------------------- //
// -------------------------------------
// Calculate material options
var cullingBuilder = new ShaderStringBuilder(1);
materialOptions.GetCull(cullingBuilder);
// -------------------------------------
// Generate defines
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
defines.AppendLine("#define _AlphaClip 1");
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex Description function
// TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces
vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
using (vertexDescriptionInputStruct.BlockSemicolonScope())
var extraPassesTemplate = File.ReadAllText(extraPassesTemplateLocation);
extraPassesTemplate = extraPassesTemplate.Replace("${Culling}", materialOptions.cullMode.ToString());
subShader.AddShaderChunk(extraPassesTemplate, true);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);
if (vertexRequirements.requiresVertexColor)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (vertexRequirements.requiresScreenPosition)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
subShader.Deindent();
subShader.AddShaderChunk("}", true);
// -------------------------------------
// Generate Output structure for Vertex Description function
GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);
// -------------------------------------
// Generate Vertex Description function
GraphUtil.GenerateVertexDescriptionFunction(
masterNode.owner as AbstractMaterialGraph,
vertexDescriptionFunction,
functionRegistry,
shaderProperties,
mode,
vertexNodes,
vertexSlots);
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex shader
GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(modelRequiements), vertexInputStruct);
// -------------------------------------
// Generate standard transformations
// This method ensures all required transform data is available in vertex and pixel stages
ShaderGenerator.GenerateStandardTransforms(
3,
10,
dummyBuilder,
vertexShader,
vertexDescriptionInputs,
dummyBuilder,
dummyBuilder,
dummyBuilder,
ShaderGraphRequirements.none,
ShaderGraphRequirements.none,
modelRequiements,
vertexRequirements,
CoordinateSpace.World);
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
// -------------------------------------
// Combine Graph sections
graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));
graph.AppendLine(vertexDescriptionInputStruct.ToString());
graph.AppendLine(functionBuilder.ToString());
graph.AppendLine(vertexDescriptionStruct.ToString());
graph.AppendLine(vertexDescriptionFunction.ToString());
graph.AppendLine(vertexInputStruct.ToString());
// -------------------------------------
// Generate final subshader
var resultPass = template.Replace("${Culling}", cullingBuilder.ToString());
resultPass = resultPass.Replace("${Defines}", defines.ToString());
resultPass = resultPass.Replace("${Graph}", graph.ToString());
resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexDescriptionInputs.ToString());
return subShader.GetShaderString(0);
return resultPass;
}
}

582
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/LightWeightUnlitSubShader.cs


[FormerName("UnityEditor.ShaderGraph.LightWeightUnlitSubShader")]
public class LightWeightUnlitSubShader : IUnlitSubShader
{
static NeededCoordinateSpace m_VertexCoordinateSpace = NeededCoordinateSpace.Object;
static NeededCoordinateSpace m_PixelCoordinateSpace = NeededCoordinateSpace.World;
struct Pass
{
public string Name;
public List<int> VertexShaderSlots;
public List<int> PixelShaderSlots;
}
Name = "Unlit",
Name = "Pass",
},
VertexShaderSlots = new List<int>()
{
UnlitMasterNode.PositionSlotId
struct Pass
public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
public string Name;
public List<int> VertexShaderSlots;
public List<int> PixelShaderSlots;
var templatePath = GetTemplatePath("lightweightUnlitPass.template");
var extraPassesTemplatePath = GetTemplatePath("lightweightUnlitExtraPasses.template");
if (!File.Exists(templatePath) || !File.Exists(extraPassesTemplatePath))
return string.Empty;
string forwardTemplate = File.ReadAllText(templatePath);
string extraTemplate = File.ReadAllText(extraPassesTemplatePath);
var masterNode = inMasterNode as UnlitMasterNode;
var pass = m_UnlitPass;
var subShader = new ShaderStringBuilder();
subShader.AppendLine("SubShader");
using (subShader.BlockScope())
{
subShader.AppendLine("Tags{ \"RenderPipeline\" = \"LightweightPipeline\"}");
var materialOptions = ShaderGenerator.GetMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
var tagsBuilder = new ShaderStringBuilder(0);
materialOptions.GetTags(tagsBuilder);
subShader.AppendLines(tagsBuilder.ToString());
subShader.AppendLines(GetShaderPassFromTemplate(
forwardTemplate,
masterNode,
pass,
mode,
materialOptions));
subShader.AppendLines(GetExtraPassesFromTemplate(extraTemplate, masterNode, pass, mode, materialOptions));
}
return subShader.ToString();
private static string GetShaderPassFromTemplate(
string template,
UnlitMasterNode masterNode,
Pass pass,
GenerationMode mode,
SurfaceMaterialOptions materialOptions)
static string GetTemplatePath(string templateName)
var builder = new ShaderStringBuilder();
builder.IncreaseIndent();
builder.IncreaseIndent();
var vertexInputs = new ShaderGenerator();
var surfaceVertexShader = new ShaderGenerator();
var surfaceDescriptionFunction = new ShaderGenerator();
var surfaceDescriptionStruct = new ShaderGenerator();
var functionRegistry = new FunctionRegistry(builder);
var surfaceInputs = new ShaderGenerator();
string relativeTemplatePath = Path.Combine("LWRP", Path.Combine("Editor", Path.Combine("ShaderGraph", templateName)));
foreach (var path in LightweightIncludePaths.GetPaths())
{
var templatePath = Path.Combine(path, relativeTemplatePath);
if (File.Exists(templatePath))
return templatePath;
}
throw new FileNotFoundException(string.Format(@"Cannot find a template with name ""{0}"".", templateName));
}
static string GetShaderPassFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
{
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// -------------------------------------
// String builders
var functionBuilder = new ShaderStringBuilder(1);
var functionRegistry = new FunctionRegistry(functionBuilder);
var defines = new ShaderStringBuilder(1);
var graph = new ShaderStringBuilder(0);
surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
var vertexDescriptionStruct = new ShaderStringBuilder(1);
var vertexDescriptionFunction = new ShaderStringBuilder(1);
var surfaceDescriptionInputStruct = new ShaderStringBuilder(1);
var surfaceDescriptionStruct = new ShaderStringBuilder(1);
var surfaceDescriptionFunction = new ShaderStringBuilder(1);
var vertexInputStruct = new ShaderStringBuilder(1);
var vertexOutputStruct = new ShaderStringBuilder(2);
var vertexShader = new ShaderStringBuilder(2);
var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
var vertexShaderOutputs = new ShaderStringBuilder(2);
var pixelShader = new ShaderStringBuilder(2);
var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
var pixelShaderSurfaceRemap = new ShaderStringBuilder(2);
// -------------------------------------
// Get Slot and Node lists per stage
var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var vertexNodes = ListPool<AbstractMaterialNode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);
var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var pixelNodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
// -------------------------------------
// Get Requirements
var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
var pixelRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment);
var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false);
var modelRequiements = ShaderGraphRequirements.none;
modelRequiements.requiresNormal |= m_PixelCoordinateSpace;
modelRequiements.requiresTangent |= m_PixelCoordinateSpace;
modelRequiements.requiresBitangent |= m_PixelCoordinateSpace;
modelRequiements.requiresPosition |= m_PixelCoordinateSpace;
modelRequiements.requiresViewDir |= m_PixelCoordinateSpace;
modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);
// ----------------------------------------------------- //
// START SHADER GENERATION //
// ----------------------------------------------------- //
// -------------------------------------
// Calculate material options
var blendingBuilder = new ShaderStringBuilder(1);
var cullingBuilder = new ShaderStringBuilder(1);
var zTestBuilder = new ShaderStringBuilder(1);
var zWriteBuilder = new ShaderStringBuilder(1);
materialOptions.GetBlend(blendingBuilder);
materialOptions.GetCull(cullingBuilder);
materialOptions.GetDepthTest(zTestBuilder);
materialOptions.GetDepthWrite(zWriteBuilder);
// -------------------------------------
// Generate defines
if (masterNode.IsSlotConnected(UnlitMasterNode.AlphaThresholdSlotId))
defines.AppendLine("#define _AlphaClip 1");
if(masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
defines.AppendLine("#define _ALPHAPREMULTIPLY_ON 1");
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex Description function
// TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces
vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
using (vertexDescriptionInputStruct.BlockSemicolonScope())
{
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);
if (vertexRequirements.requiresVertexColor)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
var activeNodeList = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);
if (vertexRequirements.requiresScreenPosition)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
var requirements = ShaderGraphRequirements.FromNodes(activeNodeList);
GraphUtil.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);
foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
}
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
// -------------------------------------
// Generate Output structure for Vertex Description function
if (requirements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);
foreach (var channel in requirements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
// -------------------------------------
// Generate Vertex Description function
surfaceInputs.Deindent();
surfaceInputs.AddShaderChunk("};", false);
GraphUtil.GenerateVertexDescriptionFunction(
masterNode.owner as AbstractMaterialGraph,
vertexDescriptionFunction,
functionRegistry,
shaderProperties,
mode,
vertexNodes,
vertexSlots);
surfaceVertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
surfaceVertexShader.Indent();
surfaceVertexShader.AddShaderChunk("return v;", false);
surfaceVertexShader.Deindent();
surfaceVertexShader.AddShaderChunk("}", false);
// ----------------------------------------------------- //
// START SURFACE DESCRIPTION //
// ----------------------------------------------------- //
var slots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
// -------------------------------------
// 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())
var slot = masterNode.FindSlot<MaterialSlot>(id);
if (slot != null)
slots.Add(slot);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);
if (surfaceRequirements.requiresVertexColor)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (surfaceRequirements.requiresScreenPosition)
surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct())
surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, true);
var usedSlots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
usedSlots.Add(masterNode.FindSlot<MaterialSlot>(id));
// -------------------------------------
// Generate Output structure for Surface Description function
GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots, true);
GraphUtil.GenerateSurfaceDescription(
activeNodeList,
// -------------------------------------
// Generate Surface Description function
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(vertexInputs.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionStruct.GetShaderString(2), false);
graph.AddShaderChunk(surfaceVertexShader.GetShaderString(2), false);
graph.AddShaderChunk(surfaceDescriptionFunction.GetShaderString(2), false);
pixelSlots);
var blendingVisitor = new ShaderGenerator();
var cullingVisitor = new ShaderGenerator();
var zTestVisitor = new ShaderGenerator();
var zWriteVisitor = new ShaderGenerator();
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
materialOptions.GetBlend(blendingVisitor);
materialOptions.GetCull(cullingVisitor);
materialOptions.GetDepthTest(zTestVisitor);
materialOptions.GetDepthWrite(zWriteVisitor);
// -------------------------------------
// Generate Input structure for Vertex shader
var interpolators = new ShaderGenerator();
var localVertexShader = new ShaderGenerator();
var localPixelShader = new ShaderGenerator();
var localSurfaceInputs = new ShaderGenerator();
var surfaceOutputRemap = new ShaderGenerator();
GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct);
var reqs = ShaderGraphRequirements.none;
// -------------------------------------
// Generate standard transformations
// This method ensures all required transform data is available in vertex and pixel stages
interpolators,
localVertexShader,
localPixelShader,
localSurfaceInputs,
requirements,
reqs,
vertexOutputStruct,
vertexShader,
vertexShaderDescriptionInputs,
vertexShaderOutputs,
pixelShader,
pixelShaderSurfaceInputs,
pixelRequirements,
surfaceRequirements,
modelRequiements,
vertexRequirements,
ShaderGenerator defines = new ShaderGenerator();
// -------------------------------------
// Generate pixel shader surface remap
if (masterNode.IsSlotConnected(UnlitMasterNode.AlphaThresholdSlotId))
defines.AddShaderChunk("#define _AlphaClip 1", true);
foreach (var slot in pixelSlots)
{
pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName);
}
if (masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
defines.AddShaderChunk("#define _ALPHAPREMULTIPLY_ON 1", true);
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
var templateLocation = GetTemplatePath(template);
// -------------------------------------
// Combine Graph sections
foreach (var slot in usedSlots)
{
surfaceOutputRemap.AddShaderChunk(slot.shaderOutputName
+ " = surf."
+ slot.shaderOutputName + ";", true);
}
graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));
if (!File.Exists(templateLocation))
return string.Empty;
graph.AppendLine(vertexDescriptionInputStruct.ToString());
graph.AppendLine(surfaceDescriptionInputStruct.ToString());
var subShaderTemplate = File.ReadAllText(templateLocation);
var resultPass = subShaderTemplate.Replace("${Defines}", defines.GetShaderString(3));
resultPass = resultPass.Replace("${Graph}", graph.GetShaderString(3));
resultPass = resultPass.Replace("${Interpolators}", interpolators.GetShaderString(3));
resultPass = resultPass.Replace("${VertexShader}", localVertexShader.GetShaderString(3));
resultPass = resultPass.Replace("${LocalPixelShader}", localPixelShader.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceInputs}", localSurfaceInputs.GetShaderString(3));
resultPass = resultPass.Replace("${SurfaceOutputRemap}", surfaceOutputRemap.GetShaderString(3));
graph.AppendLine(functionBuilder.ToString());
resultPass = resultPass.Replace("${Tags}", string.Empty);
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));
graph.AppendLine(vertexDescriptionStruct.ToString());
graph.AppendLine(vertexDescriptionFunction.ToString());
graph.AppendLine(surfaceDescriptionStruct.ToString());
graph.AppendLine(surfaceDescriptionFunction.ToString());
graph.AppendLine(vertexInputStruct.ToString());
// -------------------------------------
// Generate final subshader
var resultPass = template.Replace("${Tags}", string.Empty);
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("${Graph}", graph.ToString());
resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString());
resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString());
resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString());
resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString());
resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString());
static string GetTemplatePath(string templateName)
static string GetExtraPassesFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
string relativeTemplatePath = Path.Combine("LWRP", Path.Combine("Editor", Path.Combine("ShaderGraph", templateName)));
foreach (var path in LightweightIncludePaths.GetPaths())
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// -------------------------------------
// String builders
var dummyBuilder = new ShaderStringBuilder(0);
var shaderProperties = new PropertyCollector();
var functionBuilder = new ShaderStringBuilder(1);
var functionRegistry = new FunctionRegistry(functionBuilder);
var defines = new ShaderStringBuilder(2);
var graph = new ShaderStringBuilder(0);
var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
var vertexDescriptionStruct = new ShaderStringBuilder(1);
var vertexDescriptionFunction = new ShaderStringBuilder(1);
var vertexInputStruct = new ShaderStringBuilder(1);
var vertexShader = new ShaderStringBuilder(2);
var vertexDescriptionInputs = new ShaderStringBuilder(2);
// -------------------------------------
// Get Slot and Node lists per stage
var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot<MaterialSlot>).ToList();
var vertexNodes = ListPool<AbstractMaterialNode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);
// -------------------------------------
// Get requirements
var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
var modelRequiements = ShaderGraphRequirements.none;
modelRequiements.requiresNormal |= m_VertexCoordinateSpace;
modelRequiements.requiresPosition |= m_VertexCoordinateSpace;
modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);
// ----------------------------------------------------- //
// START SHADER GENERATION //
// ----------------------------------------------------- //
// -------------------------------------
// Calculate material options
var cullingBuilder = new ShaderStringBuilder(1);
materialOptions.GetCull(cullingBuilder);
// -------------------------------------
// Generate defines
if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
defines.AppendLine("#define _AlphaClip 1");
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex Description function
// TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces
vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
using (vertexDescriptionInputStruct.BlockSemicolonScope())
var templatePath = Path.Combine(path, relativeTemplatePath);
if (File.Exists(templatePath))
return templatePath;
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);
if (vertexRequirements.requiresVertexColor)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
if (vertexRequirements.requiresScreenPosition)
vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
throw new FileNotFoundException(string.Format(@"Cannot find a template with name ""{0}"".", templateName));
}
// -------------------------------------
// Generate Output structure for Vertex Description function
GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);
// -------------------------------------
// Generate Vertex Description function
GraphUtil.GenerateVertexDescriptionFunction(
masterNode.owner as AbstractMaterialGraph,
vertexDescriptionFunction,
functionRegistry,
shaderProperties,
mode,
vertexNodes,
vertexSlots);
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
// -------------------------------------
// Generate Input structure for Vertex shader
GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(modelRequiements), vertexInputStruct);
// -------------------------------------
// Generate standard transformations
// This method ensures all required transform data is available in vertex and pixel stages
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{ \"RenderType\" = \"Opaque\" \"RenderPipeline\" = \"LightweightPipeline\"}", true);
ShaderGenerator.GenerateStandardTransforms(
3,
10,
dummyBuilder,
vertexShader,
vertexDescriptionInputs,
dummyBuilder,
dummyBuilder,
dummyBuilder,
ShaderGraphRequirements.none,
ShaderGraphRequirements.none,
modelRequiements,
vertexRequirements,
CoordinateSpace.World);
var materialOptions = ShaderGenerator.GetMaterialOptions(masterNode.surfaceType, masterNode.alphaMode, masterNode.twoSided.isOn);
var tagsVisitor = new ShaderGenerator();
materialOptions.GetTags(tagsVisitor);
subShader.AddShaderChunk(tagsVisitor.GetShaderString(0), true);
// ----------------------------------------------------- //
// FINALIZE //
// ----------------------------------------------------- //
subShader.AddShaderChunk(
GetShaderPassFromTemplate(
"lightweightUnlitPass.template",
masterNode,
m_UnlitPass,
mode,
materialOptions),
true);
// -------------------------------------
// Combine Graph sections
var extraPassesTemplateLocation = GetTemplatePath("lightweightUnlitExtraPasses.template");
if (File.Exists(extraPassesTemplateLocation))
{
var extraPassesTemplate = File.ReadAllText(extraPassesTemplateLocation);
extraPassesTemplate = extraPassesTemplate.Replace("${Culling}", materialOptions.cullMode.ToString());
subShader.AddShaderChunk(extraPassesTemplate, true);
}
graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));
subShader.Deindent();
subShader.AddShaderChunk("}", true);
graph.AppendLine(vertexDescriptionInputStruct.ToString());
return subShader.GetShaderString(0);
graph.AppendLine(functionBuilder.ToString());
graph.AppendLine(vertexDescriptionStruct.ToString());
graph.AppendLine(vertexDescriptionFunction.ToString());
graph.AppendLine(vertexInputStruct.ToString());
// -------------------------------------
// Generate final subshader
var resultPass = template.Replace("${Culling}", cullingBuilder.ToString());
resultPass = resultPass.Replace("${Defines}", defines.ToString());
resultPass = resultPass.Replace("${Graph}", graph.ToString());
resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexDescriptionInputs.ToString());
return resultPass;
}
}

208
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightPBRExtraPasses.template


Pass
{
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
ZWrite On
ZTest LEqual
Cull ${Culling}
ZWrite On ZTest LEqual
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
// Material options generated by graph
${Culling}
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
// -------------------------------------
// Material Keywords
#pragma shader_feature _ALPHATEST_ON
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "ShaderGraphLibrary/Functions.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassShadow.hlsl"
${Graph}
struct VertexOutput
{
float2 uv : TEXCOORD0;
float4 clipPos : SV_POSITION;
};
// x: global clip space bias, y: normal world space bias
float4 _ShadowBias;
float3 _LightDirection;
ENDHLSL
VertexOutput ShadowPassVertex(GraphVertexInput v)
{
VertexOutput o;
UNITY_SETUP_INSTANCE_ID(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
o.uv = uv1;
float3 positionWS = TransformObjectToWorld(v.vertex.xyz);
float3 normalWS = TransformObjectToWorldDir(v.normal);
float invNdotL = 1.0 - saturate(dot(_LightDirection, normalWS));
float scale = invNdotL * _ShadowBias.y;
// normal bias is negative since we want to apply an inset normal offset
positionWS = normalWS * scale.xxx + positionWS;
float4 clipPos = TransformWorldToHClip(positionWS);
// _ShadowBias.x sign depens on if platform has reversed z buffer
clipPos.z += _ShadowBias.x;
#if UNITY_REVERSED_Z
clipPos.z = min(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
#else
clipPos.z = max(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
#endif
o.clipPos = clipPos;
return o;
}
half4 ShadowPassFragment() : SV_TARGET
{
return 0;
}
ENDHLSL
Name "DepthOnly"
Tags{"LightMode" = "DepthOnly"}
Name "DepthOnly"
Tags{"LightMode" = "DepthOnly"}
ZWrite On
ColorMask 0
Cull ${Culling}
ZWrite On
ColorMask 0
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma target 2.0
// Material options generated by graph
${Culling}
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
// -------------------------------------
// Material Keywords
#pragma shader_feature _ALPHATEST_ON
#pragma vertex vert
#pragma fragment frag
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "ShaderGraphLibrary/Functions.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassDepthOnly.hlsl"
ENDHLSL
${Graph}
struct VertexOutput
{
float2 uv : TEXCOORD0;
float4 clipPos : SV_POSITION;
};
VertexOutput vert(GraphVertexInput v)
{
VertexOutput o = (VertexOutput)0;
UNITY_SETUP_INSTANCE_ID(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
o.uv = uv1;
o.clipPos = TransformObjectToHClip(v.vertex.xyz);
return o;
}
half4 frag() : SV_TARGET
{
return 0;
}
ENDHLSL
Name "Meta"
Tags{"LightMode" = "Meta"}
Name "Meta"
Tags{"LightMode" = "Meta"}
Cull Off
Cull Off
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma vertex LightweightVertexMeta
#pragma fragment LightweightFragmentMeta
#pragma vertex LightweightVertexMeta
#pragma fragment LightweightFragmentMeta
#pragma shader_feature _SPECULAR_SETUP
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICSPECGLOSSMAP
#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature EDITOR_VISUALIZATION
#pragma shader_feature _SPECULAR_SETUP
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICSPECGLOSSMAP
#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature EDITOR_VISUALIZATION
#pragma shader_feature _SPECGLOSSMAP
#pragma shader_feature _SPECGLOSSMAP
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassMetaPBR.hlsl"
ENDHLSL
}
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassMetaPBR.hlsl"
ENDHLSL
}

94
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightPBRForwardPass.template


Pass
{
Name "StandardLit"
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
// Material options generated by graph
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
// Lightweight Pipeline keywords
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _VERTEX_LIGHTS
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
#pragma multi_compile _ _SHADOWS_ENABLED
// Lightweight Pipeline keywords
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _VERTEX_LIGHTS
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
#pragma multi_compile _ _SHADOWS_ENABLED
// Unity defined keywords
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile_fog
// Unity defined keywords
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile_fog
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
${Defines}
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"

${Graph}
${Graph}
struct GraphVertexOutput
{
float4 clipPos : SV_POSITION;

${Interpolators}
// Interpolators defined by graph
${VertexOutputStruct}
v = PopulateVertexData(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
GraphVertexOutput o = (GraphVertexOutput)0;

${VertexShader}
// Vertex shader outputs defined by graph
${VertexShaderOutputs}
float3 lwWNormal = TransformObjectToWorldNormal(v.normal);
float3 lwWorldPos = TransformObjectToWorld(v.vertex.xyz);
float4 clipPos = TransformWorldToHClip(lwWorldPos);

o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
o.clipPos = clipPos;
#ifdef _SHADOWS_ENABLED
#if SHADOWS_SCREEN
o.shadowCoord = ComputeShadowCoord(clipPos);
#else
o.shadowCoord = TransformWorldToShadowCoord(lwWorldPos);
#endif
#endif
#ifdef _SHADOWS_ENABLED
#if SHADOWS_SCREEN
o.shadowCoord = ComputeShadowCoord(clipPos);
#else
o.shadowCoord = TransformWorldToShadowCoord(lwWorldPos);
#endif
#endif
return o;
}

${LocalPixelShader}
// Pixel transformations performed by graph
${PixelShader}
SurfaceDescriptionInputs surfaceInput = (SurfaceDescriptionInputs)0;
SurfaceInputs surfaceInput = (SurfaceInputs)0;
${SurfaceInputs}
// Surface description inputs defined by graph
${PixelShaderSurfaceInputs}
SurfaceDescription surf = PopulateSurfaceData(surfaceInput);
float3 Albedo = float3(0.5, 0.5, 0.5);

float Alpha = 1;
float AlphaClipThreshold = 0;
${SurfaceOutputRemap}
// Surface description remap performed by graph
${PixelShaderSurfaceRemap}
InputData inputData;
inputData.positionWS = WorldSpacePosition;

}
ENDHLSL
}
}

160
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightUnlitExtraPasses.template


Pass
{
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
ZWrite On ZTest LEqual
// Material options generated by graph
${Culling}
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "ShaderGraphLibrary/Functions.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
${Graph}
struct VertexOutput
{
float2 uv : TEXCOORD0;
float4 clipPos : SV_POSITION;
};
// x: global clip space bias, y: normal world space bias
float4 _ShadowBias;
float3 _LightDirection;
VertexOutput ShadowPassVertex(GraphVertexInput v)
{
VertexOutput o;
UNITY_SETUP_INSTANCE_ID(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
o.uv = uv1;
float3 positionWS = TransformObjectToWorld(v.vertex.xyz);
float3 normalWS = TransformObjectToWorldDir(v.normal);
float invNdotL = 1.0 - saturate(dot(_LightDirection, normalWS));
float scale = invNdotL * _ShadowBias.y;
// normal bias is negative since we want to apply an inset normal offset
positionWS = normalWS * scale.xxx + positionWS;
float4 clipPos = TransformWorldToHClip(positionWS);
// _ShadowBias.x sign depens on if platform has reversed z buffer
clipPos.z += _ShadowBias.x;
#if UNITY_REVERSED_Z
clipPos.z = min(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
#else
clipPos.z = max(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
#endif
o.clipPos = clipPos;
return o;
}
half4 ShadowPassFragment() : SV_TARGET
{
return 0;
}
ENDHLSL
}
Tags{"LightMode" = "DepthOnly"}
Tags{"LightMode" = "DepthOnly"}
ZWrite On
Cull ${Culling}
ColorMask 0
ZWrite On
ColorMask 0
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
// Material options generated by graph
${Culling}
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
// -------------------------------------
// Material Keywords
#pragma shader_feature _ALPHATEST_ON
#pragma vertex vert
#pragma fragment frag
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
// Defines generated by graph
${Defines}
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "ShaderGraphLibrary/Functions.hlsl"
#include "CoreRP/ShaderLibrary/Color.hlsl"
#include "LWRP/ShaderLibrary/InputSurfaceUnlit.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassDepthOnly.hlsl"
ENDHLSL
}
${Graph}
struct VertexOutput
{
float2 uv : TEXCOORD0;
float4 clipPos : SV_POSITION;
};
VertexOutput vert(GraphVertexInput v)
{
VertexOutput o = (VertexOutput)0;
UNITY_SETUP_INSTANCE_ID(v);
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
o.uv = uv1;
o.clipPos = TransformObjectToHClip(v.vertex.xyz);
return o;
}
half4 frag() : SV_TARGET
{
return 0;
}
ENDHLSL
}

83
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/ShaderGraph/lightweightUnlitPass.template


Pass
{
Name "StandardUnlit"
Tags{"LightMode" = "LightweightForward"}
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
Tags{"LightMode" = "LightweightForward"}
// Material options generated by graph
${Tags}
${Blending}
${Culling}
${ZTest}
${ZWrite}
#pragma target 2.0
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
// -------------------------------------
// Lightweight Pipeline keywords
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fog
//--------------------------------------
// GPU Instancing
#pragma vertex vert
#pragma vertex vert
// Defines generated by graph
${Defines}
// Lighting include is needed because of GI
#include "LWRP/ShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"

${Defines}
${Graph}
${Graph}
${Interpolators}
// Interpolators defined by graph
${VertexOutputStruct}
{
v = PopulateVertexData(v);
{
// Vertex transformations performed by graph
${VertexShader}
VertexDescriptionInputs vdi = (VertexDescriptionInputs)0;
// Vertex description inputs defined by graph
${VertexShaderDescriptionInputs}
VertexDescription vd = PopulateVertexData(vdi);
v.vertex.xyz = vd.Position;
GraphVertexOutput o = (GraphVertexOutput)0;
UNITY_SETUP_INSTANCE_ID(v);

${VertexShader}
// Vertex shader outputs defined by graph
${VertexShaderOutputs}
}
}
${LocalPixelShader}
SurfaceInputs surfaceInput = (SurfaceInputs)0;
${SurfaceInputs}
// Pixel transformations performed by graph
${PixelShader}
SurfaceDescriptionInputs surfaceInput = (SurfaceDescriptionInputs)0;
// Surface description inputs defined by graph
${PixelShaderSurfaceInputs}
${SurfaceOutputRemap}
#if _AlphaClip
// Surface description remap performed by graph
${PixelShaderSurfaceRemap}
#if _AlphaClip
return half4(Color, Alpha);
return half4(Color, Alpha);
}
}

295
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");
// ----------------------------------------------------- //
// 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())
{
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);
var slots = new List<MaterialSlot>();
foreach (var id in pass.PixelShaderSlots)
foreach (var channel in pixelRequirements.requiresMeshUVs.Distinct())
var slot = masterNode.FindSlot<MaterialSlot>(id);
if (slot != null)
slots.Add(slot);
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{ \"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;
}
}
}

8
ShaderGraph/Testing/Editor/TestSlot.cs


{
public TestSlot() {}
public TestSlot(int slotId, string displayName, SlotType slotType, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, displayName, slotType, shaderStage, hidden) {}
public TestSlot(int slotId, string displayName, SlotType slotType, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, displayName, slotType, stageCapability, hidden) {}
public TestSlot(int slotId, string displayName, SlotType slotType, int priority, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, displayName, slotType, priority, shaderStage, hidden) {}
public TestSlot(int slotId, string displayName, SlotType slotType, int priority, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, displayName, slotType, priority, stageCapability, hidden) {}
public override SlotValueType valueType
{

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/BitangentMaterialSlot.cs


{}
public BitangentMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.BiTangent));
}
public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/BooleanMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
bool value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_DefaultValue = value;
m_Value = value;

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ColorMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, value, shaderStage, hidden: hidden)
: base(slotId, displayName, shaderOutputName, slotType, value, stageCapability, hidden: hidden)
{
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ColorRGBMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Color value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, (Vector4)value, shaderStage, hidden: hidden)
: base(slotId, displayName, shaderOutputName, slotType, (Vector4)value, stageCapability, hidden: hidden)
{
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/CubemapInputMaterialSlot.cs


int slotId,
string displayName,
string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/CubemapMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{}
public override SlotValueType valueType { get { return SlotValueType.Cubemap; } }

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicMatrixMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicValueMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Matrix4x4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/DynamicVectorMaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
}

12
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/GradientInputMaterialSlot.cs


int slotId,
string displayName,
string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{
}

generatePropertyBlock = false
});
}
for(int i = 0; i < 8; i++)
{
properties.AddShaderProperty(new Vector4ShaderProperty()

generatePropertyBlock = false
});
}
}
}
var prop = new GradientShaderProperty();

vector4Value = i < value.colorKeys.Length ? GradientUtils.ColorKeyToVector(value.colorKeys[i]) : Vector4.zero
});
}
for(int i = 0; i < 8; i++)
{
properties.Add(new PreviewProperty(PropertyType.Vector2)

value = slot.value;
}
}
}
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/GradientMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

{
}
}
}
}

60
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/MaterialSlot.cs


string m_ShaderOutputName;
[SerializeField]
ShaderStage m_ShaderStage;
ShaderStageCapability m_StageCapability;
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
{
m_Id = slotId;
m_DisplayName = displayName;

this.shaderStage = shaderStage;
this.stageCapability = stageCapability;
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, int priority, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, int priority, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
{
m_Id = slotId;
m_DisplayName = displayName;

m_ShaderOutputName = shaderOutputName;
this.shaderStage = shaderStage;
this.stageCapability = stageCapability;
}
public virtual VisualElement InstantiateControl()

return m_DisplayName;
}
public static MaterialSlot CreateMaterialSlot(SlotValueType type, int slotId, string displayName, string shaderOutputName, SlotType slotType, Vector4 defaultValue, ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
public static MaterialSlot CreateMaterialSlot(SlotValueType type, int slotId, string displayName, string shaderOutputName, SlotType slotType, Vector4 defaultValue, ShaderStageCapability shaderStageCapability = ShaderStageCapability.All, bool hidden = false)
return new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new DynamicMatrixMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new DynamicMatrixMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new Matrix3MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new Matrix3MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new Matrix2MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
return new Matrix2MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
? new Texture2DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
: new Texture2DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
? new Texture2DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new Texture2DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
? new CubemapInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
: new CubemapMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
? new CubemapInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new CubemapMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
? new GradientInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStage, hidden)
: new GradientMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden);
? new GradientInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new GradientMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
return new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden);
return new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden);
return new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden: hidden);
return new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden);
return new Vector3MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden: hidden);
return new Vector3MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden);
return new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStage, hidden: hidden);
return new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden);
return new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStage, hidden: hidden);
return new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStageCapability, hidden: hidden);
return new DynamicValueMaterialSlot(slotId, displayName, shaderOutputName, slotType, new Matrix4x4(defaultValue, Vector4.zero, Vector4.zero, Vector4.zero), shaderStage, hidden);
return new DynamicValueMaterialSlot(slotId, displayName, shaderOutputName, slotType, new Matrix4x4(defaultValue, Vector4.zero, Vector4.zero, Vector4.zero), shaderStageCapability, hidden);
return new BooleanMaterialSlot(slotId, displayName, shaderOutputName, slotType, false, shaderStage, hidden);
return new BooleanMaterialSlot(slotId, displayName, shaderOutputName, slotType, false, shaderStageCapability, hidden);
}
throw new ArgumentOutOfRangeException("type", type, null);

private set { m_ShaderOutputName = value; }
}
public ShaderStage shaderStage
public ShaderStageCapability stageCapability
get { return m_ShaderStage; }
set { m_ShaderStage = value; }
get { return m_StageCapability; }
set { m_StageCapability = value; }
}
public bool hasError

&& ((isInputSlot
? otherSlot.IsCompatibleWithInputSlotType(valueType)
: IsCompatibleWithInputSlotType(otherSlot.valueType)));
}
public bool IsCompatibleStageWith(MaterialSlot otherSlot)
{
var candidateStage = otherSlot.stageCapability;
return stageCapability == ShaderStageCapability.All || candidateStage == stageCapability;
}
public virtual string GetDefaultValue(GenerationMode generationMode)

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix2MaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix3MaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Matrix4MaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/NormalMaterialSlot.cs


{}
public NormalMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Normal));
}
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/PositionMaterialSlot.cs


{}
public PositionMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Position));
}
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

3
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/PreviewMode.cs


public enum PreviewMode
{
Preview2D,
Preview3D
Preview3D,
Wireframe
}
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/SamplerStateMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ScreenPositionMaterialSlot.cs


{}
public ScreenPositionMaterialSlot(int slotId, string displayName, string shaderOutputName, ScreenSpaceType screenSpaceType,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, shaderStage, hidden: hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden)
{
this.screenSpaceType = screenSpaceType;
}

return m_ScreenSpaceType.ToValueAsVariable();
}
public bool RequiresScreenPosition()
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
return !isConnected;
}

30
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ShaderGraphRequirements.cs


return newReqs;
}
public static ShaderGraphRequirements FromNodes(List<INode> nodes)
public static ShaderGraphRequirements FromNodes<T>(List<T> nodes, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool includeIntermediateSpaces = true)
where T : class, INode
NeededCoordinateSpace requiresNormal = nodes.OfType<IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal());
NeededCoordinateSpace requiresBitangent = nodes.OfType<IMayRequireBitangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresBitangent());
NeededCoordinateSpace requiresTangent = nodes.OfType<IMayRequireTangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresTangent());
NeededCoordinateSpace requiresViewDir = nodes.OfType<IMayRequireViewDirection>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresViewDirection());
NeededCoordinateSpace requiresPosition = nodes.OfType<IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition());
NeededCoordinateSpace requiresNormal = nodes.OfType<IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal(stageCapability));
NeededCoordinateSpace requiresBitangent = nodes.OfType<IMayRequireBitangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresBitangent(stageCapability));
NeededCoordinateSpace requiresTangent = nodes.OfType<IMayRequireTangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresTangent(stageCapability));
NeededCoordinateSpace requiresViewDir = nodes.OfType<IMayRequireViewDirection>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresViewDirection(stageCapability));
NeededCoordinateSpace requiresPosition = nodes.OfType<IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition(stageCapability));
bool requiresScreenPosition = nodes.OfType<IMayRequireScreenPosition>().Any(x => x.RequiresScreenPosition());
bool requiresVertexColor = nodes.OfType<IMayRequireVertexColor>().Any(x => x.RequiresVertexColor());

// if anything needs tangentspace we have make
// sure to have our othonormal basis!
var compoundSpaces = requiresBitangent | requiresNormal | requiresPosition
if(includeIntermediateSpaces)
{
var compoundSpaces = requiresBitangent | requiresNormal | requiresPosition
var needsTangentSpace = (compoundSpaces & NeededCoordinateSpace.Tangent) > 0;
if (needsTangentSpace)
{
requiresBitangent |= NeededCoordinateSpace.Object;
requiresNormal |= NeededCoordinateSpace.Object;
requiresTangent |= NeededCoordinateSpace.Object;
var needsTangentSpace = (compoundSpaces & NeededCoordinateSpace.Tangent) > 0;
if (needsTangentSpace)
{
requiresBitangent |= NeededCoordinateSpace.World;
requiresNormal |= NeededCoordinateSpace.World;
requiresTangent |= NeededCoordinateSpace.World;
}
}
var reqs = new ShaderGraphRequirements()

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/SpaceMaterialSlot.cs


{}
protected SpaceMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, shaderStage, hidden: hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden)
{
this.space = space;
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/TangentMaterialSlot.cs


{}
public TangentMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Tangent));
}
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DInputMaterialSlot.cs


int slotId,
string displayName,
string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Texture2DMaterialSlot.cs


string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{}
public override SlotValueType valueType { get { return SlotValueType.Texture2D; } }

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/UVMaterialSlot.cs


{}
public UVMaterialSlot(int slotId, string displayName, string shaderOutputName, UVChannel channel,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector2.zero, shaderStage, hidden: hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector2.zero, stageCapability, hidden: hidden)
{
this.channel = channel;
}

return string.Format("IN.{0}.xy", channel.GetUVName());
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
if (isConnected)
return false;

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector1MaterialSlot.cs


string shaderOutputName,
SlotType slotType,
float value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_DefaultValue = value;
m_Value = value;

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector2MaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector2 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
m_Labels = new[] { label1, label2 };

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector3MaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector3 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
m_Labels = new[] { label1, label2, label3 };

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/Vector4MaterialSlot.cs


string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStage shaderStage = ShaderStage.Dynamic,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
: base(slotId, displayName, shaderOutputName, slotType, shaderStage, hidden)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
m_Labels = new[] { label1, label2, label3, label4 };

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/VertexColorMaterialSlot.cs


public class VertexColorMaterialSlot : Vector4MaterialSlot, IMayRequireScreenPosition
{
public VertexColorMaterialSlot(int slotId, string displayName, string shaderOutputName,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, shaderStage, hidden: hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden)
{}
public override VisualElement InstantiateControl()

return string.Format("IN.{0}", ShaderGeneratorNames.VertexColor);
}
public bool RequiresScreenPosition()
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
return !isConnected;
}

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Graphs/ViewDirectionMaterialSlot.cs


{}
public ViewDirectionMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStage shaderStage = ShaderStage.Dynamic, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, shaderStage, hidden)
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{

return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.ViewDirection));
}
public NeededCoordinateSpace RequiresViewDirection()
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;

98
ShaderGraph/com.unity.shadergraph/Editor/Data/Implementation/NodeUtils.cs


Exclude
}
public static void DepthFirstCollectNodesFromNode(List<INode> nodeList, INode node, IncludeSelf includeSelf = IncludeSelf.Include, List<int> slotIds = null)
public static void DepthFirstCollectNodesFromNode<T>(List<T> nodeList, T node, IncludeSelf includeSelf = IncludeSelf.Include, List<int> slotIds = null)
where T : class, INode
{
// no where to start
if (node == null)

{
foreach (var edge in node.owner.GetEdges(node.GetSlotReference(slot)))
{
var outputNode = node.owner.GetNodeFromGuid(edge.outputSlot.nodeGuid);
var outputNode = node.owner.GetNodeFromGuid(edge.outputSlot.nodeGuid) as T;
if (outputNode != null)
DepthFirstCollectNodesFromNode(nodeList, outputNode);
}
}

nodeList.Add(node);
}
static Stack<INode> s_NodeStack = new Stack<INode>();
static Stack<MaterialSlot> s_SlotStack = new Stack<MaterialSlot>();
public static ShaderStage FindEffectiveShaderStage(INode initialNode, bool goingBackwards)
public static ShaderStage GetEffectiveShaderStage(MaterialSlot initialSlot, bool goingBackwards)
var shaderStage = ShaderStage.Dynamic;
s_NodeStack.Clear();
s_NodeStack.Push(initialNode);
while (s_NodeStack.Any() && shaderStage == ShaderStage.Dynamic)
var graph = initialSlot.owner.owner;
s_SlotStack.Clear();
s_SlotStack.Push(initialSlot);
while (s_SlotStack.Any())
var node = s_NodeStack.Pop();
foreach (var slot in goingBackwards ? node.GetInputSlots<MaterialSlot>() : node.GetOutputSlots<MaterialSlot>())
var slot = s_SlotStack.Pop();
ShaderStage stage;
if (slot.stageCapability.TryGetShaderStage(out stage))
return stage;
if (goingBackwards && slot.isInputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
if (shaderStage != ShaderStage.Dynamic)
break;
if (slot.shaderStage == ShaderStage.Dynamic)
var node = graph.GetNodeFromGuid(edge.outputSlot.nodeGuid);
s_SlotStack.Push(node.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId));
}
}
else if (!goingBackwards && slot.isOutputSlot)
foreach (var edge in node.owner.GetEdges(slot.slotReference))
foreach (var edge in graph.GetEdges(slot.slotReference))
var connectedNode = node.owner.GetNodeFromGuid(goingBackwards ? edge.outputSlot.nodeGuid : edge.inputSlot.nodeGuid);
var connectedSlot = goingBackwards ? connectedNode.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId) : connectedNode.FindInputSlot<MaterialSlot>(edge.inputSlot.slotId);
if (connectedSlot.shaderStage == ShaderStage.Dynamic)
s_NodeStack.Push(connectedNode);
var node = graph.GetNodeFromGuid(edge.inputSlot.nodeGuid);
s_SlotStack.Push(node.FindInputSlot<MaterialSlot>(edge.inputSlot.slotId));
}
}
shaderStage = connectedSlot.shaderStage;
break;
var ownerSlots = Enumerable.Empty<MaterialSlot>();
if (goingBackwards && slot.isOutputSlot)
ownerSlots = slot.owner.GetInputSlots<MaterialSlot>();
else if (!goingBackwards && slot.isInputSlot)
ownerSlots = slot.owner.GetOutputSlots<MaterialSlot>();
foreach (var ownerSlot in ownerSlots)
s_SlotStack.Push(ownerSlot);
// We default to fragment shader stage if all connected nodes were compatible with both.
return ShaderStage.Fragment;
}
public static ShaderStageCapability GetEffectiveShaderStageCapability(MaterialSlot initialSlot, bool goingBackwards)
{
var graph = initialSlot.owner.owner;
s_SlotStack.Clear();
s_SlotStack.Push(initialSlot);
while (s_SlotStack.Any())
{
var slot = s_SlotStack.Pop();
ShaderStage stage;
if (slot.stageCapability.TryGetShaderStage(out stage))
return slot.stageCapability;
if (goingBackwards && slot.isInputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
{
var node = graph.GetNodeFromGuid(edge.outputSlot.nodeGuid);
s_SlotStack.Push(node.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId));
}
}
else if (!goingBackwards && slot.isOutputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
{
var node = graph.GetNodeFromGuid(edge.inputSlot.nodeGuid);
s_SlotStack.Push(node.FindInputSlot<MaterialSlot>(edge.inputSlot.slotId));
}
shaderStage = slot.shaderStage;
{
var ownerSlots = Enumerable.Empty<MaterialSlot>();
if (goingBackwards && slot.isOutputSlot)
ownerSlots = slot.owner.GetInputSlots<MaterialSlot>();
else if (!goingBackwards && slot.isInputSlot)
ownerSlots = slot.owner.GetOutputSlots<MaterialSlot>();
foreach (var ownerSlot in ownerSlots)
s_SlotStack.Push(ownerSlot);
return shaderStage;
return ShaderStageCapability.All;
}
public static string GetSlotDimension(ConcreteSlotValueType slotValue)

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireBitangent.cs


{
public interface IMayRequireBitangent
{
NeededCoordinateSpace RequiresBitangent();
NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireBitangentExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireMeshUV.cs


{
public interface IMayRequireMeshUV
{
bool RequiresMeshUV(UVChannel channel);
bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireMeshUVExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireNormal.cs


{
public interface IMayRequireNormal
{
NeededCoordinateSpace RequiresNormal();
NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireNormalExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequirePosition.cs


{
public interface IMayRequirePosition
{
NeededCoordinateSpace RequiresPosition();
NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequirePositionExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireScreenPosition.cs


{
public interface IMayRequireScreenPosition
{
bool RequiresScreenPosition();
bool RequiresScreenPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireScreenPositionExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireTangent.cs


{
public interface IMayRequireTangent
{
NeededCoordinateSpace RequiresTangent();
NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireTangentExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireVertexColor.cs


{
interface IMayRequireVertexColor
{
bool RequiresVertexColor();
bool RequiresVertexColor(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireVertexColorExtensions

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Interfaces/IMayRequireViewDirection.cs


{
interface IMayRequireViewDirection
{
NeededCoordinateSpace RequiresViewDirection();
NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability = ShaderStageCapability.All);
}
public static class MayRequireViewDirectionExtensions

60
ShaderGraph/com.unity.shadergraph/Editor/Data/MasterNodes/PBRMasterNode.cs


{
[Serializable]
[Title("Master", "PBR")]
public class PBRMasterNode : MasterNode<IPBRSubShader>, IMayRequireNormal
public class PBRMasterNode : MasterNode<IPBRSubShader>, IMayRequirePosition, IMayRequireNormal
{
public const string AlbedoSlotName = "Albedo";
public const string NormalSlotName = "Normal";

public const string OcclusionSlotName = "Occlusion";
public const string AlphaSlotName = "Alpha";
public const string AlphaClipThresholdSlotName = "AlphaClipThreshold";
public const string VertexOffsetName = "VertexPosition";
public const string PositionName = "Position";
public const int AlbedoSlotId = 0;
public const int NormalSlotId = 1;

public const int OcclusionSlotId = 6;
public const int AlphaSlotId = 7;
public const int AlphaThresholdSlotId = 8;
public const int PositionSlotId = 9;
public enum Model
{

{
base.UpdateNodeAfterDeserialization();
name = "PBR Master";
AddSlot(new ColorRGBMaterialSlot(AlbedoSlotId, AlbedoSlotName, AlbedoSlotName, SlotType.Input, Color.grey, ShaderStage.Fragment));
AddSlot(new NormalMaterialSlot(NormalSlotId, NormalSlotName, NormalSlotName, CoordinateSpace.Tangent, ShaderStage.Fragment));
AddSlot(new ColorRGBMaterialSlot(EmissionSlotId, EmissionSlotName, EmissionSlotName, SlotType.Input, Color.black, ShaderStage.Fragment));
AddSlot(new PositionMaterialSlot(PositionSlotId, PositionName, PositionName, CoordinateSpace.Object, ShaderStageCapability.Vertex));
AddSlot(new ColorRGBMaterialSlot(AlbedoSlotId, AlbedoSlotName, AlbedoSlotName, SlotType.Input, Color.grey, ShaderStageCapability.Fragment));
AddSlot(new NormalMaterialSlot(NormalSlotId, NormalSlotName, NormalSlotName, CoordinateSpace.Tangent, ShaderStageCapability.Fragment));
AddSlot(new ColorRGBMaterialSlot(EmissionSlotId, EmissionSlotName, EmissionSlotName, SlotType.Input, Color.black, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(MetallicSlotId, MetallicSlotName, MetallicSlotName, SlotType.Input, 0, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(MetallicSlotId, MetallicSlotName, MetallicSlotName, SlotType.Input, 0, ShaderStageCapability.Fragment));
AddSlot(new ColorRGBMaterialSlot(SpecularSlotId, SpecularSlotName, SpecularSlotName, SlotType.Input, Color.grey, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, 0.5f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input, 1f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 1f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaThresholdSlotId, AlphaClipThresholdSlotName, AlphaClipThresholdSlotName, SlotType.Input, 0f, ShaderStage.Fragment));
AddSlot(new ColorRGBMaterialSlot(SpecularSlotId, SpecularSlotName, SpecularSlotName, SlotType.Input, Color.grey, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, 0.5f, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input, 1f, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 1f, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaThresholdSlotId, AlphaClipThresholdSlotName, AlphaClipThresholdSlotName, SlotType.Input, 0f, ShaderStageCapability.Fragment));
// clear out slot names that do not match the slots
// we support

PositionSlotId,
AlbedoSlotId,
NormalSlotId,
EmissionSlotId,

}, true);
}
public NeededCoordinateSpace RequiresNormal()
protected override VisualElement CreateCommonSettingsElement()
List<ISlot> slots = new List<ISlot>();
return new PBRSettingsView(this);
}
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
List<MaterialSlot> slots = new List<MaterialSlot>();
return slots.OfType<IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal());
List<MaterialSlot> validSlots = new List<MaterialSlot>();
for(int i = 0; i < slots.Count; i++)
{
if(slots[i].stageCapability != ShaderStageCapability.All && slots[i].stageCapability != stageCapability)
continue;
validSlots.Add(slots[i]);
}
return validSlots.OfType<IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal(stageCapability));
protected override VisualElement CreateCommonSettingsElement()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
return new PBRSettingsView(this);
List<MaterialSlot> slots = new List<MaterialSlot>();
GetSlots(slots);
List<MaterialSlot> validSlots = new List<MaterialSlot>();
for(int i = 0; i < slots.Count; i++)
{
if(slots[i].stageCapability != ShaderStageCapability.All && slots[i].stageCapability != stageCapability)
continue;
validSlots.Add(slots[i]);
}
return validSlots.OfType<IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition(stageCapability));
}
}
}

30
ShaderGraph/com.unity.shadergraph/Editor/Data/MasterNodes/UnlitMasterNode.cs


using System;
using System.Linq;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing;
using UnityEditor.ShaderGraph.Drawing.Controls;

{
[Serializable]
[Title("Master", "Unlit")]
public class UnlitMasterNode : MasterNode<IUnlitSubShader>
public class UnlitMasterNode : MasterNode<IUnlitSubShader>, IMayRequirePosition
public const string VertexOffsetName = "VertexPosition";
public const string PositionName = "Position";
public const int PositionSlotId = 9;
[SerializeField]
SurfaceType m_SurfaceType;

{
base.UpdateNodeAfterDeserialization();
name = "Unlit Master";
AddSlot(new ColorRGBMaterialSlot(ColorSlotId, ColorSlotName, ColorSlotName, SlotType.Input, Color.grey, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 1, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaThresholdSlotId, AlphaClipThresholdSlotName, AlphaClipThresholdSlotName, SlotType.Input, 0f, ShaderStage.Fragment));
AddSlot(new PositionMaterialSlot(PositionSlotId, PositionName, PositionName, CoordinateSpace.Object, ShaderStageCapability.Vertex));
AddSlot(new ColorRGBMaterialSlot(ColorSlotId, ColorSlotName, ColorSlotName, SlotType.Input, Color.grey, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 1, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaThresholdSlotId, AlphaClipThresholdSlotName, AlphaClipThresholdSlotName, SlotType.Input, 0f, ShaderStageCapability.Fragment));
// clear out slot names that do not match the slots
// we support

PositionSlotId,
ColorSlotId,
AlphaSlotId,
AlphaThresholdSlotId

protected override VisualElement CreateCommonSettingsElement()
{
return new UnlitSettingsView(this);
}
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
List<MaterialSlot> slots = new List<MaterialSlot>();
GetSlots(slots);
List<MaterialSlot> validSlots = new List<MaterialSlot>();
for(int i = 0; i < slots.Count; i++)
{
if(slots[i].stageCapability != ShaderStageCapability.All && slots[i].stageCapability != stageCapability)
continue;
validSlots.Add(slots[i]);
}
return validSlots.OfType<IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition(stageCapability));
}
}
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Artistic/Normal/NormalCreateNode.cs


AddSlot(new SamplerStateMaterialSlot(SamplerInputId, k_SamplerInputName, k_SamplerInputName, SlotType.Input));
AddSlot(new Vector1MaterialSlot(OffsetInputId, k_OffsetInputName, k_OffsetInputName, SlotType.Input, 0.5f));
AddSlot(new Vector1MaterialSlot(StrengthInputId, k_StrengthInputName, k_StrengthInputName, SlotType.Input, 8f));
AddSlot(new Vector3MaterialSlot(OutputSlotId, k_OutputSlotName, k_OutputSlotName, SlotType.Output, Vector3.zero));
AddSlot(new Vector3MaterialSlot(OutputSlotId, k_OutputSlotName, k_OutputSlotName, SlotType.Output, Vector3.zero, ShaderStageCapability.Fragment));
RemoveSlotsNameNotMatching(new[] { TextureInputId, UVInputId, SamplerInputId, OffsetInputId, StrengthInputId, OutputSlotId });
}

});
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
foreach (var slot in this.GetInputSlots<MaterialSlot>().OfType<IMayRequireMeshUV>())
{

89
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/CodeFunctionNode.cs


public Binding binding { get; private set; }
public bool hidden { get; private set; }
public Vector4? defaultValue { get; private set; }
public ShaderStageCapability stageCapability { get; private set; }
public SlotAttribute(int mSlotId, Binding mImplicitBinding)
public SlotAttribute(int mSlotId, Binding mImplicitBinding, ShaderStageCapability mStageCapability = ShaderStageCapability.All)
stageCapability = mStageCapability;
public SlotAttribute(int mSlotId, Binding mImplicitBinding, bool mHidden)
public SlotAttribute(int mSlotId, Binding mImplicitBinding, bool mHidden, ShaderStageCapability mStageCapability = ShaderStageCapability.All)
stageCapability = mStageCapability;
public SlotAttribute(int mSlotId, Binding mImplicitBinding, float defaultX, float defaultY, float defaultZ, float defaultW)
public SlotAttribute(int mSlotId, Binding mImplicitBinding, float defaultX, float defaultY, float defaultZ, float defaultW, ShaderStageCapability mStageCapability = ShaderStageCapability.All)
stageCapability = mStageCapability;
}
}

MaterialSlot s;
if (attribute.binding == Binding.None && !par.IsOut && par.ParameterType == typeof(Color))
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, hidden: attribute.hidden);
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden);
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, hidden: attribute.hidden);
s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden);
s = new ColorRGBMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, hidden: attribute.hidden);
s = new ColorRGBMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden);
else if (attribute.binding == Binding.None || par.IsOut)
s = MaterialSlot.CreateMaterialSlot(
ConvertTypeToSlotValueType(par),

par.IsOut ? SlotType.Output : SlotType.Input,
attribute.defaultValue ?? Vector4.zero,
shaderStageCapability: attribute.stageCapability,
s = CreateBoundSlot(attribute.binding, attribute.slotId, name, par.Name, attribute.hidden);
s = CreateBoundSlot(attribute.binding, attribute.slotId, name, par.Name, attribute.stageCapability, attribute.hidden);
slots.Add(s);
m_Slots.Add(attribute);

RemoveSlotsNameNotMatching(slots.Select(x => x.id));
}
private static MaterialSlot CreateBoundSlot(Binding attributeBinding, int slotId, string displayName, string shaderOutputName, bool hidden)
private static MaterialSlot CreateBoundSlot(Binding attributeBinding, int slotId, string displayName, string shaderOutputName, ShaderStageCapability shaderStageCapability, bool hidden)
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV0);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV0, shaderStageCapability);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV1);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV1, shaderStageCapability);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV2);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV2, shaderStageCapability);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV3);
return new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV3, shaderStageCapability);
return new ScreenPositionMaterialSlot(slotId, displayName, shaderOutputName, ScreenSpaceType.Default);
return new ScreenPositionMaterialSlot(slotId, displayName, shaderOutputName, ScreenSpaceType.Default, shaderStageCapability);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent);
return new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability);
return new VertexColorMaterialSlot(slotId, displayName, shaderOutputName);
return new VertexColorMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability);
default:
throw new ArgumentOutOfRangeException("attributeBinding", attributeBinding, null);
}

return attrs.FirstOrDefault();
}
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
var binding = NeededCoordinateSpace.None;
s_TempSlots.Clear();

return binding;
}
public NeededCoordinateSpace RequiresViewDirection()
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
var binding = NeededCoordinateSpace.None;
s_TempSlots.Clear();

return binding;
}
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return binding;
}
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return binding;
}
public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return binding;
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return false;
}
public bool RequiresScreenPosition()
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

return false;
}
public bool RequiresVertexColor()
public bool RequiresVertexColor(ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/BitangentVectorNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.BiTangent));
}
public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/NormalVectorNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Normal));
}
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/PositionNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Position));
}
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ScreenPositionNode.cs


visitor.AddShaderChunk(string.Format("{0}4 {1} = {2};", precision, GetVariableNameForSlot(kOutputSlotId), m_ScreenSpaceType.ToValueAsVariable()), true);
}
public bool RequiresScreenPosition()
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
return true;
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/TangentVectorNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Tangent));
}
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/UVNode.cs


visitor.AddShaderChunk(string.Format("{0}4 {1} = IN.{2};", precision, GetVariableNameForSlot(OutputSlotId), m_OutputChannel.GetUVName()), true);
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
return channel == uvChannel;
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/VertexColorNode.cs


return string.Format("IN.{0}", ShaderGeneratorNames.VertexColor);
}
public bool RequiresVertexColor()
public bool RequiresVertexColor(ShaderStageCapability stageCapability)
{
return true;
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs


return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.ViewDirection));
}
public NeededCoordinateSpace RequiresViewDirection()
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
return space.ToNeededCoordinateSpace();
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Scene/FogNode.cs


});
}
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
return CoordinateSpace.Object.ToNeededCoordinateSpace();
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleCubemapNode.cs


visitor.AddShaderChunk(result, true);
}
public NeededCoordinateSpace RequiresViewDirection()
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
var viewDirSlot = FindInputSlot<MaterialSlot>(ViewDirInputId);
var edgesViewDir = owner.GetEdges(viewDirSlot.slotReference);

return NeededCoordinateSpace.None;
}
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
var normalSlot = FindInputSlot<MaterialSlot>(NormalInputId);
var edgesNormal = owner.GetEdges(normalSlot.slotReference);

12
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Input/Texture/SampleTexture2DNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero));
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0));
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0));
AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0, ShaderStageCapability.Fragment));
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0, ShaderStageCapability.Fragment));
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
AddSlot(new UVMaterialSlot(UVInput, kUVInputName, kUVInputName, UVChannel.UV0));
AddSlot(new SamplerStateMaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input));

visitor.AddShaderChunk(string.Format("{0} {1} = {2}.a;", precision, GetVariableNameForSlot(OutputSlotAId), GetVariableNameForSlot(OutputSlotRGBAId)), true);
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

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


foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
activeNode.CollectShaderProperties(shaderProperties, mode);
var finalShader = new ShaderGenerator();
finalShader.AddShaderChunk(string.Format(@"Shader ""{0}""", outputName), false);
finalShader.AddShaderChunk("{", false);
finalShader.Indent();
finalShader.AddShaderChunk("Properties", false);
finalShader.AddShaderChunk("{", false);
finalShader.Indent();
finalShader.AddShaderChunk(shaderProperties.GetPropertiesBlock(2), false);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);
foreach (var subShader in m_SubShaders)
finalShader.AddShaderChunk(subShader.GetSubshader(this, mode), true);
finalShader.AddShaderChunk(@"FallBack ""Hidden/InternalErrorShader""", false);
finalShader.Deindent();
finalShader.AddShaderChunk("}", false);
var finalShader = new ShaderStringBuilder();
finalShader.AppendLine(@"Shader ""{0}""", outputName);
using(finalShader.BlockScope())
{
finalShader.AppendLine("Properties");
using(finalShader.BlockScope())
{
finalShader.AppendLine(shaderProperties.GetPropertiesBlock(0));
}
foreach (var subShader in m_SubShaders)
finalShader.AppendLines(subShader.GetSubshader(this, mode));
finalShader.AppendLine(@"FallBack ""Hidden/InternalErrorShader""");
}
return finalShader.GetShaderString(0);
return finalShader.ToString();
}
public bool IsPipelineCompatible(IRenderPipeline renderPipeline)

6
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Math/Vector/TransformNode.cs


return false;
}
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
if(RequiresWorldSpaceTangentTransform())
return NeededCoordinateSpace.World;

public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
if (RequiresWorldSpaceTangentTransform())
return NeededCoordinateSpace.World;

public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
if (RequiresWorldSpaceTangentTransform())
return NeededCoordinateSpace.World;

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/CheckerboardNode.cs


[Slot(1, Binding.None, 0.2f, 0.2f, 0.2f, 1f)] ColorRGB ColorA,
[Slot(2, Binding.None, 0.7f, 0.7f, 0.7f, 1f)] ColorRGB ColorB,
[Slot(3, Binding.None, 1f, 1f, 1f, 1f)] Vector2 Frequency,
[Slot(4, Binding.None)] out Vector3 Out)
[Slot(4, Binding.None, ShaderStageCapability.Fragment)] out Vector3 Out)
{
Out = Vector2.zero;
return

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Shape/EllipseNode.cs


[Slot(0, Binding.MeshUV0)] Vector2 UV,
[Slot(2, Binding.None, 0.5f, 0, 0, 0)] Vector1 Width,
[Slot(3, Binding.None, 0.5f, 0, 0, 0)] Vector1 Height,
[Slot(4, Binding.None)] out Vector1 Out)
[Slot(4, Binding.None, ShaderStageCapability.Fragment)] out Vector1 Out)
{
return
@"

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Shape/PolygonNode.cs


[Slot(1, Binding.None, 6, 0, 0, 0)] Vector1 Sides,
[Slot(2, Binding.None, 0.5f, 0, 0, 0)] Vector1 Width,
[Slot(3, Binding.None, 0.5f, 0, 0, 0)] Vector1 Height,
[Slot(4, Binding.None)] out DynamicDimensionVector Out)
[Slot(4, Binding.None, ShaderStageCapability.Fragment)] out DynamicDimensionVector Out)
{
return
@"

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Shape/RectangleNode.cs


[Slot(0, Binding.MeshUV0)] Vector2 UV,
[Slot(1, Binding.None, 0.5f, 0, 0, 0)] Vector1 Width,
[Slot(2, Binding.None, 0.5f, 0, 0, 0)] Vector1 Height,
[Slot(3, Binding.None)] out Vector1 Out)
[Slot(3, Binding.None, ShaderStageCapability.Fragment)] out Vector1 Out)
{
return
@"

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Procedural/Shape/RoundedRectangleNode.cs


[Slot(1, Binding.None, 0.5f, 0, 0, 0)] Vector1 Width,
[Slot(2, Binding.None, 0.5f, 0, 0, 0)] Vector1 Height,
[Slot(3, Binding.None, 0.1f, 0, 0, 0)] Vector1 Radius,
[Slot(4, Binding.None)] out Vector1 Out)
[Slot(4, Binding.None, ShaderStageCapability.Fragment)] out Vector1 Out)
{
return
@"

34
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/ShaderStage.cs


namespace UnityEditor.ShaderGraph
{
[Flags]
public enum ShaderStageCapability
{
Vertex = 1 << 0,
Fragment = 1 << 1,
All = Vertex | Fragment
}
Dynamic,
}
public static class ShaderStageExtensions
{
/// <summary>
/// Tries to convert a ShaderStageCapability into a ShaderStage. The conversion is only successful if the given ShaderStageCapability <paramref name="capability"/> refers to exactly 1 shader stage.
/// </summary>
/// <param name="capability">The ShaderStageCapability to convert.</param>
/// <param name="stage">If <paramref name="capability"/> refers to exactly 1 shader stage, this parameter will contain the equivalent ShaderStage of that. Otherwise the value is undefined.</param>
/// <returns>True is <paramref name="capability"/> holds exactly 1 shader stage.</returns>
public static bool TryGetShaderStage(this ShaderStageCapability capability, out ShaderStage stage)
{
switch (capability)
{
case ShaderStageCapability.Vertex:
stage = ShaderStage.Vertex;
return true;
case ShaderStageCapability.Fragment:
stage = ShaderStage.Fragment;
return true;
default:
stage = ShaderStage.Fragment;
return false;
}
}
}
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/UV/FlipbookNode.cs


});
}
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);

10
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/UV/TriplanarNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
AddSlot(new SamplerStateMaterialSlot(SamplerInputId, kSamplerInputName, kSamplerInputName, SlotType.Input));
AddSlot(new PositionMaterialSlot(PositionInputId, kPositionInputName, kPositionInputName, CoordinateSpace.World));

visitor.AddShaderChunk(sb.ToString(), false);
}
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
switch(m_TextureType)
{

}
}
public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
switch(m_TextureType)
{

36
ShaderGraph/com.unity.shadergraph/Editor/Data/Nodes/Utility/SubGraphNode.cs


}
var id = prop.guid.GetHashCode();
MaterialSlot slot = MaterialSlot.CreateMaterialSlot(slotType, id, prop.displayName, prop.referenceName, SlotType.Input, prop.defaultValue);
MaterialSlot slot = MaterialSlot.CreateMaterialSlot(slotType, id, prop.displayName, prop.referenceName, SlotType.Input, prop.defaultValue, ShaderStageCapability.Fragment);
// copy default for texture for niceness
if (slotType == SlotValueType.Texture2D && propType == PropertyType.Texture)
{

{
foreach (var slot in NodeExtensions.GetInputSlots<MaterialSlot>(subGraphOutputNode))
{
AddSlot(MaterialSlot.CreateMaterialSlot(slot.valueType, slot.id, slot.RawDisplayName(), slot.shaderOutputName, SlotType.Output, Vector4.zero));
AddSlot(MaterialSlot.CreateMaterialSlot(slot.valueType, slot.id, slot.RawDisplayName(), slot.shaderOutputName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
validNames.Add(slot.id);
}
}

referencedGraph.GenerateSubGraphFunction(SubGraphFunctionName(), registry, ShaderGraphRequirements.FromNodes(new List<INode> {this}), GenerationMode.ForReals);
}
public NeededCoordinateSpace RequiresNormal()
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
if (referencedGraph == null)
return NeededCoordinateSpace.None;

mask |= node.RequiresNormal();
mask |= node.RequiresNormal(stageCapability);
public bool RequiresMeshUV(UVChannel channel)
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
return referencedGraph.activeNodes.OfType<IMayRequireMeshUV>().Any(x => x.RequiresMeshUV(channel));
return referencedGraph.activeNodes.OfType<IMayRequireMeshUV>().Any(x => x.RequiresMeshUV(channel, stageCapability));
public bool RequiresScreenPosition()
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
return referencedGraph.activeNodes.OfType<IMayRequireScreenPosition>().Any(x => x.RequiresScreenPosition());
return referencedGraph.activeNodes.OfType<IMayRequireScreenPosition>().Any(x => x.RequiresScreenPosition(stageCapability));
public NeededCoordinateSpace RequiresViewDirection()
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
if (referencedGraph == null)
return NeededCoordinateSpace.None;

mask |= node.RequiresViewDirection();
mask |= node.RequiresViewDirection(stageCapability);
public NeededCoordinateSpace RequiresPosition()
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
if (referencedGraph == null)
return NeededCoordinateSpace.None;

mask |= node.RequiresPosition();
mask |= node.RequiresPosition(stageCapability);
public NeededCoordinateSpace RequiresTangent()
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
if (referencedGraph == null)
return NeededCoordinateSpace.None;

mask |= node.RequiresTangent();
mask |= node.RequiresTangent(stageCapability);
return mask;
});
}

return referencedGraph.activeNodes.OfType<IMayRequireTime>().Any(x => x.RequiresTime());
}
public NeededCoordinateSpace RequiresBitangent()
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
if (referencedGraph == null)
return NeededCoordinateSpace.None;

mask |= node.RequiresBitangent();
mask |= node.RequiresBitangent(stageCapability);
public bool RequiresVertexColor()
public bool RequiresVertexColor(ShaderStageCapability stageCapability)
return referencedGraph.activeNodes.OfType<IMayRequireVertexColor>().Any(x => x.RequiresVertexColor());
return referencedGraph.activeNodes.OfType<IMayRequireVertexColor>().Any(x => x.RequiresVertexColor(stageCapability));
}
}
}

2
ShaderGraph/com.unity.shadergraph/Editor/Data/SubGraph/SubGraph.cs


arguments.Add(string.Format("{0}", prop.GetPropertyAsArgumentString()));
// now pass surface inputs
arguments.Add("SurfaceInputs IN");
arguments.Add("SurfaceDescriptionInputs IN");
// Now generate outputs
foreach (var slot in graphOutputs)

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; } }

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


return newText.ToString();
}
public static void GenerateApplicationVertexInputs(ShaderGraphRequirements graphRequiements, ShaderGenerator vertexInputs)
public static void GenerateApplicationVertexInputs(ShaderGraphRequirements graphRequiements, ShaderStringBuilder vertexInputs)
vertexInputs.AddShaderChunk("struct GraphVertexInput", false);
vertexInputs.AddShaderChunk("{", false);
vertexInputs.Indent();
vertexInputs.AddShaderChunk("float4 vertex : POSITION;", false);
vertexInputs.AddShaderChunk("float3 normal : NORMAL;", false);
vertexInputs.AddShaderChunk("float4 tangent : TANGENT;", false);
if (graphRequiements.requiresVertexColor)
vertexInputs.AppendLine("struct GraphVertexInput");
using (vertexInputs.BlockSemicolonScope())
vertexInputs.AddShaderChunk("float4 color : COLOR;", false);
vertexInputs.AppendLine("float4 vertex : POSITION;");
vertexInputs.AppendLine("float3 normal : NORMAL;");
vertexInputs.AppendLine("float4 tangent : TANGENT;");
if (graphRequiements.requiresVertexColor)
{
vertexInputs.AppendLine("float4 color : COLOR;");
}
foreach (var channel in graphRequiements.requiresMeshUVs.Distinct())
vertexInputs.AppendLine("float4 texcoord{0} : TEXCOORD{0};", (int)channel);
vertexInputs.AppendLine("UNITY_VERTEX_INPUT_INSTANCE_ID");
foreach (var channel in graphRequiements.requiresMeshUVs.Distinct())
vertexInputs.AddShaderChunk(string.Format("float4 texcoord{0} : TEXCOORD{0};", (int)channel), false);
vertexInputs.AddShaderChunk("UNITY_VERTEX_INPUT_INSTANCE_ID", true);
vertexInputs.Deindent();
vertexInputs.AddShaderChunk("};", false);
}
static void Visit(List<INode> outputList, Dictionary<Guid, INode> unmarkedNodes, INode node)

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();
var vertexDescriptionFunction = new ShaderStringBuilder(0);
var surfaceDescriptionInputStruct = new ShaderStringBuilder(0);
var surfaceDescriptionStruct = new ShaderStringBuilder(0);
var surfaceDescriptionFunction = new ShaderStringBuilder(0);
surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
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);
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);
// -------------------------------------
// Get Requirements
var requirements = ShaderGraphRequirements.FromNodes(activeNodeList, ShaderStageCapability.Fragment);
var shaderProperties = new PropertyCollector();
// -------------------------------------
// 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));
finalShader.AppendLines(surfaceDescriptionInputStruct.ToString());
finalShader.AppendNewLine();
finalShader.Concat(functionBuilder);
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");
finalBuilder.AppendLines(ShaderGenerator.GetPreviewSubShader(node, requirements));
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)
surfaceDescriptionStruct.AppendLine("struct SurfaceDescription");
using(surfaceDescriptionStruct.BlockSemicolonScope())
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();
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;");
}
else
{
surfaceDescriptionStruct.AddShaderChunk("float4 PreviewOutput;", false);
}
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)
{
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);
surfaceDescriptionFunction.AppendLines(sg.GetShaderString(0));
functionRegistry.builder.currentNode = null;
// In case of the subgraph output node, the preview is generated
// from the first input to the node.
if (activeNode is SubGraphOutputNode)
if (masterNode != null)
var inputSlot = activeNode.GetInputSlots<MaterialSlot>().FirstOrDefault();
if (inputSlot != null)
if (masterNode is IMasterNode)
{
var usedSlots = slots ?? masterNode.GetInputSlots<MaterialSlot>();
foreach (var input in usedSlots)
{
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)
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);
foreach (var slot in masterNode.GetOutputSlots<MaterialSlot>())
surfaceDescriptionFunction.AppendLine("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(slot.shaderOutputName), masterNode.GetSlotValue(slot.id, mode));
activeNode.CollectShaderProperties(shaderProperties, mode);
surfaceDescriptionFunction.AppendLine("return surface;");
}
}
const string k_VertexDescriptionStructName = "VertexDescription";
public static void GenerateVertexDescriptionStruct(ShaderStringBuilder builder, List<MaterialSlot> slots)
{
builder.AppendLine("struct {0}", k_VertexDescriptionStructName);
using (builder.BlockSemicolonScope())
{
foreach (var slot in slots)
builder.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType), NodeUtils.GetHLSLSafeName(slot.shaderOutputName));
functionRegistry.builder.currentNode = null;
}
public static void GenerateVertexDescriptionFunction(
AbstractMaterialGraph graph,
ShaderStringBuilder builder,
FunctionRegistry functionRegistry,
PropertyCollector shaderProperties,
GenerationMode mode,
List<AbstractMaterialNode> nodes,
List<MaterialSlot> slots)
{
if (graph == null)
return;
if (masterNode != null)
graph.CollectShaderProperties(shaderProperties, mode);
builder.AppendLine("{0} PopulateVertexData(VertexDescriptionInputs IN)", k_VertexDescriptionStructName);
using (builder.BlockScope())
if (masterNode is IMasterNode)
ShaderGenerator sg = new ShaderGenerator();
builder.AppendLine("{0} description = ({0})0;", k_VertexDescriptionStructName);
foreach (var node in nodes)
var usedSlots = slots ?? masterNode.GetInputSlots<MaterialSlot>();
foreach (var input in usedSlots)
var generatesFunction = node as IGeneratesFunction;
if (generatesFunction != null)
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
{
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(input.shaderOutputName), input.GetDefaultValue(mode)), true);
}
functionRegistry.builder.currentNode = node;
generatesFunction.GenerateNodeFunction(functionRegistry, mode);
var generatesBodyCode = node as IGeneratesBodyCode;
if (generatesBodyCode != null)
{
generatesBodyCode.GenerateNodeCode(sg, mode);
}
node.CollectShaderProperties(shaderProperties, mode);
else if (masterNode.hasPreview)
builder.AppendLines(sg.GetShaderString(0));
foreach (var slot in slots)
foreach (var slot in masterNode.GetOutputSlots<MaterialSlot>())
surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(slot.shaderOutputName), masterNode.GetSlotValue(slot.id, mode)), true);
var isSlotConnected = slot.owner.owner.GetEdges(slot.slotReference).Any();
var slotName = NodeUtils.GetHLSLSafeName(slot.shaderOutputName);
var slotValue = isSlotConnected ? ((AbstractMaterialNode)slot.owner).GetSlotValue(slot.id, mode) : slot.GetDefaultValue(mode);
builder.AppendLine("description.{0} = {1};", slotName, slotValue);
builder.AppendLine("return description;");
surfaceDescriptionFunction.AddShaderChunk("return surface;", false);
surfaceDescriptionFunction.Deindent();
surfaceDescriptionFunction.AddShaderChunk("}", false);
}
public static GenerationResults GetPreviewShader(this AbstractMaterialGraph graph, AbstractMaterialNode node)

public static GenerationResults GetUberPreviewShader(this AbstractMaterialGraph graph)
public static GenerationResults GetUberColorShader(this AbstractMaterialGraph graph)
{
return graph.GetShader(null, GenerationMode.Preview, "hidden/preview");
}

13
ShaderGraph/com.unity.shadergraph/Editor/Data/Util/PropertyCollector.cs


public string GetPropertiesDeclaration(int baseIndentLevel)
{
var sb = new StringBuilder();
var builder = new ShaderStringBuilder(baseIndentLevel);
GetPropertiesDeclaration(builder);
return builder.ToString();
}
public void GetPropertiesDeclaration(ShaderStringBuilder builder)
{
for (var i = 0; i < baseIndentLevel; i++)
sb.Append("\t");
sb.AppendLine(prop.GetPropertyDeclarationString());
builder.AppendLine(prop.GetPropertyDeclarationString());
return sb.ToString();
}
public List<TextureInfo> GetConfiguredTexutres()

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


public static void GenerateSpaceTranslationSurfaceInputs(
NeededCoordinateSpace neededSpaces,
InterpolatorType interpolatorType,
ShaderGenerator surfaceInputs,
string toReplace = "float3 {0};")
ShaderStringBuilder builder,
string format = "float3 {0};")
surfaceInputs.AddShaderChunk(string.Format(toReplace, CoordinateSpace.Object.ToVariableName(interpolatorType)), false);
builder.AppendLine(format, CoordinateSpace.Object.ToVariableName(interpolatorType));
surfaceInputs.AddShaderChunk(string.Format(toReplace, CoordinateSpace.World.ToVariableName(interpolatorType)), false);
builder.AppendLine(format, CoordinateSpace.World.ToVariableName(interpolatorType));
surfaceInputs.AddShaderChunk(string.Format(toReplace, CoordinateSpace.View.ToVariableName(interpolatorType)), false);
builder.AppendLine(format, CoordinateSpace.View.ToVariableName(interpolatorType));
surfaceInputs.AddShaderChunk(string.Format(toReplace, CoordinateSpace.Tangent.ToVariableName(interpolatorType)), false);
builder.AppendLine(format, CoordinateSpace.Tangent.ToVariableName(interpolatorType));
ShaderGenerator interpolators,
ShaderGenerator vertexShader,
ShaderGenerator pixelShader,
ShaderGenerator surfaceInputs,
ShaderGraphRequirements graphRequiements,
ShaderStringBuilder vertexOutputStruct,
ShaderStringBuilder vertexShader,
ShaderStringBuilder vertexShaderDescriptionInputs,
ShaderStringBuilder vertexShaderOutputs,
ShaderStringBuilder pixelShader,
ShaderStringBuilder pixelShaderSurfaceInputs,
ShaderGraphRequirements pixelRequirements,
ShaderGraphRequirements surfaceRequirements,
CoordinateSpace preferedCoordinateSpace)
ShaderGraphRequirements vertexRequirements,
CoordinateSpace preferredCoordinateSpace)
if (preferedCoordinateSpace == CoordinateSpace.Tangent)
preferedCoordinateSpace = CoordinateSpace.World;
// ----------------------------------------------------- //
// SETUP //
// ----------------------------------------------------- //
// step 1:
// *generate needed interpolators
// *generate output from the vertex shader that writes into these interpolators
// *generate the pixel shader code that declares needed variables in the local scope
var combinedRequierments = graphRequiements.Union(modelRequiements);
// -------------------------------------
// Tangent space requires going via World space
if (preferredCoordinateSpace == CoordinateSpace.Tangent)
preferredCoordinateSpace = CoordinateSpace.World;
// -------------------------------------
// Generate combined graph requirements
var graphModelRequirements = pixelRequirements.Union(modelRequiements);
var combinedRequirements = vertexRequirements.Union(graphModelRequirements);
// bitangent needs normal for x product
if (combinedRequierments.requiresNormal > 0 || combinedRequierments.requiresBitangent > 0)
// ----------------------------------------------------- //
// GENERATE VERTEX > PIXEL PIPELINE //
// ----------------------------------------------------- //
// -------------------------------------
// If any stage requires component write into vertex stage
// If model or pixel requires component write into interpolators and pixel stage
// -------------------------------------
// Position
if (combinedRequirements.requiresPosition > 0)
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.Normal);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1};", name, ConvertBetweenSpace("v.normal", CoordinateSpace.Object, preferedCoordinateSpace, InputType.Normal)), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = normalize(IN.{0});", name), false);
interpolatorIndex++;
var name = preferredCoordinateSpace.ToVariableName(InterpolatorType.Position);
var preferredSpacePosition = ConvertBetweenSpace("v.vertex", CoordinateSpace.Object, preferredCoordinateSpace, InputType.Position);
vertexShader.AppendLine("float3 {0} = {1};", name, preferredSpacePosition);
if (graphModelRequirements.requiresPosition > 0)
{
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {0};", name);
pixelShader.AppendLine("float3 {0} = IN.{0};", name);
interpolatorIndex++;
}
if (combinedRequierments.requiresTangent > 0 || combinedRequierments.requiresBitangent > 0)
// -------------------------------------
// Normal
// Bitangent needs Normal for x product
if (combinedRequirements.requiresNormal > 0 || combinedRequirements.requiresBitangent > 0)
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.Tangent);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1};", name, ConvertBetweenSpace("v.tangent.xyz", CoordinateSpace.Object, preferedCoordinateSpace, InputType.Vector)), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = IN.{0};", name), false);
interpolatorIndex++;
var name = preferredCoordinateSpace.ToVariableName(InterpolatorType.Normal);
vertexShader.AppendLine("float3 {0} = {1};", name, ConvertBetweenSpace("v.normal", CoordinateSpace.Object, preferredCoordinateSpace, InputType.Normal));
if (graphModelRequirements.requiresNormal > 0 || graphModelRequirements.requiresBitangent > 0)
{
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {0};", name);
pixelShader.AppendLine("float3 {0} = normalize(IN.{0});", name);
interpolatorIndex++;
}
if (combinedRequierments.requiresBitangent > 0)
// -------------------------------------
// Tangent
if (combinedRequirements.requiresTangent > 0 || combinedRequirements.requiresBitangent > 0)
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.BiTangent);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = normalize(cross(o.{1}, o.{2}.xyz) * {3});",
var name = preferredCoordinateSpace.ToVariableName(InterpolatorType.Tangent);
vertexShader.AppendLine("float3 {0} = {1};", name, ConvertBetweenSpace("v.tangent.xyz", CoordinateSpace.Object, preferredCoordinateSpace, InputType.Vector));
if (graphModelRequirements.requiresTangent > 0 || graphModelRequirements.requiresBitangent > 0)
{
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {0};", name);
pixelShader.AppendLine("float3 {0} = IN.{0};", name);
interpolatorIndex++;
}
}
// -------------------------------------
// Bitangent
if (combinedRequirements.requiresBitangent > 0)
{
var name = preferredCoordinateSpace.ToVariableName(InterpolatorType.BiTangent);
vertexShader.AppendLine("float3 {0} = normalize(cross({1}, {2}.xyz) * {3});",
preferedCoordinateSpace.ToVariableName(InterpolatorType.Normal),
preferedCoordinateSpace.ToVariableName(InterpolatorType.Tangent),
"v.tangent.w"), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = IN.{0};", name), false);
interpolatorIndex++;
preferredCoordinateSpace.ToVariableName(InterpolatorType.Normal),
preferredCoordinateSpace.ToVariableName(InterpolatorType.Tangent),
"v.tangent.w");
if (graphModelRequirements.requiresBitangent > 0)
{
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {0};", name);
pixelShader.AppendLine("float3 {0} = IN.{0};", name);
interpolatorIndex++;
}
}
// -------------------------------------
// View Direction
if (combinedRequirements.requiresViewDir > 0)
{
var name = preferredCoordinateSpace.ToVariableName(InterpolatorType.ViewDirection);
const string worldSpaceViewDir = "SafeNormalize(_WorldSpaceCameraPos.xyz - mul(GetObjectToWorldMatrix(), float4(v.vertex.xyz, 1.0)).xyz)";
var preferredSpaceViewDir = ConvertBetweenSpace(worldSpaceViewDir, CoordinateSpace.World, preferredCoordinateSpace, InputType.Vector);
vertexShader.AppendLine("float3 {0} = {1};", name, preferredSpaceViewDir);
if (graphModelRequirements.requiresViewDir > 0)
{
vertexOutputStruct.AppendLine("float3 {0} : TEXCOORD{1};", name, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {0};", name);
pixelShader.AppendLine("float3 {0} = normalize(IN.{0});", name);
interpolatorIndex++;
}
if (combinedRequierments.requiresViewDir > 0)
// -------------------------------------
// Tangent space transform matrix
if (combinedRequirements.NeedsTangentSpace())
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.ViewDirection);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
var tangent = preferredCoordinateSpace.ToVariableName(InterpolatorType.Tangent);
var bitangent = preferredCoordinateSpace.ToVariableName(InterpolatorType.BiTangent);
var normal = preferredCoordinateSpace.ToVariableName(InterpolatorType.Normal);
if (vertexRequirements.NeedsTangentSpace())
vertexShader.AppendLine("float3x3 tangentSpaceTransform = float3x3({0},{1},{2});",
tangent, bitangent, normal);
if (graphModelRequirements.NeedsTangentSpace())
pixelShader.AppendLine("float3x3 tangentSpaceTransform = float3x3({0},{1},{2});",
tangent, bitangent, normal);
}
var worldSpaceViewDir = "SafeNormalize(_WorldSpaceCameraPos.xyz - mul(GetObjectToWorldMatrix(), float4(v.vertex.xyz, 1.0)).xyz)";
vertexShader.AddShaderChunk(string.Format("o.{0} = {1};", name, ConvertBetweenSpace(worldSpaceViewDir, CoordinateSpace.World, preferedCoordinateSpace, InputType.Vector)), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = normalize(IN.{0});", name), false);
interpolatorIndex++;
// -------------------------------------
// Vertex Color
if (combinedRequirements.requiresVertexColor)
{
var vertexColor = "v.color";
vertexShader.AppendLine("float4 {0} = {1};", ShaderGeneratorNames.VertexColor, vertexColor);
if (graphModelRequirements.requiresVertexColor)
{
vertexOutputStruct.AppendLine("float4 {0} : COLOR;", ShaderGeneratorNames.VertexColor);
vertexShaderOutputs.AppendLine("o.{0} = {0};", ShaderGeneratorNames.VertexColor);
pixelShader.AppendLine("float4 {0} = IN.{0};", ShaderGeneratorNames.VertexColor);
}
if (combinedRequierments.requiresPosition > 0)
// -------------------------------------
// Screen Position
if (combinedRequirements.requiresScreenPosition)
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.Position);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1}.xyz;", name, ConvertBetweenSpace("v.vertex", CoordinateSpace.Object, preferedCoordinateSpace, InputType.Position)), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = IN.{0};", name), false);
interpolatorIndex++;
var screenPosition = "ComputeScreenPos(mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), v.vertex.xyz)), _ProjectionParams.x)";
vertexShader.AppendLine("float4 {0} = {1};", ShaderGeneratorNames.ScreenPosition, screenPosition);
if (graphModelRequirements.requiresScreenPosition)
{
vertexOutputStruct.AppendLine("float4 {0} : TEXCOORD{1};", ShaderGeneratorNames.ScreenPosition, interpolatorIndex);
vertexShaderOutputs.AppendLine("o.{0} = {0};", ShaderGeneratorNames.ScreenPosition);
pixelShader.AppendLine("float4 {0} = IN.{0};", ShaderGeneratorNames.ScreenPosition);
interpolatorIndex++;
}
if (combinedRequierments.NeedsTangentSpace())
// -------------------------------------
// UV
foreach (var channel in combinedRequirements.requiresMeshUVs.Distinct())
vertexShader.AppendLine("float4 {0} = v.texcoord{1};", channel.GetUVName(), (int)channel);
foreach (var channel in graphModelRequirements.requiresMeshUVs.Distinct())
pixelShader.AddShaderChunk(string.Format("float3x3 tangentSpaceTransform = float3x3({0},{1},{2});",
preferedCoordinateSpace.ToVariableName(InterpolatorType.Tangent), preferedCoordinateSpace.ToVariableName(InterpolatorType.BiTangent), preferedCoordinateSpace.ToVariableName(InterpolatorType.Normal)), false);
vertexOutputStruct.AppendLine("half4 {0} : TEXCOORD{1};", channel.GetUVName(), interpolatorIndex == 0 ? "" : interpolatorIndex.ToString());
vertexShaderOutputs.AppendLine("o.{0} = {0};", channel.GetUVName());
pixelShader.AppendLine("float4 {0} = IN.{0};", channel.GetUVName());
interpolatorIndex++;
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresNormal, InterpolatorType.Normal, preferedCoordinateSpace,
// ----------------------------------------------------- //
// TRANSLATE NEEDED SPACES //
// ----------------------------------------------------- //
// -------------------------------------
// Generate the space translations needed by the vertex description
GenerateSpaceTranslations(vertexRequirements.requiresNormal, InterpolatorType.Normal, preferredCoordinateSpace,
InputType.Normal, vertexShader, Dimension.Three);
GenerateSpaceTranslations(vertexRequirements.requiresTangent, InterpolatorType.Tangent, preferredCoordinateSpace,
InputType.Vector, vertexShader, Dimension.Three);
GenerateSpaceTranslations(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, preferredCoordinateSpace,
InputType.Vector, vertexShader, Dimension.Three);
GenerateSpaceTranslations(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, preferredCoordinateSpace,
InputType.Vector, vertexShader, Dimension.Three);
GenerateSpaceTranslations(vertexRequirements.requiresPosition, InterpolatorType.Position, preferredCoordinateSpace,
InputType.Position, vertexShader, Dimension.Three);
// -------------------------------------
// Generate the space translations needed by the surface description and model
GenerateSpaceTranslations(graphModelRequirements.requiresNormal, InterpolatorType.Normal, preferredCoordinateSpace,
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresTangent, InterpolatorType.Tangent, preferedCoordinateSpace,
GenerateSpaceTranslations(graphModelRequirements.requiresTangent, InterpolatorType.Tangent, preferredCoordinateSpace,
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresBitangent, InterpolatorType.BiTangent, preferedCoordinateSpace,
GenerateSpaceTranslations(graphModelRequirements.requiresBitangent, InterpolatorType.BiTangent, preferredCoordinateSpace,
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresViewDir, InterpolatorType.ViewDirection, preferedCoordinateSpace,
GenerateSpaceTranslations(graphModelRequirements.requiresViewDir, InterpolatorType.ViewDirection, preferredCoordinateSpace,
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresPosition, InterpolatorType.Position, preferedCoordinateSpace,
GenerateSpaceTranslations(graphModelRequirements.requiresPosition, InterpolatorType.Position, preferredCoordinateSpace,
// ----------------------------------------------------- //
// START SURFACE DESCRIPTION //
// ----------------------------------------------------- //
if (combinedRequierments.requiresVertexColor)
// -------------------------------------
// Copy the locally defined values into the surface description
// structure using the requirements for ONLY the shader graph pixel stage
// additional requirements have come from the lighting model
// and are not needed in the shader graph
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);
var replaceString = "surfaceInput.{0} = {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);
if (combinedRequierments.requiresScreenPosition)
{
interpolators.AddShaderChunk(string.Format("float4 {0} : TEXCOORD{1};", ShaderGeneratorNames.ScreenPosition, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = ComputeScreenPos(mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), v.vertex)), _ProjectionParams.x);", ShaderGeneratorNames.ScreenPosition), false);
pixelShader.AddShaderChunk(string.Format("float4 {0} = IN.{0};", ShaderGeneratorNames.ScreenPosition), false);
interpolatorIndex++;
}
if (pixelRequirements.requiresVertexColor)
pixelShaderSurfaceInputs.AppendLine("surfaceInput.{0} = {0};", ShaderGeneratorNames.VertexColor);
if (pixelRequirements.requiresScreenPosition)
pixelShaderSurfaceInputs.AppendLine("surfaceInput.{0} = {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in pixelRequirements.requiresMeshUVs.Distinct())
pixelShaderSurfaceInputs.AppendLine("surfaceInput.{0} = {0};", ShaderGeneratorNames.GetUVName(channel));
foreach (var channel in combinedRequierments.requiresMeshUVs.Distinct())
{
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);
interpolatorIndex++;
}
// ----------------------------------------------------- //
// START VERTEX DESCRIPTION //
// ----------------------------------------------------- //
// step 2
// copy the locally defined values into the surface description
// structure using the requirements for ONLY the shader graph
// -------------------------------------
// Copy the locally defined values into the vertex description
// structure using the requirements for ONLY the shader graph vertex stage
var replaceString = "surfaceInput.{0} = {0};";
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresNormal, InterpolatorType.Normal, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresTangent, InterpolatorType.Tangent, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresPosition, InterpolatorType.Position, surfaceInputs, replaceString);
{
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);
}
if (graphRequiements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("surfaceInput.{0} = {0};", ShaderGeneratorNames.VertexColor), false);
if (vertexRequirements.requiresVertexColor)
vertexShaderDescriptionInputs.AppendLine("vdi.{0} = {0};", ShaderGeneratorNames.VertexColor);
if (graphRequiements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("surfaceInput.{0} = {0};", ShaderGeneratorNames.ScreenPosition), false);
if (vertexRequirements.requiresScreenPosition)
vertexShaderDescriptionInputs.AppendLine("vdi.{0} = {0};", ShaderGeneratorNames.ScreenPosition);
foreach (var channel in graphRequiements.requiresMeshUVs.Distinct())
surfaceInputs.AddShaderChunk(string.Format("surfaceInput.{0} = {0};", channel.GetUVName()), false);
foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
vertexShaderDescriptionInputs.AppendLine("vdi.{0} = {0};", channel.GetUVName(), (int)channel);
}
public enum Dimension

return "error";
}
public static void GenerateSpaceTranslationPixelShader(
public static void GenerateSpaceTranslations(
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 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,
vertexOutputStruct,
vertexShaderDescriptionInputs,
vertexShaderOutputs,
surfaceInputs,
pixelShaderSurfaceInputs,
shaderGraphRequirements,
ShaderGraphRequirements.none,
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}", vertexShader.GetShaderString(0));
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;
}

struct GraphVertexOutput
{
float4 position : POSITION;
${Interpolators}
${Interpolators}
};
GraphVertexOutput vert (GraphVertexInput v)

GraphVertexOutput o;
float3 positionWS = TransformObjectToWorld(v.vertex);
o.position = TransformWorldToHClip(positionWS);
${VertexShader}
${VertexShader}
${LocalPixelShader}
SurfaceInputs surfaceInput = (SurfaceInputs)0;;
${SurfaceInputs}
${LocalPixelShader}
SurfaceDescriptionInputs surfaceInput = (SurfaceDescriptionInputs)0;;
${SurfaceInputs}
${SurfaceOutputRemap}
${SurfaceOutputRemap}
}
ENDHLSL
}

4
ShaderGraph/com.unity.shadergraph/Editor/Data/Util/ShaderGeneratorNames.cs


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

33
ShaderGraph/com.unity.shadergraph/Editor/Data/Util/ShaderStringBuilder.cs


enum ScopeType
{
Indent,
Block
Block,
BlockSemicolon
}
StringBuilder m_StringBuilder;

m_ScopeStack = new Stack<ScopeType>();
m_Mappings = new List<ShaderStringMapping>();
m_CurrentMapping = new ShaderStringMapping();
}
public ShaderStringBuilder(int indentationLevel)
: this()
{
IncreaseIndent(indentationLevel);
}
public void AppendNewLine()

AppendLine("{");
IncreaseIndent();
m_ScopeStack.Push(ScopeType.Block);
return this;
}
public IDisposable BlockSemicolonScope()
{
AppendLine("{");
IncreaseIndent();
m_ScopeStack.Push(ScopeType.BlockSemicolon);
return this;
}

}
public void IncreaseIndent(int level)
{
for (var i = 0; i < level; i++)
IncreaseIndent();
}
public void DecreaseIndent(int level)
{
for (var i = 0; i < level; i++)
DecreaseIndent();
}
public void Dispose()
{
switch (m_ScopeStack.Pop())

case ScopeType.Block:
DecreaseIndent();
AppendLine("}");
break;
case ScopeType.BlockSemicolon:
DecreaseIndent();
AppendLine("};");
break;
}
}

69
ShaderGraph/com.unity.shadergraph/Editor/Drawing/PreviewManager.cs


MaterialPropertyBlock m_PreviewPropertyBlock;
PreviewSceneResources m_SceneResources;
Texture2D m_ErrorTexture;
Shader m_UberShader;
Shader m_ColorShader;
string m_OutputIdName;
Vector2? m_NewMasterPreviewSize;

m_ErrorTexture.filterMode = FilterMode.Point;
m_ErrorTexture.Apply();
m_SceneResources = new PreviewSceneResources();
m_UberShader = ShaderUtil.CreateShaderAsset(k_EmptyShader);
m_UberShader.hideFlags = HideFlags.HideAndDontSave;
m_ColorShader = ShaderUtil.CreateShaderAsset(k_EmptyShader);
m_ColorShader.hideFlags = HideFlags.HideAndDontSave;
m_MasterRenderData = new PreviewRenderData
{
renderTexture = new RenderTexture(400, 400, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default) { hideFlags = HideFlags.HideAndDontSave }

public void RenderPreviews()
{
UpdateShaders();
// Union time dependent previews into dirty previews
m_DirtyPreviews.UnionWith(m_TimeDependentPreviews);
PropagateNodeSet(m_DirtyPreviews);
m_NodesWithWireframePreview.Clear();
else if (node.previewMode == PreviewMode.Wireframe)
m_NodesWithWireframePreview.Add(node.tempId.index);
PropagateNodeSet(m_NodesWithWireframePreview);
m_NodesWith3DPreview.UnionWith(m_NodesWithWireframePreview);
UpdateShaders();
// Union time dependent previews into dirty previews
m_DirtyPreviews.UnionWith(m_TimeDependentPreviews);
PropagateNodeSet(m_DirtyPreviews);
foreach (var index in m_DirtyPreviews)
{
var renderData = m_RenderDatas[index];

}
IndexSet m_NodesWith3DPreview = new IndexSet();
IndexSet m_NodesWithWireframePreview = new IndexSet();
void UpdateShaders()
{

var masterNodes = new List<INode>();
var uberNodes = new List<INode>();
var colorNodes = new List<INode>();
var wireframeNodes = new List<INode>();
var node = m_Graph.GetNodeFromTempId(m_Identifiers[index]);
var node = m_Graph.GetNodeFromTempId(m_Identifiers[index]) as AbstractMaterialNode;
else if(node.previewMode == PreviewMode.Wireframe)
wireframeNodes.Add(node);
uberNodes.Add(node);
colorNodes.Add(node);
var count = Math.Min(uberNodes.Count, 1) + masterNodes.Count;
var count = Math.Min(colorNodes.Count, 1) + masterNodes.Count;
try
{

i++;
EditorUtility.DisplayProgressBar("Shader Graph", string.Format("Compiling preview shaders ({0}/{1})", i, count), 0f);
}
if (uberNodes.Count > 0)
if (colorNodes.Count > 0)
var results = m_Graph.GetUberPreviewShader();
var results = m_Graph.GetUberColorShader();
ShaderUtil.UpdateShaderAsset(m_UberShader, results.shader);
ShaderUtil.UpdateShaderAsset(m_ColorShader, results.shader);
File.WriteAllText(debugOutputPath + "/UberShader.shader", (results.shader ?? "null").Replace("UnityEngine.MaterialGraph", "Generated"));
File.WriteAllText(debugOutputPath + "/ColorShader.shader", (results.shader ?? "null").Replace("UnityEngine.MaterialGraph", "Generated"));
if (MaterialGraphAsset.ShaderHasError(m_UberShader))
if (MaterialGraphAsset.ShaderHasError(m_ColorShader))
var errors = MaterialGraphAsset.GetShaderErrors(m_UberShader);
var errors = MaterialGraphAsset.GetShaderErrors(m_ColorShader);
var message = new ShaderStringBuilder();
message.AppendLine(@"Preview shader for graph has {0} error{1}:", errors.Length, errors.Length != 1 ? "s" : "");
foreach (var error in errors)

}
}
Debug.LogWarning(message.ToString());
ShaderUtil.ClearShaderErrors(m_UberShader);
ShaderUtil.UpdateShaderAsset(m_UberShader, k_EmptyShader);
ShaderUtil.ClearShaderErrors(m_ColorShader);
ShaderUtil.UpdateShaderAsset(m_ColorShader, k_EmptyShader);
foreach (var node in uberNodes)
foreach (var node in colorNodes)
shaderData.shader = m_UberShader;
shaderData.shader = m_ColorShader;
shaderData.hasError = uberShaderHasError;
}
i++;

return;
var shaderData = renderData.shaderData;
if (!(node is IMasterNode) && (!node.hasPreview || NodeUtils.FindEffectiveShaderStage(node, true) == ShaderStage.Vertex))
if (!(node is IMasterNode) && !node.hasPreview)
{
shaderData.shaderString = null;
}

// Debug output
if (MaterialGraphAsset.ShaderHasError(shaderData.shader))
{
var errors = MaterialGraphAsset.GetShaderErrors(shaderData.shader);
foreach (var error in errors)
Debug.LogFormat("Compilation error in {3} at line {1} (on {2}):\n{0}", error.message, error.line, error.platform, "graph");
shaderData.hasError = true;
if (debugOutputPath != null)
{

{
if (renderData.shaderData != null
&& renderData.shaderData.shader != null
&& renderData.shaderData.shader != m_UberShader)
&& renderData.shaderData.shader != m_ColorShader)
Object.DestroyImmediate(renderData.shaderData.shader, true);
if (renderData.renderTexture != null)
Object.DestroyImmediate(renderData.renderTexture, true);

void ReleaseUnmanagedResources()
{
if (m_UberShader != null)
if (m_ColorShader != null)
Object.DestroyImmediate(m_UberShader, true);
m_UberShader = null;
Object.DestroyImmediate(m_ColorShader, true);
m_ColorShader = null;
}
if (m_ErrorTexture != null)
{

6
ShaderGraph/com.unity.shadergraph/Editor/Drawing/SearchWindowProvider.cs


return !materialSlot.IsCompatibleWith(connectedSlot);
});
m_Slots.RemoveAll(slot =>
{
var materialSlot = (MaterialSlot)slot;
return !materialSlot.IsCompatibleStageWith(connectedSlot);
});
if (hasSingleSlot && m_Slots.Count == 1)
{
nodeEntries.Add(new NodeEntry

17
ShaderGraph/com.unity.shadergraph/Editor/Drawing/Views/MaterialGraphView.cs


if (startSlot == null)
return compatibleAnchors;
var startStage = startSlot.shaderStage;
if (startStage == ShaderStage.Dynamic)
startStage = NodeUtils.FindEffectiveShaderStage(startSlot.owner, startSlot.isOutputSlot);
var startStage = startSlot.stageCapability;
if (startStage == ShaderStageCapability.All)
startStage = NodeUtils.GetEffectiveShaderStageCapability(startSlot, true) & NodeUtils.GetEffectiveShaderStageCapability(startSlot, false);
foreach (var candidateAnchor in ports.ToList())
{

if (startStage != ShaderStage.Dynamic)
if (startStage != ShaderStageCapability.All)
var candidateStage = candidateSlot.shaderStage;
if (candidateStage == ShaderStage.Dynamic)
candidateStage = NodeUtils.FindEffectiveShaderStage(candidateSlot.owner, !startSlot.isOutputSlot);
if (candidateStage != ShaderStage.Dynamic && candidateStage != startStage)
var candidateStage = candidateSlot.stageCapability;
if (candidateStage == ShaderStageCapability.All)
candidateStage = NodeUtils.GetEffectiveShaderStageCapability(candidateSlot, true)
& NodeUtils.GetEffectiveShaderStageCapability(candidateSlot, false);
if (candidateStage != ShaderStageCapability.All && candidateStage != startStage)
continue;
}

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

正在加载...
取消
保存