A game about forced loneliness, made by TACStudios
at master 9.6 kB view raw
1using System; 2using System.Text; 3using System.Collections.Generic; 4using System.Linq; 5using UnityEditor.ShaderGraph.Drawing.Controls; 6using UnityEngine; 7using UnityEditor.Graphing; 8using UnityEditor.ShaderGraph.Internal; 9 10namespace UnityEditor.ShaderGraph 11{ 12 [Serializable] 13 [BlackboardInputInfo(60)] 14 class VirtualTextureShaderProperty : AbstractShaderProperty<SerializableVirtualTexture> 15 { 16 public VirtualTextureShaderProperty() 17 { 18 displayName = "VirtualTexture"; 19 value = new SerializableVirtualTexture(); 20 21 // add at least one layer 22 value.layers = new List<SerializableVirtualTextureLayer>(); 23 value.layers.Add(new SerializableVirtualTextureLayer("Layer0", new SerializableTexture())); 24 value.layers.Add(new SerializableVirtualTextureLayer("Layer1", new SerializableTexture())); 25 } 26 27 public override PropertyType propertyType => PropertyType.VirtualTexture; 28 29 internal override bool isExposable => true; // the textures are exposable at least.. 30 internal override bool isRenamable => true; 31 32 internal override void GetPropertyReferenceNames(List<string> result) 33 { 34 result.Add(referenceName); 35 for (int layer = 0; layer < value.layers.Count; layer++) 36 { 37 result.Add(value.layers[layer].layerRefName); 38 } 39 } 40 41 internal override void GetPropertyDisplayNames(List<string> result) 42 { 43 result.Add(displayName); 44 for (int layer = 0; layer < value.layers.Count; layer++) 45 { 46 result.Add(value.layers[layer].layerName); 47 } 48 } 49 50 // this is used for properties exposed to the Material in the shaderlab Properties{} block 51 internal override void AppendPropertyBlockStrings(ShaderStringBuilder builder) 52 { 53 if (!value.procedural) 54 { 55 // adds properties in this format so: [TextureStack.MyStack(0)] [NoScaleOffset] Layer0("Layer0", 2D) = "white" {} 56 for (int layer = 0; layer < value.layers.Count; layer++) 57 { 58 string layerName = value.layers[layer].layerName; 59 string layerRefName = value.layers[layer].layerRefName; 60 builder.AppendLine($"{hideTagString}[TextureStack.{referenceName}({layer})][NoScaleOffset]{layerRefName}(\"{layerName}\", 2D) = \"white\" {{}}"); 61 } 62 } 63 else 64 { 65 // For procedural VT, we only need to expose a single property, indicating the referenceName and the number of layers 66 67 // Adds a property as: 68 // [ProceduralTextureStack.MyStack(1)] [NoScaleOffset] MyStack("Procedural Virtual Texture", 2D) = "white" {} 69 // or: 70 // [GlobalProceduralTextureStack.MyStack(2)] [NoScaleOffset] MyStack("Procedural Virtual Texture", 2D) = "white" {} 71 string prefixString = value.shaderDeclaration == HLSLDeclaration.UnityPerMaterial 72 ? "ProceduralTextureStack" 73 : "GlobalProceduralTextureStack"; 74 75 int numLayers = value.layers.Count; 76 builder.AppendLine($"{hideTagString}[{prefixString}.{referenceName}({numLayers})][NoScaleOffset]{referenceName}(\"{"Procedural Virtual Texture"}\", 2D) = \"white\" {{}}"); 77 } 78 } 79 80 internal override string GetPropertyBlockString() 81 { 82 // this should not be called, as it is replaced by the Append*PropertyBlockStrings function above 83 throw new NotSupportedException(); 84 } 85 86 internal override bool AllowHLSLDeclaration(HLSLDeclaration decl) => false; // disable UI, nothing to choose 87 88 internal override void ForeachHLSLProperty(Action<HLSLProperty> action) 89 { 90 int numLayers = value.layers.Count; 91 if (numLayers > 0) 92 { 93 HLSLDeclaration decl = (value.procedural) ? value.shaderDeclaration : HLSLDeclaration.UnityPerMaterial; 94 95 action(new HLSLProperty(HLSLType._CUSTOM, referenceName + "_CBDecl", decl, concretePrecision) 96 { 97 customDeclaration = (ssb) => 98 { 99 ssb.TryAppendIndentation(); 100 ssb.Append("DECLARE_STACK_CB("); 101 ssb.Append(referenceName); 102 ssb.Append(");"); 103 ssb.AppendNewLine(); 104 } 105 }); 106 107 if (!value.procedural) 108 { 109 //declare regular texture properties (for fallback case) 110 for (int i = 0; i < numLayers; i++) 111 { 112 string layerRefName = value.layers[i].layerRefName; 113 action(new HLSLProperty(HLSLType._Texture2D, layerRefName, HLSLDeclaration.Global)); 114 action(new HLSLProperty(HLSLType._SamplerState, "sampler" + layerRefName, HLSLDeclaration.Global)); 115 } 116 } 117 118 Action<ShaderStringBuilder> customDecl = (builder) => 119 { 120 // declare texture stack 121 builder.TryAppendIndentation(); 122 builder.Append("DECLARE_STACK"); 123 builder.Append((numLayers <= 1) ? "" : numLayers.ToString()); 124 builder.Append("("); 125 builder.Append(referenceName); 126 builder.Append(","); 127 for (int i = 0; i < value.layers.Count; i++) 128 { 129 if (i != 0) builder.Append(","); 130 builder.Append(value.layers[i].layerRefName); 131 } 132 builder.Append(");"); 133 builder.AppendNewLine(); 134 135 // declare the actual virtual texture property "variable" as a macro define to the BuildVTProperties function 136 builder.TryAppendIndentation(); 137 builder.Append("#define "); 138 builder.Append(referenceName); 139 builder.Append(" AddTextureType(BuildVTProperties_"); 140 builder.Append(referenceName); 141 builder.Append("()"); 142 for (int i = 0; i < value.layers.Count; i++) 143 { 144 builder.Append(","); 145 builder.Append("TEXTURETYPE_"); 146 builder.Append(value.layers[i].layerTextureType.ToString().ToUpper()); 147 } 148 builder.Append(")"); 149 builder.AppendNewLine(); 150 }; 151 152 action(new HLSLProperty(HLSLType._CUSTOM, referenceName + "_Global", HLSLDeclaration.Global, concretePrecision) 153 { 154 customDeclaration = customDecl 155 }); 156 } 157 } 158 159 // argument string used to pass this property to a subgraph 160 internal override string GetPropertyAsArgumentString(string precisionString) 161 { 162 return "VTPropertyWithTextureType " + referenceName; 163 } 164 165 // if a blackboard property is deleted, or copy/pasted, all node instances of it are replaced with this: 166 internal override AbstractMaterialNode ToConcreteNode() 167 { 168 return null; // return null to indicate there is NO concrete form of a VT property 169 } 170 171 internal override PreviewProperty GetPreviewMaterialProperty() 172 { 173 return new PreviewProperty(propertyType) 174 { 175 name = referenceName, 176 vtProperty = this 177 }; 178 } 179 180 internal override ShaderInput Copy() 181 { 182 var vt = new VirtualTextureShaderProperty 183 { 184 displayName = displayName, 185 value = new SerializableVirtualTexture(), 186 }; 187 188 // duplicate layer data, but reset reference names (they should be unique) 189 for (int layer = 0; layer < value.layers.Count; layer++) 190 { 191 var guid = Guid.NewGuid(); 192 vt.value.layers.Add(new SerializableVirtualTextureLayer(value.layers[layer])); 193 } 194 195 return vt; 196 } 197 198 internal void AddTextureInfo(List<PropertyCollector.TextureInfo> infos) 199 { 200 for (int layer = 0; layer < value.layers.Count; layer++) 201 { 202 string layerRefName = value.layers[layer].layerRefName; 203 var layerTexture = value.layers[layer].layerTexture; 204 var texture = layerTexture != null ? layerTexture.texture : null; 205 206 var textureInfo = new PropertyCollector.TextureInfo 207 { 208 name = layerRefName, 209 textureId = texture != null ? texture.GetInstanceID() : 0, 210 dimension = texture != null ? texture.dimension : UnityEngine.Rendering.TextureDimension.Any, 211 modifiable = true 212 }; 213 infos.Add(textureInfo); 214 } 215 } 216 217 internal override bool isAlwaysExposed => true; 218 internal override bool isCustomSlotAllowed => false; 219 220 public override void OnAfterDeserialize(string json) 221 { 222 // VT shader properties must be exposed so they can be picked up by the native-side VT system 223 generatePropertyBlock = true; 224 } 225 } 226}