123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- using System;
- using System.Text;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEditor.ShaderGraph.Drawing.Controls;
- using UnityEngine;
- using UnityEditor.Graphing;
- using UnityEditor.ShaderGraph.Internal;
-
- namespace UnityEditor.ShaderGraph
- {
- [Serializable]
- [BlackboardInputInfo(60)]
- class VirtualTextureShaderProperty : AbstractShaderProperty<SerializableVirtualTexture>
- {
- public VirtualTextureShaderProperty()
- {
- displayName = "VirtualTexture";
- value = new SerializableVirtualTexture();
-
- // add at least one layer
- value.layers = new List<SerializableVirtualTextureLayer>();
- value.layers.Add(new SerializableVirtualTextureLayer("Layer0", new SerializableTexture()));
- value.layers.Add(new SerializableVirtualTextureLayer("Layer1", new SerializableTexture()));
- }
-
- public override PropertyType propertyType => PropertyType.VirtualTexture;
-
- internal override bool isExposable => true; // the textures are exposable at least..
- internal override bool isRenamable => true;
-
- internal override void GetPropertyReferenceNames(List<string> result)
- {
- result.Add(referenceName);
- for (int layer = 0; layer < value.layers.Count; layer++)
- {
- result.Add(value.layers[layer].layerRefName);
- }
- }
-
- internal override void GetPropertyDisplayNames(List<string> result)
- {
- result.Add(displayName);
- for (int layer = 0; layer < value.layers.Count; layer++)
- {
- result.Add(value.layers[layer].layerName);
- }
- }
-
- // this is used for properties exposed to the Material in the shaderlab Properties{} block
- internal override void AppendPropertyBlockStrings(ShaderStringBuilder builder)
- {
- if (!value.procedural)
- {
- // adds properties in this format so: [TextureStack.MyStack(0)] [NoScaleOffset] Layer0("Layer0", 2D) = "white" {}
- for (int layer = 0; layer < value.layers.Count; layer++)
- {
- string layerName = value.layers[layer].layerName;
- string layerRefName = value.layers[layer].layerRefName;
- builder.AppendLine($"{hideTagString}[TextureStack.{referenceName}({layer})][NoScaleOffset]{layerRefName}(\"{layerName}\", 2D) = \"white\" {{}}");
- }
- }
- else
- {
- // For procedural VT, we only need to expose a single property, indicating the referenceName and the number of layers
-
- // Adds a property as:
- // [ProceduralTextureStack.MyStack(1)] [NoScaleOffset] MyStack("Procedural Virtual Texture", 2D) = "white" {}
- // or:
- // [GlobalProceduralTextureStack.MyStack(2)] [NoScaleOffset] MyStack("Procedural Virtual Texture", 2D) = "white" {}
- string prefixString = value.shaderDeclaration == HLSLDeclaration.UnityPerMaterial
- ? "ProceduralTextureStack"
- : "GlobalProceduralTextureStack";
-
- int numLayers = value.layers.Count;
- builder.AppendLine($"{hideTagString}[{prefixString}.{referenceName}({numLayers})][NoScaleOffset]{referenceName}(\"{"Procedural Virtual Texture"}\", 2D) = \"white\" {{}}");
- }
- }
-
- internal override string GetPropertyBlockString()
- {
- // this should not be called, as it is replaced by the Append*PropertyBlockStrings function above
- throw new NotSupportedException();
- }
-
- internal override bool AllowHLSLDeclaration(HLSLDeclaration decl) => false; // disable UI, nothing to choose
-
- internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
- {
- int numLayers = value.layers.Count;
- if (numLayers > 0)
- {
- HLSLDeclaration decl = (value.procedural) ? value.shaderDeclaration : HLSLDeclaration.UnityPerMaterial;
-
- action(new HLSLProperty(HLSLType._CUSTOM, referenceName + "_CBDecl", decl, concretePrecision)
- {
- customDeclaration = (ssb) =>
- {
- ssb.TryAppendIndentation();
- ssb.Append("DECLARE_STACK_CB(");
- ssb.Append(referenceName);
- ssb.Append(");");
- ssb.AppendNewLine();
- }
- });
-
- if (!value.procedural)
- {
- //declare regular texture properties (for fallback case)
- for (int i = 0; i < numLayers; i++)
- {
- string layerRefName = value.layers[i].layerRefName;
- action(new HLSLProperty(HLSLType._Texture2D, layerRefName, HLSLDeclaration.Global));
- action(new HLSLProperty(HLSLType._SamplerState, "sampler" + layerRefName, HLSLDeclaration.Global));
- }
- }
-
- Action<ShaderStringBuilder> customDecl = (builder) =>
- {
- // declare texture stack
- builder.TryAppendIndentation();
- builder.Append("DECLARE_STACK");
- builder.Append((numLayers <= 1) ? "" : numLayers.ToString());
- builder.Append("(");
- builder.Append(referenceName);
- builder.Append(",");
- for (int i = 0; i < value.layers.Count; i++)
- {
- if (i != 0) builder.Append(",");
- builder.Append(value.layers[i].layerRefName);
- }
- builder.Append(");");
- builder.AppendNewLine();
-
- // declare the actual virtual texture property "variable" as a macro define to the BuildVTProperties function
- builder.TryAppendIndentation();
- builder.Append("#define ");
- builder.Append(referenceName);
- builder.Append(" AddTextureType(BuildVTProperties_");
- builder.Append(referenceName);
- builder.Append("()");
- for (int i = 0; i < value.layers.Count; i++)
- {
- builder.Append(",");
- builder.Append("TEXTURETYPE_");
- builder.Append(value.layers[i].layerTextureType.ToString().ToUpper());
- }
- builder.Append(")");
- builder.AppendNewLine();
- };
-
- action(new HLSLProperty(HLSLType._CUSTOM, referenceName + "_Global", HLSLDeclaration.Global, concretePrecision)
- {
- customDeclaration = customDecl
- });
- }
- }
-
- // argument string used to pass this property to a subgraph
- internal override string GetPropertyAsArgumentString(string precisionString)
- {
- return "VTPropertyWithTextureType " + referenceName;
- }
-
- // if a blackboard property is deleted, or copy/pasted, all node instances of it are replaced with this:
- internal override AbstractMaterialNode ToConcreteNode()
- {
- return null; // return null to indicate there is NO concrete form of a VT property
- }
-
- internal override PreviewProperty GetPreviewMaterialProperty()
- {
- return new PreviewProperty(propertyType)
- {
- name = referenceName,
- vtProperty = this
- };
- }
-
- internal override ShaderInput Copy()
- {
- var vt = new VirtualTextureShaderProperty
- {
- displayName = displayName,
- value = new SerializableVirtualTexture(),
- };
-
- // duplicate layer data, but reset reference names (they should be unique)
- for (int layer = 0; layer < value.layers.Count; layer++)
- {
- var guid = Guid.NewGuid();
- vt.value.layers.Add(new SerializableVirtualTextureLayer(value.layers[layer]));
- }
-
- return vt;
- }
-
- internal void AddTextureInfo(List<PropertyCollector.TextureInfo> infos)
- {
- for (int layer = 0; layer < value.layers.Count; layer++)
- {
- string layerRefName = value.layers[layer].layerRefName;
- var layerTexture = value.layers[layer].layerTexture;
- var texture = layerTexture != null ? layerTexture.texture : null;
-
- var textureInfo = new PropertyCollector.TextureInfo
- {
- name = layerRefName,
- textureId = texture != null ? texture.GetInstanceID() : 0,
- dimension = texture != null ? texture.dimension : UnityEngine.Rendering.TextureDimension.Any,
- modifiable = true
- };
- infos.Add(textureInfo);
- }
- }
-
- internal override bool isAlwaysExposed => true;
- internal override bool isCustomSlotAllowed => false;
-
- public override void OnAfterDeserialize(string json)
- {
- // VT shader properties must be exposed so they can be picked up by the native-side VT system
- generatePropertyBlock = true;
- }
- }
- }
|