You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
9.4 KiB
226 lines
9.4 KiB
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; |
|
} |
|
} |
|
}
|
|
|