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.
266 lines
11 KiB
266 lines
11 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using UnityEditor.ShaderGraph;
|
|
using UnityEditor.ShaderGraph.Internal;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace UnityEditor.VFX
|
|
{
|
|
interface IVFXShaderGraphOutput
|
|
{
|
|
ShaderGraphVfxAsset GetShaderGraph();
|
|
}
|
|
|
|
static class VFXShaderGraphHelpers
|
|
{
|
|
public static string GetMissingShaderGraphErrorMessage(ShaderGraphVfxAsset shader)
|
|
{
|
|
var instanceID = shader.GetInstanceID();
|
|
var missingShaderPath = AssetDatabase.GetAssetPath(instanceID);
|
|
if (!string.IsNullOrEmpty(missingShaderPath))
|
|
{
|
|
return $" cannot be compiled because a Shader Graph asset located here '{missingShaderPath}' is missing.";
|
|
}
|
|
|
|
AssetDatabase.TryGetGUIDAndLocalFileIdentifier(shader, out var guid, out var localID);
|
|
return $" cannot be compiled because a Shader Graph with GUID '{guid}' is missing.\nYou might find the missing file by searching on your disk this guid in .meta files.";
|
|
}
|
|
|
|
private static Type GetPropertyType(AbstractShaderProperty property)
|
|
{
|
|
switch (property.propertyType)
|
|
{
|
|
case PropertyType.Color:
|
|
return typeof(Color);
|
|
case PropertyType.Texture2D:
|
|
return typeof(Texture2D);
|
|
case PropertyType.Texture2DArray:
|
|
return typeof(Texture2DArray);
|
|
case PropertyType.Texture3D:
|
|
return typeof(Texture3D);
|
|
case PropertyType.Cubemap:
|
|
return typeof(Cubemap);
|
|
case PropertyType.Gradient:
|
|
return null;
|
|
case PropertyType.Boolean:
|
|
return typeof(bool);
|
|
case PropertyType.Float:
|
|
return typeof(float);
|
|
case PropertyType.Vector2:
|
|
return typeof(Vector2);
|
|
case PropertyType.Vector3:
|
|
return typeof(Vector3);
|
|
case PropertyType.Vector4:
|
|
return typeof(Vector4);
|
|
case PropertyType.Matrix2:
|
|
return null;
|
|
case PropertyType.Matrix3:
|
|
return null;
|
|
case PropertyType.Matrix4:
|
|
return typeof(Matrix4x4);
|
|
case PropertyType.SamplerState:
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static object GetPropertyValue(AbstractShaderProperty property)
|
|
{
|
|
switch (property.propertyType)
|
|
{
|
|
case PropertyType.Texture2D:
|
|
return ((Texture2DShaderProperty) property).value.texture;
|
|
case PropertyType.Texture3D:
|
|
return ((Texture3DShaderProperty) property).value.texture;
|
|
case PropertyType.Cubemap:
|
|
return ((CubemapShaderProperty) property).value.cubemap;
|
|
case PropertyType.Texture2DArray:
|
|
return ((Texture2DArrayShaderProperty) property).value.textureArray;
|
|
default:
|
|
{
|
|
var type = GetPropertyType(property);
|
|
PropertyInfo info = property.GetType().GetProperty("value",
|
|
BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
|
|
return VFXConverter.ConvertTo(info?.GetValue(property), type);
|
|
}
|
|
}
|
|
}
|
|
|
|
public struct Property
|
|
{
|
|
public VFXPropertyWithValue property;
|
|
public bool multiCompile;
|
|
public string[] keywordsMapping;
|
|
}
|
|
|
|
public static bool HasAnyKeywordProperty(ShaderGraphVfxAsset shaderGraph)
|
|
{
|
|
foreach (var property in shaderGraph.properties)
|
|
{
|
|
if (property is ShaderGraph.ShaderKeyword)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static IEnumerable<Property> GetProperties(ShaderGraphVfxAsset shaderGraph)
|
|
{
|
|
foreach (var property in shaderGraph.properties)
|
|
{
|
|
if (property is AbstractShaderProperty shaderProperty)
|
|
{
|
|
if (shaderProperty.hidden)
|
|
continue;
|
|
|
|
var type = GetPropertyType(shaderProperty);
|
|
if (type == null)
|
|
continue;
|
|
|
|
var current = new Property()
|
|
{
|
|
keywordsMapping = null
|
|
};
|
|
|
|
if (shaderProperty.propertyType == PropertyType.Float)
|
|
{
|
|
if (property is Vector1ShaderProperty prop)
|
|
{
|
|
if (prop.floatType == FloatType.Slider)
|
|
current.property = new VFXPropertyWithValue(
|
|
new VFXProperty(type, property.referenceName,
|
|
new RangeAttribute(prop.rangeValues.x, prop.rangeValues.y)),
|
|
GetPropertyValue(shaderProperty));
|
|
else if (prop.floatType == FloatType.Integer)
|
|
current.property = new VFXPropertyWithValue(
|
|
new VFXProperty(typeof(int), property.referenceName),
|
|
VFXConverter.ConvertTo(GetPropertyValue(shaderProperty), typeof(int)));
|
|
else
|
|
current.property = new VFXPropertyWithValue(new VFXProperty(type, property.referenceName),
|
|
GetPropertyValue(shaderProperty));
|
|
}
|
|
else
|
|
{
|
|
//it could be a diffusion profile in HDRP.
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
current.property = new VFXPropertyWithValue(new VFXProperty(type, property.referenceName),
|
|
GetPropertyValue(shaderProperty));
|
|
|
|
yield return current;
|
|
|
|
}
|
|
else if (property is ShaderGraph.ShaderKeyword shaderKeyword)
|
|
{
|
|
if (!shaderKeyword.isExposed)
|
|
continue;
|
|
|
|
if (shaderKeyword.keywordType == KeywordType.Boolean)
|
|
{
|
|
yield return new Property()
|
|
{
|
|
property = new VFXPropertyWithValue(
|
|
new VFXProperty(typeof(bool), shaderKeyword.referenceName), shaderKeyword.value != 0),
|
|
multiCompile = shaderKeyword.keywordDefinition == KeywordDefinition.MultiCompile,
|
|
keywordsMapping = new[] { shaderKeyword.referenceName }
|
|
};
|
|
}
|
|
else if (shaderKeyword.keywordType == KeywordType.Enum)
|
|
{
|
|
var keywordsMapping = new string[shaderKeyword.entries.Count];
|
|
var enumNames = new string[shaderKeyword.entries.Count];
|
|
for (int index = 0; index < shaderKeyword.entries.Count; ++index)
|
|
{
|
|
keywordsMapping[index] = shaderKeyword.referenceName + "_" + shaderKeyword.entries[index].referenceName;
|
|
enumNames[index] = shaderKeyword.entries[index].displayName;
|
|
}
|
|
|
|
yield return new Property
|
|
{
|
|
property = new VFXPropertyWithValue(
|
|
new VFXProperty(typeof(uint), shaderKeyword.referenceName, new VFXPropertyAttributes(new EnumAttribute(enumNames))), (uint)shaderKeyword.value),
|
|
multiCompile = shaderKeyword.keywordDefinition == KeywordDefinition.MultiCompile,
|
|
keywordsMapping = keywordsMapping
|
|
};
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("Unsupported keyword type: " + shaderKeyword.keywordType);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("Unsupported property type: " + property);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static IEnumerable<VFXNamedExpression> GetTextureConstant(ShaderGraphVfxAsset shaderGraph)
|
|
{
|
|
foreach (var tex in shaderGraph.textureInfos)
|
|
{
|
|
switch (tex.dimension)
|
|
{
|
|
case TextureDimension.Tex2D:
|
|
yield return new VFXNamedExpression(
|
|
new VFXTexture2DValue(tex.instanceID, VFXValue.Mode.Variable), tex.name);
|
|
break;
|
|
case TextureDimension.Tex3D:
|
|
yield return new VFXNamedExpression(
|
|
new VFXTexture3DValue(tex.instanceID, VFXValue.Mode.Variable), tex.name);
|
|
break;
|
|
case TextureDimension.Cube:
|
|
yield return new VFXNamedExpression(
|
|
new VFXTextureCubeValue(tex.instanceID, VFXValue.Mode.Variable), tex.name);
|
|
break;
|
|
case TextureDimension.Tex2DArray:
|
|
yield return new VFXNamedExpression(
|
|
new VFXTexture2DArrayValue(tex.instanceID, VFXValue.Mode.Variable), tex.name);
|
|
break;
|
|
case TextureDimension.CubeArray:
|
|
yield return new VFXNamedExpression(
|
|
new VFXTextureCubeArrayValue(tex.instanceID, VFXValue.Mode.Variable), tex.name);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static bool IsTexture(PropertyType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case PropertyType.Texture2D:
|
|
case PropertyType.Texture2DArray:
|
|
case PropertyType.Texture3D:
|
|
case PropertyType.Cubemap:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static ShaderGraphVfxAsset GetShaderGraph(VFXContext context)
|
|
{
|
|
if (context is IVFXShaderGraphOutput shaderGraphOutput)
|
|
return shaderGraphOutput.GetShaderGraph();
|
|
return null;
|
|
}
|
|
|
|
public static void GetShaderGraphParameter(ShaderGraphVfxAsset shaderGraph, out List<string> fragmentParameters, out List<string> vertexParameter)
|
|
{
|
|
fragmentParameters = new List<string>();
|
|
vertexParameter = new List<string>();
|
|
|
|
foreach (var param in shaderGraph.fragmentProperties)
|
|
if (!IsTexture(param.propertyType)) // Remove exposed textures from list of interpolants
|
|
fragmentParameters.Add(param.referenceName);
|
|
|
|
foreach (var param in shaderGraph.vertexProperties)
|
|
if (!IsTexture(param.propertyType)) // Remove exposed textures from list of interpolants
|
|
vertexParameter.Add(param.referenceName);
|
|
}
|
|
}
|
|
}
|