initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
@ -0,0 +1,120 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Calculate Level Of Detail Texture 2D")]
|
||||
class CalculateLevelOfDetailTexture2DNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireMeshUV
|
||||
{
|
||||
[SerializeField]
|
||||
bool m_Clamp = true;
|
||||
|
||||
[ToggleControl]
|
||||
public ToggleData clamp
|
||||
{
|
||||
get => new ToggleData(m_Clamp);
|
||||
set
|
||||
{
|
||||
m_Clamp = value.isOn;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
public const int OutputSlotLODId = 0;
|
||||
public const int TextureInputId = 1;
|
||||
public const int UVInput = 2;
|
||||
public const int SamplerInput = 3;
|
||||
|
||||
const string kOutputSlotLODName = "LOD";
|
||||
const string kTextureInputName = "Texture";
|
||||
const string kUVInputName = "UV";
|
||||
const string kSamplerInputName = "Sampler";
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public CalculateLevelOfDetailTexture2DNode()
|
||||
{
|
||||
name = "Calculate Level Of Detail Texture 2D";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotLODId, kOutputSlotLODName, kOutputSlotLODName, SlotType.Output, 0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
|
||||
AddSlot(new UVMaterialSlot(UVInput, kUVInputName, kUVInputName, UVChannel.UV0));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input));
|
||||
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotLODId, TextureInputId, UVInput, SamplerInput });
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
var textureSlot = FindInputSlot<Texture2DInputMaterialSlot>(TextureInputId);
|
||||
textureSlot.defaultType = Texture2DShaderProperty.DefaultType.White;
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var uvName = GetSlotValue(UVInput, generationMode);
|
||||
|
||||
//Sampler input slot
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInput);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
|
||||
var id = GetSlotValue(TextureInputId, generationMode);
|
||||
|
||||
sb.AppendLine("#if (SHADER_TARGET >= 41)");
|
||||
{
|
||||
var func = m_Clamp ? "CalculateLevelOfDetail" : "CalculateLevelOfDetailUnclamped";
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.tex.{2}({3}.samplerstate, {4});"
|
||||
, GetVariableNameForSlot(OutputSlotLODId)
|
||||
, id
|
||||
, func
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id
|
||||
, uvName));
|
||||
}
|
||||
sb.AppendLine("#else");
|
||||
{
|
||||
var dUVdx = string.Format("ddx({0} * {1}.texelSize.zw)", uvName, id);
|
||||
var dUVdy = string.Format("ddy({0} * {1}.texelSize.zw)", uvName, id);
|
||||
var delta_max_sqr = string.Format("max(dot({0}, {0}), dot({1}, {1}))", dUVdx, dUVdy);
|
||||
sb.AppendLine(string.Format("$precision {0};", GetVariableNameForSlot(OutputSlotLODId)));
|
||||
sb.AppendLine(string.Format("{0} = 0.5f*log2({1});", GetVariableNameForSlot(OutputSlotLODId), delta_max_sqr));
|
||||
sb.AppendLine(string.Format("{0} = max({0}, 0);", GetVariableNameForSlot(OutputSlotLODId)));
|
||||
if (m_Clamp)
|
||||
{
|
||||
sb.AppendLine("#if defined(MIP_COUNT_SUPPORTED)");
|
||||
sb.AppendLine(string.Format("{0} = min({0}, GetMipCount(TEXTURE2D_ARGS({1}.tex, {2}.samplerstate))-1);", GetVariableNameForSlot(OutputSlotLODId), id, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id));
|
||||
sb.AppendLine("#endif");
|
||||
}
|
||||
}
|
||||
sb.AppendLine("#endif");
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
var result = false;
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresMeshUV(channel))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tempSlots.Clear();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 03cdc5d395730c74ebabff3988c5110d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,100 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Cubemap Asset")]
|
||||
[HasDependencies(typeof(MinimalCubemapAssetNode))]
|
||||
class CubemapAssetNode : AbstractMaterialNode, IPropertyFromNode
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public CubemapAssetNode()
|
||||
{
|
||||
name = "Cubemap Asset";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new CubemapMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private SerializableCubemap m_Cubemap = new SerializableCubemap();
|
||||
|
||||
[CubemapControl("")]
|
||||
public Cubemap cubemap
|
||||
{
|
||||
get { return m_Cubemap.cubemap; }
|
||||
set
|
||||
{
|
||||
if (m_Cubemap.cubemap == value)
|
||||
return;
|
||||
m_Cubemap.cubemap = value;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
string GetTexturePropertyName()
|
||||
{
|
||||
return base.GetVariableNameForSlot(OutputSlotId);
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return $"UnityBuildTextureCubeStruct({GetTexturePropertyName()})";
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
properties.AddShaderProperty(new CubemapShaderProperty()
|
||||
{
|
||||
overrideReferenceName = GetTexturePropertyName(),
|
||||
generatePropertyBlock = true,
|
||||
value = m_Cubemap,
|
||||
modifiable = false
|
||||
});
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
properties.Add(new PreviewProperty(PropertyType.Cubemap)
|
||||
{
|
||||
name = GetTexturePropertyName(),
|
||||
cubemapValue = cubemap
|
||||
});
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
var prop = new CubemapShaderProperty { value = m_Cubemap };
|
||||
if (cubemap != null)
|
||||
prop.displayName = cubemap.name;
|
||||
return prop;
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
|
||||
class MinimalCubemapAssetNode : IHasDependencies
|
||||
{
|
||||
[SerializeField]
|
||||
private SerializableCubemap m_Cubemap = null;
|
||||
|
||||
public void GetSourceAssetDependencies(AssetCollection assetCollection)
|
||||
{
|
||||
var guidString = m_Cubemap.guid;
|
||||
if (!string.IsNullOrEmpty(guidString) && GUID.TryParse(guidString, out var guid))
|
||||
{
|
||||
assetCollection.AddAssetDependency(guid, AssetCollection.Flags.IncludeInExportPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 968ed0a541658844486b1ac5ab57ee2d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,131 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Gather Texture 2D")]
|
||||
class GatherTexture2DNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireMeshUV
|
||||
{
|
||||
public const int OutputSlotRGBAId = 0;
|
||||
public const int OutputSlotRId = 5;
|
||||
public const int OutputSlotGId = 6;
|
||||
public const int OutputSlotBId = 7;
|
||||
public const int OutputSlotAId = 8;
|
||||
public const int TextureInputId = 1;
|
||||
public const int UVInput = 2;
|
||||
public const int SamplerInput = 3;
|
||||
public const int OffsetInput = 4;
|
||||
|
||||
const string kOutputSlotRGBAName = "RGBA";
|
||||
const string kOutputSlotRName = "R";
|
||||
const string kOutputSlotGName = "G";
|
||||
const string kOutputSlotBName = "B";
|
||||
const string kOutputSlotAName = "A";
|
||||
const string kTextureInputName = "Texture";
|
||||
const string kUVInputName = "UV";
|
||||
const string kSamplerInputName = "Sampler";
|
||||
const string kOffsetInputName = "Offset";
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public GatherTexture2DNode()
|
||||
{
|
||||
name = "Gather Texture 2D";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero, ShaderStageCapability.All));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
|
||||
AddSlot(new UVMaterialSlot(UVInput, kUVInputName, kUVInputName, UVChannel.UV0));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input));
|
||||
AddSlot(new Vector2MaterialSlot(OffsetInput, kOffsetInputName, kOffsetInputName, SlotType.Input, Vector2.zero, ShaderStageCapability.All, null, null, false, true));
|
||||
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotRGBAId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId, TextureInputId, UVInput, SamplerInput, OffsetInput });
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
var textureSlot = FindInputSlot<Texture2DInputMaterialSlot>(TextureInputId);
|
||||
textureSlot.defaultType = Texture2DShaderProperty.DefaultType.White;
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var uvName = GetSlotValue(UVInput, generationMode);
|
||||
|
||||
//Sampler input slot
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInput);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
|
||||
var id = GetSlotValue(TextureInputId, generationMode);
|
||||
var offset = GetSlotValue(OffsetInput, generationMode);
|
||||
|
||||
sb.AppendLine("#if (SHADER_TARGET >= 41)");
|
||||
{
|
||||
sb.AppendLine(string.Format("$precision4 {0} = {1}.tex.Gather({2}.samplerstate, {3}, {4});"
|
||||
, GetVariableNameForSlot(OutputSlotRGBAId)
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id
|
||||
, uvName
|
||||
, offset));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.r;", GetVariableNameForSlot(OutputSlotRId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.g;", GetVariableNameForSlot(OutputSlotGId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.b;", GetVariableNameForSlot(OutputSlotBId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.a;", GetVariableNameForSlot(OutputSlotAId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
}
|
||||
sb.AppendLine("#else");
|
||||
{
|
||||
// Gather offsets defined in this order:
|
||||
// (-,+),(+,+),(+,-),(-,-)
|
||||
|
||||
var uvR = string.Format("(floor({0} * {1}.texelSize.zw + $precision2(-0.5, 0.5)) + trunc({2}) + $precision2(0.5, 0.5)) * {1}.texelSize.xy", uvName, id, offset);
|
||||
var uvG = string.Format("(floor({0} * {1}.texelSize.zw + $precision2(0.5, 0.5)) + trunc({2}) + $precision2(0.5, 0.5)) * {1}.texelSize.xy", uvName, id, offset);
|
||||
var uvB = string.Format("(floor({0} * {1}.texelSize.zw + $precision2(0.5, -0.5)) + trunc({2}) + $precision2(0.5, 0.5)) * {1}.texelSize.xy", uvName, id, offset);
|
||||
var uvA = string.Format("(floor({0} * {1}.texelSize.zw + $precision2(-0.5, -0.5)) + trunc({2}) + $precision2(0.5, 0.5)) * {1}.texelSize.xy", uvName, id, offset);
|
||||
|
||||
sb.AppendLine(string.Format("$precision {0} = SAMPLE_TEXTURE2D_LOD({1}.tex, {2}.samplerstate, {3}, 0).r;", GetVariableNameForSlot(OutputSlotRId), id, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id, uvR));
|
||||
sb.AppendLine(string.Format("$precision {0} = SAMPLE_TEXTURE2D_LOD({1}.tex, {2}.samplerstate, {3}, 0).r;", GetVariableNameForSlot(OutputSlotGId), id, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id, uvG));
|
||||
sb.AppendLine(string.Format("$precision {0} = SAMPLE_TEXTURE2D_LOD({1}.tex, {2}.samplerstate, {3}, 0).r;", GetVariableNameForSlot(OutputSlotBId), id, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id, uvB));
|
||||
sb.AppendLine(string.Format("$precision {0} = SAMPLE_TEXTURE2D_LOD({1}.tex, {2}.samplerstate, {3}, 0).r;", GetVariableNameForSlot(OutputSlotAId), id, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id, uvA));
|
||||
|
||||
sb.AppendLine(string.Format("$precision4 {0} = $precision4({1},{2},{3},{4});"
|
||||
, GetVariableNameForSlot(OutputSlotRGBAId)
|
||||
, GetVariableNameForSlot(OutputSlotRId)
|
||||
, GetVariableNameForSlot(OutputSlotGId)
|
||||
, GetVariableNameForSlot(OutputSlotBId)
|
||||
, GetVariableNameForSlot(OutputSlotAId)));
|
||||
}
|
||||
sb.AppendLine("#endif");
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
var result = false;
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresMeshUV(channel))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tempSlots.Clear();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e52355d9fc877154b9403531b2837081
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,136 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
#if PROCEDURAL_VT_IN_GRAPH
|
||||
[Title("Input", "Texture", "Procedural Virtual Texture")]
|
||||
class ProceduralVirtualTextureNode : AbstractMaterialNode
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public ProceduralVirtualTextureNode()
|
||||
{
|
||||
UpdateNodeAfterDeserialization();
|
||||
SetLayerCount(2);
|
||||
|
||||
vtProperty.displayName = "ProceduralVirtualTexture";
|
||||
vtProperty.overrideReferenceName = "MyPVT";
|
||||
vtProperty.value.procedural = true;
|
||||
vtProperty.value.shaderDeclaration = HLSLDeclaration.UnityPerMaterial;
|
||||
|
||||
UpdateName();
|
||||
}
|
||||
|
||||
void UpdateName()
|
||||
{
|
||||
name = "Procedural Virtual Texture: " + vtProperty.overrideReferenceName;
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new VirtualTextureMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
|
||||
SetLayerCount(layers);
|
||||
vtProperty.generatePropertyBlock = true;
|
||||
vtProperty.hidden = true;
|
||||
}
|
||||
|
||||
public override int latestVersion => 1;
|
||||
public override void OnAfterMultiDeserialize(string json)
|
||||
{
|
||||
if (sgVersion == 0)
|
||||
{
|
||||
// version 0 was implicitly declaring PVT stacks as Global shader properties
|
||||
shaderDeclaration = HLSLDeclaration.Global;
|
||||
ChangeVersion(1);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private VirtualTextureShaderProperty vtProperty = new VirtualTextureShaderProperty();
|
||||
|
||||
void SetLayerCount(int layers)
|
||||
{
|
||||
var uniqueName = objectId;
|
||||
vtProperty.value.layers.Clear();
|
||||
layers = System.Math.Max(System.Math.Min(layers, SampleVirtualTextureNode.kMaxLayers), SampleVirtualTextureNode.kMinLayers);
|
||||
for (int x = 0; x < layers; x++)
|
||||
{
|
||||
vtProperty.value.layers.Add(new SerializableVirtualTextureLayer("Layer" + x + "_" + uniqueName, "Layer" + x + "_" + uniqueName, null));
|
||||
}
|
||||
}
|
||||
|
||||
[IdentifierControl("Name")]
|
||||
public string vtName
|
||||
{
|
||||
get { return vtProperty.overrideReferenceName; }
|
||||
set
|
||||
{
|
||||
if (vtProperty.overrideReferenceName == value)
|
||||
return;
|
||||
vtProperty.overrideReferenceName = value;
|
||||
UpdateName();
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
[IntegerControl("Layers")]
|
||||
public int layers
|
||||
{
|
||||
get { return vtProperty.value.layers.Count; }
|
||||
set
|
||||
{
|
||||
if (vtProperty.value.layers.Count == value)
|
||||
return;
|
||||
|
||||
SetLayerCount(value);
|
||||
Dirty(ModificationScope.Topological);
|
||||
//Hack to handle downstream SampleVirtualTextureNodes
|
||||
owner.ValidateGraph();
|
||||
}
|
||||
}
|
||||
|
||||
internal HLSLDeclaration shaderDeclaration
|
||||
{
|
||||
get { return vtProperty.value.shaderDeclaration; }
|
||||
set
|
||||
{
|
||||
if (vtProperty.value.shaderDeclaration == value)
|
||||
return;
|
||||
|
||||
vtProperty.value.shaderDeclaration = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
properties.AddShaderProperty(vtProperty);
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
properties.Add(new PreviewProperty(PropertyType.VirtualTexture)
|
||||
{
|
||||
name = GetVariableNameForSlot(OutputSlotId),
|
||||
vtProperty = vtProperty
|
||||
});
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
return vtProperty;
|
||||
}
|
||||
|
||||
// to show Shader Declaration in the node settings, as if this node was itself a real AbstractShaderProperty
|
||||
internal bool AllowHLSLDeclaration(HLSLDeclaration decl) =>
|
||||
(decl == HLSLDeclaration.Global || decl == HLSLDeclaration.UnityPerMaterial);
|
||||
}
|
||||
#endif // PROCEDURAL_VT_IN_GRAPH
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 49a3a90a50f5fbf4ba608b8e4afe373a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,91 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[FormerName("UnityEditor.ShaderGraph.CubemapNode")]
|
||||
[Title("Input", "Texture", "Sample Reflected Cubemap")]
|
||||
class SampleCubemapNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireViewDirection, IMayRequireNormal
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
public const int CubemapInputId = 1;
|
||||
public const int ViewDirInputId = 2;
|
||||
public const int NormalInputId = 3;
|
||||
public const int SamplerInputId = 5;
|
||||
public const int LODInputId = 4;
|
||||
const string kOutputSlotName = "Out";
|
||||
const string kCubemapInputName = "Cube";
|
||||
const string kViewDirInputName = "ViewDir";
|
||||
const string kNormalInputName = "Normal";
|
||||
const string kSamplerInputName = "Sampler";
|
||||
const string kLODInputName = "LOD";
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public SampleCubemapNode()
|
||||
{
|
||||
name = "Sample Reflected Cubemap";
|
||||
m_PreviewMode = PreviewMode.Preview3D;
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
|
||||
AddSlot(new CubemapInputMaterialSlot(CubemapInputId, kCubemapInputName, kCubemapInputName));
|
||||
AddSlot(new ViewDirectionMaterialSlot(ViewDirInputId, kViewDirInputName, kViewDirInputName, CoordinateSpace.Object));
|
||||
AddSlot(new NormalMaterialSlot(NormalInputId, kNormalInputName, kNormalInputName, CoordinateSpace.Object));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInputId, kSamplerInputName, kSamplerInputName, SlotType.Input));
|
||||
AddSlot(new Vector1MaterialSlot(LODInputId, kLODInputName, kLODInputName, SlotType.Input, 0));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId, CubemapInputId, ViewDirInputId, NormalInputId, SamplerInputId, LODInputId });
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
//Sampler input slot
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInputId);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
|
||||
var id = GetSlotValue(CubemapInputId, generationMode);
|
||||
string result = string.Format("$precision4 {0} = SAMPLE_TEXTURECUBE_LOD({1}.tex, {2}.samplerstate, reflect(-{3}, {4}), {5});"
|
||||
, GetVariableNameForSlot(OutputSlotId)
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : id
|
||||
, GetSlotValue(ViewDirInputId, generationMode)
|
||||
, GetSlotValue(NormalInputId, generationMode)
|
||||
, GetSlotValue(LODInputId, generationMode));
|
||||
|
||||
sb.AppendLine(result);
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
|
||||
{
|
||||
var viewDirSlot = FindInputSlot<MaterialSlot>(ViewDirInputId);
|
||||
var edgesViewDir = owner.GetEdges(viewDirSlot.slotReference);
|
||||
if (!edgesViewDir.Any())
|
||||
return CoordinateSpace.Object.ToNeededCoordinateSpace();
|
||||
else
|
||||
return NeededCoordinateSpace.None;
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
|
||||
{
|
||||
var normalSlot = FindInputSlot<MaterialSlot>(NormalInputId);
|
||||
var edgesNormal = owner.GetEdges(normalSlot.slotReference);
|
||||
if (!edgesNormal.Any())
|
||||
return CoordinateSpace.Object.ToNeededCoordinateSpace();
|
||||
else
|
||||
return NeededCoordinateSpace.None;
|
||||
}
|
||||
|
||||
public override void OnAfterDeserialize()
|
||||
{
|
||||
base.OnAfterDeserialize();
|
||||
|
||||
name = "Sample Reflected Cubemap";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6eaeb9c846408f74daeadcc3314810e4
|
||||
timeCreated: 1495637741
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,76 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Sample Cubemap")]
|
||||
class SampleRawCubemapNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireNormal
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
public const int CubemapInputId = 1;
|
||||
public const int NormalInputId = 2;
|
||||
public const int SamplerInputId = 3;
|
||||
public const int LODInputId = 4;
|
||||
const string kOutputSlotName = "Out";
|
||||
const string kCubemapInputName = "Cube";
|
||||
const string kNormalInputName = "Dir";
|
||||
const string kSamplerInputName = "Sampler";
|
||||
const string kLODInputName = "LOD";
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public SampleRawCubemapNode()
|
||||
{
|
||||
name = "Sample Cubemap";
|
||||
m_PreviewMode = PreviewMode.Preview3D;
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero));
|
||||
AddSlot(new CubemapInputMaterialSlot(CubemapInputId, kCubemapInputName, kCubemapInputName));
|
||||
AddSlot(new NormalMaterialSlot(NormalInputId, kNormalInputName, kNormalInputName, CoordinateSpace.World));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInputId, kSamplerInputName, kSamplerInputName, SlotType.Input));
|
||||
AddSlot(new Vector1MaterialSlot(LODInputId, kLODInputName, kLODInputName, SlotType.Input, 0));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId, CubemapInputId, NormalInputId, SamplerInputId, LODInputId });
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
//Sampler input slot
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInputId);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
|
||||
var id = GetSlotValue(CubemapInputId, generationMode);
|
||||
string result = string.Format("$precision4 {0} = SAMPLE_TEXTURECUBE_LOD({1}.tex, {2}.samplerstate, {3}, {4});"
|
||||
, GetVariableNameForSlot(OutputSlotId)
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : id
|
||||
, GetSlotValue(NormalInputId, generationMode)
|
||||
, GetSlotValue(LODInputId, generationMode));
|
||||
|
||||
sb.AppendLine(result);
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
|
||||
{
|
||||
var normalSlot = FindInputSlot<MaterialSlot>(NormalInputId);
|
||||
var edgesNormal = owner.GetEdges(normalSlot.slotReference);
|
||||
if (!edgesNormal.Any())
|
||||
return CoordinateSpace.World.ToNeededCoordinateSpace();
|
||||
else
|
||||
return NeededCoordinateSpace.None;
|
||||
}
|
||||
|
||||
public override void OnAfterDeserialize()
|
||||
{
|
||||
base.OnAfterDeserialize();
|
||||
|
||||
name = "Sample Cubemap";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1790cabd561426148b5f93f010b5b046
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,112 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Sample Texture 2D Array")]
|
||||
class SampleTexture2DArrayNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireMeshUV
|
||||
{
|
||||
public const int OutputSlotRGBAId = 0;
|
||||
public const int OutputSlotRId = 4;
|
||||
public const int OutputSlotGId = 5;
|
||||
public const int OutputSlotBId = 6;
|
||||
public const int OutputSlotAId = 7;
|
||||
public const int TextureInputId = 1;
|
||||
public const int UVInput = 2;
|
||||
public const int SamplerInput = 3;
|
||||
public const int IndexInputId = 8;
|
||||
|
||||
const string kOutputSlotRGBAName = "RGBA";
|
||||
const string kOutputSlotRName = "R";
|
||||
const string kOutputSlotGName = "G";
|
||||
const string kOutputSlotBName = "B";
|
||||
const string kOutputSlotAName = "A";
|
||||
const string kTextureInputName = "Texture Array";
|
||||
const string kUVInputName = "UV";
|
||||
const string kSamplerInputName = "Sampler";
|
||||
const string kIndexInputName = "Index";
|
||||
const string kDefaultSampleMacro = "SAMPLE_TEXTURE2D_ARRAY";
|
||||
const string kSampleMacroNoBias = "PLATFORM_SAMPLE_TEXTURE2D_ARRAY";
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public SampleTexture2DArrayNode()
|
||||
{
|
||||
name = "Sample Texture 2D Array";
|
||||
synonyms = new string[] { "stack", "pile" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_EnableGlobalMipBias = false;
|
||||
internal bool enableGlobalMipBias
|
||||
{
|
||||
set { m_EnableGlobalMipBias = value; }
|
||||
get { return m_EnableGlobalMipBias; }
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Texture2DArrayInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
|
||||
AddSlot(new Vector1MaterialSlot(IndexInputId, kIndexInputName, kIndexInputName, SlotType.Input, 0));
|
||||
AddSlot(new UVMaterialSlot(UVInput, kUVInputName, kUVInputName, UVChannel.UV0));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotRGBAId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId, TextureInputId, IndexInputId, UVInput, SamplerInput });
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var uvName = GetSlotValue(UVInput, generationMode);
|
||||
var indexName = GetSlotValue(IndexInputId, generationMode);
|
||||
|
||||
//Sampler input slot
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInput);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
|
||||
var id = GetSlotValue(TextureInputId, generationMode);
|
||||
var result = string.Format("$precision4 {0} = {1}({2}.tex, {3}.samplerstate, {4}, {5});"
|
||||
, GetVariableNameForSlot(OutputSlotRGBAId)
|
||||
, m_EnableGlobalMipBias ? kDefaultSampleMacro : kSampleMacroNoBias
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id
|
||||
, uvName
|
||||
, indexName);
|
||||
|
||||
sb.AppendLine(result);
|
||||
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.r;", GetVariableNameForSlot(OutputSlotRId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.g;", GetVariableNameForSlot(OutputSlotGId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.b;", GetVariableNameForSlot(OutputSlotBId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.a;", GetVariableNameForSlot(OutputSlotAId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
var result = false;
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresMeshUV(channel))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tempSlots.Clear();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0789ef77e28f0406dbb0970c5a8e7a2c
|
||||
timeCreated: 1495637741
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,167 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Sample Texture 2D LOD")]
|
||||
class SampleTexture2DLODNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireMeshUV
|
||||
{
|
||||
public const int OutputSlotRGBAId = 0;
|
||||
public const int OutputSlotRId = 5;
|
||||
public const int OutputSlotGId = 6;
|
||||
public const int OutputSlotBId = 7;
|
||||
public const int OutputSlotAId = 8;
|
||||
|
||||
public const int TextureInputId = 1;
|
||||
public const int UVInputId = 2;
|
||||
public const int SamplerInputId = 3;
|
||||
public const int LODInputId = 4;
|
||||
|
||||
const string kOutputSlotRGBAName = "RGBA";
|
||||
const string kOutputSlotRName = "R";
|
||||
const string kOutputSlotGName = "G";
|
||||
const string kOutputSlotBName = "B";
|
||||
const string kOutputSlotAName = "A";
|
||||
|
||||
const string kTextureInputName = "Texture";
|
||||
const string kUVInputName = "UV";
|
||||
const string kSamplerInputName = "Sampler";
|
||||
const string kLODInputName = "LOD";
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public SampleTexture2DLODNode()
|
||||
{
|
||||
name = "Sample Texture 2D LOD";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private TextureType m_TextureType = TextureType.Default;
|
||||
|
||||
[EnumControl("Type")]
|
||||
public TextureType textureType
|
||||
{
|
||||
get { return m_TextureType; }
|
||||
set
|
||||
{
|
||||
if (m_TextureType == value)
|
||||
return;
|
||||
|
||||
m_TextureType = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
|
||||
ValidateNode();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private NormalMapSpace m_NormalMapSpace = NormalMapSpace.Tangent;
|
||||
|
||||
[EnumControl("Space")]
|
||||
public NormalMapSpace normalMapSpace
|
||||
{
|
||||
get { return m_NormalMapSpace; }
|
||||
set
|
||||
{
|
||||
if (m_NormalMapSpace == value)
|
||||
return;
|
||||
|
||||
m_NormalMapSpace = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero, ShaderStageCapability.All));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
|
||||
AddSlot(new UVMaterialSlot(UVInputId, kUVInputName, kUVInputName, UVChannel.UV0));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInputId, kSamplerInputName, kSamplerInputName, SlotType.Input));
|
||||
AddSlot(new Vector1MaterialSlot(LODInputId, kLODInputName, kLODInputName, SlotType.Input, 0));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotRGBAId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId, TextureInputId, UVInputId, SamplerInputId, LODInputId });
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
var textureSlot = FindInputSlot<Texture2DInputMaterialSlot>(TextureInputId);
|
||||
textureSlot.defaultType = (textureType == TextureType.Normal ? Texture2DShaderProperty.DefaultType.NormalMap : Texture2DShaderProperty.DefaultType.White);
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var uvName = GetSlotValue(UVInputId, generationMode);
|
||||
|
||||
//Sampler input slot
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInputId);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
|
||||
var lodSlot = GetSlotValue(LODInputId, generationMode);
|
||||
|
||||
var id = GetSlotValue(TextureInputId, generationMode);
|
||||
|
||||
// GLES2 does not always support LOD sampling
|
||||
sb.AppendLine("#if defined(SHADER_API_GLES) && (SHADER_TARGET < 30)");
|
||||
{
|
||||
sb.AppendLine(" $precision4 {0} = $precision4(0.0f, 0.0f, 0.0f, 1.0f);", GetVariableNameForSlot(OutputSlotRGBAId));
|
||||
}
|
||||
sb.AppendLine("#else");
|
||||
{
|
||||
var result = string.Format(" $precision4 {0} = SAMPLE_TEXTURE2D_LOD({1}.tex, {2}.samplerstate, {1}.GetTransformedUV({3}), {4});"
|
||||
, GetVariableNameForSlot(OutputSlotRGBAId)
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : id
|
||||
, uvName
|
||||
, lodSlot);
|
||||
|
||||
sb.AppendLine(result);
|
||||
}
|
||||
sb.AppendLine("#endif");
|
||||
|
||||
if (textureType == TextureType.Normal)
|
||||
{
|
||||
if (normalMapSpace == NormalMapSpace.Tangent)
|
||||
{
|
||||
sb.AppendLine(string.Format("{0}.rgb = UnpackNormal({0});", GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(string.Format("{0}.rgb = UnpackNormalRGB({0});", GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.r;", GetVariableNameForSlot(OutputSlotRId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.g;", GetVariableNameForSlot(OutputSlotGId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.b;", GetVariableNameForSlot(OutputSlotBId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.a;", GetVariableNameForSlot(OutputSlotAId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
var result = false;
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresMeshUV(channel))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 64b637768540cce4f83b9b10cdcacd23
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,171 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum TextureType
|
||||
{
|
||||
Default,
|
||||
Normal
|
||||
};
|
||||
|
||||
[FormerName("UnityEditor.ShaderGraph.Texture2DNode")]
|
||||
[Title("Input", "Texture", "Sample Texture 2D")]
|
||||
class SampleTexture2DNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireMeshUV
|
||||
{
|
||||
public const int OutputSlotRGBAId = 0;
|
||||
public const int OutputSlotRId = 4;
|
||||
public const int OutputSlotGId = 5;
|
||||
public const int OutputSlotBId = 6;
|
||||
public const int OutputSlotAId = 7;
|
||||
public const int TextureInputId = 1;
|
||||
public const int UVInput = 2;
|
||||
public const int SamplerInput = 3;
|
||||
|
||||
const string kOutputSlotRGBAName = "RGBA";
|
||||
const string kOutputSlotRName = "R";
|
||||
const string kOutputSlotGName = "G";
|
||||
const string kOutputSlotBName = "B";
|
||||
const string kOutputSlotAName = "A";
|
||||
const string kTextureInputName = "Texture";
|
||||
const string kUVInputName = "UV";
|
||||
const string kSamplerInputName = "Sampler";
|
||||
const string kDefaultSampleMacro = "SAMPLE_TEXTURE2D";
|
||||
const string kSampleMacroNoBias = "PLATFORM_SAMPLE_TEXTURE2D";
|
||||
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public SampleTexture2DNode()
|
||||
{
|
||||
name = "Sample Texture 2D";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private TextureType m_TextureType = TextureType.Default;
|
||||
|
||||
[EnumControl("Type")]
|
||||
public TextureType textureType
|
||||
{
|
||||
get { return m_TextureType; }
|
||||
set
|
||||
{
|
||||
if (m_TextureType == value)
|
||||
return;
|
||||
|
||||
m_TextureType = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
|
||||
ValidateNode();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private NormalMapSpace m_NormalMapSpace = NormalMapSpace.Tangent;
|
||||
|
||||
[EnumControl("Space")]
|
||||
public NormalMapSpace normalMapSpace
|
||||
{
|
||||
get { return m_NormalMapSpace; }
|
||||
set
|
||||
{
|
||||
if (m_NormalMapSpace == value)
|
||||
return;
|
||||
|
||||
m_NormalMapSpace = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_EnableGlobalMipBias = true;
|
||||
internal bool enableGlobalMipBias
|
||||
{
|
||||
set { m_EnableGlobalMipBias = value; }
|
||||
get { return m_EnableGlobalMipBias; }
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
|
||||
AddSlot(new UVMaterialSlot(UVInput, kUVInputName, kUVInputName, UVChannel.UV0));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotRGBAId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId, TextureInputId, UVInput, SamplerInput });
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
var textureSlot = FindInputSlot<Texture2DInputMaterialSlot>(TextureInputId);
|
||||
textureSlot.defaultType = (textureType == TextureType.Normal ? Texture2DShaderProperty.DefaultType.NormalMap : Texture2DShaderProperty.DefaultType.White);
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var uvName = GetSlotValue(UVInput, generationMode);
|
||||
|
||||
//Sampler input slot
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInput);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
|
||||
var id = GetSlotValue(TextureInputId, generationMode);
|
||||
var result = string.Format("$precision4 {0} = {1}({2}.tex, {3}.samplerstate, {2}.GetTransformedUV({4}));"
|
||||
, GetVariableNameForSlot(OutputSlotRGBAId)
|
||||
, m_EnableGlobalMipBias ? kDefaultSampleMacro : kSampleMacroNoBias
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id
|
||||
, uvName);
|
||||
|
||||
sb.AppendLine(result);
|
||||
|
||||
if (textureType == TextureType.Normal)
|
||||
{
|
||||
if (normalMapSpace == NormalMapSpace.Tangent)
|
||||
{
|
||||
sb.AppendLine(string.Format("{0}.rgb = UnpackNormal({0});", GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(string.Format("{0}.rgb = UnpackNormalRGB({0});", GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.r;", GetVariableNameForSlot(OutputSlotRId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
|
||||
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.g;", GetVariableNameForSlot(OutputSlotGId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.b;", GetVariableNameForSlot(OutputSlotBId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.a;", GetVariableNameForSlot(OutputSlotAId), GetVariableNameForSlot(OutputSlotRGBAId)));
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
var result = false;
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresMeshUV(channel))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tempSlots.Clear();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5ca9d434229e11f44888abcbf66062a5
|
||||
timeCreated: 1495637741
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,58 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Sample Texture 3D")]
|
||||
class SampleTexture3DNode : AbstractMaterialNode, IGeneratesBodyCode
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
public const int TextureInputId = 1;
|
||||
public const int UVInput = 2;
|
||||
public const int SamplerInput = 3;
|
||||
|
||||
const string kOutputSlotName = "Out";
|
||||
const string kTextureInputName = "Texture";
|
||||
const string kUVInputName = "UV";
|
||||
const string kSamplerInputName = "Sampler";
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public SampleTexture3DNode()
|
||||
{
|
||||
name = "Sample Texture 3D";
|
||||
synonyms = new string[] { "volume" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Texture3DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
|
||||
AddSlot(new Vector3MaterialSlot(UVInput, kUVInputName, kUVInputName, SlotType.Input, Vector3.zero));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId, TextureInputId, UVInput, SamplerInput });
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var uvName = GetSlotValue(UVInput, generationMode);
|
||||
|
||||
//Sampler input slot
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInput);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
|
||||
var id = GetSlotValue(TextureInputId, generationMode);
|
||||
var result = string.Format("$precision4 {0} = SAMPLE_TEXTURE3D({1}.tex, {2}.samplerstate, {3});"
|
||||
, GetVariableNameForSlot(OutputSlotId)
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : id
|
||||
, uvName);
|
||||
|
||||
sb.AppendLine(result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0c9bd58ae163e49acb187db417dbfd95
|
||||
timeCreated: 1495637741
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,567 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.Graphing.Util;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEditor.ShaderGraph.Drawing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", SampleVirtualTextureNode.DefaultNodeTitle)]
|
||||
class SampleVirtualTextureNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction, IMayRequireMeshUV, IMayRequireTime, IMayRequireScreenPosition
|
||||
{
|
||||
public const string DefaultNodeTitle = "Sample Virtual Texture";
|
||||
|
||||
public const int kMinLayers = 1;
|
||||
public const int kMaxLayers = 4;
|
||||
|
||||
// input slots
|
||||
public const int UVInputId = 0;
|
||||
public const int VirtualTextureInputId = 1;
|
||||
public const int LODInputId = 2;
|
||||
public const int BiasInputId = 3;
|
||||
public const int DxInputId = 4;
|
||||
public const int DyInputId = 5;
|
||||
|
||||
// output slots
|
||||
[NonSerialized]
|
||||
public readonly int[] OutputSlotIds = { 11, 12, 13, 14 };
|
||||
|
||||
const string UVInputName = "UV";
|
||||
const string VirtualTextureInputName = "VT";
|
||||
const string LODSlotName = "Lod";
|
||||
const string BiasSlotName = "Bias";
|
||||
const string DxSlotName = "Dx";
|
||||
const string DySlotName = "Dy";
|
||||
|
||||
static string[] OutputSlotNames = { "Out", "Out2", "Out3", "Out4" };
|
||||
|
||||
public override bool hasPreview { get { return false; } }
|
||||
|
||||
// Keep these in sync with "VirtualTexturing.hlsl"
|
||||
public enum LodCalculation
|
||||
{
|
||||
[InspectorName("Automatic")]
|
||||
VtLevel_Automatic = 0,
|
||||
[InspectorName("Lod Level")]
|
||||
VtLevel_Lod = 1,
|
||||
[InspectorName("Lod Bias")]
|
||||
VtLevel_Bias = 2,
|
||||
[InspectorName("Derivatives")]
|
||||
VtLevel_Derivatives = 3
|
||||
}
|
||||
|
||||
public enum AddressMode
|
||||
{
|
||||
[InspectorName("Wrap")]
|
||||
VtAddressMode_Wrap = 0,
|
||||
[InspectorName("Clamp")]
|
||||
VtAddressMode_Clamp = 1,
|
||||
}
|
||||
|
||||
public enum FilterMode
|
||||
{
|
||||
[InspectorName("Anisotropic")]
|
||||
VtFilter_Anisotropic = 0
|
||||
}
|
||||
|
||||
public enum UvSpace
|
||||
{
|
||||
[InspectorName("Regular")]
|
||||
VtUvSpace_Regular = 0,
|
||||
[InspectorName("Pre Transformed")]
|
||||
VtUvSpace_PreTransformed = 1
|
||||
}
|
||||
|
||||
public enum QualityMode
|
||||
{
|
||||
[InspectorName("Low")]
|
||||
VtSampleQuality_Low = 0,
|
||||
[InspectorName("High")]
|
||||
VtSampleQuality_High = 1
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
AddressMode m_AddressMode = AddressMode.VtAddressMode_Wrap;
|
||||
public AddressMode addressMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_AddressMode;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_AddressMode == value)
|
||||
return;
|
||||
|
||||
m_AddressMode = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
LodCalculation m_LodCalculation = LodCalculation.VtLevel_Automatic;
|
||||
public LodCalculation lodCalculation
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_LodCalculation;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_LodCalculation == value)
|
||||
return;
|
||||
|
||||
m_LodCalculation = value;
|
||||
RebuildAllSlots(true); // LOD calculation may have associated slots that need to be updated
|
||||
Dirty(ModificationScope.Topological); // slots ShaderStageCapability could have changed, so trigger Topo change
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
QualityMode m_SampleQuality = QualityMode.VtSampleQuality_High;
|
||||
public QualityMode sampleQuality
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_SampleQuality;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_SampleQuality == value)
|
||||
return;
|
||||
|
||||
m_SampleQuality = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_EnableGlobalMipBias = true;
|
||||
public bool enableGlobalMipBias
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_EnableGlobalMipBias;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_EnableGlobalMipBias == value)
|
||||
return;
|
||||
|
||||
m_EnableGlobalMipBias = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
bool m_NoFeedback; // aka !AutomaticStreaming
|
||||
public bool noFeedback
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_NoFeedback;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_NoFeedback == value)
|
||||
return;
|
||||
|
||||
m_NoFeedback = value;
|
||||
RebuildAllSlots(true);
|
||||
Dirty(ModificationScope.Topological); // slots ShaderStageCapability could have changed, so trigger Topo change
|
||||
}
|
||||
}
|
||||
|
||||
public SampleVirtualTextureNode() : this(false, false)
|
||||
{ }
|
||||
|
||||
public SampleVirtualTextureNode(bool isLod = false, bool noResolve = false)
|
||||
{
|
||||
name = "Sample Virtual Texture";
|
||||
synonyms = new string[] { "buffer" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
UpdateLayerOutputSlots(true);
|
||||
}
|
||||
|
||||
// rebuilds the number of output slots, and also updates their ShaderStageCapability
|
||||
private int outputLayerSlotCount = 0;
|
||||
void UpdateLayerOutputSlots(bool inspectProperty, List<int> usedSlots = null)
|
||||
{
|
||||
// the default is to show all 4 slots, so we don't lose any existing connections
|
||||
int layerCount = kMaxLayers;
|
||||
|
||||
if (inspectProperty)
|
||||
{
|
||||
var vtProperty = GetSlotProperty(VirtualTextureInputId) as VirtualTextureShaderProperty;
|
||||
if (vtProperty != null)
|
||||
{
|
||||
layerCount = vtProperty?.value?.layers?.Count ?? kMaxLayers;
|
||||
}
|
||||
if (outputLayerSlotCount == layerCount)
|
||||
{
|
||||
if (usedSlots != null)
|
||||
for (int i = 0; i < layerCount; i++)
|
||||
usedSlots.Add(OutputSlotIds[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < kMaxLayers; i++)
|
||||
{
|
||||
int outputID = OutputSlotIds[i];
|
||||
Vector4MaterialSlot outputSlot = FindSlot<Vector4MaterialSlot>(outputID);
|
||||
if (i < layerCount)
|
||||
{
|
||||
// add or update it
|
||||
if (outputSlot == null)
|
||||
{
|
||||
string outputName = OutputSlotNames[i];
|
||||
outputSlot = new Vector4MaterialSlot(outputID, outputName, outputName, SlotType.Output, Vector4.zero, (noFeedback && m_LodCalculation == LodCalculation.VtLevel_Lod) ? ShaderStageCapability.All : ShaderStageCapability.Fragment);
|
||||
AddSlot(outputSlot);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputSlot.stageCapability = (noFeedback && m_LodCalculation == LodCalculation.VtLevel_Lod) ? ShaderStageCapability.All : ShaderStageCapability.Fragment;
|
||||
}
|
||||
if (usedSlots != null)
|
||||
usedSlots.Add(outputID);
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove it
|
||||
if (outputSlot != null)
|
||||
RemoveSlot(OutputSlotIds[i]);
|
||||
}
|
||||
}
|
||||
outputLayerSlotCount = layerCount;
|
||||
}
|
||||
|
||||
public void RebuildAllSlots(bool inspectProperty)
|
||||
{
|
||||
List<int> usedSlots = new List<int>();
|
||||
|
||||
AddSlot(new UVMaterialSlot(UVInputId, UVInputName, UVInputName, UVChannel.UV0));
|
||||
usedSlots.Add(UVInputId);
|
||||
|
||||
AddSlot(new VirtualTextureInputMaterialSlot(VirtualTextureInputId, VirtualTextureInputName, VirtualTextureInputName));
|
||||
usedSlots.Add(VirtualTextureInputId);
|
||||
|
||||
// at this point we can't tell how many output slots we will have (because we can't find the VT property yet)
|
||||
// so, we create all of the possible output slots, so any edges created will connect properly
|
||||
// then we can trim down the set of slots later..
|
||||
UpdateLayerOutputSlots(inspectProperty, usedSlots);
|
||||
|
||||
// Create slots
|
||||
|
||||
if (m_LodCalculation == LodCalculation.VtLevel_Lod)
|
||||
{
|
||||
var slot = new Vector1MaterialSlot(LODInputId, LODSlotName, LODSlotName, SlotType.Input, 0.0f, ShaderStageCapability.All, LODSlotName);
|
||||
AddSlot(slot);
|
||||
usedSlots.Add(LODInputId);
|
||||
}
|
||||
|
||||
if (m_LodCalculation == LodCalculation.VtLevel_Bias)
|
||||
{
|
||||
var slot = new Vector1MaterialSlot(BiasInputId, BiasSlotName, BiasSlotName, SlotType.Input, 0.0f, ShaderStageCapability.Fragment, BiasSlotName);
|
||||
AddSlot(slot);
|
||||
usedSlots.Add(BiasInputId);
|
||||
}
|
||||
|
||||
if (m_LodCalculation == LodCalculation.VtLevel_Derivatives)
|
||||
{
|
||||
var slot1 = new Vector2MaterialSlot(DxInputId, DxSlotName, DxSlotName, SlotType.Input, Vector2.one, ShaderStageCapability.All, DxSlotName);
|
||||
var slot2 = new Vector2MaterialSlot(DyInputId, DySlotName, DySlotName, SlotType.Input, Vector2.one, ShaderStageCapability.All, DySlotName);
|
||||
AddSlot(slot1);
|
||||
AddSlot(slot2);
|
||||
usedSlots.Add(DxInputId);
|
||||
usedSlots.Add(DyInputId);
|
||||
}
|
||||
|
||||
RemoveSlotsNameNotMatching(usedSlots, true);
|
||||
}
|
||||
|
||||
public override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
RebuildAllSlots(false);
|
||||
}
|
||||
|
||||
const string k_NoPropertyConnected = "A VirtualTexture property must be connected to the VT slot";
|
||||
public override void ValidateNode()
|
||||
{
|
||||
base.ValidateNode();
|
||||
if (!IsSlotConnected(VirtualTextureInputId))
|
||||
{
|
||||
owner.AddValidationError(objectId, k_NoPropertyConnected);
|
||||
}
|
||||
else
|
||||
{
|
||||
var vtProp = GetSlotProperty(VirtualTextureInputId) as VirtualTextureShaderProperty;
|
||||
if (vtProp == null)
|
||||
{
|
||||
owner.AddValidationError(objectId, $"VT slot is not connected to a valid VirtualTexture property");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFeedbackVariableName()
|
||||
{
|
||||
return GetVariableNameForNode() + "_fb";
|
||||
}
|
||||
|
||||
void AppendVtParameters(ShaderStringBuilder sb, string uvExpr, string lodExpr, string dxExpr, string dyExpr, AddressMode address, FilterMode filter, LodCalculation lod, UvSpace space, QualityMode quality, bool enableGlobalMipBias)
|
||||
{
|
||||
sb.AppendLine("VtInputParameters vtParams;");
|
||||
sb.AppendLine("vtParams.uv = " + uvExpr + ";");
|
||||
sb.AppendLine("vtParams.lodOrOffset = " + lodExpr + ";");
|
||||
sb.AppendLine("vtParams.dx = " + dxExpr + ";");
|
||||
sb.AppendLine("vtParams.dy = " + dyExpr + ";");
|
||||
sb.AppendLine("vtParams.addressMode = " + address + ";");
|
||||
sb.AppendLine("vtParams.filterMode = " + filter + ";");
|
||||
sb.AppendLine("vtParams.levelMode = " + lod + ";");
|
||||
sb.AppendLine("vtParams.uvMode = " + space + ";");
|
||||
sb.AppendLine("vtParams.sampleQuality = " + quality + ";");
|
||||
sb.AppendLine("vtParams.enableGlobalMipBias = " + (enableGlobalMipBias ? "1" : "0") + ";");
|
||||
sb.AppendLine("#if defined(SHADER_STAGE_RAY_TRACING)");
|
||||
sb.AppendLine("if (vtParams.levelMode == VtLevel_Automatic || vtParams.levelMode == VtLevel_Bias)");
|
||||
using (sb.BlockScope())
|
||||
{
|
||||
sb.AppendLine("vtParams.levelMode = VtLevel_Lod;");
|
||||
sb.AppendLine("vtParams.lodOrOffset = 0.0f;");
|
||||
}
|
||||
sb.AppendLine("#endif");
|
||||
}
|
||||
|
||||
void AppendVtSample(ShaderStringBuilder sb, string propertiesName, string vtInputVariable, string infoVariable, int layerIndex, string outputVariableName)
|
||||
{
|
||||
sb.TryAppendIndentation();
|
||||
sb.Append(outputVariableName); sb.Append(" = ");
|
||||
sb.Append("SampleVTLayerWithTextureType(");
|
||||
sb.Append(propertiesName); sb.Append(", ");
|
||||
sb.Append(vtInputVariable); sb.Append(", ");
|
||||
sb.Append(infoVariable); sb.Append(", ");
|
||||
sb.Append(layerIndex.ToString()); sb.Append(");");
|
||||
sb.AppendNewLine();
|
||||
}
|
||||
|
||||
// Node generations
|
||||
string GetFunctionName(out List<int> layerIndices)
|
||||
{
|
||||
string name = "SampleVirtualTexture_" + addressMode + "_" + lodCalculation + "_" + m_SampleQuality;
|
||||
layerIndices = new List<int>();
|
||||
|
||||
if (IsSlotConnected(VirtualTextureInputId))
|
||||
{
|
||||
var vtProperty = GetSlotProperty(VirtualTextureInputId) as VirtualTextureShaderProperty;
|
||||
if (vtProperty != null)
|
||||
{
|
||||
int layerCount = vtProperty.value.layers.Count;
|
||||
for (int layer = 0; layer < layerCount; layer++)
|
||||
{
|
||||
if (IsSlotConnected(OutputSlotIds[layer]))
|
||||
{
|
||||
layerIndices.Add(layer);
|
||||
name = name + "_" + layer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
string functionName = GetFunctionName(out var layerOutputLayerIndex);
|
||||
|
||||
if (layerOutputLayerIndex.Count <= 0)
|
||||
return;
|
||||
|
||||
registry.ProvideFunction(functionName, s =>
|
||||
{
|
||||
string lodExpr = "0.0f";
|
||||
string dxExpr = "0.0f";
|
||||
string dyExpr = "0.0f";
|
||||
|
||||
// function header
|
||||
s.TryAppendIndentation();
|
||||
s.Append("float4 ");
|
||||
s.Append(functionName);
|
||||
s.Append("(float2 uv");
|
||||
switch (lodCalculation)
|
||||
{
|
||||
case LodCalculation.VtLevel_Lod:
|
||||
s.Append(", float lod");
|
||||
lodExpr = "lod";
|
||||
break;
|
||||
case LodCalculation.VtLevel_Bias:
|
||||
s.Append(", float bias");
|
||||
lodExpr = "bias";
|
||||
break;
|
||||
case LodCalculation.VtLevel_Derivatives:
|
||||
s.Append(", float2 dx, float2 dy");
|
||||
dxExpr = "dx";
|
||||
dyExpr = "dy";
|
||||
break;
|
||||
}
|
||||
s.Append(", VTPropertyWithTextureType vtProperty");
|
||||
for (int i = 0; i < layerOutputLayerIndex.Count; i++)
|
||||
{
|
||||
s.Append(", out float4 Layer" + layerOutputLayerIndex[i]);
|
||||
}
|
||||
s.Append(")");
|
||||
s.AppendNewLine();
|
||||
|
||||
// function body
|
||||
using (s.BlockScope())
|
||||
{
|
||||
AppendVtParameters(
|
||||
s,
|
||||
"uv",
|
||||
lodExpr,
|
||||
dxExpr,
|
||||
dyExpr,
|
||||
m_AddressMode,
|
||||
FilterMode.VtFilter_Anisotropic,
|
||||
m_LodCalculation,
|
||||
UvSpace.VtUvSpace_Regular,
|
||||
m_SampleQuality,
|
||||
m_EnableGlobalMipBias);
|
||||
|
||||
s.AppendLine("StackInfo info = PrepareVT(vtProperty.vtProperty, vtParams);");
|
||||
|
||||
for (int i = 0; i < layerOutputLayerIndex.Count; i++)
|
||||
{
|
||||
// sample virtual texture layer
|
||||
int layer = layerOutputLayerIndex[i];
|
||||
AppendVtSample(s, "vtProperty", "vtParams", "info", layer, "Layer" + layer);
|
||||
}
|
||||
|
||||
s.AppendLine("return GetResolveOutput(info);");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
bool success = false;
|
||||
if (IsSlotConnected(VirtualTextureInputId))
|
||||
{
|
||||
var vtProperty = GetSlotProperty(VirtualTextureInputId) as VirtualTextureShaderProperty;
|
||||
if (vtProperty != null)
|
||||
{
|
||||
var layerOutputVariables = new List<string>();
|
||||
int layerCount = vtProperty.value.layers.Count;
|
||||
for (int i = 0; i < layerCount; i++)
|
||||
{
|
||||
if (IsSlotConnected(OutputSlotIds[i]))
|
||||
{
|
||||
// declare output variables up front
|
||||
string layerOutputVariable = GetVariableNameForSlot(OutputSlotIds[i]);
|
||||
sb.AppendLine("$precision4 " + layerOutputVariable + ";");
|
||||
layerOutputVariables.Add(layerOutputVariable);
|
||||
}
|
||||
}
|
||||
|
||||
if (layerOutputVariables.Count > 0)
|
||||
{
|
||||
// assign feedback variable
|
||||
sb.TryAppendIndentation();
|
||||
if (!noFeedback)
|
||||
{
|
||||
sb.Append("float4 ");
|
||||
sb.Append(GetFeedbackVariableName());
|
||||
sb.Append(" = ");
|
||||
}
|
||||
sb.Append(GetFunctionName(out var unused));
|
||||
sb.Append("(");
|
||||
sb.Append(GetSlotValue(UVInputId, generationMode));
|
||||
switch (lodCalculation)
|
||||
{
|
||||
case LodCalculation.VtLevel_Lod:
|
||||
case LodCalculation.VtLevel_Bias:
|
||||
sb.Append(", ");
|
||||
sb.Append((lodCalculation == LodCalculation.VtLevel_Lod) ? GetSlotValue(LODInputId, generationMode) : GetSlotValue(BiasInputId, generationMode));
|
||||
break;
|
||||
case LodCalculation.VtLevel_Derivatives:
|
||||
sb.Append(", ");
|
||||
sb.Append(GetSlotValue(DxInputId, generationMode));
|
||||
sb.Append(", ");
|
||||
sb.Append(GetSlotValue(DyInputId, generationMode));
|
||||
break;
|
||||
}
|
||||
sb.Append(", ");
|
||||
sb.Append(vtProperty.referenceName);
|
||||
foreach (string layerOutputVariable in layerOutputVariables)
|
||||
{
|
||||
sb.Append(", ");
|
||||
sb.Append(layerOutputVariable);
|
||||
}
|
||||
sb.Append(");");
|
||||
sb.AppendNewLine();
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!success)
|
||||
{
|
||||
// set all outputs to zero
|
||||
for (int i = 0; i < kMaxLayers; i++)
|
||||
{
|
||||
if (IsSlotConnected(OutputSlotIds[i]))
|
||||
{
|
||||
// declare output variables up front
|
||||
string layerOutputVariable = GetVariableNameForSlot(OutputSlotIds[i]);
|
||||
sb.AppendLine("$precision4 " + layerOutputVariable + " = 0;");
|
||||
}
|
||||
}
|
||||
// TODO: should really just disable feedback in this case (need different feedback interface to do this)
|
||||
sb.AppendLine("$precision4 " + GetFeedbackVariableName() + " = 1;");
|
||||
}
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
// this adds default properties for all of our unconnected inputs
|
||||
base.CollectShaderProperties(properties, generationMode);
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(Internal.UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresMeshUV(channel))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RequiresTime()
|
||||
{
|
||||
// HACK: This ensures we repaint in shadergraph so data that gets streamed in also becomes visible.
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RequiresScreenPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All)
|
||||
{
|
||||
// Feedback dithering requires screen position (and only works in Pixel Shader currently)
|
||||
return stageCapability.HasFlag(ShaderStageCapability.Fragment) && !noFeedback;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 29b42276bd0679743bb3386305aa7691
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Sampler State")]
|
||||
class SamplerStateNode : AbstractMaterialNode, IPropertyFromNode
|
||||
{
|
||||
[SerializeField]
|
||||
private TextureSamplerState.FilterMode m_filter = TextureSamplerState.FilterMode.Linear;
|
||||
|
||||
[EnumControl]
|
||||
public TextureSamplerState.FilterMode filter
|
||||
{
|
||||
get { return m_filter; }
|
||||
set
|
||||
{
|
||||
if (m_filter == value)
|
||||
return;
|
||||
|
||||
m_filter = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private TextureSamplerState.WrapMode m_wrap = TextureSamplerState.WrapMode.Repeat;
|
||||
|
||||
[EnumControl]
|
||||
public TextureSamplerState.WrapMode wrap
|
||||
{
|
||||
get { return m_wrap; }
|
||||
set
|
||||
{
|
||||
if (m_wrap == value)
|
||||
return;
|
||||
|
||||
m_wrap = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private TextureSamplerState.Anisotropic m_aniso = TextureSamplerState.Anisotropic.None;
|
||||
|
||||
public TextureSamplerState.Anisotropic anisotropic
|
||||
{
|
||||
get { return m_aniso; }
|
||||
set
|
||||
{
|
||||
if (m_aniso == value)
|
||||
return;
|
||||
|
||||
m_aniso = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
public SamplerStateNode()
|
||||
{
|
||||
name = "Sampler State";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public override bool hasPreview { get { return false; } }
|
||||
|
||||
private const int kOutputSlotId = 0;
|
||||
private const string kOutputSlotName = "Out";
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new SamplerStateMaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
|
||||
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
|
||||
}
|
||||
|
||||
string GetSamplerStatePropertyName()
|
||||
{
|
||||
return GetVariableNameForNode();
|
||||
}
|
||||
|
||||
string GetSamplerStateVariableName()
|
||||
{
|
||||
return $"UnityBuildSamplerStateStruct({GetSamplerStatePropertyName()})";
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return GetSamplerStateVariableName();
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
properties.AddShaderProperty(new SamplerStateShaderProperty()
|
||||
{
|
||||
overrideReferenceName = GetSamplerStatePropertyName(),
|
||||
generatePropertyBlock = false,
|
||||
|
||||
value = new TextureSamplerState()
|
||||
{
|
||||
filter = m_filter,
|
||||
wrap = m_wrap,
|
||||
anisotropic = m_aniso
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override string GetVariableNameForNode()
|
||||
{
|
||||
return TextureSamplerState.BuildSamplerStateName(filter, wrap, anisotropic);
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
return new SamplerStateShaderProperty
|
||||
{
|
||||
value = new TextureSamplerState()
|
||||
{
|
||||
filter = this.filter,
|
||||
wrap = this.wrap,
|
||||
anisotropic = this.anisotropic
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return kOutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5fe2c333e043511478cc507ee61a8c21
|
||||
timeCreated: 1495658099
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,48 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Texel Size")]
|
||||
class Texture2DPropertiesNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireMeshUV
|
||||
{
|
||||
public const int OutputSlotWId = 0;
|
||||
public const int OutputSlotHId = 2;
|
||||
public const int TextureInputId = 1;
|
||||
const string kOutputSlotWName = "Width";
|
||||
const string kOutputSlotHName = "Height";
|
||||
const string kTextureInputName = "Texture";
|
||||
|
||||
public override bool hasPreview { get { return false; } }
|
||||
|
||||
public Texture2DPropertiesNode()
|
||||
{
|
||||
name = "Texel Size";
|
||||
synonyms = new string[] { "texture size" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotWId, kOutputSlotWName, kOutputSlotWName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Vector1MaterialSlot(OutputSlotHId, kOutputSlotHName, kOutputSlotHName, SlotType.Output, 0, ShaderStageCapability.All));
|
||||
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotWId, OutputSlotHId, TextureInputId });
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.texelSize.z;", GetVariableNameForSlot(OutputSlotWId), GetSlotValue(TextureInputId, generationMode)));
|
||||
sb.AppendLine(string.Format("$precision {0} = {1}.texelSize.w;", GetVariableNameForSlot(OutputSlotHId), GetSlotValue(TextureInputId, generationMode)));
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ab454fbbbc9f31d4083c178cf885c672
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,101 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Texture 2D Array Asset")]
|
||||
[HasDependencies(typeof(Minimal2dArrayTextureAssetNode))]
|
||||
class Texture2DArrayAssetNode : AbstractMaterialNode, IPropertyFromNode
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public Texture2DArrayAssetNode()
|
||||
{
|
||||
name = "Texture 2D Array Asset";
|
||||
synonyms = new string[] { "stack", "pile" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Texture2DArrayMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private SerializableTextureArray m_Texture = new SerializableTextureArray();
|
||||
|
||||
[TextureArrayControl("")]
|
||||
public Texture2DArray texture
|
||||
{
|
||||
get { return m_Texture.textureArray; }
|
||||
set
|
||||
{
|
||||
if (m_Texture.textureArray == value)
|
||||
return;
|
||||
m_Texture.textureArray = value;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
string GetTexturePropertyName()
|
||||
{
|
||||
return base.GetVariableNameForSlot(OutputSlotId);
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return $"UnityBuildTexture2DArrayStruct({GetTexturePropertyName()})";
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
properties.AddShaderProperty(new Texture2DArrayShaderProperty()
|
||||
{
|
||||
overrideReferenceName = GetTexturePropertyName(),
|
||||
generatePropertyBlock = true,
|
||||
value = m_Texture,
|
||||
modifiable = false
|
||||
});
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
properties.Add(new PreviewProperty(PropertyType.Texture2DArray)
|
||||
{
|
||||
name = GetTexturePropertyName(),
|
||||
textureValue = texture
|
||||
});
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
var prop = new Texture2DArrayShaderProperty { value = m_Texture };
|
||||
if (texture != null)
|
||||
prop.displayName = texture.name;
|
||||
return prop;
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
|
||||
class Minimal2dArrayTextureAssetNode : IHasDependencies
|
||||
{
|
||||
[SerializeField]
|
||||
private SerializableTextureArray m_Texture = null;
|
||||
|
||||
public void GetSourceAssetDependencies(AssetCollection assetCollection)
|
||||
{
|
||||
var guidString = m_Texture.guid;
|
||||
if (!string.IsNullOrEmpty(guidString) && GUID.TryParse(guidString, out var guid))
|
||||
{
|
||||
assetCollection.AddAssetDependency(guid, AssetCollection.Flags.IncludeInExportPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 34c0298d9fb6e4bc9aedbeeeeb8b8054
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,102 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Texture 2D Asset")]
|
||||
[HasDependencies(typeof(Minimal2d3dTextureAssetNode))]
|
||||
class Texture2DAssetNode : AbstractMaterialNode, IPropertyFromNode
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public Texture2DAssetNode()
|
||||
{
|
||||
name = "Texture 2D Asset";
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Texture2DMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private SerializableTexture m_Texture = new SerializableTexture();
|
||||
|
||||
[TextureControl("")]
|
||||
public Texture texture
|
||||
{
|
||||
get { return m_Texture.texture; }
|
||||
set
|
||||
{
|
||||
if (m_Texture.texture == value)
|
||||
return;
|
||||
m_Texture.texture = value;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
string GetTexturePropertyName()
|
||||
{
|
||||
return base.GetVariableNameForSlot(OutputSlotId);
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return $"UnityBuildTexture2DStructNoScale({GetTexturePropertyName()})";
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
properties.AddShaderProperty(new Texture2DShaderProperty()
|
||||
{
|
||||
overrideReferenceName = GetTexturePropertyName(),
|
||||
generatePropertyBlock = true,
|
||||
value = m_Texture,
|
||||
modifiable = false
|
||||
});
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
properties.Add(new PreviewProperty(PropertyType.Texture2D)
|
||||
{
|
||||
name = GetTexturePropertyName(),
|
||||
textureValue = texture,
|
||||
texture2DDefaultType = Texture2DShaderProperty.DefaultType.White
|
||||
});
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
var prop = new Texture2DShaderProperty { value = m_Texture };
|
||||
if (texture != null)
|
||||
prop.displayName = texture.name;
|
||||
return prop;
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
|
||||
// this is used for Texture2D AND Texture3D
|
||||
class Minimal2d3dTextureAssetNode : IHasDependencies
|
||||
{
|
||||
[SerializeField]
|
||||
private SerializableTexture m_Texture = null;
|
||||
|
||||
public void GetSourceAssetDependencies(AssetCollection assetCollection)
|
||||
{
|
||||
var guidString = m_Texture.guid;
|
||||
if (!string.IsNullOrEmpty(guidString) && GUID.TryParse(guidString, out var guid))
|
||||
{
|
||||
assetCollection.AddAssetDependency(guid, AssetCollection.Flags.IncludeInExportPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9c629b78a2ec57749ab4f76f4f42f423
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,86 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("Input", "Texture", "Texture 3D Asset")]
|
||||
[HasDependencies(typeof(Minimal2d3dTextureAssetNode))]
|
||||
class Texture3DAssetNode : AbstractMaterialNode, IPropertyFromNode
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public Texture3DAssetNode()
|
||||
{
|
||||
name = "Texture 3D Asset";
|
||||
synonyms = new string[] { "volume" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Texture3DMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId });
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private SerializableTexture m_Texture = new SerializableTexture();
|
||||
|
||||
[Texture3DControl("")]
|
||||
public Texture3D texture
|
||||
{
|
||||
get { return m_Texture.texture as Texture3D; }
|
||||
set
|
||||
{
|
||||
if (m_Texture.texture == value)
|
||||
return;
|
||||
m_Texture.texture = value;
|
||||
Dirty(ModificationScope.Node);
|
||||
}
|
||||
}
|
||||
|
||||
string GetTexturePropertyName()
|
||||
{
|
||||
return base.GetVariableNameForSlot(OutputSlotId);
|
||||
}
|
||||
|
||||
public override string GetVariableNameForSlot(int slotId)
|
||||
{
|
||||
return $"UnityBuildTexture3DStruct({GetTexturePropertyName()})";
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
properties.AddShaderProperty(new Texture3DShaderProperty()
|
||||
{
|
||||
overrideReferenceName = GetTexturePropertyName(),
|
||||
generatePropertyBlock = true,
|
||||
value = m_Texture,
|
||||
modifiable = false
|
||||
});
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
properties.Add(new PreviewProperty(PropertyType.Texture3D)
|
||||
{
|
||||
name = GetTexturePropertyName(),
|
||||
textureValue = texture
|
||||
});
|
||||
}
|
||||
|
||||
public AbstractShaderProperty AsShaderProperty()
|
||||
{
|
||||
var prop = new Texture3DShaderProperty { value = m_Texture };
|
||||
if (texture != null)
|
||||
prop.displayName = texture.name;
|
||||
return prop;
|
||||
}
|
||||
|
||||
public int outputSlotId { get { return OutputSlotId; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0b009ba9b523742a0ad6530e14a063a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,183 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.Graphing.Util;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEditor.ShaderGraph.Drawing;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
// TODO: rename this file to VirtualTexturingFeedbackUtils
|
||||
static class VirtualTexturingFeedbackUtils
|
||||
{
|
||||
// TODO: could get rid of this if we could run a codegen prepass (with proper keyword #ifdef)
|
||||
public static void GenerateVirtualTextureFeedback(
|
||||
List<AbstractMaterialNode> downstreamNodesIncludingRoot,
|
||||
List<int>[] keywordPermutationsPerNode,
|
||||
ShaderStringBuilder surfaceDescriptionFunction,
|
||||
KeywordCollector shaderKeywords)
|
||||
{
|
||||
// A note on how we handle vt feedback in combination with keywords:
|
||||
// We essentially generate a fully separate feedback path for each permutation of keywords
|
||||
// so per permutation we gather variables contribution to feedback and we generate
|
||||
// feedback gathering for each permutation individually.
|
||||
|
||||
var feedbackVariablesPerPermutation = PooledList<PooledList<string>>.Get();
|
||||
try
|
||||
{
|
||||
if (shaderKeywords.permutations.Count >= 1)
|
||||
{
|
||||
for (int i = 0; i < shaderKeywords.permutations.Count; i++)
|
||||
{
|
||||
feedbackVariablesPerPermutation.Add(PooledList<string>.Get());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a dummy single permutation
|
||||
feedbackVariablesPerPermutation.Add(PooledList<string>.Get());
|
||||
}
|
||||
|
||||
int index = 0; //for keywordPermutationsPerNode
|
||||
foreach (var node in downstreamNodesIncludingRoot)
|
||||
{
|
||||
if (node is SampleVirtualTextureNode vtNode)
|
||||
{
|
||||
if (vtNode.noFeedback) continue;
|
||||
if (keywordPermutationsPerNode[index] == null)
|
||||
{
|
||||
Debug.Assert(shaderKeywords.permutations.Count == 0, $"Shader has {shaderKeywords.permutations.Count} permutations but keywordPermutationsPerNode of some nodes are null.");
|
||||
feedbackVariablesPerPermutation[0].Add(vtNode.GetFeedbackVariableName());
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (int perm in keywordPermutationsPerNode[index])
|
||||
{
|
||||
feedbackVariablesPerPermutation[perm].Add(vtNode.GetFeedbackVariableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node is SubGraphNode sgNode)
|
||||
{
|
||||
if (sgNode.asset == null) continue;
|
||||
if (keywordPermutationsPerNode[index] == null)
|
||||
{
|
||||
Debug.Assert(shaderKeywords.permutations.Count == 0, $"Shader has {shaderKeywords.permutations.Count} permutations but keywordPermutationsPerNode of some nodes are null.");
|
||||
foreach (var feedbackSlot in sgNode.asset.vtFeedbackVariables)
|
||||
{
|
||||
feedbackVariablesPerPermutation[0].Add(node.GetVariableNameForNode() + "_" + feedbackSlot);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var feedbackSlot in sgNode.asset.vtFeedbackVariables)
|
||||
{
|
||||
foreach (int perm in keywordPermutationsPerNode[index])
|
||||
{
|
||||
feedbackVariablesPerPermutation[perm].Add(node.GetVariableNameForNode() + "_" + feedbackSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
foreach (var feedbackVariables in feedbackVariablesPerPermutation)
|
||||
{
|
||||
// If it's a dummy single always-on permutation don't put an ifdef around the code
|
||||
if (shaderKeywords.permutations.Count >= 1)
|
||||
{
|
||||
surfaceDescriptionFunction.AppendLine(KeywordUtil.GetKeywordPermutationConditional(index));
|
||||
}
|
||||
|
||||
using (surfaceDescriptionFunction.BlockScope())
|
||||
{
|
||||
if (feedbackVariables.Count == 0)
|
||||
{
|
||||
string feedBackCode = "surface.VTPackedFeedback = float4(1.0f,1.0f,1.0f,1.0f);";
|
||||
surfaceDescriptionFunction.AppendLine(feedBackCode);
|
||||
}
|
||||
else if (feedbackVariables.Count == 1)
|
||||
{
|
||||
string feedBackCode = "surface.VTPackedFeedback = GetPackedVTFeedback(" + feedbackVariables[0] + ");";
|
||||
surfaceDescriptionFunction.AppendLine(feedBackCode);
|
||||
}
|
||||
else if (feedbackVariables.Count > 1)
|
||||
{
|
||||
surfaceDescriptionFunction.AppendLine("float4 VTFeedback_array[" + feedbackVariables.Count + "];");
|
||||
|
||||
int arrayIndex = 0;
|
||||
foreach (var variable in feedbackVariables)
|
||||
{
|
||||
surfaceDescriptionFunction.AppendLine("VTFeedback_array[" + arrayIndex + "] = " + variable + ";");
|
||||
arrayIndex++;
|
||||
}
|
||||
|
||||
surfaceDescriptionFunction.AppendLine("uint pixelColumn = (IN.ScreenPosition.x / IN.ScreenPosition.w) * _ScreenParams.x;");
|
||||
surfaceDescriptionFunction.AppendLine(
|
||||
"surface.VTPackedFeedback = GetPackedVTFeedback(VTFeedback_array[(pixelColumn + _FrameCount) % (uint)" + feedbackVariables.Count + "]);");
|
||||
}
|
||||
}
|
||||
|
||||
if (shaderKeywords.permutations.Count >= 1)
|
||||
{
|
||||
surfaceDescriptionFunction.AppendLine("#endif");
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var list in feedbackVariablesPerPermutation)
|
||||
{
|
||||
list.Dispose();
|
||||
}
|
||||
feedbackVariablesPerPermutation.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically add a streaming feedback node and correctly connect it to stack samples are connected to it and it is connected to the master node output
|
||||
public static List<string> GetFeedbackVariables(SubGraphOutputNode masterNode)
|
||||
{
|
||||
// TODO: make use a generic interface instead of hard-coding the node types that we need to look at here
|
||||
var VTNodes = GraphUtil.FindDownStreamNodesOfType<SampleVirtualTextureNode>(masterNode);
|
||||
var subGraphNodes = GraphUtil.FindDownStreamNodesOfType<SubGraphNode>(masterNode);
|
||||
|
||||
List<string> result = new List<string>();
|
||||
|
||||
// Early out if there are no nodes we care about in the graph
|
||||
if (subGraphNodes.Count <= 0 && VTNodes.Count <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Add inputs to feedback node
|
||||
foreach (var node in VTNodes)
|
||||
{
|
||||
if (node.noFeedback) continue;
|
||||
result.Add(node.GetFeedbackVariableName());
|
||||
}
|
||||
|
||||
foreach (var node in subGraphNodes)
|
||||
{
|
||||
if (node.asset == null) continue;
|
||||
// TODO: subgraph.GetFeedbackVariableNames(...)
|
||||
foreach (var feedbackSlot in node.asset.vtFeedbackVariables)
|
||||
{
|
||||
result.Add(node.GetVariableNameForNode() + "_" + feedbackSlot);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e2db046575851ad4c806c1fb14f28290
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue