This commit is contained in:
2021-06-13 10:28:03 +02:00
parent eb70603c85
commit df2d24cbd3
7487 changed files with 943244 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
using System;
namespace UnityEditor.ShaderGraph
{
[AttributeUsage(AttributeTargets.Struct)]
class GenerateBlocksAttribute : Attribute
{
internal string path { get; set; }
public GenerateBlocksAttribute(string path = "")
{
this.path = path;
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
// this class is used to track asset dependencies in shadergraphs and subgraphs
// that is: it tracks files that the shadergraph or subgraph must access to generate the shader
// this data is used to automatically re-import the shadergraphs or subgraphs when any of the tracked files change
[GenerationAPI]
internal class AssetCollection
{
[Flags]
public enum Flags
{
SourceDependency = 1 << 0, // ShaderGraph directly reads the source file in the Assets directory
ArtifactDependency = 1 << 1, // ShaderGraph reads the import result artifact (i.e. subgraph import)
IsSubGraph = 1 << 2, // This asset is a SubGraph (used when we need to get multiple levels of dependencies)
IncludeInExportPackage = 1 << 3 // This asset should be pulled into any .unitypackages built via "Export Package.."
}
internal Dictionary<GUID, Flags> assets = new Dictionary<GUID, Flags>();
internal IEnumerable<GUID> assetGUIDs { get { return assets.Keys; } }
public AssetCollection()
{
}
internal void Clear()
{
assets.Clear();
}
// these are assets that we read the source files directly (directly reading the file out of the Assets directory)
public void AddAssetDependency(GUID assetGUID, Flags flags)
{
if (assets.TryGetValue(assetGUID, out Flags existingFlags))
{
assets[assetGUID] = existingFlags | flags;
}
else
{
assets.Add(assetGUID, flags);
}
}
}
}

View File

@@ -0,0 +1,71 @@
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class DefineCollection : IEnumerable<DefineCollection.Item>
{
public class Item : IConditional, IShaderString
{
public KeywordDescriptor descriptor { get; }
public FieldCondition[] fieldConditions { get; }
public string value => descriptor.ToDefineString(index);
// KeywordType.Boolean, index 0: disable, 1: enable
// KeywordType.Enum, index into enum entries
public int index { get; }
public Item(KeywordDescriptor descriptor, int index, FieldCondition[] fieldConditions)
{
this.descriptor = descriptor;
this.fieldConditions = fieldConditions;
this.index = index;
}
}
readonly List<Item> m_Items;
public DefineCollection()
{
m_Items = new List<Item>();
}
public DefineCollection Add(DefineCollection defines)
{
foreach (DefineCollection.Item item in defines)
{
m_Items.Add(item);
}
return this;
}
public DefineCollection Add(KeywordDescriptor descriptor, int index)
{
m_Items.Add(new Item(descriptor, index, null));
return this;
}
public DefineCollection Add(KeywordDescriptor descriptor, int index, FieldCondition fieldCondition)
{
m_Items.Add(new Item(descriptor, index, new FieldCondition[] { fieldCondition }));
return this;
}
public DefineCollection Add(KeywordDescriptor descriptor, int index, FieldCondition[] fieldConditions)
{
m_Items.Add(new Item(descriptor, index, fieldConditions));
return this;
}
public IEnumerator<Item> GetEnumerator()
{
return m_Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class DependencyCollection : IEnumerable<DependencyCollection.Item>
{
public class Item
{
public FieldDependency dependency { get; }
public Item(FieldDependency dependency)
{
this.dependency = dependency;
}
}
readonly List<DependencyCollection.Item> m_Items;
public DependencyCollection()
{
m_Items = new List<DependencyCollection.Item>();
}
public DependencyCollection Add(DependencyCollection dependencies)
{
foreach (DependencyCollection.Item item in dependencies)
{
m_Items.Add(item);
}
return this;
}
public DependencyCollection Add(FieldDependency dependency)
{
m_Items.Add(new Item(dependency));
return this;
}
public IEnumerator<DependencyCollection.Item> GetEnumerator()
{
return m_Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,52 @@
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class FieldCollection : IEnumerable<FieldCollection.Item>
{
public class Item
{
public FieldDescriptor field { get; }
public Item(FieldDescriptor field)
{
this.field = field;
}
}
readonly List<FieldCollection.Item> m_Items;
public FieldCollection()
{
m_Items = new List<FieldCollection.Item>();
}
public FieldCollection Add(FieldCollection fields)
{
foreach (FieldCollection.Item item in fields)
{
m_Items.Add(item);
}
return this;
}
public FieldCollection Add(FieldDescriptor field)
{
m_Items.Add(new Item(field));
return this;
}
public IEnumerator<FieldCollection.Item> GetEnumerator()
{
return m_Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,66 @@
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class IncludeCollection : IEnumerable<IncludeCollection.Item>
{
public class Item : IConditional, IShaderString
{
public IncludeDescriptor descriptor { get; }
public FieldCondition[] fieldConditions { get; }
public string value => $"#include \"{descriptor.value}\"";
public Item(IncludeDescriptor descriptor, FieldCondition[] fieldConditions)
{
this.descriptor = descriptor;
this.fieldConditions = fieldConditions;
}
}
readonly List<Item> m_Items;
public IncludeCollection()
{
m_Items = new List<Item>();
}
public IncludeCollection Add(IncludeCollection includes)
{
foreach (IncludeCollection.Item item in includes)
{
m_Items.Add(item);
}
return this;
}
public IncludeCollection Add(string include, IncludeLocation location)
{
m_Items.Add(new Item(new IncludeDescriptor() { value = include, location = location }, null));
return this;
}
public IncludeCollection Add(string include, IncludeLocation location, FieldCondition fieldCondition)
{
m_Items.Add(new Item(new IncludeDescriptor() { value = include, location = location }, new FieldCondition[] { fieldCondition }));
return this;
}
public IncludeCollection Add(string include, IncludeLocation location, FieldCondition[] fieldConditions)
{
m_Items.Add(new Item(new IncludeDescriptor() { value = include, location = location }, fieldConditions));
return this;
}
public IEnumerator<Item> GetEnumerator()
{
return m_Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class KeywordCollection : IEnumerable<KeywordCollection.Item>
{
public class Item : IConditional, IShaderString
{
public KeywordDescriptor descriptor { get; }
public FieldCondition[] fieldConditions { get; }
public string value => descriptor.ToDeclarationString();
public Item(KeywordDescriptor descriptor, FieldCondition[] fieldConditions)
{
this.descriptor = descriptor;
this.fieldConditions = fieldConditions;
}
}
readonly List<Item> m_Items;
public KeywordCollection()
{
m_Items = new List<Item>();
}
public KeywordCollection Add(KeywordCollection keywords)
{
foreach (KeywordCollection.Item item in keywords)
{
m_Items.Add(item);
}
return this;
}
public KeywordCollection Add(KeywordDescriptor descriptor)
{
m_Items.Add(new Item(descriptor, null));
return this;
}
public KeywordCollection Add(KeywordDescriptor descriptor, FieldCondition fieldCondition)
{
m_Items.Add(new Item(descriptor, new FieldCondition[] { fieldCondition }));
return this;
}
public KeywordCollection Add(KeywordDescriptor descriptor, FieldCondition[] fieldConditions)
{
m_Items.Add(new Item(descriptor, fieldConditions));
return this;
}
public IEnumerator<Item> GetEnumerator()
{
return m_Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,66 @@
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class PassCollection : IEnumerable<PassCollection.Item>
{
public class Item : IConditional
{
public PassDescriptor descriptor { get; }
public FieldCondition[] fieldConditions { get; }
public Item(PassDescriptor descriptor, FieldCondition[] fieldConditions)
{
this.descriptor = descriptor;
this.fieldConditions = fieldConditions;
}
}
readonly List<Item> m_Items;
public PassCollection()
{
m_Items = new List<Item>();
}
public PassCollection Add(PassCollection passes)
{
foreach (PassCollection.Item item in passes)
{
m_Items.Add(item);
}
return this;
}
public PassCollection Add(PassDescriptor descriptor)
{
m_Items.Add(new Item(descriptor, null));
return this;
}
public PassCollection Add(PassDescriptor descriptor, FieldCondition fieldCondition)
{
m_Items.Add(new Item(descriptor, new FieldCondition[] { fieldCondition }));
return this;
}
public PassCollection Add(PassDescriptor descriptor, FieldCondition[] fieldConditions)
{
m_Items.Add(new Item(descriptor, fieldConditions));
return this;
}
public IEnumerator<Item> GetEnumerator()
{
return m_Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class PragmaCollection : IEnumerable<PragmaCollection.Item>
{
public class Item : IConditional, IShaderString
{
public PragmaDescriptor descriptor { get; }
public FieldCondition[] fieldConditions { get; }
public string value => $"#pragma {descriptor.value}";
public Item(PragmaDescriptor descriptor, FieldCondition[] fieldConditions)
{
this.descriptor = descriptor;
this.fieldConditions = fieldConditions;
}
}
readonly List<Item> m_Items;
public PragmaCollection()
{
m_Items = new List<Item>();
}
public PragmaCollection Add(PragmaCollection pragmas)
{
foreach (PragmaCollection.Item item in pragmas)
{
m_Items.Add(item);
}
return this;
}
public PragmaCollection Add(PragmaDescriptor descriptor)
{
m_Items.Add(new Item(descriptor, null));
return this;
}
public PragmaCollection Add(PragmaDescriptor descriptor, FieldCondition fieldCondition)
{
m_Items.Add(new Item(descriptor, new FieldCondition[] { fieldCondition }));
return this;
}
public PragmaCollection Add(PragmaDescriptor descriptor, FieldCondition[] fieldConditions)
{
m_Items.Add(new Item(descriptor, fieldConditions));
return this;
}
public IEnumerator<Item> GetEnumerator()
{
return m_Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class RenderStateCollection : IEnumerable<RenderStateCollection.Item>
{
public class Item : IConditional, IShaderString
{
public RenderStateDescriptor descriptor { get; }
public FieldCondition[] fieldConditions { get; }
public string value => descriptor.value;
public Item(RenderStateDescriptor descriptor, FieldCondition[] fieldConditions)
{
this.descriptor = descriptor;
this.fieldConditions = fieldConditions;
}
}
readonly List<Item> m_Items;
public RenderStateCollection()
{
m_Items = new List<Item>();
}
public RenderStateCollection Add(RenderStateCollection renderStates)
{
foreach (RenderStateCollection.Item item in renderStates)
{
m_Items.Add(item);
}
return this;
}
public RenderStateCollection Add(RenderStateDescriptor descriptor)
{
m_Items.Add(new Item(descriptor, null));
return this;
}
public RenderStateCollection Add(RenderStateDescriptor descriptor, FieldCondition fieldCondition)
{
m_Items.Add(new Item(descriptor, new FieldCondition[] { fieldCondition }));
return this;
}
public RenderStateCollection Add(RenderStateDescriptor descriptor, FieldCondition[] fieldConditions)
{
m_Items.Add(new Item(descriptor, fieldConditions));
return this;
}
public IEnumerator<Item> GetEnumerator()
{
return m_Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,66 @@
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class StructCollection : IEnumerable<StructCollection.Item>
{
public class Item : IConditional
{
public StructDescriptor descriptor { get; }
public FieldCondition[] fieldConditions { get; }
public Item(StructDescriptor descriptor, FieldCondition[] fieldConditions)
{
this.descriptor = descriptor;
this.fieldConditions = fieldConditions;
}
}
readonly List<StructCollection.Item> m_Items;
public StructCollection()
{
m_Items = new List<StructCollection.Item>();
}
public StructCollection Add(StructCollection structs)
{
foreach (StructCollection.Item item in structs)
{
m_Items.Add(item);
}
return this;
}
public StructCollection Add(StructDescriptor descriptor)
{
m_Items.Add(new StructCollection.Item(descriptor, null));
return this;
}
public StructCollection Add(StructDescriptor descriptor, FieldCondition fieldCondition)
{
m_Items.Add(new StructCollection.Item(descriptor, new FieldCondition[] { fieldCondition }));
return this;
}
public StructCollection Add(StructDescriptor descriptor, FieldCondition[] fieldConditions)
{
m_Items.Add(new StructCollection.Item(descriptor, fieldConditions));
return this;
}
public IEnumerator<StructCollection.Item> GetEnumerator()
{
return m_Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class TargetActiveBlockContext
{
public List<BlockFieldDescriptor> activeBlocks { get; private set; }
public List<BlockFieldDescriptor> currentBlocks { get; private set; }
public PassDescriptor? pass { get; private set; }
public TargetActiveBlockContext(List<BlockFieldDescriptor> currentBlocks, PassDescriptor? pass)
{
activeBlocks = new List<BlockFieldDescriptor>();
this.currentBlocks = currentBlocks;
this.pass = pass;
}
public void AddBlock(BlockFieldDescriptor block, bool conditional = true)
{
if (conditional == true)
{
activeBlocks.Add(block);
}
}
}
}

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class TargetFieldContext
{
public List<ConditionalField> conditionalFields { get; private set; }
public PassDescriptor pass { get; private set; }
public List<(BlockFieldDescriptor descriptor, bool isDefaultValue)> blocks { get; private set; }
public List<BlockFieldDescriptor> connectedBlocks { get; private set; }
public bool hasDotsProperties { get; private set; }
// NOTE: active blocks (and connectedBlocks) do not include temporarily added default blocks
public TargetFieldContext(PassDescriptor pass, List<(BlockFieldDescriptor descriptor, bool isDefaultValue)> activeBlocks, List<BlockFieldDescriptor> connectedBlocks, bool hasDotsProperties)
{
conditionalFields = new List<ConditionalField>();
this.pass = pass;
this.blocks = activeBlocks;
this.connectedBlocks = connectedBlocks;
this.hasDotsProperties = hasDotsProperties;
}
public void AddField(FieldDescriptor field, bool conditional = true)
{
conditionalFields.Add(new ConditionalField(field, conditional));
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
using UnityEditor.Graphing.Util;
using UnityEditor.ShaderGraph.Drawing;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class TargetPropertyGUIContext : VisualElement
{
const int kIndentWidthInPixel = 15;
public int globalIndentLevel {get; set;} = 0;
public TargetPropertyGUIContext()
{
}
public void AddProperty<T>(string label, BaseField<T> field, bool condition, EventCallback<ChangeEvent<T>> evt)
{
if (condition == true)
{
AddProperty<T>(label, field, evt);
}
}
public void AddProperty<T>(string label, int indentLevel, BaseField<T> field, bool condition, EventCallback<ChangeEvent<T>> evt)
{
if (condition == true)
{
AddProperty<T>(label, indentLevel, field, evt);
}
}
public void AddProperty<T>(string label, BaseField<T> field, EventCallback<ChangeEvent<T>> evt)
{
AddProperty<T>(label, 0, field, evt);
}
public void AddProperty<T>(string label, int indentLevel, BaseField<T> field, EventCallback<ChangeEvent<T>> evt)
{
if (field is INotifyValueChanged<T> notifyValueChanged)
{
notifyValueChanged.RegisterValueChangedCallback(evt);
}
var propertyRow = new PropertyRow(new Label(label));
ApplyPadding(propertyRow, indentLevel);
propertyRow.Add(field);
this.hierarchy.Add(propertyRow);
}
public void AddLabel(string label, int indentLevel)
{
var propertyRow = new PropertyRow(new Label(label));
ApplyPadding(propertyRow, indentLevel);
this.hierarchy.Add(propertyRow);
}
public void AddHelpBox(MessageType messageType, string messageText)
{
var helpBox = new HelpBoxRow(messageType);
helpBox.Add(new Label(messageText));
this.hierarchy.Add(helpBox);
}
void ApplyPadding(PropertyRow row, int indentLevel)
{
row.Q(className: "unity-label").style.marginLeft = (globalIndentLevel + indentLevel) * kIndentWidthInPixel;
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Linq;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class TargetSetupContext
{
public List<SubShaderDescriptor> subShaders { get; private set; }
public List<(string shaderGUI, string renderPipelineAssetType)> customEditorForRenderPipelines { get; private set; }
public AssetCollection assetCollection { get; private set; }
public string defaultShaderGUI { get; private set; }
// pass a HashSet to the constructor to have it gather asset dependency GUIDs
public TargetSetupContext(AssetCollection assetCollection = null)
{
subShaders = new List<SubShaderDescriptor>();
this.customEditorForRenderPipelines = new List<(string shaderGUI, string renderPipelineAssetType)>();
this.assetCollection = assetCollection;
}
public void AddSubShader(SubShaderDescriptor subShader)
{
subShaders.Add(subShader);
}
public void AddAssetDependency(GUID guid, AssetCollection.Flags flags)
{
assetCollection?.AddAssetDependency(guid, flags);
}
public void SetDefaultShaderGUI(string defaultShaderGUI)
{
this.defaultShaderGUI = defaultShaderGUI;
}
public void AddCustomEditorForRenderPipeline(string shaderGUI, Type renderPipelineAssetType)
{
this.customEditorForRenderPipelines.Add((shaderGUI, renderPipelineAssetType.FullName));
}
public bool HasCustomEditorForRenderPipeline(Type renderPipelineAssetType)
=> this.customEditorForRenderPipelines.Any(c => c.renderPipelineAssetType == renderPipelineAssetType.FullName);
}
}

View File

@@ -0,0 +1,138 @@
using UnityEngine;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
// This whole file is regrettable.
// However, right now we need an abstraction for MaterialSlot for use with BlockFieldDescriptors.
// MaterialSlot is very leaky, so we cant make it public but we need BlockFieldDescriptor to be public.
// All MaterialSlot types required by a BlockFieldDescriptor need a matching Control here.
// We also need a corresponding case in BlockNode.AddSlot for each control.
public interface IControl
{
ShaderGraphRequirements GetRequirements();
}
public class PositionControl : IControl
{
public CoordinateSpace space { get; private set; }
public PositionControl(CoordinateSpace space)
{
this.space = space;
}
public ShaderGraphRequirements GetRequirements()
{
return new ShaderGraphRequirements() { requiresPosition = space.ToNeededCoordinateSpace() };
}
}
public class NormalControl : IControl
{
public CoordinateSpace space { get; private set; }
public NormalControl(CoordinateSpace space)
{
this.space = space;
}
public ShaderGraphRequirements GetRequirements()
{
return new ShaderGraphRequirements() { requiresNormal = space.ToNeededCoordinateSpace() };
}
}
public class TangentControl : IControl
{
public CoordinateSpace space { get; private set; }
public TangentControl(CoordinateSpace space)
{
this.space = space;
}
public ShaderGraphRequirements GetRequirements()
{
return new ShaderGraphRequirements() { requiresTangent = space.ToNeededCoordinateSpace() };
}
}
public class ColorControl : IControl
{
public Color value { get; private set; }
public bool hdr { get; private set; }
public ColorControl(Color value, bool hdr)
{
this.value = value;
this.hdr = hdr;
}
public ShaderGraphRequirements GetRequirements()
{
return ShaderGraphRequirements.none;
}
}
public class ColorRGBAControl : IControl
{
public Color value { get; private set; }
public ColorRGBAControl(Color value)
{
this.value = value;
}
public ShaderGraphRequirements GetRequirements()
{
return ShaderGraphRequirements.none;
}
}
public class FloatControl : IControl
{
public float value { get; private set; }
public FloatControl(float value)
{
this.value = value;
}
public ShaderGraphRequirements GetRequirements()
{
return ShaderGraphRequirements.none;
}
}
public class Vector2Control : IControl
{
public Vector2 value { get; private set; }
public Vector2Control(Vector2 value)
{
this.value = value;
}
public ShaderGraphRequirements GetRequirements()
{
return ShaderGraphRequirements.none;
}
}
public class Vector3Control : IControl
{
public Vector3 value { get; private set; }
public Vector3Control(Vector3 value)
{
this.value = value;
}
public ShaderGraphRequirements GetRequirements()
{
return ShaderGraphRequirements.none;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal struct ConditionalField
{
public FieldDescriptor field { get; }
public bool condition { get; }
public ConditionalField(FieldDescriptor field, bool condition)
{
this.field = field;
this.condition = condition;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class FieldCondition
{
public FieldDescriptor field { get; }
public bool condition { get; }
public FieldCondition(FieldDescriptor field, bool condition)
{
this.field = field;
this.condition = condition;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal struct FieldDependency
{
public FieldDescriptor field;
public FieldDescriptor dependsOn;
public FieldDependency(FieldDescriptor field, FieldDescriptor dependsOn)
{
this.field = field;
this.dependsOn = dependsOn;
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
namespace UnityEditor.ShaderGraph
{
[Serializable][GenerationAPI]
internal struct KeywordEntry
{
public int id; // Used to determine what MaterialSlot an entry belongs to
public string displayName;
public string referenceName;
// In this case, we will handle the actual IDs later
public KeywordEntry(string displayName, string referenceName)
{
this.id = -1;
this.displayName = displayName;
this.referenceName = referenceName;
}
internal KeywordEntry(int id, string displayName, string referenceName)
{
this.id = id;
this.displayName = displayName;
this.referenceName = referenceName;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
namespace UnityEditor.ShaderGraph
{
internal class BlockFieldDescriptor : FieldDescriptor
{
public string displayName { get; }
public IControl control { get; }
public ShaderStage shaderStage { get; }
public bool isHidden { get; }
public bool isUnknown { get; }
internal string path { get; set; }
public BlockFieldDescriptor(string tag, string referenceName, string define, IControl control, ShaderStage shaderStage, bool isHidden = false, bool isUnknown = false)
: base(tag, referenceName, define)
{
this.displayName = referenceName;
this.control = control;
this.shaderStage = shaderStage;
this.isHidden = isHidden;
this.isUnknown = isUnknown;
}
public BlockFieldDescriptor(string tag, string referenceName, string displayName, string define, IControl control, ShaderStage shaderStage, bool isHidden = false, bool isUnknown = false)
: base(tag, referenceName, define)
{
this.displayName = displayName;
this.control = control;
this.shaderStage = shaderStage;
this.isHidden = isHidden;
this.isUnknown = isUnknown;
}
}
// TODO: This exposes the MaterialSlot API
// TODO: This needs to be removed but is currently required by HDRP for DiffusionProfileInputMaterialSlot
internal class CustomSlotBlockFieldDescriptor : BlockFieldDescriptor
{
public Func<MaterialSlot> createSlot;
public CustomSlotBlockFieldDescriptor(string tag, string referenceName, string define, Func<MaterialSlot> createSlot)
: base(tag, referenceName, define, null, ShaderStage.Fragment)
{
this.createSlot = createSlot;
}
public CustomSlotBlockFieldDescriptor(string tag, string referenceName, string displayName, string define, Func<MaterialSlot> createSlot)
: base(tag, referenceName, displayName, define, null, ShaderStage.Fragment)
{
this.createSlot = createSlot;
}
}
}

View File

@@ -0,0 +1,51 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class FieldDescriptor
{
// Default
public string tag { get; }
public string name { get; }
public string define { get; }
// StructField
public string type { get; }
public int vectorCount { get; }
public string semantic { get; }
public string preprocessor { get; }
public StructFieldOptions subscriptOptions { get; }
public FieldDescriptor(string tag, string name, string define)
{
this.tag = tag;
this.name = name;
this.define = define;
}
public FieldDescriptor(string tag, string name, string define, ShaderValueType type,
string semantic = "", string preprocessor = "", StructFieldOptions subscriptOptions = StructFieldOptions.Static)
{
this.tag = tag;
this.name = name;
this.define = define;
this.type = type.ToShaderString();
this.vectorCount = type.GetVectorCount();
this.semantic = semantic;
this.preprocessor = preprocessor;
this.subscriptOptions = subscriptOptions;
}
public FieldDescriptor(string tag, string name, string define, string type,
string semantic = "", string preprocessor = "", StructFieldOptions subscriptOptions = StructFieldOptions.Static)
{
this.tag = tag;
this.name = name;
this.define = define;
this.type = type;
this.vectorCount = 0;
this.semantic = semantic;
this.preprocessor = preprocessor;
this.subscriptOptions = subscriptOptions;
}
}
}

View File

@@ -0,0 +1,9 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal class IncludeDescriptor
{
public string value;
public IncludeLocation location;
}
}

View File

@@ -0,0 +1,14 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal struct KeywordDescriptor
{
public string displayName;
public string referenceName;
public KeywordType type;
public KeywordDefinition definition;
public KeywordScope scope;
public int value;
public KeywordEntry[] entries;
}
}

View File

@@ -0,0 +1,37 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal struct PassDescriptor
{
// Definition
public string displayName;
public string referenceName;
public string lightMode;
public bool useInPreview;
public bool virtualTextureFeedback;
// Templates
public string passTemplatePath;
public string[] sharedTemplateDirectories;
// Port mask
public BlockFieldDescriptor[] validVertexBlocks;
public BlockFieldDescriptor[] validPixelBlocks;
// Collections
public StructCollection structs;
public FieldCollection requiredFields;
public DependencyCollection fieldDependencies;
public RenderStateCollection renderStates;
public PragmaCollection pragmas;
public DefineCollection defines;
public KeywordCollection keywords;
public IncludeCollection includes;
// Methods
public bool Equals(PassDescriptor other)
{
return referenceName == other.referenceName;
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Linq;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal struct PragmaDescriptor
{
public string value;
}
[GenerationAPI]
internal static class Pragma
{
static string GetPlatformList(Platform[] platforms)
{
var rendererStrings = platforms.Select(x => x.ToShaderString());
return string.Join(" ", rendererStrings);
}
public static PragmaDescriptor Target(ShaderModel value) => new PragmaDescriptor { value = $"target {value.ToShaderString()}" };
public static PragmaDescriptor Vertex(string value) => new PragmaDescriptor { value = $"vertex {value}" };
public static PragmaDescriptor Fragment(string value) => new PragmaDescriptor { value = $"fragment {value}" };
public static PragmaDescriptor Geometry(string value) => new PragmaDescriptor { value = $"geometry {value}" };
public static PragmaDescriptor Hull(string value) => new PragmaDescriptor { value = $"hull {value}" };
public static PragmaDescriptor Domain(string value) => new PragmaDescriptor { value = $"domain {value}" };
public static PragmaDescriptor Raytracing(string value) => new PragmaDescriptor { value = $"raytracing {value}" };
public static PragmaDescriptor OnlyRenderers(Platform[] renderers) => new PragmaDescriptor { value = $"only_renderers {GetPlatformList(renderers)}" };
public static PragmaDescriptor ExcludeRenderers(Platform[] renderers) => new PragmaDescriptor { value = $"exclude_renderers {GetPlatformList(renderers)}" };
public static PragmaDescriptor PreferHlslCC(Platform[] renderers) => new PragmaDescriptor { value = $"prefer_hlslcc {GetPlatformList(renderers)}" };
public static PragmaDescriptor InstancingOptions(InstancingOptions value) => new PragmaDescriptor { value = $"instancing_options {value.ToShaderString()}" };
public static PragmaDescriptor MultiCompileInstancing => new PragmaDescriptor { value = "multi_compile_instancing" };
public static PragmaDescriptor DOTSInstancing => new PragmaDescriptor { value = "multi_compile _ DOTS_INSTANCING_ON" };
public static PragmaDescriptor MultiCompileFog => new PragmaDescriptor { value = "multi_compile_fog" };
public static PragmaDescriptor EditorSyncCompilation => new PragmaDescriptor { value = "editor_sync_compilation" };
}
}

View File

@@ -0,0 +1,47 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum RenderStateType
{
Cull,
Blend,
BlendOp,
ZTest,
ZWrite,
ColorMask,
ZClip,
Stencil,
AlphaToMask,
}
[GenerationAPI]
internal struct RenderStateDescriptor
{
public string value;
public RenderStateType type;
}
[GenerationAPI]
internal static class RenderState
{
public static RenderStateDescriptor Cull(Cull value) => new RenderStateDescriptor { type = RenderStateType.Cull, value = $"Cull {value}" };
public static RenderStateDescriptor Cull(string value) => new RenderStateDescriptor { type = RenderStateType.Cull, value = $"Cull {value}" };
public static RenderStateDescriptor Blend(Blend src, Blend dst) => new RenderStateDescriptor { type = RenderStateType.Blend, value = $"Blend {src} {dst}" };
public static RenderStateDescriptor Blend(string src, string dst) => new RenderStateDescriptor { type = RenderStateType.Blend, value = $"Blend {src} {dst}" };
public static RenderStateDescriptor Blend(Blend src, Blend dst, Blend alphaSrc, Blend alphaDst) => new RenderStateDescriptor { type = RenderStateType.Blend, value = $"Blend {src} {dst}, {alphaSrc} {alphaDst}" };
public static RenderStateDescriptor Blend(string src, string dst, string alphaSrc, string alphaDst) => new RenderStateDescriptor { type = RenderStateType.Blend, value = $"Blend {src} {dst}, {alphaSrc} {alphaDst}" };
public static RenderStateDescriptor Blend(string value) => new RenderStateDescriptor { type = RenderStateType.Blend, value = value };
public static RenderStateDescriptor BlendOp(BlendOp op) => new RenderStateDescriptor { type = RenderStateType.BlendOp, value = $"BlendOp {op}" };
public static RenderStateDescriptor BlendOp(string op) => new RenderStateDescriptor { type = RenderStateType.BlendOp, value = $"BlendOp {op}" };
public static RenderStateDescriptor BlendOp(BlendOp op, BlendOp opAlpha) => new RenderStateDescriptor { type = RenderStateType.BlendOp, value = $"BlendOp {op}, {opAlpha}" };
public static RenderStateDescriptor BlendOp(string op, string opAlpha) => new RenderStateDescriptor { type = RenderStateType.BlendOp, value = $"BlendOp {op}, {opAlpha}" };
public static RenderStateDescriptor ZTest(ZTest value) => new RenderStateDescriptor { type = RenderStateType.ZTest, value = $"ZTest {value}" };
public static RenderStateDescriptor ZTest(string value) => new RenderStateDescriptor { type = RenderStateType.ZTest, value = $"ZTest {value}" };
public static RenderStateDescriptor ZWrite(ZWrite value) => new RenderStateDescriptor { type = RenderStateType.ZWrite, value = $"ZWrite {value}" };
public static RenderStateDescriptor ZWrite(string value) => new RenderStateDescriptor { type = RenderStateType.ZWrite, value = $"ZWrite {value}" };
public static RenderStateDescriptor ZClip(string value) => new RenderStateDescriptor { type = RenderStateType.ZClip, value = $"ZClip {value}" };
public static RenderStateDescriptor ColorMask(string value) => new RenderStateDescriptor { type = RenderStateType.ColorMask, value = $"{value}" };
public static RenderStateDescriptor AlphaToMask(string value) => new RenderStateDescriptor { type = RenderStateType.AlphaToMask, value = $"AlphaToMask {value}" };
public static RenderStateDescriptor Stencil(StencilDescriptor value) => new RenderStateDescriptor { type = RenderStateType.Stencil, value = value.ToShaderString() };
}
}

View File

@@ -0,0 +1,17 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal struct StencilDescriptor
{
public string WriteMask;
public string Ref;
public string Comp;
public string ZFail;
public string Fail;
public string Pass;
public string CompBack;
public string ZFailBack;
public string FailBack;
public string PassBack;
}
}

View File

@@ -0,0 +1,10 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal struct StructDescriptor
{
public string name;
public bool packFields;
public FieldDescriptor[] fields;
}
}

View File

@@ -0,0 +1,13 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal struct SubShaderDescriptor
{
public string pipelineTag;
public string customTags;
public string renderType;
public string renderQueue;
public bool generatesPreview;
public PassCollection passes;
}
}

View File

@@ -0,0 +1,17 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum Blend
{
One,
Zero,
SrcColor,
SrcAlpha,
DstColor,
DstAlpha,
OneMinusSrcColor,
OneMinusSrcAlpha,
OneMinusDstColor,
OneMinusDstAlpha,
}
}

View File

@@ -0,0 +1,12 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum BlendOp
{
Add,
Sub,
RevSub,
Min,
Max,
}
}

View File

@@ -0,0 +1,10 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum Cull
{
Back,
Front,
Off,
}
}

View File

@@ -0,0 +1,9 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum IncludeLocation
{
Pregraph,
Postgraph
}
}

View File

@@ -0,0 +1,31 @@
using System;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum InstancingOptions
{
RenderingLayer,
NoLightProbe,
NoLodFade,
}
[GenerationAPI]
internal static class InstancingOptionsExtensions
{
public static string ToShaderString(this InstancingOptions options)
{
switch (options)
{
case InstancingOptions.RenderingLayer:
return "renderinglayer";
case InstancingOptions.NoLightProbe:
return "nolightprobe";
case InstancingOptions.NoLodFade:
return "nolodfade";
default:
throw new ArgumentOutOfRangeException();
}
}
}
}

View File

@@ -0,0 +1,10 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum KeywordDefinition
{
ShaderFeature, // adds #pragma shaderfeature for the keyword
MultiCompile, // adds #pragma multicompile for the keyword
Predefined // does not add ShaderFeature or MultiCompile pragmas, and is forced to be !exposed
}
}

View File

@@ -0,0 +1,9 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum KeywordScope
{
Local,
Global
}
}

View File

@@ -0,0 +1,9 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum KeywordType
{
Boolean,
Enum
}
}

View File

@@ -0,0 +1,12 @@
using System;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum NormalDropOffSpace
{
Tangent,
Object,
World
}
}

View File

@@ -0,0 +1,67 @@
using System;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum Platform
{
D3D11,
GLCore,
GLES,
GLES3,
Metal,
Vulkan,
D3D9,
XboxOne,
GameCoreXboxOne,
GameCoreXboxSeries,
Playstation,
Switch,
}
[GenerationAPI]
internal static class PlatformExtensions
{
public static string ToShaderString(this Platform platform)
{
switch (platform)
{
case Platform.D3D11:
return "d3d11";
case Platform.GLCore:
return "glcore";
case Platform.GLES:
return "gles";
case Platform.GLES3:
return "gles3";
case Platform.Metal:
return "metal";
case Platform.Vulkan:
return "vulkan";
case Platform.D3D9:
return "d3d11_9x";
case Platform.XboxOne:
return "xboxone";
case Platform.GameCoreXboxOne:
return "xboxone";
case Platform.GameCoreXboxSeries:
return "xboxseries";
case Platform.Playstation:
return "playstation";
case Platform.Switch:
return "switch";
default:
throw new ArgumentOutOfRangeException();
}
}
}
internal static class PragmaRenderers
{
// Return high end platform list for the only renderer directive (The list use by HDRP)
internal static Platform[] GetHighEndPlatformArray()
{
return new Platform[] { Platform.D3D11, Platform.Playstation, Platform.XboxOne, Platform.GameCoreXboxSeries, Platform.Vulkan, Platform.Metal, Platform.Switch };
}
}
}

View File

@@ -0,0 +1,23 @@
namespace UnityEditor.ShaderGraph.Internal
{
[GenerationAPI]
public enum PropertyType
{
Color,
Texture2D,
Texture2DArray,
Texture3D,
Cubemap,
Gradient,
Boolean,
Float,
Vector2,
Vector3,
Vector4,
Matrix2,
Matrix3,
Matrix4,
SamplerState,
VirtualTexture
}
}

View File

@@ -0,0 +1,12 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum RenderQueue
{
Background,
Geometry,
Transparent,
Overlay,
AlphaTest
}
}

View File

@@ -0,0 +1,12 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum RenderType
{
Opaque,
Transparent,
TransparentCutout,
Background,
Overlay
}
}

View File

@@ -0,0 +1,46 @@
using System;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum ShaderModel
{
Target20,
Target25,
Target30,
Target35,
Target40,
Target45,
Target46,
Target50
}
[GenerationAPI]
internal static class ShaderModelExtensions
{
public static string ToShaderString(this ShaderModel shaderModel)
{
switch (shaderModel)
{
case ShaderModel.Target20:
return "2.0";
case ShaderModel.Target25:
return "2.5";
case ShaderModel.Target30:
return "3.0";
case ShaderModel.Target35:
return "3.5";
case ShaderModel.Target40:
return "4.0";
case ShaderModel.Target45:
return "4.5";
case ShaderModel.Target46:
return "4.6";
case ShaderModel.Target50:
return "5.0";
default:
throw new ArgumentOutOfRangeException();
}
}
}
}

View File

@@ -0,0 +1,18 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum ShaderValueType
{
Boolean,
Float,
Float2,
Float3,
Float4,
Matrix2,
Matrix3,
Matrix4,
Integer,
Uint,
Uint4,
}
}

View File

@@ -0,0 +1,10 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum StructFieldOptions
{
Static = 0,
Optional = 1 << 0,
Generated = 1 << 1
}
}

View File

@@ -0,0 +1,14 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum ZTest
{
Less,
Greater,
LEqual,
GEqual,
Equal,
NotEqual,
Always,
}
}

View File

@@ -0,0 +1,9 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal enum ZWrite
{
On,
Off,
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph.Internal
{
public struct GraphCode
{
public string code { get; internal set; }
public ShaderGraphRequirements requirements { get; internal set; }
public IEnumerable<AbstractShaderProperty> properties;
}
}

View File

@@ -0,0 +1,11 @@
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
interface IHasMetadata
{
string identifier { get; }
ScriptableObject GetMetadataObject();
}
}

View File

@@ -0,0 +1,33 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
public struct OutputMetadata
{
[SerializeField]
int m_Index;
[SerializeField]
string m_ReferenceName;
[SerializeField]
int m_Id;
internal OutputMetadata(int index, string referenceName, int id)
{
m_Index = index;
m_ReferenceName = referenceName;
m_Id = id;
}
public int index => m_Index;
public int id => m_Id;
public string referenceName => m_ReferenceName;
internal bool isValid => referenceName != null;
}
}

View File

@@ -0,0 +1,165 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph.Internal
{
internal interface IActiveFields : KeywordDependentCollection.IInstance, KeywordDependentCollection.ISet<IActiveFields>
{
IEnumerable<FieldDescriptor> fields { get; }
bool Add(FieldDescriptor field);
bool Contains(FieldDescriptor field);
bool Contains(string value);
}
internal interface IActiveFieldsSet : KeywordDependentCollection.ISet<IActiveFields>
{
void AddAll(FieldDescriptor field);
}
internal sealed class ActiveFields : KeywordDependentCollection<
HashSet<FieldDescriptor>,
ActiveFields.All,
ActiveFields.AllPermutations,
ActiveFields.ForPermutationIndex,
ActiveFields.Base,
IActiveFields,
IActiveFieldsSet
>
{
public struct ForPermutationIndex : IActiveFields, IActiveFieldsSet
{
private ActiveFields m_Source;
private int m_PermutationIndex;
public KeywordDependentCollection.KeywordPermutationInstanceType type => KeywordDependentCollection.KeywordPermutationInstanceType.Permutation;
public IEnumerable<IActiveFields> instances => Enumerable.Repeat<IActiveFields>(this, 1);
public IEnumerable<FieldDescriptor> fields =>
m_Source.baseStorage.Union(m_Source.GetOrCreateForPermutationIndex(m_PermutationIndex));
public int instanceCount => 1;
public int permutationIndex => m_PermutationIndex;
internal ForPermutationIndex(ActiveFields source, int index)
{
m_Source = source;
m_PermutationIndex = index;
}
public bool Add(FieldDescriptor field)
=> m_Source.GetOrCreateForPermutationIndex(m_PermutationIndex).Add(field);
public bool Contains(FieldDescriptor field) =>
m_Source.baseStorage.Contains(field)
|| m_Source.GetOrCreateForPermutationIndex(m_PermutationIndex).Contains(field);
public bool Contains(string value) => m_Source.baseStorage.Where(x => x.ToFieldString() == value).Any()
|| m_Source.GetOrCreateForPermutationIndex(m_PermutationIndex).Where(x => x.ToFieldString() == value).Any();
public void AddAll(FieldDescriptor field) => Add(field);
}
public struct Base : IActiveFields, IActiveFieldsSet
{
private ActiveFields m_Source;
public IEnumerable<FieldDescriptor> fields => m_Source.baseStorage;
public int instanceCount => 1;
public int permutationIndex => - 1;
public KeywordDependentCollection.KeywordPermutationInstanceType type => KeywordDependentCollection.KeywordPermutationInstanceType.Base;
public IEnumerable<IActiveFields> instances => Enumerable.Repeat<IActiveFields>(this, 1);
internal Base(ActiveFields source)
{
m_Source = source;
}
public bool Add(FieldDescriptor field) => m_Source.baseStorage.Add(field);
public bool Contains(FieldDescriptor field) => m_Source.baseStorage.Contains(field);
public bool Contains(string value) => m_Source.baseStorage.Where(x => x.ToFieldString() == value).Any();
public void AddAll(FieldDescriptor field) => Add(field);
}
public struct All : IActiveFieldsSet
{
private ActiveFields m_Source;
public int instanceCount => m_Source.permutationCount + 1;
internal All(ActiveFields source)
{
m_Source = source;
}
public void AddAll(FieldDescriptor field)
{
m_Source.baseInstance.Add(field);
for (var i = 0; i < m_Source.permutationCount; ++i)
m_Source.GetOrCreateForPermutationIndex(i).Add(field);
}
public IEnumerable<IActiveFields> instances
{
get
{
var self = this;
return m_Source.permutationStorages
.Select((v, i) => new ForPermutationIndex(self.m_Source, i) as IActiveFields)
.Union(Enumerable.Repeat((IActiveFields)m_Source.baseInstance, 1));
}
}
}
public struct AllPermutations : IActiveFieldsSet
{
private ActiveFields m_Source;
public int instanceCount => m_Source.permutationCount;
internal AllPermutations(ActiveFields source)
{
m_Source = source;
}
public void AddAll(FieldDescriptor field)
{
for (var i = 0; i < m_Source.permutationCount; ++i)
m_Source.GetOrCreateForPermutationIndex(i).Add(field);
}
public IEnumerable<IActiveFields> instances
{
get
{
var self = this;
return m_Source.permutationStorages
.Select((v, i) => new ForPermutationIndex(self.m_Source, i) as IActiveFields);
}
}
}
public struct NoPermutation : IActiveFields, IActiveFieldsSet
{
private ActiveFields m_Source;
public IEnumerable<FieldDescriptor> fields => m_Source.baseStorage;
public int instanceCount => 1;
public int permutationIndex => - 1;
public KeywordDependentCollection.KeywordPermutationInstanceType type => KeywordDependentCollection.KeywordPermutationInstanceType.Base;
internal NoPermutation(ActiveFields source)
{
m_Source = source;
}
public bool Add(FieldDescriptor field) => m_Source.baseInstance.Add(field);
public bool Contains(FieldDescriptor field) => m_Source.baseStorage.Contains(field);
public bool Contains(string value) => m_Source.baseStorage.Where(x => x.ToFieldString() == value).Any();
public void AddAll(FieldDescriptor field) => Add(field);
public IEnumerable<IActiveFields> instances => Enumerable.Repeat<IActiveFields>(this, 1);
}
protected override All CreateAllSmartPointer() => new All(this);
protected override AllPermutations CreateAllPermutationsSmartPointer() => new AllPermutations(this);
protected override ForPermutationIndex CreateForPermutationSmartPointer(int index) => new ForPermutationIndex(this, index);
protected override Base CreateBaseSmartPointer() => new Base(this);
}
}

View File

@@ -0,0 +1,886 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
using UnityEditor.ShaderGraph.Drawing;
using UnityEngine.Rendering;
using UnityEngine.Assertions;
using Pool = UnityEngine.Pool;
namespace UnityEditor.ShaderGraph
{
class Generator
{
const string kDebugSymbol = "SHADERGRAPH_DEBUG";
GraphData m_GraphData;
AbstractMaterialNode m_OutputNode;
Target[] m_Targets;
List<BlockNode> m_ActiveBlocks;
List<BlockNode> m_TemporaryBlocks;
GenerationMode m_Mode;
string m_Name;
ShaderStringBuilder m_Builder;
List<PropertyCollector.TextureInfo> m_ConfiguredTextures;
AssetCollection m_assetCollection;
public string generatedShader => m_Builder.ToCodeBlock();
public List<PropertyCollector.TextureInfo> configuredTextures => m_ConfiguredTextures;
public List<BlockNode> temporaryBlocks => m_TemporaryBlocks;
public Generator(GraphData graphData, AbstractMaterialNode outputNode, GenerationMode mode, string name, AssetCollection assetCollection)
{
m_GraphData = graphData;
m_OutputNode = outputNode;
m_Mode = mode;
m_Name = name;
m_Builder = new ShaderStringBuilder();
m_ConfiguredTextures = new List<PropertyCollector.TextureInfo>();
m_assetCollection = assetCollection;
m_ActiveBlocks = graphData.GetNodes<BlockNode>().ToList();
m_TemporaryBlocks = new List<BlockNode>();
GetTargetImplementations();
BuildShader();
}
void GetTargetImplementations()
{
if (m_OutputNode == null)
{
m_Targets = m_GraphData.activeTargets.ToArray();
}
else
{
m_Targets = new Target[] { new PreviewTarget() };
}
}
public ActiveFields GatherActiveFieldsFromNode(AbstractMaterialNode outputNode, PassDescriptor pass, List<(BlockFieldDescriptor descriptor, bool isDefaultValue)> activeBlocks, List<BlockFieldDescriptor> connectedBlocks, Target target)
{
var activeFields = new ActiveFields();
if (outputNode == null)
{
bool hasDotsProperties = false;
m_GraphData.ForeachHLSLProperty(h =>
{
if (h.declaration == HLSLDeclaration.HybridPerInstance)
hasDotsProperties = true;
});
var context = new TargetFieldContext(pass, activeBlocks, connectedBlocks, hasDotsProperties);
target.GetFields(ref context);
var fields = GenerationUtils.GetActiveFieldsFromConditionals(context.conditionalFields.ToArray());
foreach (FieldDescriptor field in fields)
activeFields.baseInstance.Add(field);
}
// Preview shader
else
{
activeFields.baseInstance.Add(Fields.GraphPixel);
}
return activeFields;
}
void BuildShader()
{
var activeNodeList = Pool.ListPool<AbstractMaterialNode>.Get();
bool ignoreActiveState = (m_Mode == GenerationMode.Preview); // for previews, we ignore node active state
if (m_OutputNode == null)
{
foreach (var block in m_ActiveBlocks)
{
// IsActive is equal to if any active implementation has set active blocks
// This avoids another call to SetActiveBlocks on each TargetImplementation
if (!block.isActive)
continue;
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, block, NodeUtils.IncludeSelf.Include, ignoreActiveState: ignoreActiveState);
}
}
else
{
NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, m_OutputNode, ignoreActiveState: ignoreActiveState);
}
var shaderProperties = new PropertyCollector();
var shaderKeywords = new KeywordCollector();
m_GraphData.CollectShaderProperties(shaderProperties, m_Mode);
m_GraphData.CollectShaderKeywords(shaderKeywords, m_Mode);
if (m_GraphData.GetKeywordPermutationCount() > ShaderGraphPreferences.variantLimit)
{
m_GraphData.AddValidationError(m_OutputNode.objectId, ShaderKeyword.kVariantLimitWarning, Rendering.ShaderCompilerMessageSeverity.Error);
m_ConfiguredTextures = shaderProperties.GetConfiguredTextures();
m_Builder.AppendLines(ShaderGraphImporter.k_ErrorShader);
}
foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
activeNode.CollectShaderProperties(shaderProperties, m_Mode);
// Collect excess shader properties from the TargetImplementation
foreach (var target in m_Targets)
{
// TODO: Setup is required to ensure all Targets are initialized
// TODO: Find a way to only require this once
TargetSetupContext context = new TargetSetupContext();
target.Setup(ref context);
target.CollectShaderProperties(shaderProperties, m_Mode);
}
// set the property collector to read only
// (to ensure no rogue target or pass starts adding more properties later..)
shaderProperties.SetReadOnly();
m_Builder.AppendLine(@"Shader ""{0}""", m_Name);
using (m_Builder.BlockScope())
{
GenerationUtils.GeneratePropertiesBlock(m_Builder, shaderProperties, shaderKeywords, m_Mode);
for (int i = 0; i < m_Targets.Length; i++)
{
TargetSetupContext context = new TargetSetupContext(m_assetCollection);
// Instead of setup target, we can also just do get context
m_Targets[i].Setup(ref context);
var subShaderProperties = GetSubShaderPropertiesForTarget(m_Targets[i], m_GraphData, m_Mode, m_OutputNode, m_TemporaryBlocks);
foreach (var subShader in context.subShaders)
{
GenerateSubShader(i, subShader, subShaderProperties);
}
var customEditor = context.defaultShaderGUI;
if (customEditor != null && m_Targets[i].WorksWithSRP(GraphicsSettings.currentRenderPipeline))
{
m_Builder.AppendLine("CustomEditor \"" + customEditor + "\"");
}
foreach (var rpCustomEditor in context.customEditorForRenderPipelines)
{
m_Builder.AppendLine($"CustomEditorForRenderPipeline \"{rpCustomEditor.shaderGUI}\" \"{rpCustomEditor.renderPipelineAssetType}\"");
}
}
m_Builder.AppendLine(@"FallBack ""Hidden/Shader Graph/FallbackError""");
}
m_ConfiguredTextures = shaderProperties.GetConfiguredTextures();
}
void GenerateSubShader(int targetIndex, SubShaderDescriptor descriptor, PropertyCollector subShaderProperties)
{
if (descriptor.passes == null)
return;
// Early out of preview generation if no passes are used in preview
if (m_Mode == GenerationMode.Preview && descriptor.generatesPreview == false)
return;
m_Builder.AppendLine("SubShader");
using (m_Builder.BlockScope())
{
GenerationUtils.GenerateSubShaderTags(m_Targets[targetIndex], descriptor, m_Builder);
// Get block descriptor list here (from ALL active blocks)
List<(BlockFieldDescriptor descriptor, bool isDefaultValue)> activeBlockDescriptors = m_ActiveBlocks.Select(x => (x.descriptor, x.GetInputSlots<MaterialSlot>().FirstOrDefault().IsUsingDefaultValue())).ToList();
var connectedBlockDescriptors = m_ActiveBlocks.Where(x => x.IsSlotConnected(0)).Select(x => x.descriptor).ToList();
foreach (PassCollection.Item pass in descriptor.passes)
{
var activeFields = GatherActiveFieldsFromNode(m_OutputNode, pass.descriptor, activeBlockDescriptors, connectedBlockDescriptors, m_Targets[targetIndex]);
// TODO: cleanup this preview check, needed for HD decal preview pass
if (m_Mode == GenerationMode.Preview)
activeFields.baseInstance.Add(Fields.IsPreview);
// Check masternode fields for valid passes
if (pass.TestActive(activeFields))
GenerateShaderPass(targetIndex, pass.descriptor, activeFields, activeBlockDescriptors.Select(x => x.descriptor).ToList(), subShaderProperties);
}
}
}
// this builds the list of properties for a Target / Graph combination
static PropertyCollector GetSubShaderPropertiesForTarget(Target target, GraphData graph, GenerationMode generationMode, AbstractMaterialNode outputNode, List<BlockNode> outTemporaryBlockNodes)
{
PropertyCollector subshaderProperties = new PropertyCollector();
// Collect shader properties declared by active nodes
using (var activeNodes = PooledHashSet<AbstractMaterialNode>.Get())
{
if (outputNode == null)
{
// shader graph builds active nodes starting from the set of active blocks
var currentBlocks = graph.GetNodes<BlockNode>();
var activeBlockContext = new TargetActiveBlockContext(currentBlocks.Select(x => x.descriptor).ToList(), null);
target.GetActiveBlocks(ref activeBlockContext);
foreach (var blockFieldDesc in activeBlockContext.activeBlocks)
{
bool foundBlock = false;
// attempt to get BlockNode(s) from the stack
var vertBlockNode = graph.vertexContext.blocks.FirstOrDefault(x => x.value.descriptor == blockFieldDesc).value;
if (vertBlockNode != null)
{
activeNodes.Add(vertBlockNode);
foundBlock = true;
}
var fragBlockNode = graph.fragmentContext.blocks.FirstOrDefault(x => x.value.descriptor == blockFieldDesc).value;
if (fragBlockNode != null)
{
activeNodes.Add(fragBlockNode);
foundBlock = true;
}
if (!foundBlock)
{
// block doesn't exist (user deleted it)
// create a temporary block -- don't add to graph, but use it to gather properties
var block = new BlockNode();
block.Init(blockFieldDesc);
block.owner = graph;
activeNodes.Add(block);
// We need to make a list of all of the temporary blocks added
// (This is used by the PreviewManager to generate a PreviewProperty)
outTemporaryBlockNodes.Add(block);
}
}
}
else
{
// preview and/or subgraphs build their active node set based on the single output node
activeNodes.Add(outputNode);
}
PreviewManager.PropagateNodes(activeNodes, PreviewManager.PropagationDirection.Upstream, activeNodes);
// NOTE: this is NOT a deterministic ordering
foreach (var node in activeNodes)
node.CollectShaderProperties(subshaderProperties, generationMode);
// So we sort the properties after
subshaderProperties.Sort();
}
// Collect graph properties
{
graph.CollectShaderProperties(subshaderProperties, generationMode);
}
// Collect shader properties declared by the Target
{
target.CollectShaderProperties(subshaderProperties, generationMode);
}
subshaderProperties.SetReadOnly();
return subshaderProperties;
}
void GenerateShaderPass(int targetIndex, PassDescriptor pass, ActiveFields activeFields, List<BlockFieldDescriptor> currentBlockDescriptors, PropertyCollector subShaderProperties)
{
// Early exit if pass is not used in preview
if (m_Mode == GenerationMode.Preview && !pass.useInPreview)
return;
// --------------------------------------------------
// Debug
// Get scripting symbols
BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);
bool isDebug = defines.Contains(kDebugSymbol);
// --------------------------------------------------
// Setup
// Initiailize Collectors
var propertyCollector = new PropertyCollector();
var keywordCollector = new KeywordCollector();
m_GraphData.CollectShaderKeywords(keywordCollector, m_Mode);
// Get upstream nodes from ShaderPass port mask
List<AbstractMaterialNode> vertexNodes;
List<AbstractMaterialNode> pixelNodes;
// Get Port references from ShaderPass
var pixelSlots = new List<MaterialSlot>();
var vertexSlots = new List<MaterialSlot>();
if (m_OutputNode == null)
{
// Update supported block list for current target implementation
var activeBlockContext = new TargetActiveBlockContext(currentBlockDescriptors, pass);
m_Targets[targetIndex].GetActiveBlocks(ref activeBlockContext);
void ProcessStackForPass(ContextData contextData, BlockFieldDescriptor[] passBlockMask,
List<AbstractMaterialNode> nodeList, List<MaterialSlot> slotList)
{
if (passBlockMask == null)
return;
foreach (var blockFieldDescriptor in passBlockMask)
{
// Mask blocks on active state
// TODO: Can we merge these?
if (!activeBlockContext.activeBlocks.Contains(blockFieldDescriptor))
continue;
// Attempt to get BlockNode from the stack
var block = contextData.blocks.FirstOrDefault(x => x.value.descriptor == blockFieldDescriptor).value;
// If the BlockNode doesnt exist in the stack we need to create one
// TODO: Can we do the code gen without a node instance?
if (block == null)
{
block = new BlockNode();
block.Init(blockFieldDescriptor);
block.owner = m_GraphData;
}
// Dont collect properties from temp nodes
else
{
block.CollectShaderProperties(propertyCollector, m_Mode);
}
// Add nodes and slots from supported vertex blocks
NodeUtils.DepthFirstCollectNodesFromNode(nodeList, block, NodeUtils.IncludeSelf.Include);
slotList.Add(block.FindSlot<MaterialSlot>(0));
activeFields.baseInstance.Add(block.descriptor);
}
}
// Mask blocks per pass
vertexNodes = Pool.ListPool<AbstractMaterialNode>.Get();
pixelNodes = Pool.ListPool<AbstractMaterialNode>.Get();
// Process stack for vertex and fragment
ProcessStackForPass(m_GraphData.vertexContext, pass.validVertexBlocks, vertexNodes, vertexSlots);
ProcessStackForPass(m_GraphData.fragmentContext, pass.validPixelBlocks, pixelNodes, pixelSlots);
// Collect excess shader properties from the TargetImplementation
m_Targets[targetIndex].CollectShaderProperties(propertyCollector, m_Mode);
}
else if (m_OutputNode is SubGraphOutputNode)
{
GenerationUtils.GetUpstreamNodesForShaderPass(m_OutputNode, pass, out vertexNodes, out pixelNodes);
var slot = m_OutputNode.GetInputSlots<MaterialSlot>().FirstOrDefault();
if (slot != null)
pixelSlots = new List<MaterialSlot>() { slot };
else
pixelSlots = new List<MaterialSlot>();
vertexSlots = new List<MaterialSlot>();
}
else
{
GenerationUtils.GetUpstreamNodesForShaderPass(m_OutputNode, pass, out vertexNodes, out pixelNodes);
pixelSlots = new List<MaterialSlot>()
{
new Vector4MaterialSlot(0, "Out", "Out", SlotType.Output, Vector4.zero) { owner = m_OutputNode },
};
vertexSlots = new List<MaterialSlot>();
}
// Track permutation indices for all nodes
List<int>[] vertexNodePermutations = new List<int>[vertexNodes.Count];
List<int>[] pixelNodePermutations = new List<int>[pixelNodes.Count];
// Get active fields from upstream Node requirements
ShaderGraphRequirementsPerKeyword graphRequirements;
GenerationUtils.GetActiveFieldsAndPermutationsForNodes(pass, keywordCollector, vertexNodes, pixelNodes,
vertexNodePermutations, pixelNodePermutations, activeFields, out graphRequirements);
// GET CUSTOM ACTIVE FIELDS HERE!
// Get active fields from ShaderPass
GenerationUtils.AddRequiredFields(pass.requiredFields, activeFields.baseInstance);
// Function Registry
var functionBuilder = new ShaderStringBuilder();
var functionRegistry = new FunctionRegistry(functionBuilder);
// Hash table of named $splice(name) commands
// Key: splice token
// Value: string to splice
Dictionary<string, string> spliceCommands = new Dictionary<string, string>();
// --------------------------------------------------
// Dependencies
// Propagate active field requirements using dependencies
// Must be executed before types are built
foreach (var instance in activeFields.all.instances)
{
GenerationUtils.ApplyFieldDependencies(instance, pass.fieldDependencies);
}
// --------------------------------------------------
// Pass Setup
// Name
if (!string.IsNullOrEmpty(pass.displayName))
{
spliceCommands.Add("PassName", $"Name \"{pass.displayName}\"");
}
else
{
spliceCommands.Add("PassName", "// Name: <None>");
}
// Tags
if (!string.IsNullOrEmpty(pass.lightMode))
{
spliceCommands.Add("LightMode", $"\"LightMode\" = \"{pass.lightMode}\"");
}
else
{
spliceCommands.Add("LightMode", "// LightMode: <None>");
}
// --------------------------------------------------
// Pass Code
// Render State
using (var renderStateBuilder = new ShaderStringBuilder())
{
// Render states need to be separated by RenderState.Type
// The first passing ConditionalRenderState of each type is inserted
foreach (RenderStateType type in Enum.GetValues(typeof(RenderStateType)))
{
var renderStates = pass.renderStates?.Where(x => x.descriptor.type == type);
if (renderStates != null)
{
foreach (RenderStateCollection.Item renderState in renderStates)
{
if (renderState.TestActive(activeFields))
{
renderStateBuilder.AppendLine(renderState.value);
// Cull is the only render state type that causes a compilation error
// when there are multiple Cull directive with different values in a pass.
if (type == RenderStateType.Cull)
break;
}
}
}
}
string command = GenerationUtils.GetSpliceCommand(renderStateBuilder.ToCodeBlock(), "RenderState");
spliceCommands.Add("RenderState", command);
}
// Pragmas
using (var passPragmaBuilder = new ShaderStringBuilder())
{
if (pass.pragmas != null)
{
foreach (PragmaCollection.Item pragma in pass.pragmas)
{
if (pragma.TestActive(activeFields))
passPragmaBuilder.AppendLine(pragma.value);
}
}
string command = GenerationUtils.GetSpliceCommand(passPragmaBuilder.ToCodeBlock(), "PassPragmas");
spliceCommands.Add("PassPragmas", command);
}
// Includes
using (var preGraphIncludeBuilder = new ShaderStringBuilder())
{
if (pass.includes != null)
{
foreach (IncludeCollection.Item include in pass.includes.Where(x => x.descriptor.location == IncludeLocation.Pregraph))
{
if (include.TestActive(activeFields))
preGraphIncludeBuilder.AppendLine(include.value);
}
}
string command = GenerationUtils.GetSpliceCommand(preGraphIncludeBuilder.ToCodeBlock(), "PreGraphIncludes");
spliceCommands.Add("PreGraphIncludes", command);
}
using (var postGraphIncludeBuilder = new ShaderStringBuilder())
{
if (pass.includes != null)
{
foreach (IncludeCollection.Item include in pass.includes.Where(x => x.descriptor.location == IncludeLocation.Postgraph))
{
if (include.TestActive(activeFields))
postGraphIncludeBuilder.AppendLine(include.value);
}
}
string command = GenerationUtils.GetSpliceCommand(postGraphIncludeBuilder.ToCodeBlock(), "PostGraphIncludes");
spliceCommands.Add("PostGraphIncludes", command);
}
// Keywords
using (var passKeywordBuilder = new ShaderStringBuilder())
{
if (pass.keywords != null)
{
foreach (KeywordCollection.Item keyword in pass.keywords)
{
if (keyword.TestActive(activeFields))
passKeywordBuilder.AppendLine(keyword.value);
}
}
string command = GenerationUtils.GetSpliceCommand(passKeywordBuilder.ToCodeBlock(), "PassKeywords");
spliceCommands.Add("PassKeywords", command);
}
// -----------------------------
// Generated structs and Packing code
var interpolatorBuilder = new ShaderStringBuilder();
var passStructs = new List<StructDescriptor>();
if (pass.structs != null)
{
passStructs.AddRange(pass.structs.Select(x => x.descriptor));
foreach (StructCollection.Item shaderStruct in pass.structs)
{
if (shaderStruct.descriptor.packFields == false)
continue; //skip structs that do not need interpolator packs
List<int> packedCounts = new List<int>();
var packStruct = new StructDescriptor();
//generate packed functions
if (activeFields.permutationCount > 0)
{
var generatedPackedTypes = new Dictionary<string, (ShaderStringBuilder, List<int>)>();
foreach (var instance in activeFields.allPermutations.instances)
{
var instanceGenerator = new ShaderStringBuilder();
GenerationUtils.GenerateInterpolatorFunctions(shaderStruct.descriptor, instance, out instanceGenerator);
var key = instanceGenerator.ToCodeBlock();
if (generatedPackedTypes.TryGetValue(key, out var value))
value.Item2.Add(instance.permutationIndex);
else
generatedPackedTypes.Add(key, (instanceGenerator, new List<int> { instance.permutationIndex }));
}
var isFirst = true;
foreach (var generated in generatedPackedTypes)
{
if (isFirst)
{
isFirst = false;
interpolatorBuilder.AppendLine(KeywordUtil.GetKeywordPermutationSetConditional(generated.Value.Item2));
}
else
interpolatorBuilder.AppendLine(KeywordUtil.GetKeywordPermutationSetConditional(generated.Value.Item2).Replace("#if", "#elif"));
//interpolatorBuilder.Concat(generated.Value.Item1);
interpolatorBuilder.AppendLines(generated.Value.Item1.ToString());
}
if (generatedPackedTypes.Count > 0)
interpolatorBuilder.AppendLine("#endif");
}
else
{
GenerationUtils.GenerateInterpolatorFunctions(shaderStruct.descriptor, activeFields.baseInstance, out interpolatorBuilder);
}
//using interp index from functions, generate packed struct descriptor
GenerationUtils.GeneratePackedStruct(shaderStruct.descriptor, activeFields, out packStruct);
passStructs.Add(packStruct);
}
}
if (interpolatorBuilder.length != 0) //hard code interpolators to float, TODO: proper handle precision
interpolatorBuilder.ReplaceInCurrentMapping(PrecisionUtil.Token, ConcretePrecision.Single.ToShaderString());
else
interpolatorBuilder.AppendLine("//Interpolator Packs: <None>");
spliceCommands.Add("InterpolatorPack", interpolatorBuilder.ToCodeBlock());
// Generated String Builders for all struct types
var passStructBuilder = new ShaderStringBuilder();
if (passStructs != null)
{
var structBuilder = new ShaderStringBuilder();
foreach (StructDescriptor shaderStruct in passStructs)
{
GenerationUtils.GenerateShaderStruct(shaderStruct, activeFields, out structBuilder);
structBuilder.ReplaceInCurrentMapping(PrecisionUtil.Token, ConcretePrecision.Single.ToShaderString()); //hard code structs to float, TODO: proper handle precision
passStructBuilder.Concat(structBuilder);
}
}
if (passStructBuilder.length == 0)
passStructBuilder.AppendLine("//Pass Structs: <None>");
spliceCommands.Add("PassStructs", passStructBuilder.ToCodeBlock());
// --------------------------------------------------
// Graph Vertex
var vertexBuilder = new ShaderStringBuilder();
// If vertex modification enabled
if (activeFields.baseInstance.Contains(Fields.GraphVertex) && vertexSlots != null)
{
// Setup
string vertexGraphInputName = "VertexDescriptionInputs";
string vertexGraphOutputName = "VertexDescription";
string vertexGraphFunctionName = "VertexDescriptionFunction";
var vertexGraphFunctionBuilder = new ShaderStringBuilder();
var vertexGraphOutputBuilder = new ShaderStringBuilder();
// Build vertex graph outputs
// Add struct fields to active fields
GenerationUtils.GenerateVertexDescriptionStruct(vertexGraphOutputBuilder, vertexSlots, vertexGraphOutputName, activeFields.baseInstance);
// Build vertex graph functions from ShaderPass vertex port mask
GenerationUtils.GenerateVertexDescriptionFunction(
m_GraphData,
vertexGraphFunctionBuilder,
functionRegistry,
propertyCollector,
keywordCollector,
m_Mode,
m_OutputNode,
vertexNodes,
vertexNodePermutations,
vertexSlots,
vertexGraphInputName,
vertexGraphFunctionName,
vertexGraphOutputName);
// Generate final shader strings
vertexBuilder.AppendLines(vertexGraphOutputBuilder.ToString());
vertexBuilder.AppendNewLine();
vertexBuilder.AppendLines(vertexGraphFunctionBuilder.ToString());
}
// Add to splice commands
if (vertexBuilder.length == 0)
vertexBuilder.AppendLine("// GraphVertex: <None>");
spliceCommands.Add("GraphVertex", vertexBuilder.ToCodeBlock());
// --------------------------------------------------
// Graph Pixel
// Setup
string pixelGraphInputName = "SurfaceDescriptionInputs";
string pixelGraphOutputName = "SurfaceDescription";
string pixelGraphFunctionName = "SurfaceDescriptionFunction";
var pixelGraphOutputBuilder = new ShaderStringBuilder();
var pixelGraphFunctionBuilder = new ShaderStringBuilder();
// Build pixel graph outputs
// Add struct fields to active fields
GenerationUtils.GenerateSurfaceDescriptionStruct(pixelGraphOutputBuilder, pixelSlots, pixelGraphOutputName, activeFields.baseInstance, m_OutputNode is SubGraphOutputNode, pass.virtualTextureFeedback);
// Build pixel graph functions from ShaderPass pixel port mask
GenerationUtils.GenerateSurfaceDescriptionFunction(
pixelNodes,
pixelNodePermutations,
m_OutputNode,
m_GraphData,
pixelGraphFunctionBuilder,
functionRegistry,
propertyCollector,
keywordCollector,
m_Mode,
pixelGraphFunctionName,
pixelGraphOutputName,
null,
pixelSlots,
pixelGraphInputName,
pass.virtualTextureFeedback);
using (var pixelBuilder = new ShaderStringBuilder())
{
// Generate final shader strings
pixelBuilder.AppendLines(pixelGraphOutputBuilder.ToString());
pixelBuilder.AppendNewLine();
pixelBuilder.AppendLines(pixelGraphFunctionBuilder.ToString());
// Add to splice commands
if (pixelBuilder.length == 0)
pixelBuilder.AppendLine("// GraphPixel: <None>");
spliceCommands.Add("GraphPixel", pixelBuilder.ToCodeBlock());
}
// --------------------------------------------------
// Graph Functions
if (functionBuilder.length == 0)
functionBuilder.AppendLine("// GraphFunctions: <None>");
spliceCommands.Add("GraphFunctions", functionBuilder.ToCodeBlock());
// --------------------------------------------------
// Graph Keywords
using (var keywordBuilder = new ShaderStringBuilder())
{
keywordCollector.GetKeywordsDeclaration(keywordBuilder, m_Mode);
if (keywordBuilder.length == 0)
keywordBuilder.AppendLine("// GraphKeywords: <None>");
spliceCommands.Add("GraphKeywords", keywordBuilder.ToCodeBlock());
}
// --------------------------------------------------
// Graph Properties
using (var propertyBuilder = new ShaderStringBuilder())
{
subShaderProperties.GetPropertiesDeclaration(propertyBuilder, m_Mode, m_GraphData.concretePrecision);
if (propertyBuilder.length == 0)
propertyBuilder.AppendLine("// GraphProperties: <None>");
spliceCommands.Add("GraphProperties", propertyBuilder.ToCodeBlock());
}
// --------------------------------------------------
// Dots Instanced Graph Properties
bool hasDotsProperties = subShaderProperties.HasDotsProperties();
using (var dotsInstancedPropertyBuilder = new ShaderStringBuilder())
{
if (hasDotsProperties)
dotsInstancedPropertyBuilder.AppendLines(subShaderProperties.GetDotsInstancingPropertiesDeclaration(m_Mode));
else
dotsInstancedPropertyBuilder.AppendLine("// HybridV1InjectedBuiltinProperties: <None>");
spliceCommands.Add("HybridV1InjectedBuiltinProperties", dotsInstancedPropertyBuilder.ToCodeBlock());
}
// --------------------------------------------------
// Dots Instancing Options
using (var dotsInstancingOptionsBuilder = new ShaderStringBuilder())
{
// Hybrid Renderer V1 requires some magic defines to work, which we enable
// if the shader graph has a nonzero amount of DOTS instanced properties.
// This can be removed once Hybrid V1 is removed.
#if !ENABLE_HYBRID_RENDERER_V2
if (hasDotsProperties)
{
dotsInstancingOptionsBuilder.AppendLine("#if SHADER_TARGET >= 35 && (defined(SHADER_API_D3D11) || defined(SHADER_API_GLES3) || defined(SHADER_API_GLCORE) || defined(SHADER_API_XBOXONE) || defined(SHADER_API_GAMECORE) || defined(SHADER_API_PSSL) || defined(SHADER_API_VULKAN) || defined(SHADER_API_METAL))");
dotsInstancingOptionsBuilder.AppendLine(" #define UNITY_SUPPORT_INSTANCING");
dotsInstancingOptionsBuilder.AppendLine("#endif");
dotsInstancingOptionsBuilder.AppendLine("#if defined(UNITY_SUPPORT_INSTANCING) && defined(INSTANCING_ON)");
dotsInstancingOptionsBuilder.AppendLine(" #define UNITY_HYBRID_V1_INSTANCING_ENABLED");
dotsInstancingOptionsBuilder.AppendLine("#endif");
}
#endif
if (dotsInstancingOptionsBuilder.length == 0)
dotsInstancingOptionsBuilder.AppendLine("// DotsInstancingOptions: <None>");
spliceCommands.Add("DotsInstancingOptions", dotsInstancingOptionsBuilder.ToCodeBlock());
}
// --------------------------------------------------
// Graph Defines
using (var graphDefines = new ShaderStringBuilder())
{
graphDefines.AppendLine("#define SHADERPASS {0}", pass.referenceName);
if (pass.defines != null)
{
foreach (DefineCollection.Item define in pass.defines)
{
if (define.TestActive(activeFields))
graphDefines.AppendLine(define.value);
}
}
if (graphRequirements.permutationCount > 0)
{
List<int> activePermutationIndices;
// Depth Texture
activePermutationIndices = graphRequirements.allPermutations.instances
.Where(p => p.requirements.requiresDepthTexture)
.Select(p => p.permutationIndex)
.ToList();
if (activePermutationIndices.Count > 0)
{
graphDefines.AppendLine(KeywordUtil.GetKeywordPermutationSetConditional(activePermutationIndices));
graphDefines.AppendLine("#define REQUIRE_DEPTH_TEXTURE");
graphDefines.AppendLine("#endif");
}
// Opaque Texture
activePermutationIndices = graphRequirements.allPermutations.instances
.Where(p => p.requirements.requiresCameraOpaqueTexture)
.Select(p => p.permutationIndex)
.ToList();
if (activePermutationIndices.Count > 0)
{
graphDefines.AppendLine(KeywordUtil.GetKeywordPermutationSetConditional(activePermutationIndices));
graphDefines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE");
graphDefines.AppendLine("#endif");
}
}
else
{
// Depth Texture
if (graphRequirements.baseInstance.requirements.requiresDepthTexture)
graphDefines.AppendLine("#define REQUIRE_DEPTH_TEXTURE");
// Opaque Texture
if (graphRequirements.baseInstance.requirements.requiresCameraOpaqueTexture)
graphDefines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE");
}
// Add to splice commands
spliceCommands.Add("GraphDefines", graphDefines.ToCodeBlock());
}
// --------------------------------------------------
// Debug
// Debug output all active fields
using (var debugBuilder = new ShaderStringBuilder())
{
if (isDebug)
{
// Active fields
debugBuilder.AppendLine("// ACTIVE FIELDS:");
foreach (FieldDescriptor field in activeFields.baseInstance.fields)
{
debugBuilder.AppendLine($"//{field.tag}.{field.name}");
}
}
if (debugBuilder.length == 0)
debugBuilder.AppendLine("// <None>");
// Add to splice commands
spliceCommands.Add("Debug", debugBuilder.ToCodeBlock());
}
// --------------------------------------------------
// Finalize
// Pass Template
string passTemplatePath = pass.passTemplatePath;
// Shared Templates
string[] sharedTemplateDirectories = pass.sharedTemplateDirectories;
if (!File.Exists(passTemplatePath))
return;
// Process Template
var templatePreprocessor = new ShaderSpliceUtil.TemplatePreprocessor(activeFields, spliceCommands,
isDebug, sharedTemplateDirectories, m_assetCollection);
templatePreprocessor.ProcessTemplateFile(passTemplatePath);
m_Builder.Concat(templatePreprocessor.GetShaderCode());
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
// Required for Unity to handle nested array serialization
[Serializable]
struct IntArray
{
public int[] array;
public int this[int i]
{
get => array[i];
set => array[i] = value;
}
public static implicit operator IntArray(int[] array)
{
return new IntArray { array = array };
}
public static implicit operator int[](IntArray array)
{
return array.array;
}
}
[Serializable]
class GraphCompilationResult
{
public string[] codeSnippets;
public int[] sharedCodeIndices;
public IntArray[] outputCodeIndices;
public string GenerateCode(int[] outputIndices)
{
var codeIndexSet = new HashSet<int>();
foreach (var codeIndex in sharedCodeIndices)
{
codeIndexSet.Add(codeIndex);
}
foreach (var outputIndex in outputIndices)
{
foreach (var codeIndex in outputCodeIndices[outputIndex].array)
{
codeIndexSet.Add(codeIndex);
}
}
var codeIndices = new int[codeIndexSet.Count];
codeIndexSet.CopyTo(codeIndices);
Array.Sort(codeIndices);
var charCount = 0;
foreach (var codeIndex in codeIndices)
{
charCount += codeSnippets[codeIndex].Length;
}
var sb = new StringBuilder();
sb.EnsureCapacity(charCount);
foreach (var codeIndex in codeIndices)
{
sb.Append(codeSnippets[codeIndex]);
}
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
namespace UnityEditor.ShaderGraph
{
struct MatrixNames
{
public const string Model = "UNITY_MATRIX_M";
public const string ModelInverse = "UNITY_MATRIX_I_M";
public const string View = "UNITY_MATRIX_V";
public const string ViewInverse = "UNITY_MATRIX_I_V";
public const string Projection = "UNITY_MATRIX_P";
public const string ProjectionInverse = "UNITY_MATRIX_I_P";
public const string ViewProjection = "UNITY_MATRIX_VP";
public const string ViewProjectionInverse = "UNITY_MATRIX_I_VP";
}
}

View File

@@ -0,0 +1,399 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using TextureDimension = UnityEngine.Rendering.TextureDimension;
namespace UnityEditor.ShaderGraph
{
class PropertyCollector
{
public struct TextureInfo
{
public string name;
public int textureId;
public TextureDimension dimension;
public bool modifiable;
}
bool m_ReadOnly;
List<HLSLProperty> m_HLSLProperties = null;
// reference name ==> property index in list
Dictionary<string, int> m_ReferenceNames = new Dictionary<string, int>();
// list of properties (kept in a list to maintain deterministic declaration order)
List<AbstractShaderProperty> m_Properties = new List<AbstractShaderProperty>();
public int propertyCount => m_Properties.Count;
public IEnumerable<AbstractShaderProperty> properties => m_Properties;
public AbstractShaderProperty GetProperty(int index) { return m_Properties[index]; }
public void Sort()
{
if (m_ReadOnly)
{
Debug.LogError("Cannot sort the properties when the PropertyCollector is already marked ReadOnly");
return;
}
m_Properties.Sort((a, b) => String.CompareOrdinal(a.referenceName, b.referenceName));
// reference name indices are now messed up, rebuild them
m_ReferenceNames.Clear();
for (int i = 0; i < m_Properties.Count; i++)
m_ReferenceNames.Add(m_Properties[i].referenceName, i);
}
public void SetReadOnly()
{
m_ReadOnly = true;
}
private static bool EquivalentHLSLProperties(AbstractShaderProperty a, AbstractShaderProperty b)
{
bool equivalent = true;
var bHLSLProps = new List<HLSLProperty>();
b.ForeachHLSLProperty(bh => bHLSLProps.Add(bh));
a.ForeachHLSLProperty(ah =>
{
var i = bHLSLProps.FindIndex(bh => bh.name == ah.name);
if (i < 0)
equivalent = false;
else
{
var bh = bHLSLProps[i];
if ((ah.name != bh.name) ||
(ah.type != bh.type) ||
(ah.precision != bh.precision) ||
(ah.declaration != bh.declaration) ||
((ah.customDeclaration == null) != (bh.customDeclaration == null)))
{
equivalent = false;
}
else if (ah.customDeclaration != null)
{
var ssba = new ShaderStringBuilder();
var ssbb = new ShaderStringBuilder();
ah.customDeclaration(ssba);
bh.customDeclaration(ssbb);
if (ssba.ToCodeBlock() != ssbb.ToCodeBlock())
equivalent = false;
}
bHLSLProps.RemoveAt(i);
}
});
return equivalent && (bHLSLProps.Count == 0);
}
public void AddShaderProperty(AbstractShaderProperty prop)
{
if (m_ReadOnly)
{
Debug.LogError("ERROR attempting to add property to readonly collection");
return;
}
int propIndex = -1;
if (m_ReferenceNames.TryGetValue(prop.referenceName, out propIndex))
{
// existing referenceName
var existingProp = m_Properties[propIndex];
if (existingProp != prop)
{
// duplicate reference name, but different property instances
if (existingProp.GetType() != prop.GetType())
{
Debug.LogError("Two properties with the same reference name (" + prop.referenceName + ") using different types");
}
else
{
if (!EquivalentHLSLProperties(existingProp, prop))
Debug.LogError("Two properties with the same reference name (" + prop.referenceName + ") produce different HLSL properties");
}
}
}
else
{
// new referenceName, new property
propIndex = m_Properties.Count;
m_Properties.Add(prop);
m_ReferenceNames.Add(prop.referenceName, propIndex);
}
}
private List<HLSLProperty> BuildHLSLPropertyList()
{
SetReadOnly();
if (m_HLSLProperties == null)
{
m_HLSLProperties = new List<HLSLProperty>();
foreach (var p in m_Properties)
p.ForeachHLSLProperty(h => m_HLSLProperties.Add(h));
}
return m_HLSLProperties;
}
public void GetPropertiesDeclaration(ShaderStringBuilder builder, GenerationMode mode, ConcretePrecision inheritedPrecision)
{
foreach (var prop in properties)
{
prop.ValidateConcretePrecision(inheritedPrecision);
}
// build a list of all HLSL properties
var hlslProps = BuildHLSLPropertyList();
if (mode == GenerationMode.Preview)
{
builder.AppendLine("CBUFFER_START(UnityPerMaterial)");
// all non-gpu instanced properties (even non-batchable ones!)
// this is because for preview we convert all properties to UnityPerMaterial properties
// as we will be submitting the default preview values via the Material.. :)
foreach (var h in hlslProps)
{
if ((h.declaration == HLSLDeclaration.UnityPerMaterial) ||
(h.declaration == HLSLDeclaration.Global))
{
h.AppendTo(builder);
}
}
// gpu-instanced properties
var gpuInstancedProps = hlslProps.Where(h => h.declaration == HLSLDeclaration.HybridPerInstance);
if (gpuInstancedProps.Any())
{
builder.AppendLine("#ifdef UNITY_HYBRID_V1_INSTANCING_ENABLED");
foreach (var h in gpuInstancedProps)
{
h.AppendTo(builder, name => name + "_dummy");
}
builder.AppendLine("#else // V2");
foreach (var h in gpuInstancedProps)
{
h.AppendTo(builder);
}
builder.AppendLine("#endif");
}
builder.AppendLine("CBUFFER_END");
return;
}
// Hybrid V1 generates a special version of UnityPerMaterial, which has dummy constants for
// instanced properties, and regular constants for other properties.
// Hybrid V2 generates a perfectly normal UnityPerMaterial, but needs to append
// a UNITY_DOTS_INSTANCING_START/END block after it that contains the instanced properties.
#if !ENABLE_HYBRID_RENDERER_V2
builder.AppendLine("CBUFFER_START(UnityPerMaterial)");
// non-GPU-instanced batchable properties go first in the UnityPerMaterial cbuffer
foreach (var h in hlslProps)
if (h.declaration == HLSLDeclaration.UnityPerMaterial)
h.AppendTo(builder);
// followed by GPU-instanced batchable properties
var gpuInstancedProperties = hlslProps.Where(h => h.declaration == HLSLDeclaration.HybridPerInstance);
if (gpuInstancedProperties.Any())
{
builder.AppendLine("#ifdef UNITY_HYBRID_V1_INSTANCING_ENABLED");
foreach (var hlslProp in gpuInstancedProperties)
hlslProp.AppendTo(builder, name => name + "_dummy");
builder.AppendLine("#else");
foreach (var hlslProp in gpuInstancedProperties)
hlslProp.AppendTo(builder);
builder.AppendLine("#endif");
}
builder.AppendLine("CBUFFER_END");
#else
// TODO: need to test this path with HYBRID_RENDERER_V2 ...
builder.AppendLine("CBUFFER_START(UnityPerMaterial)");
int instancedCount = 0;
foreach (var h in hlslProps)
{
if (h.declaration == HLSLDeclaration.UnityPerMaterial)
h.AppendTo(builder);
else if (h.declaration == HLSLDeclaration.HybridPerInstance)
instancedCount++;
}
if (instancedCount > 0)
{
builder.AppendLine("// Hybrid instanced properties");
foreach (var h in hlslProps.Where(h => h.declaration == HLSLDeclaration.HybridPerInstance))
h.AppendTo(builder);
}
builder.AppendLine("CBUFFER_END");
if (instancedCount > 0)
{
builder.AppendLine("#if defined(UNITY_DOTS_INSTANCING_ENABLED)");
builder.AppendLine("// DOTS instancing definitions");
builder.AppendLine("UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)");
foreach (var h in hlslProps.Where(h => h.declaration == HLSLDeclaration.HybridPerInstance))
{
var n = h.name;
string type = h.GetValueTypeString();
builder.AppendLine($" UNITY_DOTS_INSTANCED_PROP({type}, {n})");
}
builder.AppendLine("UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)");
builder.AppendLine("// DOTS instancing usage macros");
foreach (var h in hlslProps.Where(h => h.declaration == HLSLDeclaration.HybridPerInstance))
{
var n = h.name;
string type = h.GetValueTypeString();
builder.AppendLine($"#define {n} UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO({type}, Metadata_{n})");
}
builder.AppendLine("#endif");
}
#endif
builder.AppendNewLine();
builder.AppendLine("// Object and Global properties");
foreach (var h in hlslProps)
if (h.declaration == HLSLDeclaration.Global)
h.AppendTo(builder);
}
public bool HasDotsProperties()
{
var hlslProps = BuildHLSLPropertyList();
bool hasDotsProperties = false;
foreach (var h in hlslProps)
{
if (h.declaration == HLSLDeclaration.HybridPerInstance)
hasDotsProperties = true;
}
return hasDotsProperties;
}
public string GetDotsInstancingPropertiesDeclaration(GenerationMode mode)
{
// Hybrid V1 needs to declare a special macro to that is injected into
// builtin instancing variables.
// Hybrid V2 does not need it.
#if !ENABLE_HYBRID_RENDERER_V2
var builder = new ShaderStringBuilder();
var batchAll = (mode == GenerationMode.Preview);
// build a list of all HLSL properties
var hybridHLSLProps = BuildHLSLPropertyList().Where(h => h.declaration == HLSLDeclaration.HybridPerInstance);
if (hybridHLSLProps.Any())
{
builder.AppendLine("#if defined(UNITY_HYBRID_V1_INSTANCING_ENABLED)");
builder.AppendLine("#define HYBRID_V1_CUSTOM_ADDITIONAL_MATERIAL_VARS \\");
int count = 0;
foreach (var prop in hybridHLSLProps)
{
// Combine multiple UNITY_DEFINE_INSTANCED_PROP lines with \ so the generated
// macro expands into multiple definitions if there are more than one.
if (count > 0)
{
builder.Append("\\");
builder.AppendNewLine();
}
builder.Append("UNITY_DEFINE_INSTANCED_PROP(");
builder.Append(prop.GetValueTypeString());
builder.Append(", ");
builder.Append(prop.name);
builder.Append("_Array)");
count++;
}
builder.AppendNewLine();
foreach (var prop in hybridHLSLProps)
{
string varName = $"{prop.name}_Array";
builder.AppendLine("#define {0} UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, {1})", prop.name, varName);
}
}
builder.AppendLine("#endif");
return builder.ToString();
#else
return "";
#endif
}
public List<TextureInfo> GetConfiguredTextures()
{
var result = new List<TextureInfo>();
// TODO: this should be interface based instead of looking for hard coded types
foreach (var prop in properties.OfType<Texture2DShaderProperty>())
{
if (prop.referenceName != null)
{
var textureInfo = new TextureInfo
{
name = prop.referenceName,
textureId = prop.value.texture != null ? prop.value.texture.GetInstanceID() : 0,
dimension = TextureDimension.Tex2D,
modifiable = prop.modifiable
};
result.Add(textureInfo);
}
}
foreach (var prop in properties.OfType<Texture2DArrayShaderProperty>())
{
if (prop.referenceName != null)
{
var textureInfo = new TextureInfo
{
name = prop.referenceName,
textureId = prop.value.textureArray != null ? prop.value.textureArray.GetInstanceID() : 0,
dimension = TextureDimension.Tex2DArray,
modifiable = prop.modifiable
};
result.Add(textureInfo);
}
}
foreach (var prop in properties.OfType<Texture3DShaderProperty>())
{
if (prop.referenceName != null)
{
var textureInfo = new TextureInfo
{
name = prop.referenceName,
textureId = prop.value.texture != null ? prop.value.texture.GetInstanceID() : 0,
dimension = TextureDimension.Tex3D,
modifiable = prop.modifiable
};
result.Add(textureInfo);
}
}
foreach (var prop in properties.OfType<CubemapShaderProperty>())
{
if (prop.referenceName != null)
{
var textureInfo = new TextureInfo
{
name = prop.referenceName,
textureId = prop.value.cubemap != null ? prop.value.cubemap.GetInstanceID() : 0,
dimension = TextureDimension.Cube,
modifiable = prop.modifiable
};
result.Add(textureInfo);
}
}
foreach (var prop in properties.OfType<VirtualTextureShaderProperty>().Where(p => p.referenceName != null))
{
prop.AddTextureInfo(result);
}
return result;
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
static class ShaderGeneratorNames
{
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 FaceSign = "FaceSign";
public const string TimeParameters = "TimeParameters";
public const string BoneWeights = "BoneWeights";
public const string BoneIndices = "BoneIndices";
public const string VertexID = "VertexID";
public static string GetUVName(this UVChannel channel)
{
return UV[(int)channel];
}
}
}

View File

@@ -0,0 +1,474 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
static class ShaderSpliceUtil
{
private static char[] channelNames =
{ 'x', 'y', 'z', 'w' };
public static string GetChannelSwizzle(int firstChannel, int channelCount)
{
System.Text.StringBuilder result = new System.Text.StringBuilder();
int lastChannel = System.Math.Min(firstChannel + channelCount - 1, 4);
for (int index = firstChannel; index <= lastChannel; index++)
{
result.Append(channelNames[index]);
}
return result.ToString();
}
// returns the offset of the first non-whitespace character, in the range [start, end] inclusive ... will return end if none found
private static int SkipWhitespace(string str, int start, int end)
{
int index = start;
while (index < end)
{
char c = str[index];
if (!Char.IsWhiteSpace(c))
{
break;
}
index++;
}
return index;
}
public class TemplatePreprocessor
{
// inputs
ActiveFields activeFields;
Dictionary<string, string> namedFragments;
string[] templatePaths;
bool isDebug;
// intermediates
HashSet<string> includedFiles;
// outputs
ShaderStringBuilder result;
AssetCollection assetCollection;
public TemplatePreprocessor(ActiveFields activeFields, Dictionary<string, string> namedFragments, bool isDebug, string[] templatePaths, AssetCollection assetCollection, ShaderStringBuilder outShaderCodeResult = null)
{
this.activeFields = activeFields;
this.namedFragments = namedFragments;
this.isDebug = isDebug;
this.templatePaths = templatePaths;
this.assetCollection = assetCollection;
this.result = outShaderCodeResult ?? new ShaderStringBuilder();
includedFiles = new HashSet<string>();
}
public ShaderStringBuilder GetShaderCode()
{
return result;
}
public void ProcessTemplateFile(string filePath)
{
if (File.Exists(filePath) &&
!includedFiles.Contains(filePath))
{
includedFiles.Add(filePath);
if (assetCollection != null)
{
GUID guid = AssetDatabase.GUIDFromAssetPath(filePath);
if (!guid.Empty())
assetCollection.AddAssetDependency(guid, AssetCollection.Flags.SourceDependency);
}
string[] templateLines = File.ReadAllLines(filePath);
foreach (string line in templateLines)
{
ProcessTemplateLine(line, 0, line.Length);
}
}
}
private struct Token
{
public string s;
public int start;
public int end;
public Token(string s, int start, int end)
{
this.s = s;
this.start = start;
this.end = end;
}
public static Token Invalid()
{
return new Token(null, 0, 0);
}
public bool IsValid()
{
return (s != null);
}
public bool Is(string other)
{
int len = end - start;
return (other.Length == len) && (0 == string.Compare(s, start, other, 0, len));
}
public string GetString()
{
int len = end - start;
if (len > 0)
{
return s.Substring(start, end - start);
}
return null;
}
}
public void ProcessTemplateLine(string line, int start, int end)
{
bool appendEndln = true;
int cur = start;
while (cur < end)
{
// find an escape code '$'
int dollar = line.IndexOf('$', cur, end - cur);
if (dollar < 0)
{
// no escape code found in the remaining code -- just append the rest verbatim
AppendSubstring(line, cur, true, end, false);
break;
}
else
{
// found $ escape sequence
Token command = ParseIdentifier(line, dollar + 1, end);
if (!command.IsValid())
{
Error("ERROR: $ must be followed by a command string (if, splice, or include)", line, dollar + 1);
break;
}
else
{
if (command.Is("include"))
{
ProcessIncludeCommand(command, end);
appendEndln = false;
break; // include command always ignores the rest of the line, error or not
}
else if (command.Is("splice"))
{
if (!ProcessSpliceCommand(command, end, ref cur))
{
// error, skip the rest of the line
break;
}
}
else
{
// let's see if it is a predicate
Token predicate = ParseUntil(line, dollar + 1, end, ':');
if (!predicate.IsValid())
{
Error("ERROR: unrecognized command: " + command.GetString(), line, command.start);
break;
}
else
{
if (!ProcessPredicate(predicate, end, ref cur, ref appendEndln))
{
break; // skip the rest of the line
}
}
}
}
}
}
if (appendEndln)
{
result.AppendNewLine();
}
}
private void ProcessIncludeCommand(Token includeCommand, int lineEnd)
{
if (Expect(includeCommand.s, includeCommand.end, '('))
{
Token param = ParseString(includeCommand.s, includeCommand.end + 1, lineEnd);
if (!param.IsValid())
{
Error("ERROR: $include expected a string file path parameter", includeCommand.s, includeCommand.end + 1);
}
else
{
bool found = false;
string includeLocation = null;
// Use reverse order in the array, higher number element have higher priority in case $include exist in several directories
for (int i = templatePaths.Length - 1; i >= 0; i--)
{
string templatePath = templatePaths[i];
includeLocation = Path.Combine(templatePath, param.GetString());
if (File.Exists(includeLocation))
{
found = true;
break;
}
}
if (!found)
{
string errorStr = "ERROR: $include cannot find file : " + param.GetString() + ". Looked into:\n";
foreach (string templatePath in templatePaths)
{
errorStr += "// " + templatePath + "\n";
}
Error(errorStr, includeCommand.s, param.start);
}
else
{
int endIndex = result.length;
using (var temp = new ShaderStringBuilder())
{
// Wrap in debug mode
if (isDebug)
{
result.AppendLine("//-------------------------------------------------------------------------------------");
result.AppendLine("// TEMPLATE INCLUDE : " + param.GetString());
result.AppendLine("//-------------------------------------------------------------------------------------");
result.AppendNewLine();
}
// Recursively process templates
ProcessTemplateFile(includeLocation);
// Wrap in debug mode
if (isDebug)
{
result.AppendNewLine();
result.AppendLine("//-------------------------------------------------------------------------------------");
result.AppendLine("// END TEMPLATE INCLUDE : " + param.GetString());
result.AppendLine("//-------------------------------------------------------------------------------------");
}
result.AppendNewLine();
// Required to enforce indentation rules
// Append lines from this include into temporary StringBuilder
// Reduce result length to remove this include
temp.AppendLines(result.ToString(endIndex, result.length - endIndex));
result.length = endIndex;
result.AppendLines(temp.ToCodeBlock());
}
}
}
}
}
private bool ProcessSpliceCommand(Token spliceCommand, int lineEnd, ref int cur)
{
if (!Expect(spliceCommand.s, spliceCommand.end, '('))
{
return false;
}
else
{
Token param = ParseUntil(spliceCommand.s, spliceCommand.end + 1, lineEnd, ')');
if (!param.IsValid())
{
Error("ERROR: splice command is missing a ')'", spliceCommand.s, spliceCommand.start);
return false;
}
else
{
// append everything before the beginning of the escape sequence
AppendSubstring(spliceCommand.s, cur, true, spliceCommand.start - 1, false);
// find the named fragment
string name = param.GetString(); // unfortunately this allocates a new string
string fragment;
if ((namedFragments != null) && namedFragments.TryGetValue(name, out fragment))
{
// splice the fragment
result.Append(fragment);
}
else
{
// no named fragment found
result.Append("/* WARNING: $splice Could not find named fragment '{0}' */", name);
}
// advance to just after the ')' and continue parsing
cur = param.end + 1;
}
}
return true;
}
private bool ProcessPredicate(Token predicate, int endLine, ref int cur, ref bool appendEndln)
{
// eval if(param)
var fieldName = predicate.GetString();
var nonwhitespace = SkipWhitespace(predicate.s, predicate.end + 1, endLine);
if (!fieldName.StartsWith("features") && activeFields.permutationCount > 0)
{
var passedPermutations = activeFields.allPermutations.instances.Where(i => i.Contains(fieldName)).ToList();
if (passedPermutations.Count > 0)
{
var ifdefs = KeywordUtil.GetKeywordPermutationSetConditional(
passedPermutations.Select(i => i.permutationIndex).ToList()
);
result.AppendLine(ifdefs);
//Append the rest of the line
AppendSubstring(predicate.s, nonwhitespace, true, endLine, false);
result.AppendNewLine();
result.AppendLine("#endif");
return false;
}
else
{
appendEndln = false; //if line isn't active, remove whitespace
}
return false;
}
else
{
// eval if(param)
if (activeFields.baseInstance.Contains(fieldName))
{
// predicate is active
// append everything before the beginning of the escape sequence
AppendSubstring(predicate.s, cur, true, predicate.start - 1, false);
// continue parsing the rest of the line, starting with the first nonwhitespace character
cur = nonwhitespace;
return true;
}
else
{
// predicate is not active
if (isDebug)
{
// append everything before the beginning of the escape sequence
AppendSubstring(predicate.s, cur, true, predicate.start - 1, false);
// append the rest of the line, commented out
result.Append("// ");
AppendSubstring(predicate.s, nonwhitespace, true, endLine, false);
}
else
{
// don't append anything
appendEndln = false;
}
return false;
}
}
}
private Token ParseIdentifier(string code, int start, int end)
{
if (start < end)
{
char c = code[start];
if (Char.IsLetter(c) || (c == '_'))
{
int cur = start + 1;
while (cur < end)
{
c = code[cur];
if (!(Char.IsLetterOrDigit(c) || (c == '_')))
break;
cur++;
}
return new Token(code, start, cur);
}
}
return Token.Invalid();
}
private Token ParseString(string line, int start, int end)
{
if (Expect(line, start, '"'))
{
return ParseUntil(line, start + 1, end, '"');
}
return Token.Invalid();
}
private Token ParseUntil(string line, int start, int end, char endChar)
{
int cur = start;
while (cur < end)
{
if (line[cur] == endChar)
{
return new Token(line, start, cur);
}
cur++;
}
return Token.Invalid();
}
private bool Expect(string line, int location, char expected)
{
if ((location < line.Length) && (line[location] == expected))
{
return true;
}
Error("Expected '" + expected + "'", line, location);
return false;
}
private void Error(string error, string line, int location)
{
// append the line for context
result.Append("\n");
result.Append("// ");
AppendSubstring(line, 0, true, line.Length, false);
result.Append("\n");
// append the location marker, and error description
result.Append("// ");
result.AppendSpaces(location);
result.Append("^ ");
result.Append(error);
result.Append("\n");
}
// an easier to use version of substring Append() -- explicit inclusion on each end, and checks for positive length
private void AppendSubstring(string str, int start, bool includeStart, int end, bool includeEnd)
{
if (!includeStart)
{
start++;
}
if (!includeEnd)
{
end--;
}
int count = end - start + 1;
if (count > 0)
{
result.Append(str, start, count);
}
}
}
}
}

View File

@@ -0,0 +1,252 @@
using System;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using UnityEditor.Graphing;
using System.Globalization;
namespace UnityEditor.ShaderGraph
{
struct ShaderStringMapping
{
public AbstractMaterialNode node { get; set; }
// public List<AbstractMaterialNode> nodes { get; set; }
public int startIndex { get; set; }
public int count { get; set; }
}
class ShaderStringBuilder : IDisposable
{
enum ScopeType
{
Indent,
Block,
BlockSemicolon
}
StringBuilder m_StringBuilder;
Stack<ScopeType> m_ScopeStack;
int m_IndentationLevel;
ShaderStringMapping m_CurrentMapping;
List<ShaderStringMapping> m_Mappings;
const string k_IndentationString = " ";
const string k_NewLineString = "\n";
internal AbstractMaterialNode currentNode
{
get { return m_CurrentMapping.node; }
set
{
m_CurrentMapping.count = m_StringBuilder.Length - m_CurrentMapping.startIndex;
if (m_CurrentMapping.count > 0)
m_Mappings.Add(m_CurrentMapping);
m_CurrentMapping.node = value;
m_CurrentMapping.startIndex = m_StringBuilder.Length;
m_CurrentMapping.count = 0;
}
}
internal List<ShaderStringMapping> mappings
{
get { return m_Mappings; }
}
public ShaderStringBuilder()
{
m_StringBuilder = new 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()
{
m_StringBuilder.Append(k_NewLineString);
}
public void AppendLine(string value)
{
if (!string.IsNullOrEmpty(value))
{
AppendIndentation();
m_StringBuilder.Append(value);
}
AppendNewLine();
}
[StringFormatMethod("formatString")]
public void AppendLine(string formatString, params object[] args)
{
AppendIndentation();
m_StringBuilder.AppendFormat(CultureInfo.InvariantCulture, formatString, args);
AppendNewLine();
}
public void AppendLines(string lines)
{
if (string.IsNullOrEmpty(lines))
return;
var splitLines = lines.Split('\n');
var lineCount = splitLines.Length;
var lastLine = splitLines[lineCount - 1];
if (string.IsNullOrEmpty(lastLine) || lastLine == "\r")
lineCount--;
for (var i = 0; i < lineCount; i++)
AppendLine(splitLines[i].Trim('\r'));
}
public void Append(string value)
{
m_StringBuilder.Append(value);
}
public void Append(string value, int start, int count)
{
m_StringBuilder.Append(value, start, count);
}
[StringFormatMethod("formatString")]
public void Append(string formatString, params object[] args)
{
m_StringBuilder.AppendFormat(formatString, args);
}
public void AppendSpaces(int count)
{
m_StringBuilder.Append(' ', count);
}
public void AppendIndentation()
{
for (var i = 0; i < m_IndentationLevel; i++)
m_StringBuilder.Append(k_IndentationString);
}
public IDisposable IndentScope()
{
m_ScopeStack.Push(ScopeType.Indent);
IncreaseIndent();
return this;
}
public IDisposable BlockScope()
{
AppendLine("{");
IncreaseIndent();
m_ScopeStack.Push(ScopeType.Block);
return this;
}
public IDisposable BlockSemicolonScope()
{
AppendLine("{");
IncreaseIndent();
m_ScopeStack.Push(ScopeType.BlockSemicolon);
return this;
}
public void IncreaseIndent()
{
m_IndentationLevel++;
}
public void IncreaseIndent(int level)
{
for (var i = 0; i < level; i++)
IncreaseIndent();
}
public void DecreaseIndent()
{
m_IndentationLevel--;
}
public void DecreaseIndent(int level)
{
for (var i = 0; i < level; i++)
DecreaseIndent();
}
public void Dispose()
{
if (m_ScopeStack.Count == 0)
return;
switch (m_ScopeStack.Pop())
{
case ScopeType.Indent:
DecreaseIndent();
break;
case ScopeType.Block:
DecreaseIndent();
AppendLine("}");
break;
case ScopeType.BlockSemicolon:
DecreaseIndent();
AppendLine("};");
break;
}
}
public void Concat(ShaderStringBuilder other)
{
// First re-add all the mappings from `other`, such that their mappings are transformed.
foreach (var mapping in other.m_Mappings)
{
currentNode = mapping.node;
// Use `AppendLines` to indent according to the current indentation.
AppendLines(other.ToString(mapping.startIndex, mapping.count));
}
currentNode = other.currentNode;
AppendLines(other.ToString(other.m_CurrentMapping.startIndex, other.length - other.m_CurrentMapping.startIndex));
}
public void ReplaceInCurrentMapping(string oldValue, string newValue)
{
int start = m_CurrentMapping.startIndex;
int end = m_StringBuilder.Length - start;
m_StringBuilder.Replace(oldValue, newValue, start, end);
}
public string ToCodeBlock()
{
// Remove new line
if (m_StringBuilder.Length > 0)
m_StringBuilder.Length = m_StringBuilder.Length - 1;
// Set indentations
m_StringBuilder.Replace(Environment.NewLine, Environment.NewLine + k_IndentationString);
return m_StringBuilder.ToString();
}
public override string ToString()
{
return m_StringBuilder.ToString();
}
public string ToString(int startIndex, int length)
{
return m_StringBuilder.ToString(startIndex, length);
}
internal void Clear()
{
m_StringBuilder.Length = 0;
}
internal int length
{
get { return m_StringBuilder.Length; }
set { m_StringBuilder.Length = value; }
}
}
}

View File

@@ -0,0 +1,207 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Serialization;
using UnityEngine;
using TextureDimension = UnityEngine.Rendering.TextureDimension;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
public struct TextureInfo
{
public TextureInfo(string name, Texture texture, TextureDimension dimension)
{
this.name = name;
this.texture = texture;
this.dimension = dimension;
Debug.Assert(texture == null || texture.dimension == dimension);
}
public string name;
public Texture texture;
public TextureDimension dimension;
public int instanceID => texture != null ? texture.GetInstanceID() : 0;
}
public sealed class ShaderGraphVfxAsset : ScriptableObject, ISerializationCallbackReceiver
{
private class ShaderGraphVfxAssetData : JsonObject
{
public List<JsonData<AbstractShaderProperty>> m_Properties = new List<JsonData<AbstractShaderProperty>>();
}
public const int BaseColorSlotId = 1;
public const int MetallicSlotId = 2;
public const int SmoothnessSlotId = 3;
public const int NormalSlotId = 8;
public const int AlphaSlotId = 4;
public const int EmissiveSlotId = 5;
public const int ColorSlotId = 6;
public const int AlphaThresholdSlotId = 7;
[SerializeField]
public bool lit;
[SerializeField]
public bool alphaClipping;
[SerializeField]
internal GraphCompilationResult compilationResult;
[SerializeField]
internal ShaderGraphRequirements[] portRequirements;
[SerializeField]
string m_EvaluationFunctionName;
[SerializeField]
string m_InputStructName;
[SerializeField]
string m_OutputStructName;
[SerializeField]
ConcretePrecision m_ConcretePrecision = ConcretePrecision.Single;
ShaderGraphVfxAssetData m_Data = new ShaderGraphVfxAssetData();
[SerializeField]
private SerializationHelper.JSONSerializedElement m_SerializedVfxAssetData;
[SerializeField]
internal IntArray[] outputPropertyIndices;
internal ConcretePrecision concretePrecision
{
get => m_ConcretePrecision;
set => m_ConcretePrecision = value;
}
[SerializeField]
OutputMetadata[] m_Outputs;
[SerializeField]
TextureInfo[] m_TextureInfos;
public IEnumerable<TextureInfo> textureInfos { get => m_TextureInfos; }
internal void SetTextureInfos(IList<PropertyCollector.TextureInfo> textures)
{
m_TextureInfos = textures.Select(t => new TextureInfo(t.name, EditorUtility.InstanceIDToObject(t.textureId) as Texture, t.dimension)).ToArray();
}
internal void SetOutputs(OutputMetadata[] outputs)
{
m_Outputs = outputs;
}
public OutputMetadata GetOutput(int id)
{
return m_Outputs.FirstOrDefault(t => t.id == id);
}
public bool HasOutput(int id)
{
return m_Outputs.Any(t => t.id == id);
}
public string evaluationFunctionName
{
get { return m_EvaluationFunctionName; }
internal set { m_EvaluationFunctionName = value; }
}
public string inputStructName
{
get { return m_InputStructName; }
internal set { m_InputStructName = value; }
}
public string outputStructName
{
get { return m_OutputStructName; }
internal set { m_OutputStructName = value; }
}
public List<AbstractShaderProperty> properties
{
get
{
EnsureProperties();
return m_Data.m_Properties.SelectValue().ToList();
}
}
internal void SetProperties(List<AbstractShaderProperty> propertiesList)
{
m_Data.m_Properties.Clear();
foreach (var property in propertiesList)
{
m_Data.m_Properties.Add(property);
}
var json = MultiJson.Serialize(m_Data);
m_SerializedVfxAssetData = new SerializationHelper.JSONSerializedElement() { JSONnodeData = json };
m_Data = null;
}
void EnsureProperties()
{
if ((m_Data == null || m_Data.m_Properties == null || !m_Data.m_Properties.Any()) && !String.IsNullOrEmpty(m_SerializedVfxAssetData.JSONnodeData))
{
m_Data = new ShaderGraphVfxAssetData();
MultiJson.Deserialize(m_Data , m_SerializedVfxAssetData.JSONnodeData);
}
foreach (var property in m_Data.m_Properties.SelectValue())
{
property.ValidateConcretePrecision(m_ConcretePrecision);
}
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
m_Data = null;
}
void ISerializationCallbackReceiver.OnBeforeSerialize() {}
public GraphCode GetCode(OutputMetadata[] outputs)
{
var graphCode = new GraphCode();
graphCode.requirements = ShaderGraphRequirements.none;
var outputIndices = new int[outputs.Length];
for (var i = 0; i < outputs.Length; i++)
{
if (!outputs[i].isValid)
{
throw new ArgumentException($"Invalid {nameof(OutputMetadata)} at index {i}.", nameof(outputs));
}
outputIndices[i] = outputs[i].index;
graphCode.requirements = graphCode.requirements.Union(portRequirements[outputs[i].index]);
}
graphCode.code = compilationResult.GenerateCode(outputIndices);
var propertyIndexSet = new HashSet<int>();
foreach (var outputIndex in outputIndices)
{
foreach (var propertyIndex in outputPropertyIndices[outputIndex].array)
{
propertyIndexSet.Add(propertyIndex);
}
}
var propertyIndices = propertyIndexSet.ToArray();
Array.Sort(propertyIndices);
var filteredProperties = propertyIndices.Select(i => properties[i]).ToArray();
graphCode.properties = filteredProperties;
return graphCode;
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.ShaderGraph.Serialization;
namespace UnityEditor.ShaderGraph
{
[Serializable, GenerationAPI] // TODO: Public
internal abstract class SubTarget : JsonObject
{
internal abstract Type targetType { get; }
internal Target target { get; set; }
public string displayName { get; set; }
public bool isHidden { get; set; }
public abstract bool IsActive();
public abstract void Setup(ref TargetSetupContext context);
public abstract void GetFields(ref TargetFieldContext context);
public abstract void GetActiveBlocks(ref TargetActiveBlockContext context);
public abstract void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo);
public virtual void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode) {}
public virtual void ProcessPreviewMaterial(Material material) {}
public virtual object saveContext => null;
}
[GenerationAPI] // TODO: Public
internal abstract class SubTarget<T> : SubTarget where T : Target
{
internal override Type targetType => typeof(T);
public new T target
{
get => base.target as T;
set => base.target = value;
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UIElements;
using UnityEditor.ShaderGraph.Serialization;
namespace UnityEditor.ShaderGraph
{
[Serializable, GenerationAPI] // TODO: Public
internal abstract class Target : JsonObject
{
public string displayName { get; set; }
public bool isHidden { get; set; }
public abstract bool IsActive();
public abstract void Setup(ref TargetSetupContext context);
public abstract void GetFields(ref TargetFieldContext context);
public abstract void GetActiveBlocks(ref TargetActiveBlockContext context);
public abstract void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<string> registerUndo);
public virtual void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode) {}
public virtual void ProcessPreviewMaterial(Material material) {}
public virtual object saveContext => null;
public virtual bool IsNodeAllowedByTarget(Type nodeType)
{
NeverAllowedByTargetAttribute never = NodeClassCache.GetAttributeOnNodeType<NeverAllowedByTargetAttribute>(nodeType);
return never == null;
}
public abstract bool WorksWithSRP(RenderPipelineAsset scriptableRenderPipeline);
}
}

View File

@@ -0,0 +1,60 @@
using UnityEngine;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
internal static class BlockFields
{
[GenerateBlocks]
public struct VertexDescription
{
public static string name = "VertexDescription";
public static BlockFieldDescriptor Position = new BlockFieldDescriptor(VertexDescription.name, "Position", "VERTEXDESCRIPTION_POSITION",
new PositionControl(CoordinateSpace.Object), ShaderStage.Vertex);
public static BlockFieldDescriptor Normal = new BlockFieldDescriptor(VertexDescription.name, "Normal", "VERTEXDESCRIPTION_NORMAL",
new NormalControl(CoordinateSpace.Object), ShaderStage.Vertex);
public static BlockFieldDescriptor Tangent = new BlockFieldDescriptor(VertexDescription.name, "Tangent", "VERTEXDESCRIPTION_TANGENT",
new TangentControl(CoordinateSpace.Object), ShaderStage.Vertex);
}
[GenerateBlocks]
public struct SurfaceDescription
{
public static string name = "SurfaceDescription";
public static BlockFieldDescriptor BaseColor = new BlockFieldDescriptor(SurfaceDescription.name, "BaseColor", "Base Color", "SURFACEDESCRIPTION_BASECOLOR",
new ColorControl(UnityEngine.Color.grey, false), ShaderStage.Fragment);
public static BlockFieldDescriptor NormalTS = new BlockFieldDescriptor(SurfaceDescription.name, "NormalTS", "Normal (Tangent Space)", "SURFACEDESCRIPTION_NORMALTS",
new NormalControl(CoordinateSpace.Tangent), ShaderStage.Fragment);
public static BlockFieldDescriptor NormalOS = new BlockFieldDescriptor(SurfaceDescription.name, "NormalOS", "Normal (Object Space)", "SURFACEDESCRIPTION_NORMALOS",
new NormalControl(CoordinateSpace.Object), ShaderStage.Fragment);
public static BlockFieldDescriptor NormalWS = new BlockFieldDescriptor(SurfaceDescription.name, "NormalWS", "Normal (World Space)", "SURFACEDESCRIPTION_NORMALWS",
new NormalControl(CoordinateSpace.World), ShaderStage.Fragment);
public static BlockFieldDescriptor Metallic = new BlockFieldDescriptor(SurfaceDescription.name, "Metallic", "SURFACEDESCRIPTION_METALLIC",
new FloatControl(0.0f), ShaderStage.Fragment);
public static BlockFieldDescriptor Specular = new BlockFieldDescriptor(SurfaceDescription.name, "Specular", "Specular Color", "SURFACEDESCRIPTION_SPECULAR",
new ColorControl(UnityEngine.Color.grey, false), ShaderStage.Fragment);
public static BlockFieldDescriptor Smoothness = new BlockFieldDescriptor(SurfaceDescription.name, "Smoothness", "SURFACEDESCRIPTION_SMOOTHNESS",
new FloatControl(0.5f), ShaderStage.Fragment);
public static BlockFieldDescriptor Occlusion = new BlockFieldDescriptor(SurfaceDescription.name, "Occlusion", "Ambient Occlusion", "SURFACEDESCRIPTION_OCCLUSION",
new FloatControl(1.0f), ShaderStage.Fragment);
public static BlockFieldDescriptor Emission = new BlockFieldDescriptor(SurfaceDescription.name, "Emission", "SURFACEDESCRIPTION_EMISSION",
new ColorControl(UnityEngine.Color.black, true), ShaderStage.Fragment);
public static BlockFieldDescriptor Alpha = new BlockFieldDescriptor(SurfaceDescription.name, "Alpha", "SURFACEDESCRIPTION_ALPHA",
new FloatControl(1.0f), ShaderStage.Fragment);
public static BlockFieldDescriptor AlphaClipThreshold = new BlockFieldDescriptor(SurfaceDescription.name, "AlphaClipThreshold", "Alpha Clip Threshold", "SURFACEDESCRIPTION_ALPHACLIPTHRESHOLD",
new FloatControl(0.5f), ShaderStage.Fragment);
public static BlockFieldDescriptor CoatMask = new BlockFieldDescriptor(SurfaceDescription.name, "CoatMask", "Coat Mask", "SURFACEDESCRIPTION_COATMASK",
new FloatControl(0.0f), ShaderStage.Fragment);
public static BlockFieldDescriptor CoatSmoothness = new BlockFieldDescriptor(SurfaceDescription.name, "CoatSmoothness", "Coat Smoothness", "SURFACEDESCRIPTION_COATSMOOTHNESS",
new FloatControl(1.0f), ShaderStage.Fragment);
}
[GenerateBlocks]
public struct SurfaceDescriptionLegacy
{
public static string name = "SurfaceDescription";
public static BlockFieldDescriptor SpriteColor = new BlockFieldDescriptor(SurfaceDescription.name, "SpriteColor", "SURFACEDESCRIPTION_SPRITECOLOR",
new ColorRGBAControl(UnityEngine.Color.white), ShaderStage.Fragment, isHidden: true);
}
}
}

View File

@@ -0,0 +1,104 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal static class FieldDependencies
{
public static DependencyCollection Varyings = new DependencyCollection
{
new FieldDependency(StructFields.Varyings.positionWS, StructFields.Attributes.positionOS),
new FieldDependency(StructFields.Varyings.normalWS, StructFields.Attributes.normalOS),
new FieldDependency(StructFields.Varyings.tangentWS, StructFields.Attributes.tangentOS),
new FieldDependency(StructFields.Varyings.texCoord0, StructFields.Attributes.uv0),
new FieldDependency(StructFields.Varyings.texCoord1, StructFields.Attributes.uv1),
new FieldDependency(StructFields.Varyings.texCoord2, StructFields.Attributes.uv2),
new FieldDependency(StructFields.Varyings.texCoord3, StructFields.Attributes.uv3),
new FieldDependency(StructFields.Varyings.color, StructFields.Attributes.color),
new FieldDependency(StructFields.Varyings.instanceID, StructFields.Attributes.instanceID),
};
public static DependencyCollection VertexDescription = new DependencyCollection
{
new FieldDependency(StructFields.VertexDescriptionInputs.ObjectSpaceNormal, StructFields.Attributes.normalOS),
new FieldDependency(StructFields.VertexDescriptionInputs.WorldSpaceNormal, StructFields.Attributes.normalOS),
new FieldDependency(StructFields.VertexDescriptionInputs.ViewSpaceNormal, StructFields.VertexDescriptionInputs.WorldSpaceNormal),
new FieldDependency(StructFields.VertexDescriptionInputs.ObjectSpaceTangent, StructFields.Attributes.tangentOS),
new FieldDependency(StructFields.VertexDescriptionInputs.WorldSpaceTangent, StructFields.Attributes.tangentOS),
new FieldDependency(StructFields.VertexDescriptionInputs.ViewSpaceTangent, StructFields.VertexDescriptionInputs.WorldSpaceTangent),
new FieldDependency(StructFields.VertexDescriptionInputs.ObjectSpaceBiTangent, StructFields.Attributes.normalOS),
new FieldDependency(StructFields.VertexDescriptionInputs.ObjectSpaceBiTangent, StructFields.Attributes.tangentOS),
new FieldDependency(StructFields.VertexDescriptionInputs.WorldSpaceBiTangent, StructFields.VertexDescriptionInputs.ObjectSpaceBiTangent),
new FieldDependency(StructFields.VertexDescriptionInputs.ViewSpaceBiTangent, StructFields.VertexDescriptionInputs.WorldSpaceBiTangent),
new FieldDependency(StructFields.VertexDescriptionInputs.ObjectSpacePosition, StructFields.Attributes.positionOS),
new FieldDependency(StructFields.VertexDescriptionInputs.WorldSpacePosition, StructFields.Attributes.positionOS),
new FieldDependency(StructFields.VertexDescriptionInputs.AbsoluteWorldSpacePosition, StructFields.Attributes.positionOS),
new FieldDependency(StructFields.VertexDescriptionInputs.ViewSpacePosition, StructFields.VertexDescriptionInputs.WorldSpacePosition),
new FieldDependency(StructFields.VertexDescriptionInputs.WorldSpaceViewDirection, StructFields.VertexDescriptionInputs.WorldSpacePosition),
new FieldDependency(StructFields.VertexDescriptionInputs.ObjectSpaceViewDirection, StructFields.VertexDescriptionInputs.WorldSpaceViewDirection),
new FieldDependency(StructFields.VertexDescriptionInputs.ViewSpaceViewDirection, StructFields.VertexDescriptionInputs.WorldSpaceViewDirection),
new FieldDependency(StructFields.VertexDescriptionInputs.TangentSpaceViewDirection, StructFields.VertexDescriptionInputs.WorldSpaceViewDirection),
new FieldDependency(StructFields.VertexDescriptionInputs.TangentSpaceViewDirection, StructFields.VertexDescriptionInputs.WorldSpaceTangent),
new FieldDependency(StructFields.VertexDescriptionInputs.TangentSpaceViewDirection, StructFields.VertexDescriptionInputs.WorldSpaceBiTangent),
new FieldDependency(StructFields.VertexDescriptionInputs.TangentSpaceViewDirection, StructFields.VertexDescriptionInputs.WorldSpaceNormal),
new FieldDependency(StructFields.VertexDescriptionInputs.ScreenPosition, StructFields.VertexDescriptionInputs.WorldSpacePosition),
new FieldDependency(StructFields.VertexDescriptionInputs.uv0, StructFields.Attributes.uv0),
new FieldDependency(StructFields.VertexDescriptionInputs.uv1, StructFields.Attributes.uv1),
new FieldDependency(StructFields.VertexDescriptionInputs.uv2, StructFields.Attributes.uv2),
new FieldDependency(StructFields.VertexDescriptionInputs.uv3, StructFields.Attributes.uv3),
new FieldDependency(StructFields.VertexDescriptionInputs.VertexColor, StructFields.Attributes.color),
new FieldDependency(StructFields.VertexDescriptionInputs.BoneWeights, StructFields.Attributes.weights),
new FieldDependency(StructFields.VertexDescriptionInputs.BoneIndices, StructFields.Attributes.indices),
new FieldDependency(StructFields.VertexDescriptionInputs.VertexID, StructFields.Attributes.vertexID),
};
public static DependencyCollection SurfaceDescription = new DependencyCollection
{
new FieldDependency(StructFields.SurfaceDescriptionInputs.WorldSpaceNormal, StructFields.Varyings.normalWS),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ObjectSpaceNormal, StructFields.SurfaceDescriptionInputs.WorldSpaceNormal),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ViewSpaceNormal, StructFields.SurfaceDescriptionInputs.WorldSpaceNormal),
new FieldDependency(StructFields.SurfaceDescriptionInputs.WorldSpaceTangent, StructFields.Varyings.tangentWS),
new FieldDependency(StructFields.SurfaceDescriptionInputs.WorldSpaceTangent, StructFields.SurfaceDescriptionInputs.WorldSpaceNormal),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ObjectSpaceTangent, StructFields.SurfaceDescriptionInputs.WorldSpaceTangent),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ViewSpaceTangent, StructFields.SurfaceDescriptionInputs.WorldSpaceTangent),
new FieldDependency(StructFields.SurfaceDescriptionInputs.WorldSpaceBiTangent, StructFields.SurfaceDescriptionInputs.WorldSpaceNormal),
new FieldDependency(StructFields.SurfaceDescriptionInputs.WorldSpaceBiTangent, StructFields.SurfaceDescriptionInputs.WorldSpaceTangent),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ObjectSpaceBiTangent, StructFields.SurfaceDescriptionInputs.WorldSpaceBiTangent),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ViewSpaceBiTangent, StructFields.SurfaceDescriptionInputs.WorldSpaceBiTangent),
new FieldDependency(StructFields.SurfaceDescriptionInputs.WorldSpacePosition, StructFields.Varyings.positionWS),
new FieldDependency(StructFields.SurfaceDescriptionInputs.AbsoluteWorldSpacePosition, StructFields.Varyings.positionWS),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ObjectSpacePosition, StructFields.Varyings.positionWS),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ViewSpacePosition, StructFields.Varyings.positionWS),
new FieldDependency(StructFields.SurfaceDescriptionInputs.WorldSpaceViewDirection, StructFields.Varyings.viewDirectionWS),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ObjectSpaceViewDirection, StructFields.SurfaceDescriptionInputs.WorldSpaceViewDirection),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ViewSpaceViewDirection, StructFields.SurfaceDescriptionInputs.WorldSpaceViewDirection),
new FieldDependency(StructFields.SurfaceDescriptionInputs.TangentSpaceViewDirection, StructFields.SurfaceDescriptionInputs.WorldSpaceViewDirection),
new FieldDependency(StructFields.SurfaceDescriptionInputs.TangentSpaceViewDirection, StructFields.SurfaceDescriptionInputs.WorldSpaceTangent),
new FieldDependency(StructFields.SurfaceDescriptionInputs.TangentSpaceViewDirection, StructFields.SurfaceDescriptionInputs.WorldSpaceBiTangent),
new FieldDependency(StructFields.SurfaceDescriptionInputs.TangentSpaceViewDirection, StructFields.SurfaceDescriptionInputs.WorldSpaceNormal),
new FieldDependency(StructFields.SurfaceDescriptionInputs.ScreenPosition, StructFields.SurfaceDescriptionInputs.WorldSpacePosition),
new FieldDependency(StructFields.SurfaceDescriptionInputs.uv0, StructFields.Varyings.texCoord0),
new FieldDependency(StructFields.SurfaceDescriptionInputs.uv1, StructFields.Varyings.texCoord1),
new FieldDependency(StructFields.SurfaceDescriptionInputs.uv2, StructFields.Varyings.texCoord2),
new FieldDependency(StructFields.SurfaceDescriptionInputs.uv3, StructFields.Varyings.texCoord3),
new FieldDependency(StructFields.SurfaceDescriptionInputs.VertexColor, StructFields.Varyings.color),
new FieldDependency(StructFields.SurfaceDescriptionInputs.FaceSign, StructFields.Varyings.cullFace),
};
public static DependencyCollection Default = new DependencyCollection
{
{ Varyings },
{ VertexDescription },
{ SurfaceDescription },
};
}
}

View File

@@ -0,0 +1,25 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal static class Fields
{
#region Tags
public const string kFeatures = "features";
public const string kSurfaceType = "SurfaceType";
public const string kBlendMode = "BlendMode";
#endregion
#region Fields
// These are core Fields shared between URP and HDRP etc.
public static FieldDescriptor GraphVertex = new FieldDescriptor(kFeatures, "graphVertex", "FEATURES_GRAPH_VERTEX");
public static FieldDescriptor GraphPixel = new FieldDescriptor(kFeatures, "graphPixel", "FEATURES_GRAPH_PIXEL");
public static FieldDescriptor AlphaClip = new FieldDescriptor(string.Empty, "AlphaClip", "_AlphaClip 1");
public static FieldDescriptor AlphaTest = new FieldDescriptor(string.Empty, "AlphaTest", "_ALPHA_TEST 1");
public static FieldDescriptor BlendAlpha = new FieldDescriptor(kBlendMode, "Alpha", "_BLENDMODE_ALPHA 1"); // Universal, vfx: HDRP?
public static FieldDescriptor DoubleSided = new FieldDescriptor(string.Empty, "DoubleSided", "_DOUBLE_SIDED 1"); // Universal, duplicated in HD
public static FieldDescriptor IsPreview = new FieldDescriptor(string.Empty, "isPreview", "SHADERGRAPH_PREVIEW");
public static FieldDescriptor LodCrossFade = new FieldDescriptor(string.Empty, "LodCrossFade", "_LODCROSSFADE 1"); // HD only
public static FieldDescriptor AlphaToMask = new FieldDescriptor(string.Empty, "AlphaToMask", "_ALPHATOMASK_ON 1"); // HD only
#endregion
}
}

View File

@@ -0,0 +1,214 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal static class StructFields
{
public struct Attributes
{
public static string name = "Attributes";
public static FieldDescriptor positionOS = new FieldDescriptor(Attributes.name, "positionOS", "", ShaderValueType.Float3, "POSITION");
public static FieldDescriptor normalOS = new FieldDescriptor(Attributes.name, "normalOS", "ATTRIBUTES_NEED_NORMAL", ShaderValueType.Float3,
"NORMAL", subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor tangentOS = new FieldDescriptor(Attributes.name, "tangentOS", "ATTRIBUTES_NEED_TANGENT", ShaderValueType.Float4,
"TANGENT", subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv0 = new FieldDescriptor(Attributes.name, "uv0", "ATTRIBUTES_NEED_TEXCOORD0", ShaderValueType.Float4,
"TEXCOORD0", subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv1 = new FieldDescriptor(Attributes.name, "uv1", "ATTRIBUTES_NEED_TEXCOORD1", ShaderValueType.Float4,
"TEXCOORD1", subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv2 = new FieldDescriptor(Attributes.name, "uv2", "ATTRIBUTES_NEED_TEXCOORD2", ShaderValueType.Float4,
"TEXCOORD2", subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv3 = new FieldDescriptor(Attributes.name, "uv3", "ATTRIBUTES_NEED_TEXCOORD3", ShaderValueType.Float4,
"TEXCOORD3", subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor weights = new FieldDescriptor(Attributes.name, "weights", "ATTRIBUTES_NEED_BLENDWEIGHTS", ShaderValueType.Float4,
"BLENDWEIGHTS", subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor indices = new FieldDescriptor(Attributes.name, "indices", "ATTRIBUTES_NEED_BLENDINDICES", ShaderValueType.Uint4,
"BLENDINDICES", subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor color = new FieldDescriptor(Attributes.name, "color", "ATTRIBUTES_NEED_COLOR", ShaderValueType.Float4,
"COLOR", subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor instanceID = new FieldDescriptor(Attributes.name, "instanceID", "", ShaderValueType.Uint,
"INSTANCEID_SEMANTIC", "UNITY_ANY_INSTANCING_ENABLED");
public static FieldDescriptor vertexID = new FieldDescriptor(Attributes.name, "vertexID", "ATTRIBUTES_NEED_VERTEXID", ShaderValueType.Uint,
"SV_VertexID", subscriptOptions: StructFieldOptions.Optional);
}
public struct Varyings
{
public static string name = "Varyings";
public static FieldDescriptor positionCS = new FieldDescriptor(Varyings.name, "positionCS", "", ShaderValueType.Float4, "SV_POSITION");
public static FieldDescriptor positionWS = new FieldDescriptor(Varyings.name, "positionWS", "VARYINGS_NEED_POSITION_WS", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor normalWS = new FieldDescriptor(Varyings.name, "normalWS", "VARYINGS_NEED_NORMAL_WS", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor tangentWS = new FieldDescriptor(Varyings.name, "tangentWS", "VARYINGS_NEED_TANGENT_WS", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor texCoord0 = new FieldDescriptor(Varyings.name, "texCoord0", "VARYINGS_NEED_TEXCOORD0", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor texCoord1 = new FieldDescriptor(Varyings.name, "texCoord1", "VARYINGS_NEED_TEXCOORD1", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor texCoord2 = new FieldDescriptor(Varyings.name, "texCoord2", "VARYINGS_NEED_TEXCOORD2", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor texCoord3 = new FieldDescriptor(Varyings.name, "texCoord3", "VARYINGS_NEED_TEXCOORD3", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor color = new FieldDescriptor(Varyings.name, "color", "VARYINGS_NEED_COLOR", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor viewDirectionWS = new FieldDescriptor(Varyings.name, "viewDirectionWS", "VARYINGS_NEED_VIEWDIRECTION_WS", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor screenPosition = new FieldDescriptor(Varyings.name, "screenPosition", "VARYINGS_NEED_SCREENPOSITION", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor instanceID = new FieldDescriptor(Varyings.name, "instanceID", "", ShaderValueType.Uint,
"CUSTOM_INSTANCE_ID", "UNITY_ANY_INSTANCING_ENABLED");
public static FieldDescriptor cullFace = new FieldDescriptor(Varyings.name, "cullFace", "VARYINGS_NEED_CULLFACE", "FRONT_FACE_TYPE",
"FRONT_FACE_SEMANTIC", "defined(SHADER_STAGE_FRAGMENT) && defined(VARYINGS_NEED_CULLFACE)", StructFieldOptions.Generated & StructFieldOptions.Optional);
}
public struct VertexDescriptionInputs
{
public static string name = "VertexDescriptionInputs";
public static FieldDescriptor ObjectSpaceNormal = new FieldDescriptor(VertexDescriptionInputs.name, "ObjectSpaceNormal", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpaceNormal = new FieldDescriptor(VertexDescriptionInputs.name, "ViewSpaceNormal", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpaceNormal = new FieldDescriptor(VertexDescriptionInputs.name, "WorldSpaceNormal", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpaceNormal = new FieldDescriptor(VertexDescriptionInputs.name, "TangentSpaceNormal", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ObjectSpaceTangent = new FieldDescriptor(VertexDescriptionInputs.name, "ObjectSpaceTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpaceTangent = new FieldDescriptor(VertexDescriptionInputs.name, "ViewSpaceTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpaceTangent = new FieldDescriptor(VertexDescriptionInputs.name, "WorldSpaceTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpaceTangent = new FieldDescriptor(VertexDescriptionInputs.name, "TangentSpaceTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ObjectSpaceBiTangent = new FieldDescriptor(VertexDescriptionInputs.name, "ObjectSpaceBiTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpaceBiTangent = new FieldDescriptor(VertexDescriptionInputs.name, "ViewSpaceBiTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpaceBiTangent = new FieldDescriptor(VertexDescriptionInputs.name, "WorldSpaceBiTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpaceBiTangent = new FieldDescriptor(VertexDescriptionInputs.name, "TangentSpaceBiTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ObjectSpaceViewDirection = new FieldDescriptor(VertexDescriptionInputs.name, "ObjectSpaceViewDirection", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpaceViewDirection = new FieldDescriptor(VertexDescriptionInputs.name, "ViewSpaceViewDirection", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpaceViewDirection = new FieldDescriptor(VertexDescriptionInputs.name, "WorldSpaceViewDirection", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpaceViewDirection = new FieldDescriptor(VertexDescriptionInputs.name, "TangentSpaceViewDirection", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ObjectSpacePosition = new FieldDescriptor(VertexDescriptionInputs.name, "ObjectSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpacePosition = new FieldDescriptor(VertexDescriptionInputs.name, "ViewSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpacePosition = new FieldDescriptor(VertexDescriptionInputs.name, "WorldSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpacePosition = new FieldDescriptor(VertexDescriptionInputs.name, "TangentSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor AbsoluteWorldSpacePosition = new FieldDescriptor(VertexDescriptionInputs.name, "AbsoluteWorldSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ScreenPosition = new FieldDescriptor(VertexDescriptionInputs.name, "ScreenPosition", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv0 = new FieldDescriptor(VertexDescriptionInputs.name, "uv0", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv1 = new FieldDescriptor(VertexDescriptionInputs.name, "uv1", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv2 = new FieldDescriptor(VertexDescriptionInputs.name, "uv2", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv3 = new FieldDescriptor(VertexDescriptionInputs.name, "uv3", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor VertexColor = new FieldDescriptor(VertexDescriptionInputs.name, "VertexColor", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TimeParameters = new FieldDescriptor(VertexDescriptionInputs.name, "TimeParameters", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor BoneWeights = new FieldDescriptor(VertexDescriptionInputs.name, "BoneWeights", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor BoneIndices = new FieldDescriptor(VertexDescriptionInputs.name, "BoneIndices", "", ShaderValueType.Uint4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor VertexID = new FieldDescriptor(VertexDescriptionInputs.name, "VertexID", "", ShaderValueType.Uint,
subscriptOptions: StructFieldOptions.Optional);
}
public struct SurfaceDescriptionInputs
{
public static string name = "SurfaceDescriptionInputs";
public static FieldDescriptor ObjectSpaceNormal = new FieldDescriptor(SurfaceDescriptionInputs.name, "ObjectSpaceNormal", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpaceNormal = new FieldDescriptor(SurfaceDescriptionInputs.name, "ViewSpaceNormal", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpaceNormal = new FieldDescriptor(SurfaceDescriptionInputs.name, "WorldSpaceNormal", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpaceNormal = new FieldDescriptor(SurfaceDescriptionInputs.name, "TangentSpaceNormal", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ObjectSpaceTangent = new FieldDescriptor(SurfaceDescriptionInputs.name, "ObjectSpaceTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpaceTangent = new FieldDescriptor(SurfaceDescriptionInputs.name, "ViewSpaceTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpaceTangent = new FieldDescriptor(SurfaceDescriptionInputs.name, "WorldSpaceTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpaceTangent = new FieldDescriptor(SurfaceDescriptionInputs.name, "TangentSpaceTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ObjectSpaceBiTangent = new FieldDescriptor(SurfaceDescriptionInputs.name, "ObjectSpaceBiTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpaceBiTangent = new FieldDescriptor(SurfaceDescriptionInputs.name, "ViewSpaceBiTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpaceBiTangent = new FieldDescriptor(SurfaceDescriptionInputs.name, "WorldSpaceBiTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpaceBiTangent = new FieldDescriptor(SurfaceDescriptionInputs.name, "TangentSpaceBiTangent", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ObjectSpaceViewDirection = new FieldDescriptor(SurfaceDescriptionInputs.name, "ObjectSpaceViewDirection", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpaceViewDirection = new FieldDescriptor(SurfaceDescriptionInputs.name, "ViewSpaceViewDirection", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpaceViewDirection = new FieldDescriptor(SurfaceDescriptionInputs.name, "WorldSpaceViewDirection", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpaceViewDirection = new FieldDescriptor(SurfaceDescriptionInputs.name, "TangentSpaceViewDirection", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ObjectSpacePosition = new FieldDescriptor(SurfaceDescriptionInputs.name, "ObjectSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ViewSpacePosition = new FieldDescriptor(SurfaceDescriptionInputs.name, "ViewSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor WorldSpacePosition = new FieldDescriptor(SurfaceDescriptionInputs.name, "WorldSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TangentSpacePosition = new FieldDescriptor(SurfaceDescriptionInputs.name, "TangentSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor AbsoluteWorldSpacePosition = new FieldDescriptor(SurfaceDescriptionInputs.name, "AbsoluteWorldSpacePosition", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor ScreenPosition = new FieldDescriptor(SurfaceDescriptionInputs.name, "ScreenPosition", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv0 = new FieldDescriptor(SurfaceDescriptionInputs.name, "uv0", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv1 = new FieldDescriptor(SurfaceDescriptionInputs.name, "uv1", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv2 = new FieldDescriptor(SurfaceDescriptionInputs.name, "uv2", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor uv3 = new FieldDescriptor(SurfaceDescriptionInputs.name, "uv3", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor VertexColor = new FieldDescriptor(SurfaceDescriptionInputs.name, "VertexColor", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor TimeParameters = new FieldDescriptor(SurfaceDescriptionInputs.name, "TimeParameters", "", ShaderValueType.Float3,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor FaceSign = new FieldDescriptor(SurfaceDescriptionInputs.name, "FaceSign", "", ShaderValueType.Float,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor BoneWeights = new FieldDescriptor(SurfaceDescriptionInputs.name, "BoneWeights", "", ShaderValueType.Float4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor BoneIndices = new FieldDescriptor(SurfaceDescriptionInputs.name, "BoneIndices", "", ShaderValueType.Uint4,
subscriptOptions: StructFieldOptions.Optional);
public static FieldDescriptor VertexID = new FieldDescriptor(SurfaceDescriptionInputs.name, "VertexID", "", ShaderValueType.Uint,
subscriptOptions: StructFieldOptions.Optional);
}
}
}

View File

@@ -0,0 +1,118 @@
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
internal static class Structs
{
public static StructDescriptor Attributes = new StructDescriptor()
{
name = "Attributes",
packFields = false,
fields = new FieldDescriptor[]
{
StructFields.Attributes.positionOS,
StructFields.Attributes.normalOS,
StructFields.Attributes.tangentOS,
StructFields.Attributes.uv0,
StructFields.Attributes.uv1,
StructFields.Attributes.uv2,
StructFields.Attributes.uv3,
StructFields.Attributes.color,
StructFields.Attributes.instanceID,
StructFields.Attributes.weights,
StructFields.Attributes.indices,
StructFields.Attributes.vertexID,
}
};
public static StructDescriptor VertexDescriptionInputs = new StructDescriptor()
{
name = "VertexDescriptionInputs",
packFields = false,
fields = new FieldDescriptor[]
{
StructFields.VertexDescriptionInputs.ObjectSpaceNormal,
StructFields.VertexDescriptionInputs.ViewSpaceNormal,
StructFields.VertexDescriptionInputs.WorldSpaceNormal,
StructFields.VertexDescriptionInputs.TangentSpaceNormal,
StructFields.VertexDescriptionInputs.ObjectSpaceTangent,
StructFields.VertexDescriptionInputs.ViewSpaceTangent,
StructFields.VertexDescriptionInputs.WorldSpaceTangent,
StructFields.VertexDescriptionInputs.TangentSpaceTangent,
StructFields.VertexDescriptionInputs.ObjectSpaceBiTangent,
StructFields.VertexDescriptionInputs.ViewSpaceBiTangent,
StructFields.VertexDescriptionInputs.WorldSpaceBiTangent,
StructFields.VertexDescriptionInputs.TangentSpaceBiTangent,
StructFields.VertexDescriptionInputs.ObjectSpaceViewDirection,
StructFields.VertexDescriptionInputs.ViewSpaceViewDirection,
StructFields.VertexDescriptionInputs.WorldSpaceViewDirection,
StructFields.VertexDescriptionInputs.TangentSpaceViewDirection,
StructFields.VertexDescriptionInputs.ObjectSpacePosition,
StructFields.VertexDescriptionInputs.ViewSpacePosition,
StructFields.VertexDescriptionInputs.WorldSpacePosition,
StructFields.VertexDescriptionInputs.TangentSpacePosition,
StructFields.VertexDescriptionInputs.AbsoluteWorldSpacePosition,
StructFields.VertexDescriptionInputs.ScreenPosition,
StructFields.VertexDescriptionInputs.uv0,
StructFields.VertexDescriptionInputs.uv1,
StructFields.VertexDescriptionInputs.uv2,
StructFields.VertexDescriptionInputs.uv3,
StructFields.VertexDescriptionInputs.VertexColor,
StructFields.VertexDescriptionInputs.TimeParameters,
StructFields.VertexDescriptionInputs.BoneWeights,
StructFields.VertexDescriptionInputs.BoneIndices,
StructFields.VertexDescriptionInputs.VertexID,
}
};
public static StructDescriptor SurfaceDescriptionInputs = new StructDescriptor()
{
name = "SurfaceDescriptionInputs",
packFields = false,
fields = new FieldDescriptor[]
{
StructFields.SurfaceDescriptionInputs.ObjectSpaceNormal,
StructFields.SurfaceDescriptionInputs.ViewSpaceNormal,
StructFields.SurfaceDescriptionInputs.WorldSpaceNormal,
StructFields.SurfaceDescriptionInputs.TangentSpaceNormal,
StructFields.SurfaceDescriptionInputs.ObjectSpaceTangent,
StructFields.SurfaceDescriptionInputs.ViewSpaceTangent,
StructFields.SurfaceDescriptionInputs.WorldSpaceTangent,
StructFields.SurfaceDescriptionInputs.TangentSpaceTangent,
StructFields.SurfaceDescriptionInputs.ObjectSpaceBiTangent,
StructFields.SurfaceDescriptionInputs.ViewSpaceBiTangent,
StructFields.SurfaceDescriptionInputs.WorldSpaceBiTangent,
StructFields.SurfaceDescriptionInputs.TangentSpaceBiTangent,
StructFields.SurfaceDescriptionInputs.ObjectSpaceViewDirection,
StructFields.SurfaceDescriptionInputs.ViewSpaceViewDirection,
StructFields.SurfaceDescriptionInputs.WorldSpaceViewDirection,
StructFields.SurfaceDescriptionInputs.TangentSpaceViewDirection,
StructFields.SurfaceDescriptionInputs.ObjectSpacePosition,
StructFields.SurfaceDescriptionInputs.ViewSpacePosition,
StructFields.SurfaceDescriptionInputs.WorldSpacePosition,
StructFields.SurfaceDescriptionInputs.TangentSpacePosition,
StructFields.SurfaceDescriptionInputs.AbsoluteWorldSpacePosition,
StructFields.SurfaceDescriptionInputs.ScreenPosition,
StructFields.SurfaceDescriptionInputs.uv0,
StructFields.SurfaceDescriptionInputs.uv1,
StructFields.SurfaceDescriptionInputs.uv2,
StructFields.SurfaceDescriptionInputs.uv3,
StructFields.SurfaceDescriptionInputs.VertexColor,
StructFields.SurfaceDescriptionInputs.TimeParameters,
StructFields.SurfaceDescriptionInputs.FaceSign,
StructFields.SurfaceDescriptionInputs.BoneWeights,
StructFields.SurfaceDescriptionInputs.BoneIndices,
StructFields.SurfaceDescriptionInputs.VertexID,
}
};
}
}

View File

@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
sealed class PreviewTarget : Target
{
static readonly GUID kSourceCodeGuid = new GUID("7464b9fcde08e5645a16b9b8ae1e573c"); // PreviewTarget.cs
public PreviewTarget()
{
displayName = "Preview";
isHidden = true;
}
public override bool IsActive() => false;
public override void Setup(ref TargetSetupContext context)
{
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
context.AddSubShader(SubShaders.Preview);
}
public override void GetFields(ref TargetFieldContext context)
{
}
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
{
}
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
}
public override bool WorksWithSRP(RenderPipelineAsset scriptableRenderPipeline) => true;
static class SubShaders
{
public static SubShaderDescriptor Preview = new SubShaderDescriptor()
{
renderQueue = "Geometry",
renderType = "Opaque",
generatesPreview = true,
passes = new PassCollection { Passes.Preview },
};
}
static class Passes
{
public static PassDescriptor Preview = new PassDescriptor()
{
// Definition
referenceName = "SHADERPASS_PREVIEW",
useInPreview = true,
// Templates
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Collections
structs = new StructCollection
{
{ Structs.Attributes },
{ StructDescriptors.PreviewVaryings },
{ Structs.SurfaceDescriptionInputs },
{ Structs.VertexDescriptionInputs },
},
fieldDependencies = FieldDependencies.Default,
pragmas = new PragmaCollection
{
{ Pragma.Vertex("vert") },
{ Pragma.Fragment("frag") },
},
defines = new DefineCollection
{
{ KeywordDescriptors.PreviewKeyword, 1 },
},
includes = new IncludeCollection
{
// Pre-graph
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl", IncludeLocation.Pregraph }, // TODO: put this on a conditional
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/ShaderVariables.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/ShaderVariablesFunctions.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl", IncludeLocation.Pregraph },
// Post-graph
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/PreviewVaryings.hlsl", IncludeLocation.Postgraph },
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/PreviewPass.hlsl", IncludeLocation.Postgraph },
}
};
}
static class StructDescriptors
{
public static StructDescriptor PreviewVaryings = new StructDescriptor()
{
name = "Varyings",
packFields = true,
fields = new[]
{
StructFields.Varyings.positionCS,
StructFields.Varyings.positionWS,
StructFields.Varyings.normalWS,
StructFields.Varyings.tangentWS,
StructFields.Varyings.texCoord0,
StructFields.Varyings.texCoord1,
StructFields.Varyings.texCoord2,
StructFields.Varyings.texCoord3,
StructFields.Varyings.color,
StructFields.Varyings.viewDirectionWS,
StructFields.Varyings.screenPosition,
StructFields.Varyings.instanceID,
StructFields.Varyings.cullFace,
}
};
}
static class KeywordDescriptors
{
public static KeywordDescriptor PreviewKeyword = new KeywordDescriptor()
{
displayName = "Preview",
referenceName = "SHADERGRAPH_PREVIEW",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
}
}
}

View File

@@ -0,0 +1,148 @@
#if VFX_GRAPH_10_0_0_OR_NEWER
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Drawing;
using UnityEditor.Graphing.Util;
using UnityEditor.ShaderGraph.Internal;
using UnityEditor.ShaderGraph.Legacy;
namespace UnityEditor.ShaderGraph
{
sealed class VFXTarget : Target, ILegacyTarget
{
[SerializeField]
bool m_Lit;
[SerializeField]
bool m_AlphaTest = false;
public VFXTarget()
{
displayName = "Visual Effect";
}
public bool lit
{
get => m_Lit;
set => m_Lit = value;
}
public bool alphaTest
{
get => m_AlphaTest;
set => m_AlphaTest = value;
}
public override bool IsActive() => true;
public override void Setup(ref TargetSetupContext context)
{
}
public override void GetFields(ref TargetFieldContext context)
{
}
public override bool IsNodeAllowedByTarget(Type nodeType)
{
return base.IsNodeAllowedByTarget(nodeType);
}
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
{
context.AddBlock(BlockFields.SurfaceDescription.BaseColor);
context.AddBlock(BlockFields.SurfaceDescription.Alpha);
context.AddBlock(BlockFields.SurfaceDescription.Metallic, lit);
context.AddBlock(BlockFields.SurfaceDescription.Smoothness, lit);
context.AddBlock(BlockFields.SurfaceDescription.NormalTS, lit);
context.AddBlock(BlockFields.SurfaceDescription.Emission);
context.AddBlock(BlockFields.SurfaceDescription.AlphaClipThreshold, alphaTest);
}
enum MaterialMode
{
Unlit,
Lit
}
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
context.AddProperty("Material", new EnumField(MaterialMode.Unlit) { value = m_Lit ? MaterialMode.Lit : MaterialMode.Unlit }, evt =>
{
var newLit = (MaterialMode)evt.newValue == MaterialMode.Lit;
if (Equals(m_Lit, newLit))
return;
registerUndo("Change Material Lit");
m_Lit = newLit;
onChange();
});
context.AddProperty("Alpha Clipping", new Toggle() { value = m_AlphaTest }, (evt) =>
{
if (Equals(m_AlphaTest, evt.newValue))
return;
registerUndo("Change Alpha Test");
m_AlphaTest = evt.newValue;
onChange();
});
}
public static Dictionary<BlockFieldDescriptor, int> s_BlockMap = new Dictionary<BlockFieldDescriptor, int>()
{
{ BlockFields.SurfaceDescription.BaseColor, ShaderGraphVfxAsset.ColorSlotId },
{ BlockFields.SurfaceDescription.Metallic, ShaderGraphVfxAsset.MetallicSlotId },
{ BlockFields.SurfaceDescription.Smoothness, ShaderGraphVfxAsset.SmoothnessSlotId },
{ BlockFields.SurfaceDescription.NormalTS, ShaderGraphVfxAsset.NormalSlotId },
{ BlockFields.SurfaceDescription.Emission, ShaderGraphVfxAsset.EmissiveSlotId },
{ BlockFields.SurfaceDescription.Alpha, ShaderGraphVfxAsset.AlphaSlotId },
{ BlockFields.SurfaceDescription.AlphaClipThreshold, ShaderGraphVfxAsset.AlphaThresholdSlotId },
};
public bool TryUpgradeFromMasterNode(IMasterNode1 masterNode, out Dictionary<BlockFieldDescriptor, int> blockMap)
{
blockMap = null;
if (!(masterNode is VisualEffectMasterNode1 vfxMasterNode))
return false;
lit = vfxMasterNode.m_Lit;
alphaTest = vfxMasterNode.m_AlphaTest;
blockMap = new Dictionary<BlockFieldDescriptor, int>();
if (lit)
{
blockMap.Add(BlockFields.SurfaceDescription.BaseColor, ShaderGraphVfxAsset.BaseColorSlotId);
blockMap.Add(BlockFields.SurfaceDescription.Metallic, ShaderGraphVfxAsset.MetallicSlotId);
blockMap.Add(BlockFields.SurfaceDescription.Smoothness, ShaderGraphVfxAsset.SmoothnessSlotId);
blockMap.Add(BlockFields.SurfaceDescription.NormalTS, ShaderGraphVfxAsset.NormalSlotId);
blockMap.Add(BlockFields.SurfaceDescription.Emission, ShaderGraphVfxAsset.EmissiveSlotId);
}
else
{
blockMap.Add(BlockFields.SurfaceDescription.BaseColor, ShaderGraphVfxAsset.ColorSlotId);
}
blockMap.Add(BlockFields.SurfaceDescription.Alpha, ShaderGraphVfxAsset.AlphaSlotId);
if (alphaTest)
{
blockMap.Add(BlockFields.SurfaceDescription.AlphaClipThreshold, ShaderGraphVfxAsset.AlphaThresholdSlotId);
}
return true;
}
public override bool WorksWithSRP(RenderPipelineAsset scriptableRenderPipeline)
{
return GraphicsSettings.currentRenderPipeline != null && scriptableRenderPipeline?.GetType() == GraphicsSettings.currentRenderPipeline.GetType();
}
}
}
#endif

View File

@@ -0,0 +1,57 @@
SurfaceDescriptionInputs BuildSurfaceDescriptionInputs(Varyings input)
{
SurfaceDescriptionInputs output;
ZERO_INITIALIZE(SurfaceDescriptionInputs, output);
$SurfaceDescriptionInputs.WorldSpaceNormal: // must use interpolated tangent, bitangent and normal before they are normalized in the pixel shader.
$SurfaceDescriptionInputs.WorldSpaceNormal: float3 unnormalizedNormalWS = input.normalWS;
$SurfaceDescriptionInputs.WorldSpaceNormal: const float renormFactor = 1.0 / length(unnormalizedNormalWS);
$SurfaceDescriptionInputs.WorldSpaceBiTangent: // use bitangent on the fly like in hdrp
$SurfaceDescriptionInputs.WorldSpaceBiTangent: // IMPORTANT! If we ever support Flip on double sided materials ensure bitangent and tangent are NOT flipped.
$SurfaceDescriptionInputs.WorldSpaceBiTangent: float crossSign = (input.tangentWS.w > 0.0 ? 1.0 : -1.0) * GetOddNegativeScale();
$SurfaceDescriptionInputs.WorldSpaceBiTangent: float3 bitang = crossSign * cross(input.normalWS.xyz, input.tangentWS.xyz);
$SurfaceDescriptionInputs.WorldSpaceNormal: output.WorldSpaceNormal = renormFactor*input.normalWS.xyz; // we want a unit length Normal Vector node in shader graph
$SurfaceDescriptionInputs.ObjectSpaceNormal: output.ObjectSpaceNormal = normalize(mul(output.WorldSpaceNormal, (float3x3) UNITY_MATRIX_M)); // transposed multiplication by inverse matrix to handle normal scale
$SurfaceDescriptionInputs.ViewSpaceNormal: output.ViewSpaceNormal = mul(output.WorldSpaceNormal, (float3x3) UNITY_MATRIX_I_V); // transposed multiplication by inverse matrix to handle normal scale
$SurfaceDescriptionInputs.TangentSpaceNormal: output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f);
$SurfaceDescriptionInputs.WorldSpaceTangent: // to preserve mikktspace compliance we use same scale renormFactor as was used on the normal.
$SurfaceDescriptionInputs.WorldSpaceTangent: // This is explained in section 2.2 in "surface gradient based bump mapping framework"
$SurfaceDescriptionInputs.WorldSpaceTangent: output.WorldSpaceTangent = renormFactor*input.tangentWS.xyz;
$SurfaceDescriptionInputs.WorldSpaceBiTangent: output.WorldSpaceBiTangent = renormFactor*bitang;
$SurfaceDescriptionInputs.ObjectSpaceTangent: output.ObjectSpaceTangent = TransformWorldToObjectDir(output.WorldSpaceTangent);
$SurfaceDescriptionInputs.ViewSpaceTangent: output.ViewSpaceTangent = TransformWorldToViewDir(output.WorldSpaceTangent);
$SurfaceDescriptionInputs.TangentSpaceTangent: output.TangentSpaceTangent = float3(1.0f, 0.0f, 0.0f);
$SurfaceDescriptionInputs.ObjectSpaceBiTangent: output.ObjectSpaceBiTangent = TransformWorldToObjectDir(output.WorldSpaceBiTangent);
$SurfaceDescriptionInputs.ViewSpaceBiTangent: output.ViewSpaceBiTangent = TransformWorldToViewDir(output.WorldSpaceBiTangent);
$SurfaceDescriptionInputs.TangentSpaceBiTangent: output.TangentSpaceBiTangent = float3(0.0f, 1.0f, 0.0f);
$SurfaceDescriptionInputs.WorldSpaceViewDirection: output.WorldSpaceViewDirection = input.viewDirectionWS; //TODO: by default normalized in HD, but not in universal
$SurfaceDescriptionInputs.ObjectSpaceViewDirection: output.ObjectSpaceViewDirection = TransformWorldToObjectDir(output.WorldSpaceViewDirection);
$SurfaceDescriptionInputs.ViewSpaceViewDirection: output.ViewSpaceViewDirection = TransformWorldToViewDir(output.WorldSpaceViewDirection);
$SurfaceDescriptionInputs.TangentSpaceViewDirection: float3x3 tangentSpaceTransform = float3x3(output.WorldSpaceTangent,output.WorldSpaceBiTangent,output.WorldSpaceNormal);
$SurfaceDescriptionInputs.TangentSpaceViewDirection: output.TangentSpaceViewDirection = length(output.WorldSpaceViewDirection) * TransformWorldToTangent(output.WorldSpaceViewDirection, tangentSpaceTransform);
$SurfaceDescriptionInputs.WorldSpacePosition: output.WorldSpacePosition = input.positionWS;
$SurfaceDescriptionInputs.ObjectSpacePosition: output.ObjectSpacePosition = TransformWorldToObject(input.positionWS);
$SurfaceDescriptionInputs.ViewSpacePosition: output.ViewSpacePosition = TransformWorldToView(input.positionWS);
$SurfaceDescriptionInputs.TangentSpacePosition: output.TangentSpacePosition = float3(0.0f, 0.0f, 0.0f);
$SurfaceDescriptionInputs.AbsoluteWorldSpacePosition:output.AbsoluteWorldSpacePosition = GetAbsolutePositionWS(input.positionWS);
$SurfaceDescriptionInputs.ScreenPosition: output.ScreenPosition = ComputeScreenPos(TransformWorldToHClip(input.positionWS), _ProjectionParams.x);
$SurfaceDescriptionInputs.uv0: output.uv0 = input.texCoord0;
$SurfaceDescriptionInputs.uv1: output.uv1 = input.texCoord1;
$SurfaceDescriptionInputs.uv2: output.uv2 = input.texCoord2;
$SurfaceDescriptionInputs.uv3: output.uv3 = input.texCoord3;
$SurfaceDescriptionInputs.VertexColor: output.VertexColor = input.color;
$SurfaceDescriptionInputs.TimeParameters: output.TimeParameters = _TimeParameters.xyz; // This is mainly for LW as HD overwrite this value
#if defined(SHADER_STAGE_FRAGMENT) && defined(VARYINGS_NEED_CULLFACE)
#define BUILD_SURFACE_DESCRIPTION_INPUTS_OUTPUT_FACESIGN output.FaceSign = IS_FRONT_VFACE(input.cullFace, true, false);
#else
#define BUILD_SURFACE_DESCRIPTION_INPUTS_OUTPUT_FACESIGN
#endif
$SurfaceDescriptionInputs.FaceSign: BUILD_SURFACE_DESCRIPTION_INPUTS_OUTPUT_FACESIGN
#undef BUILD_SURFACE_DESCRIPTION_INPUTS_OUTPUT_FACESIGN
return output;
}

View File

@@ -0,0 +1,40 @@
VertexDescriptionInputs BuildVertexDescriptionInputs(Attributes input)
{
VertexDescriptionInputs output;
ZERO_INITIALIZE(VertexDescriptionInputs, output);
$VertexDescriptionInputs.ObjectSpaceNormal: output.ObjectSpaceNormal = input.normalOS;
$VertexDescriptionInputs.WorldSpaceNormal: output.WorldSpaceNormal = TransformObjectToWorldNormal(input.normalOS);
$VertexDescriptionInputs.ViewSpaceNormal: output.ViewSpaceNormal = TransformWorldToViewDir(output.WorldSpaceNormal);
$VertexDescriptionInputs.TangentSpaceNormal: output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f);
$VertexDescriptionInputs.ObjectSpaceTangent: output.ObjectSpaceTangent = input.tangentOS.xyz;
$VertexDescriptionInputs.WorldSpaceTangent: output.WorldSpaceTangent = TransformObjectToWorldDir(input.tangentOS.xyz);
$VertexDescriptionInputs.ViewSpaceTangent: output.ViewSpaceTangent = TransformWorldToViewDir(output.WorldSpaceTangent);
$VertexDescriptionInputs.TangentSpaceTangent: output.TangentSpaceTangent = float3(1.0f, 0.0f, 0.0f);
$VertexDescriptionInputs.ObjectSpaceBiTangent: output.ObjectSpaceBiTangent = normalize(cross(input.normalOS, input.tangentOS) * (input.tangentOS.w > 0.0f ? 1.0f : -1.0f) * GetOddNegativeScale());
$VertexDescriptionInputs.WorldSpaceBiTangent: output.WorldSpaceBiTangent = TransformObjectToWorldDir(output.ObjectSpaceBiTangent);
$VertexDescriptionInputs.ViewSpaceBiTangent: output.ViewSpaceBiTangent = TransformWorldToViewDir(output.WorldSpaceBiTangent);
$VertexDescriptionInputs.TangentSpaceBiTangent: output.TangentSpaceBiTangent = float3(0.0f, 1.0f, 0.0f);
$VertexDescriptionInputs.ObjectSpacePosition: output.ObjectSpacePosition = input.positionOS;
$VertexDescriptionInputs.WorldSpacePosition: output.WorldSpacePosition = TransformObjectToWorld(input.positionOS);
$VertexDescriptionInputs.ViewSpacePosition: output.ViewSpacePosition = TransformWorldToView(output.WorldSpacePosition);
$VertexDescriptionInputs.TangentSpacePosition: output.TangentSpacePosition = float3(0.0f, 0.0f, 0.0f);
$VertexDescriptionInputs.AbsoluteWorldSpacePosition:output.AbsoluteWorldSpacePosition = GetAbsolutePositionWS(TransformObjectToWorld(input.positionOS));
$VertexDescriptionInputs.WorldSpaceViewDirection: output.WorldSpaceViewDirection = GetWorldSpaceNormalizeViewDir(output.WorldSpacePosition);
$VertexDescriptionInputs.ObjectSpaceViewDirection: output.ObjectSpaceViewDirection = TransformWorldToObjectDir(output.WorldSpaceViewDirection);
$VertexDescriptionInputs.ViewSpaceViewDirection: output.ViewSpaceViewDirection = length(output.WorldSpaceViewDirection) * TransformWorldToViewDir(output.WorldSpaceViewDirection);
$VertexDescriptionInputs.TangentSpaceViewDirection: float3x3 tangentSpaceTransform = float3x3(output.WorldSpaceTangent,output.WorldSpaceBiTangent,output.WorldSpaceNormal);
$VertexDescriptionInputs.TangentSpaceViewDirection: output.TangentSpaceViewDirection = TransformWorldToTangent(output.WorldSpaceViewDirection, tangentSpaceTransform);
$VertexDescriptionInputs.ScreenPosition: output.ScreenPosition = ComputeScreenPos(TransformWorldToHClip(output.WorldSpacePosition), _ProjectionParams.x);
$VertexDescriptionInputs.uv0: output.uv0 = input.uv0;
$VertexDescriptionInputs.uv1: output.uv1 = input.uv1;
$VertexDescriptionInputs.uv2: output.uv2 = input.uv2;
$VertexDescriptionInputs.uv3: output.uv3 = input.uv3;
$VertexDescriptionInputs.VertexColor: output.VertexColor = input.color;
$VertexDescriptionInputs.TimeParameters: output.TimeParameters = _TimeParameters.xyz;
$VertexDescriptionInputs.BoneWeights: output.BoneWeights = input.weights;
$VertexDescriptionInputs.BoneIndices: output.BoneIndices = input.indices;
$VertexDescriptionInputs.VertexID: output.VertexID = input.vertexID;
return output;
}

View File

@@ -0,0 +1,103 @@
Pass
{
$splice(PassName)
Tags
{
$splice(LightMode)
}
// Render State
$splice(RenderState)
// Debug
$splice(Debug)
// --------------------------------------------------
// Pass
HLSLPROGRAM
// Pragmas
$splice(PassPragmas)
$splice(DotsInstancingOptions)
$splice(HybridV1InjectedBuiltinProperties)
// Keywords
$splice(PassKeywords)
$splice(GraphKeywords)
// Defines
$SurfaceType.Transparent: #define _SURFACE_TYPE_TRANSPARENT 1
$AlphaClip: #define _AlphaClip 1
$Normal: #define _NORMALMAP 1
$SpecularSetup: #define _SPECULAR_SETUP
$BlendMode.Add: #define _BLENDMODE_ADD 1
$BlendMode.Premultiply: #define _ALPHAPREMULTIPLY_ON 1
$NormalDropOffTS: #define _NORMAL_DROPOFF_TS 1
$NormalDropOffOS: #define _NORMAL_DROPOFF_OS 1
$NormalDropOffWS: #define _NORMAL_DROPOFF_WS 1
$Attributes.normalOS: #define ATTRIBUTES_NEED_NORMAL
$Attributes.tangentOS: #define ATTRIBUTES_NEED_TANGENT
$Attributes.uv0: #define ATTRIBUTES_NEED_TEXCOORD0
$Attributes.uv1: #define ATTRIBUTES_NEED_TEXCOORD1
$Attributes.uv2: #define ATTRIBUTES_NEED_TEXCOORD2
$Attributes.uv3: #define ATTRIBUTES_NEED_TEXCOORD3
$Attributes.color: #define ATTRIBUTES_NEED_COLOR
$Varyings.positionWS: #define VARYINGS_NEED_POSITION_WS
$Varyings.normalWS: #define VARYINGS_NEED_NORMAL_WS
$Varyings.tangentWS: #define VARYINGS_NEED_TANGENT_WS
$Varyings.texCoord0: #define VARYINGS_NEED_TEXCOORD0
$Varyings.texCoord1: #define VARYINGS_NEED_TEXCOORD1
$Varyings.texCoord2: #define VARYINGS_NEED_TEXCOORD2
$Varyings.texCoord3: #define VARYINGS_NEED_TEXCOORD3
$Varyings.color: #define VARYINGS_NEED_COLOR
$Varyings.viewDirectionWS: #define VARYINGS_NEED_VIEWDIRECTION_WS
$Varyings.bitangentWS: #define VARYINGS_NEED_BITANGENT_WS
$Varyings.screenPosition: #define VARYINGS_NEED_SCREENPOSITION
$Varyings.fogFactorAndVertexLight: #define VARYINGS_NEED_FOG_AND_VERTEX_LIGHT
$Varyings.cullFace: #define VARYINGS_NEED_CULLFACE
$features.graphVertex: #define FEATURES_GRAPH_VERTEX
$Universal.UseLegacySpriteBlocks: #define UNIVERSAL_USELEGACYSPRITEBLOCKS
$splice(PassInstancing)
$splice(GraphDefines)
$splice(DotsInstancingVars)
// Includes
$splice(PreGraphIncludes)
// --------------------------------------------------
// Structs and Packing
$splice(PassStructs)
$splice(InterpolatorPack)
// --------------------------------------------------
// Graph
// Graph Properties
$splice(GraphProperties)
// Graph Functions
$splice(GraphFunctions)
// Graph Vertex
$splice(GraphVertex)
// Graph Pixel
$splice(GraphPixel)
// --------------------------------------------------
// Build Graph Inputs
$features.graphVertex: $include("BuildVertexDescriptionInputs.template.hlsl")
$features.graphPixel: $include("BuildSurfaceDescriptionInputs.template.hlsl")
// --------------------------------------------------
// Main
$splice(PostGraphIncludes)
ENDHLSL
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Serialization;
using UnityEngine.Pool;
namespace UnityEditor.ShaderGraph
{
static class TargetUtils
{
public static void ProcessSubTargetList(ref JsonData<SubTarget> activeSubTarget, ref List<SubTarget> subTargets)
{
if (subTargets == null || subTargets.Count == 0)
return;
// assign the initial sub-target, if none is assigned yet
if (activeSubTarget.value == null)
{
// this is a bit of a hack: prefer subtargets named "Lit" if they exist, otherwise default to the first one
// in the future, we should make the default sub-target user configurable
var litSubTarget = subTargets.FirstOrDefault(x => x.displayName == "Lit");
if (litSubTarget != null)
activeSubTarget = litSubTarget;
else
activeSubTarget = subTargets[0];
return;
}
// Update SubTarget list with active SubTarget
var activeSubTargetType = activeSubTarget.value.GetType();
var activeSubTargetCurrent = subTargets.FirstOrDefault(x => x.GetType() == activeSubTargetType);
var index = subTargets.IndexOf(activeSubTargetCurrent);
subTargets[index] = activeSubTarget;
}
public static List<SubTarget> GetSubTargets<T>(T target) where T : Target
{
// Get Variants
var subTargets = ListPool<SubTarget>.Get();
var typeCollection = TypeCache.GetTypesDerivedFrom<SubTarget>();
foreach (var type in typeCollection)
{
if (type.IsAbstract || !type.IsClass)
continue;
var subTarget = (SubTarget)Activator.CreateInstance(type);
if (!subTarget.isHidden && subTarget.targetType.Equals(typeof(T)))
{
subTarget.target = target;
subTargets.Add(subTarget);
}
}
return subTargets;
}
}
}