Adaug proiectul Unity

This commit is contained in:
2026-11-01 23:39:55 +02:00
parent cb14d9d37d
commit 863eac8f2c
23463 changed files with 5412601 additions and 0 deletions
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 50a860756cfb850468867cc0b3e55a5a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace UnityEditor.Rendering
{
/// <summary>
/// Provider for a set of Materials Upgraders
/// </summary>
public interface IMaterialUpgradersProvider
{
/// <summary>
/// Returns a list of custom MaterialUpgrader instances.
/// </summary>
/// <returns>A list of upgraders</returns>
IEnumerable<MaterialUpgrader> GetUpgraders();
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 245f99d8bedd61c4780fbe93fdee0cb8
@@ -0,0 +1,64 @@
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.Rendering
{
internal class MaterialFinder
{
public static Dictionary<string, List<(Material parent, List<Material> variants)>> GroupAllMaterialsInProject()
{
var allMaterials = AssetDatabaseHelper.FindAssets<Material>();
Dictionary<string, List<(Material parent, List<Material> variants)>> result = new();
foreach (var material in allMaterials)
{
if (AssetDatabase.GetAssetPath(material).StartsWith("Packages", System.StringComparison.InvariantCultureIgnoreCase))
continue;
var shader = material.shader;
if (shader == null)
continue;
// Try get the shader entry, if not present create it
if (!result.TryGetValue(shader.name, out var list))
{
list = new List<(Material parent, List<Material> variants)>();
result[shader.name] = list;
}
bool isMaterialVariant = material.parent != null;
if (isMaterialVariant)
{
var entry = list.Find(e => e.parent == material.parent);
if (entry == default)
{
entry = (material.parent, new List<Material> { material });
list.Add(entry);
}
else
{
entry.variants.Add(material);
}
}
else
{
var entry = list.Find(e => e.parent == material);
if (entry == default)
{
entry = (material, new List<Material>());
list.Add(entry);
}
else
{
// Already present as parent, do nothing
}
}
}
return result;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7bc000bdbe3a2f346b6216538613e14d
@@ -0,0 +1,571 @@
using System;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering
{
/// <summary>
/// Material Upgrader class.
/// </summary>
public partial class MaterialUpgrader
{
internal static readonly string k_DialogKey = $"{nameof(UnityEditor)}.{nameof(Rendering)}.{nameof(MaterialUpgrader)}.ConfirmMaterialConversion";
#region Internal API
/// <summary>
/// Represents an entry describing material properties
/// </summary>
internal class MaterialInfo
{
/// <summary>
/// The material name
/// </summary>
public string Name { get; set; }
/// <summary>
/// The material being evaluated.
/// </summary>
[CanBeNull]
public Material Material { get; set; }
/// <summary>
/// The current shader of the material.
/// </summary>
public string ShaderName { get; set; }
/// <summary>
/// If the material is a variant
/// </summary>
public bool IsVariant { get; set; }
/// <summary>
/// The base material name
/// </summary>
public string BaseMaterialName { get; set; }
/// <summary>
/// The base material is <see cref="IsVariant"/> is true
/// </summary>
[CanBeNull]
public Material BaseMaterial { get; set; }
/// <summary>
/// Determines whether the specified object is equal to the current <see cref="MaterialInfo"/>.
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj)
{
if (obj is not MaterialInfo other)
return false;
return string.Equals(ShaderName, other.ShaderName, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Serves as the default hash function.
/// </summary>
/// <returns>A hash code for the current object.</returns>
public override int GetHashCode()
{
return ShaderName?.GetHashCode() ?? 0;
}
}
/// <summary>
/// Represents an entry describing whether a material is available for upgrade,
/// along with the reason if it's not.
/// </summary>
internal class MaterialUpgradeEntry
{
/// <summary>
/// The material being evaluated.
/// </summary>
public MaterialInfo MaterialInfo { get; set; }
/// <summary>
/// Indicates whether the material is available for upgrade.
/// </summary>
public bool AvailableForUpgrade { get; set; }
/// <summary>
/// If the material is not available for upgrade, this provides the reason why.
/// Empty if <see cref="AvailableForUpgrade"/> is true.
/// </summary>
public string NotAvailableForUpgradeReason { get; set; }
/// <summary>
/// Determines whether the specified object is equal to the current <see cref="MaterialUpgradeEntry"/>.
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj)
{
if (obj is not MaterialUpgradeEntry other)
return false;
return Equals(MaterialInfo, other.MaterialInfo) &&
AvailableForUpgrade == other.AvailableForUpgrade &&
string.Equals(NotAvailableForUpgradeReason, other.NotAvailableForUpgradeReason, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Serves as the default hash function.
/// </summary>
/// <returns>A hash code for the current object.</returns>
public override int GetHashCode()
{
return HashCode.Combine(MaterialInfo, AvailableForUpgrade, NotAvailableForUpgradeReason);
}
}
internal static MaterialUpgrader GetUpgrader(List<MaterialUpgrader> upgraders, Material material)
{
if (material == null || material.shader == null)
return null;
string shaderName = material.shader.name;
for (int i = 0; i != upgraders.Count; i++)
{
if (upgraders[i].OldShaderPath == shaderName)
return upgraders[i];
}
return null;
}
static void SaveAssetsAndFreeMemory()
{
AssetDatabase.SaveAssets();
GC.Collect();
EditorUtility.UnloadUnusedAssetsImmediate();
AssetDatabase.Refresh();
}
/// <summary>
/// Returns if the material has a mapping upgrader
/// </summary>
/// <param name="upgraders">The available upgrader list</param>
/// <param name="material">The material to check</param>
/// <returns></returns>
static bool IsMaterialUpgradable(List<MaterialUpgrader> upgraders, Material material)
{
if (material == null || upgraders == null)
throw new ArgumentException("Invalid input: upgraders or material is null.");
return GetUpgrader(upgraders, material) != null;
}
/// Extracts shader paths from a list of upgraders into two sets:
/// one for shaders to upgrade (old) and one for shaders already upgraded (new).
internal static void GetUpgraderShaderPaths(List<MaterialUpgrader> upgraders, out HashSet<string> oldShaders, out HashSet<string> newShaders)
{
oldShaders = new HashSet<string>();
newShaders = new HashSet<string>();
if (upgraders == null)
return;
foreach (var upgrader in upgraders)
{
if (!string.IsNullOrEmpty(upgrader.OldShaderPath))
oldShaders.Add(upgrader.OldShaderPath);
if (!string.IsNullOrEmpty(upgrader.NewShaderPath))
newShaders.Add(upgrader.NewShaderPath);
}
}
internal static MaterialInfo ToMaterialInfo(Material material)
{
Material baseMaterial = material;
if (material.isVariant)
{
// Traverse up to the root material
while (baseMaterial.isVariant && baseMaterial.parent != null)
{
baseMaterial = baseMaterial.parent;
}
}
return new MaterialInfo
{
Name = material.name,
Material = material,
ShaderName = material.shader.name,
IsVariant = material.isVariant,
BaseMaterialName = baseMaterial.name,
BaseMaterial = baseMaterial
};
}
internal static List<MaterialInfo> GatherInfo(IEnumerable<Material> materials)
{
var materialsInfo = new List<MaterialInfo>();
foreach (var material in materials)
{
if (material == null || material.shader == null)
continue;
materialsInfo.Add(ToMaterialInfo(material));
}
return materialsInfo;
}
internal static IEnumerable<MaterialUpgradeEntry> FetchUpgradeOptions(HashSet<string> upgradersAvailable, HashSet<string> shaderNamesToIgnore, List<MaterialInfo> materialInfo)
{
foreach (var material in materialInfo)
{
var shaderName = material.ShaderName;
bool isShaderIgnored = shaderNamesToIgnore.Contains(shaderName);
if (isShaderIgnored)
continue;
bool isUpgradable = !material.IsVariant && upgradersAvailable.Contains(shaderName);
string reason = isUpgradable ? string.Empty : GenerateReason(material);
yield return new MaterialUpgradeEntry
{
MaterialInfo = material,
AvailableForUpgrade = isUpgradable,
NotAvailableForUpgradeReason = reason
};
}
}
internal static List<Material> FetchAllMaterialsInProject()
{
List<Material> materials = new(AssetDatabaseHelper.FindAssets<Material>(".mat"));
// Add the build in material of terrain ( must be always available )
if (Terrain.activeTerrains.Length > 0)
{
materials.Add(Terrain.activeTerrain.materialTemplate);
}
return materials;
}
/// <summary>
/// Given a set of material assets in the project and determines whether they are eligible for upgrade.
/// </summary>
/// <param name="upgraders">A list of <see cref="MaterialUpgrader"/> instances to use for determining upgradability.</param>
/// <param name="materials"> A list of materials to check for upgrade options, if null Unity asumes that you want all project materials.</param>
/// <returns>
/// An enumerable of <see cref="MaterialUpgradeEntry"/> representing each material and whether it can be upgraded.
/// </returns>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="upgraders"/> is null.</exception>
internal static IEnumerable<MaterialUpgradeEntry> FetchUpgradeOptions(List<MaterialUpgrader> upgraders, List<Material> materials = null)
{
if (upgraders == null)
throw new ArgumentNullException(nameof(upgraders));
// If no materials are provided, gather all materials in the project.
if (materials == null)
{
materials = FetchAllMaterialsInProject();
}
var materialInfo = GatherInfo(materials);
GetUpgraderShaderPaths(upgraders, out var upgradersAvailable, out var shaderNamesToIgnore);
return FetchUpgradeOptions(upgradersAvailable, shaderNamesToIgnore, materialInfo);
}
internal static string GenerateReason(MaterialInfo material)
{
string reason = $"No upgrader available to convert material '{material.Name}'";
if (material.IsVariant)
{
reason += $", a variant of '{material.BaseMaterialName}',";
}
reason += $" using shader '{material.BaseMaterialName}'.";
return reason;
}
static StringBuilder s_UpgradeLog = new StringBuilder();
internal static string PerformUpgradeInternal(
List<MaterialUpgradeEntry> materialUpgrades,
List<MaterialUpgrader> upgraders,
HashSet<string> shaderNamesToIgnore,
string progressBarName,
bool showProgressBar = true,
UpgradeFlags flags = UpgradeFlags.None)
{
s_UpgradeLog.Clear();
if (materialUpgrades.Count > 0)
{
s_UpgradeLog.AppendLine($"{progressBarName}");
bool anyMaterialModified = false;
for (int materialIndex = 0; materialIndex < materialUpgrades.Count; ++materialIndex)
{
var entry = materialUpgrades[materialIndex];
if (showProgressBar)
{
if (EditorUtility.DisplayCancelableProgressBar(progressBarName, $"({materialIndex} of {materialUpgrades.Count}) {entry.MaterialInfo.Name}", (float)materialIndex / (float)materialUpgrades.Count))
{
s_UpgradeLog.AppendLine("Process cancelled by user.");
break;
}
}
if (!entry.AvailableForUpgrade || shaderNamesToIgnore.Contains(entry.MaterialInfo.ShaderName))
{
s_UpgradeLog.AppendLine($"Skipping material: {entry.MaterialInfo.Name} - {entry.NotAvailableForUpgradeReason}");
}
else
{
s_UpgradeLog.AppendLine($"Upgrading material: {entry.MaterialInfo.Name} using shader: {entry.MaterialInfo.ShaderName}");
if (entry.MaterialInfo.Material != null)
{
Upgrade(entry.MaterialInfo.Material, upgraders, flags);
anyMaterialModified = true;
}
}
}
if (anyMaterialModified)
AssetDatabase.SaveAssets();
if (showProgressBar)
EditorUtility.ClearProgressBar();
}
return s_UpgradeLog.ToString();
}
static void PerformUpgrade(List<MaterialUpgradeEntry> materialUpgrades, List<MaterialUpgrader> upgraders, HashSet<string> shaderNamesToIgnore, string progressBarName, UpgradeFlags flags = UpgradeFlags.None)
{
if (materialUpgrades == null || materialUpgrades.Count == 0)
{
Debug.LogWarning("No materials found for upgrade.");
return;
}
bool CanPerformUpgrade()
{
const string title = "Confirm Material Conversion";
const string message = "This action will modify materials and cannot be easily undone. It is strongly recommended to have a backup or use version control before continuing.";
const string proceed = "Proceed";
const string cancel = "Cancel";
if (Application.isBatchMode)
return true;
return EditorUtility.DisplayDialog(title, message, proceed, cancel, DialogOptOutDecisionType.ForThisMachine, k_DialogKey);
}
if (CanPerformUpgrade())
{
string upgradeLog = PerformUpgradeInternal(materialUpgrades, upgraders, shaderNamesToIgnore, progressBarName, true, flags);
Debug.Log(upgradeLog);
}
}
#endregion
#region Public API
/// <summary>
/// Checking if project folder contains any materials that can not be automatic upgraded.
/// </summary>
/// <param name="upgraders">List if <see cref="MaterialUpgrader"/></param>
/// <returns>Returns true if at least one material uses a non-built-in shader</returns>
public static bool ProjectContainsNonAutomaticUpgradePath(List<MaterialUpgrader> upgraders)
{
foreach (var material in AssetDatabaseHelper.FindAssets<Material>(".mat"))
{
if (!IsMaterialUpgradable(upgraders, material))
return true;
}
return false;
}
/// <summary>
/// Upgrade the project folder.
/// </summary>
/// <param name="upgraders">List of upgraders.</param>
/// <param name="progressBarName">Name of the progress bar.</param>
/// <param name="flags">Material Upgrader flags.</param>
public static void UpgradeProjectFolder(List<MaterialUpgrader> upgraders, string progressBarName, UpgradeFlags flags = UpgradeFlags.None)
{
HashSet<string> shaderNamesToIgnore = new HashSet<string>();
UpgradeProjectFolder(upgraders, shaderNamesToIgnore, progressBarName, flags);
}
/// <summary>
/// Fetches all upgraders that support the given render pipeline asset type
/// </summary>
/// <param name="renderPipelineAssetType">The RP asset type</param>
/// <returns>A list with all the upgraders in for the given pipeline</returns>
public static List<MaterialUpgrader> FetchAllUpgradersForPipeline(Type renderPipelineAssetType)
{
if (!typeof(RenderPipelineAsset).IsAssignableFrom(renderPipelineAssetType))
throw new ArgumentException($"Type '{renderPipelineAssetType.FullName}' must inherit from RenderPipelineAsset.", nameof(renderPipelineAssetType));
return MaterialUpgraderRegistry.instance.GetMaterialUpgradersForPipeline(renderPipelineAssetType);
}
/// <summary>
/// Fetches all materials in the project that are upgradable to the given render pipeline asset type
/// </summary>
/// <param name="renderPipelineAssetType">The RP asset type</param>
/// <returns>A list with all the materials in the project</returns>
public static List<Material> FetchAllUpgradableMaterialsForPipeline(Type renderPipelineAssetType)
{
var upgraders = FetchAllUpgradersForPipeline(renderPipelineAssetType);
if (upgraders == null || upgraders.Count == 0)
{
Debug.LogWarning($"No material upgraders found for pipeline: {renderPipelineAssetType.Name}");
return new List<Material>();
}
var allMaterials = FetchAllMaterialsInProject();
var materialsAvailableForUpgrade = new List<Material>();
foreach (var option in FetchUpgradeOptions(upgraders, allMaterials))
{
if (!option.AvailableForUpgrade)
continue;
materialsAvailableForUpgrade.Add(option.MaterialInfo.Material);
}
return materialsAvailableForUpgrade;
}
/// <summary>
/// Upgrade a material.
/// </summary>
/// <param name="material">Material to upgrade.</param>
/// <param name="upgrader">Material upgrader.</param>
/// <param name="flags">Material Upgrader flags.</param>
public static void Upgrade(Material material, MaterialUpgrader upgrader, UpgradeFlags flags)
{
using (ListPool<MaterialUpgrader>.Get(out List<MaterialUpgrader> upgraders))
{
upgraders.Add(upgrader);
Upgrade(material, upgraders, flags);
}
}
/// <summary>
/// Upgrade a material.
/// </summary>
/// <param name="material">Material to upgrade.</param>
/// <param name="upgraders">List of Material upgraders.</param>
/// <param name="flags">Material Upgrader flags.</param>
public static void Upgrade(Material material, List<MaterialUpgrader> upgraders, UpgradeFlags flags)
{
if (material == null || upgraders == null || upgraders.Count == 0)
return;
string message = string.Empty;
if (Upgrade(material, upgraders, flags, ref message))
return;
if (!string.IsNullOrEmpty(message))
{
Debug.Log(message);
}
}
/// <summary>
/// Upgrade a material.
/// </summary>
/// <param name="material">Material to upgrade.</param>
/// <param name="upgraders">List of Material upgraders.</param>
/// <param name="flags">Material upgrader flags.</param>
/// <param name="message">Error message to be outputted when no material upgraders are suitable for given material if the flags <see cref="UpgradeFlags.LogMessageWhenNoUpgraderFound"/> is used.</param>
/// <returns>Returns true if the upgrader was found for the passed in material.</returns>
public static bool Upgrade(Material material, List<MaterialUpgrader> upgraders, UpgradeFlags flags, ref string message)
{
if (material == null)
return false;
var upgrader = GetUpgrader(upgraders, material);
if (upgrader != null)
{
upgrader.Upgrade(material, flags);
return true;
}
if ((flags & UpgradeFlags.LogMessageWhenNoUpgraderFound) == UpgradeFlags.LogMessageWhenNoUpgraderFound)
{
message =
$"{material.name} material was not upgraded. There's no upgrader to convert {material.shader.name} shader to selected pipeline";
return false;
}
return true;
}
/// <summary>
/// Upgrade the project folder.
/// </summary>
/// <param name="upgraders">List of upgraders.</param>
/// <param name="shaderNamesToIgnore">Set of shader names to ignore.</param>
/// <param name="progressBarName">Name of the progress bar.</param>
/// <param name="flags">Material Upgrader flags.</param>
public static void UpgradeProjectFolder(List<MaterialUpgrader> upgraders, HashSet<string> shaderNamesToIgnore, string progressBarName, UpgradeFlags flags = UpgradeFlags.None)
{
using (ListPool<MaterialUpgradeEntry>.Get(out var tmp))
{
tmp.AddRange(FetchUpgradeOptions(upgraders));
PerformUpgrade(tmp, upgraders, shaderNamesToIgnore, progressBarName, flags);
}
}
/// <summary>
/// Upgrade the selection.
/// </summary>
/// <param name="upgraders">List of upgraders.</param>
/// <param name="progressBarName">Name of the progress bar.</param>
/// <param name="flags">Material Upgrader flags.</param>
public static void UpgradeSelection(List<MaterialUpgrader> upgraders, string progressBarName, UpgradeFlags flags = UpgradeFlags.None)
{
HashSet<string> shaderNamesToIgnore = new HashSet<string>();
UpgradeSelection(upgraders, shaderNamesToIgnore, progressBarName, flags);
}
/// <summary>
/// Upgrade the selection.
/// </summary>
/// <param name="upgraders">List of upgraders.</param>
/// <param name="shaderNamesToIgnore">Set of shader names to ignore.</param>
/// <param name="progressBarName">Name of the progress bar.</param>
/// <param name="flags">Material Upgrader flags.</param>
public static void UpgradeSelection(List<MaterialUpgrader> upgraders, HashSet<string> shaderNamesToIgnore, string progressBarName, UpgradeFlags flags = UpgradeFlags.None)
{
using (ListPool<MaterialUpgradeEntry>.Get(out var tmp))
{
using (ListPool<Material>.Get(out var selectedMaterials))
{
var selection = Selection.objects;
if (selection != null)
{
for (int i = 0; i < selection.Length; ++i)
{
if (selection[i] is Material m)
selectedMaterials.Add(m);
}
}
tmp.AddRange(FetchUpgradeOptions(upgraders, selectedMaterials));
}
PerformUpgrade(tmp, upgraders, shaderNamesToIgnore, progressBarName, flags);
}
}
#endregion
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 91bd3583117bf334eb9150fbfd3b22b3
@@ -0,0 +1,479 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
namespace UnityEditor.Rendering
{
public partial class MaterialUpgrader
{
// Track memory usage to trigger periodic cleanup and prevent out-of-memory crashes
// This prevents out-of-memory crashes on DX12/Vulkan where GPU memory cannot fall back to disk
private static long s_MemoryUsedSinceLastCleanup = 0;
private const long kMemoryThresholdBytes = 2L * 1024L * 1024L * 1024L; // 2 GB threshold
/// <summary>
/// The priority of the upgrader.
/// </summary>
public virtual int priority => 0;
/// <summary>
/// Material Upgrader finalizer delegate.
/// </summary>
/// <param name="mat">Material</param>
public delegate void MaterialFinalizer(Material mat);
string m_OldShader;
string m_NewShader;
/// <summary>
/// Retrieves path to new shader.
/// </summary>
public string NewShaderPath => m_NewShader;
/// <summary>
/// Retrieves path to old shader.
/// </summary>
public string OldShaderPath => m_OldShader;
/// <summary>
/// Material finalizer.
/// </summary>
public MaterialFinalizer Finalizer { get; private set;}
Dictionary<string, string> m_TextureRename = new Dictionary<string, string>();
Dictionary<string, string> m_FloatRename = new Dictionary<string, string>();
Dictionary<string, string> m_ColorRename = new Dictionary<string, string>();
Dictionary<string, float> m_FloatPropertiesToSet = new Dictionary<string, float>();
Dictionary<string, Color> m_ColorPropertiesToSet = new Dictionary<string, Color>();
List<string> m_TexturesToRemove = new List<string>();
Dictionary<string, Texture> m_TexturesToSet = new Dictionary<string, Texture>();
interface IKeywordMigration
{
void Apply(Material srcMaterial, Material dstMaterial);
}
class KeywordRename : IKeywordMigration
{
public string oldKeyword;
public string newKeyword;
public void Apply(Material srcMaterial, Material dstMaterial)
{
bool isEnabled = srcMaterial.IsKeywordEnabled(oldKeyword);
CoreUtils.SetKeyword(dstMaterial, newKeyword, isEnabled);
}
}
class KeywordToFloat : IKeywordMigration
{
public string keyword;
public string property;
public float setVal, unsetVal;
public void Apply(Material srcMaterial, Material dstMaterial)
{
if (!dstMaterial.HasProperty(property))
return;
dstMaterial.SetFloat(property, srcMaterial.IsKeywordEnabled(keyword) ? setVal : unsetVal);
}
}
List<IKeywordMigration> m_KeywordMigrations = new List<IKeywordMigration>();
Dictionary<string, (string, System.Func<float, bool>)> m_ConditionalFloatRename;
/// <summary>
/// Type of property to rename.
/// </summary>
public enum MaterialPropertyType
{
/// <summary>Texture reference property.</summary>
Texture = 0,
/// <summary>Float property.</summary>
Float = 1,
/// <summary>Color property.</summary>
Color = 2,
/// <summary>Count property.</summary>
Count = 3
}
/// <summary>
/// Retrieves a collection of renamed parameters of a specific MaterialPropertyType.
/// </summary>
/// <param name="type">Material Property Type</param>
/// <returns>Dictionary of property names to their renamed values.</returns>
/// <exception cref="ArgumentException">type is not valid.</exception>
public IReadOnlyDictionary<string, string> GetPropertyRenameMap(MaterialPropertyType type)
{
switch (type)
{
case MaterialPropertyType.Texture: return m_TextureRename;
case MaterialPropertyType.Float: return m_FloatRename;
case MaterialPropertyType.Color: return m_ColorRename;
default: throw new ArgumentException(nameof(type));
}
}
/// <summary>
/// Upgrade Flags
/// </summary>
[Flags]
public enum UpgradeFlags
{
/// <summary>None.</summary>
None = 0,
/// <summary>LogErrorOnNonExistingProperty.</summary>
LogErrorOnNonExistingProperty = 1,
/// <summary>CleanupNonUpgradedProperties.</summary>
CleanupNonUpgradedProperties = 2,
/// <summary>LogMessageWhenNoUpgraderFound.</summary>
LogMessageWhenNoUpgraderFound = 4
}
/// <summary>
/// Upgrade method.
/// </summary>
/// <param name="material">Material to upgrade.</param>
/// <param name="flags">Upgrade flag</param>
public virtual void Upgrade(Material material, UpgradeFlags flags)
{
if (material == null)
throw new ArgumentNullException(nameof(material));
var shader = Shader.Find(m_NewShader);
if (shader == null)
{
Debug.LogError($"Unable to find destination shader {m_NewShader} when trying to upgrade {material.name}");
return;
}
Material newMaterial;
if ((flags & UpgradeFlags.CleanupNonUpgradedProperties) != 0)
{
newMaterial = new Material(shader);
}
else
{
newMaterial = UnityEngine.Object.Instantiate(material) as Material;
newMaterial.shader = shader;
}
Convert(material, newMaterial);
// Material Variants will not change the shader as is a parent only thing
if (material.parent == null)
material.shader = shader;
material.CopyPropertiesFromMaterial(newMaterial);
UnityEngine.Object.DestroyImmediate(newMaterial);
Finalizer?.Invoke(material);
// Track memory and periodically unload assets to prevent out-of-memory crashes
long memoryUsed = EstimateMaterialMemoryUsage(material);
s_MemoryUsedSinceLastCleanup += memoryUsed;
if (s_MemoryUsedSinceLastCleanup >= kMemoryThresholdBytes)
{
//Debug.Log($"MaterialUpgrader: Memory threshold reached ({s_MemoryUsedSinceLastCleanup / (1024f * 1024f * 1024f):F2} GB). Saving assets and freeing memory...");
SaveAssetsAndFreeMemory();
s_MemoryUsedSinceLastCleanup = 0;
}
}
// Overridable function to implement custom material upgrading functionality
/// <summary>
/// Custom material conversion method.
/// </summary>
/// <param name="srcMaterial">Source material.</param>
/// <param name="dstMaterial">Destination material.</param>
public virtual void Convert(Material srcMaterial, Material dstMaterial)
{
foreach (var t in m_TextureRename)
{
if (!srcMaterial.HasProperty(t.Key) || !dstMaterial.HasProperty(t.Value))
continue;
dstMaterial.SetTextureScale(t.Value, srcMaterial.GetTextureScale(t.Key));
dstMaterial.SetTextureOffset(t.Value, srcMaterial.GetTextureOffset(t.Key));
dstMaterial.SetTexture(t.Value, srcMaterial.GetTexture(t.Key));
}
foreach (var t in m_FloatRename)
{
if (!srcMaterial.HasProperty(t.Key) || !dstMaterial.HasProperty(t.Value))
continue;
dstMaterial.SetFloat(t.Value, srcMaterial.GetFloat(t.Key));
}
foreach (var t in m_ColorRename)
{
if (!srcMaterial.HasProperty(t.Key) || !dstMaterial.HasProperty(t.Value))
continue;
dstMaterial.SetColor(t.Value, srcMaterial.GetColor(t.Key));
}
foreach (var prop in m_TexturesToRemove)
{
if (!dstMaterial.HasProperty(prop))
continue;
dstMaterial.SetTexture(prop, null);
}
foreach (var prop in m_TexturesToSet)
{
if (!dstMaterial.HasProperty(prop.Key))
continue;
dstMaterial.SetTexture(prop.Key, prop.Value);
}
foreach (var prop in m_FloatPropertiesToSet)
{
if (!dstMaterial.HasProperty(prop.Key))
continue;
dstMaterial.SetFloat(prop.Key, prop.Value);
}
foreach (var prop in m_ColorPropertiesToSet)
{
if (!dstMaterial.HasProperty(prop.Key))
continue;
dstMaterial.SetColor(prop.Key, prop.Value);
}
// Handle keyword migrations
foreach (var migration in m_KeywordMigrations)
{
migration.Apply(srcMaterial, dstMaterial);
}
// Handle conditional float renaming
if (m_ConditionalFloatRename != null)
{
foreach (var (oldName, (newName, condition)) in m_ConditionalFloatRename)
{
if (srcMaterial.HasProperty(oldName) &&
condition(srcMaterial.GetFloat(oldName)) &&
dstMaterial.HasProperty(newName))
{
dstMaterial.SetFloat(newName, 1.0f);
}
}
}
}
/// <summary>
/// Rename shader.
/// </summary>
/// <param name="oldName">Old name.</param>
/// <param name="newName">New name.</param>
/// <param name="finalizer">Finalizer delegate.</param>
public void RenameShader(string oldName, string newName, MaterialFinalizer finalizer = null)
{
m_OldShader = oldName;
m_NewShader = newName;
Finalizer = finalizer;
}
/// <summary>
/// Rename Texture Parameter.
/// </summary>
/// <param name="oldName">Old name.</param>
/// <param name="newName">New name.</param>
public void RenameTexture(string oldName, string newName)
{
m_TextureRename[oldName] = newName;
}
/// <summary>
/// Rename Float Parameter.
/// </summary>
/// <param name="oldName">Old name.</param>
/// <param name="newName">New name.</param>
public void RenameFloat(string oldName, string newName)
{
m_FloatRename[oldName] = newName;
}
/// <summary>
/// Rename Color Parameter.
/// </summary>
/// <param name="oldName">Old name.</param>
/// <param name="newName">New name.</param>
public void RenameColor(string oldName, string newName)
{
m_ColorRename[oldName] = newName;
}
/// <summary>
/// Remove Texture Parameter.
/// </summary>
/// <param name="name">Parameter name.</param>
public void RemoveTexture(string name)
{
m_TexturesToRemove.Add(name);
}
/// <summary>
/// Set float property.
/// </summary>
/// <param name="propertyName">Property name.</param>
/// <param name="value">Property value.</param>
public void SetFloat(string propertyName, float value)
{
m_FloatPropertiesToSet[propertyName] = value;
}
/// <summary>
/// Set color property.
/// </summary>
/// <param name="propertyName">Property name.</param>
/// <param name="value">Property value.</param>
public void SetColor(string propertyName, Color value)
{
m_ColorPropertiesToSet[propertyName] = value;
}
/// <summary>
/// Set texture property.
/// </summary>
/// <param name="propertyName">Property name.</param>
/// <param name="value">Property value.</param>
public void SetTexture(string propertyName, Texture value)
{
m_TexturesToSet[propertyName] = value;
}
/// <summary>
/// Rename a keyword to float.
/// </summary>
/// <param name="oldName">Old name.</param>
/// <param name="newName">New name.</param>
/// <param name="setVal">Value when set.</param>
/// <param name="unsetVal">Value when unset.</param>
public void RenameKeywordToFloat(string oldName, string newName, float setVal, float unsetVal)
{
m_KeywordMigrations.Add(new KeywordToFloat { keyword = oldName, property = newName, setVal = setVal, unsetVal = unsetVal });
}
/// <summary>
/// Rename a float property conditionally based on its value
/// </summary>
/// <param name="oldName">Old property name</param>
/// <param name="newName">New property name</param>
/// <param name="condition">Condition function that takes the float value and returns true if renaming should occur</param>
protected void RenameFloat(string oldName, string newName, System.Func<float, bool> condition)
{
(m_ConditionalFloatRename ??= new Dictionary<string, (string, System.Func<float, bool>)>())[oldName] = (newName, condition);
}
/// <summary>
/// Rename a keyword from old shader to new shader.
/// </summary>
/// <param name="oldName">Old keyword name.</param>
/// <param name="newName">New keyword name.</param>
public void RenameKeyword(string oldName, string newName)
{
m_KeywordMigrations.Add(new KeywordRename { oldKeyword = oldName, newKeyword = newName });
}
/// <summary>
/// Transfer a keyword state from old shader to new shader (same keyword name in both shaders).
/// Use this when the keyword name doesn't change between shaders, only forwarding its enabled/disabled state.
/// </summary>
/// <param name="keywordName">Keyword name to transfer.</param>
public void TransferKeyword(string keywordName)
{
m_KeywordMigrations.Add(new KeywordRename { oldKeyword = keywordName, newKeyword = keywordName });
}
private static ulong ComputeTextureSize(Texture texture)
{
if (texture == null)
return 0;
UnityEngine.Experimental.Rendering.GraphicsFormat format;
int depthOrArraySlices = 1;
int cubeFaces = 1;
switch (texture)
{
case Texture2D tex2D:
format = UnityEngine.Experimental.Rendering.GraphicsFormatUtility.GetGraphicsFormat(tex2D.format, false);
break;
case Texture3D tex3D:
format = UnityEngine.Experimental.Rendering.GraphicsFormatUtility.GetGraphicsFormat(tex3D.format, false);
depthOrArraySlices = tex3D.depth;
break;
case Texture2DArray tex2DArray:
format = UnityEngine.Experimental.Rendering.GraphicsFormatUtility.GetGraphicsFormat(tex2DArray.format, false);
depthOrArraySlices = tex2DArray.depth;
break;
case CubemapArray cubeArray:
format = UnityEngine.Experimental.Rendering.GraphicsFormatUtility.GetGraphicsFormat(cubeArray.format, false);
cubeFaces = 6;
depthOrArraySlices = cubeArray.cubemapCount;
break;
case Cubemap cube:
format = UnityEngine.Experimental.Rendering.GraphicsFormatUtility.GetGraphicsFormat(cube.format, false);
cubeFaces = 6;
break;
case RenderTexture rt:
format = rt.graphicsFormat != UnityEngine.Experimental.Rendering.GraphicsFormat.None
? rt.graphicsFormat
: rt.depthStencilFormat;
depthOrArraySlices = Mathf.Max(1, rt.volumeDepth);
if (rt.dimension == UnityEngine.Rendering.TextureDimension.Cube ||
rt.dimension == UnityEngine.Rendering.TextureDimension.CubeArray)
{
cubeFaces = 6;
}
break;
default:
format = UnityEngine.Experimental.Rendering.GraphicsFormat.R8G8B8A8_UNorm;
break;
}
ulong sliceSize = UnityEngine.Experimental.Rendering.GraphicsFormatUtility.ComputeMipmapSize(texture.width, texture.height, format);
return sliceSize * (ulong)depthOrArraySlices * (ulong)cubeFaces;
}
private static long EstimateMaterialMemoryUsage(Material material)
{
if (material == null || material.shader == null)
return 0;
long totalBytes = 0;
var shader = material.shader;
int propertyCount = shader.GetPropertyCount();
for (int i = 0; i < propertyCount; i++)
{
if (shader.GetPropertyType(i) == UnityEngine.Rendering.ShaderPropertyType.Texture)
{
string propertyName = shader.GetPropertyName(i);
var texture = material.GetTexture(propertyName);
totalBytes += (long)ComputeTextureSize(texture);
}
}
return totalBytes;
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 67b996d0727a74b029aff1545143be17
timeCreated: 1479851694
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,52 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering
{
class MaterialUpgraderEditMenus
{
private static readonly List<MaterialUpgrader> s_Empty = new List<MaterialUpgrader>();
public static List<MaterialUpgrader> GetCurrentSRPUpgraders()
{
if (!GraphicsSettings.isScriptableRenderPipelineEnabled)
return s_Empty;
return MaterialUpgrader.FetchAllUpgradersForPipeline(GraphicsSettings.currentRenderPipelineAssetType);
}
[MenuItem("Edit/Rendering/Materials/Convert All Built-In Materials to Current SRP", true)]
internal static bool UpgradeMaterialsProjectValidate()
{
return GraphicsSettings.isScriptableRenderPipelineEnabled;
}
[MenuItem("Edit/Rendering/Materials/Convert All Built-In Materials to Current SRP", priority = CoreUtils.Priorities.editMenuPriority + 1)]
internal static void UpgradeMaterialsProject()
{
MaterialUpgrader.UpgradeProjectFolder(GetCurrentSRPUpgraders(), "Upgrade to SRP Material");
}
[MenuItem("Edit/Rendering/Materials/Convert Selected Built-In Materials to Current SRP", true)]
internal static bool UpgradeMaterialsSelectionValidate()
{
if (Selection.objects.Length == 0 || !GraphicsSettings.isScriptableRenderPipelineEnabled)
return false;
foreach (var obj in Selection.objects)
{
if (obj is not Material)
return false;
}
return true;
}
[MenuItem("Edit/Rendering/Materials/Convert Selected Built-In Materials to Current SRP", priority = CoreUtils.Priorities.editMenuPriority + 2)]
internal static void UpgradeMaterialsSelection()
{
MaterialUpgrader.UpgradeSelection(GetCurrentSRPUpgraders(), "Upgrade to SRP Material");
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 81cce92cea62afc46ae47b09fa3c8c6e
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering
{
/// <summary>
/// Class to handle the Material Upgraders and fetching of them
/// </summary>
internal class MaterialUpgraderRegistry
{
private static Lazy<MaterialUpgraderRegistry> m_Instance = new(() => new MaterialUpgraderRegistry());
/// <summary>
/// Singleton instance of the registry.
/// </summary>
public static MaterialUpgraderRegistry instance => m_Instance.Value;
Dictionary<Type, List<MaterialUpgrader>> m_UpgradersSupportedByPipeline = new();
/// <summary>
/// Returns a list of <see cref="MaterialUpgrader"/> with a given asset type
/// </summary>
/// <param name="renderPipelineAssetType">A valid RP asset type</param>
/// <returns>Returns a list of <see cref="MaterialUpgrader"/></returns>
public List<MaterialUpgrader> GetMaterialUpgradersForPipeline(Type renderPipelineAssetType)
{
List<MaterialUpgrader> materialUpgraders = GetOrCreateMaterialUpgradersForPipeline(renderPipelineAssetType);
materialUpgraders.AddRange(GetOrCreateMaterialUpgradersForPipeline(typeof(RenderPipelineAsset)));
materialUpgraders.Sort(CompareUpgradersByOldShaderAndPriority);
return materialUpgraders;
}
private int CompareUpgradersByOldShaderAndPriority(MaterialUpgrader a, MaterialUpgrader b)
{
string nameA = a?.OldShaderPath ?? string.Empty;
string nameB = b?.OldShaderPath ?? string.Empty;
int nameComparison = string.Compare(nameA, nameB, StringComparison.Ordinal);
if (nameComparison != 0)
return nameComparison;
// If names are the same, compare by priority
return b.priority.CompareTo(a.priority);
}
MaterialUpgraderRegistry()
{
var providerTypes = TypeCache.GetTypesDerivedFrom<IMaterialUpgradersProvider>();
foreach (var providerType in providerTypes)
{
if (providerType.IsAbstract)
continue;
var provider = Activator.CreateInstance(providerType) as IMaterialUpgradersProvider;
var upgraders = provider.GetUpgraders();
if (upgraders == null)
continue;
var pipelineTypes = GetSupportedPipelines(providerType);
if (pipelineTypes.Length == 0)
pipelineTypes = new Type[] { typeof(RenderPipelineAsset) }; // Default to all pipelines if none specified
foreach (var pipelineType in pipelineTypes)
{
var upgradersForPipeline = GetOrCreateMaterialUpgradersForPipeline(pipelineType);
foreach(var upgrader in upgraders)
{
upgradersForPipeline.Add(upgrader);
}
}
}
}
private static Type[] GetSupportedPipelines(Type upgraderType)
{
var attr = upgraderType.GetCustomAttribute<SupportedOnRenderPipelineAttribute>();
if (attr == null)
throw new InvalidOperationException($"Missing {nameof(SupportedOnRenderPipelineAttribute)} on {upgraderType}");
return attr.renderPipelineTypes;
}
private List<MaterialUpgrader> GetOrCreateMaterialUpgradersForPipeline(Type renderPipelineAssetType)
{
if (!typeof(RenderPipelineAsset).IsAssignableFrom(renderPipelineAssetType))
throw new ArgumentException($"Type '{renderPipelineAssetType.FullName}' must inherit from RenderPipelineAsset.", nameof(renderPipelineAssetType));
if (!m_UpgradersSupportedByPipeline.TryGetValue(renderPipelineAssetType, out var upgradersForPipeline))
{
upgradersForPipeline = new List<MaterialUpgrader>();
m_UpgradersSupportedByPipeline[renderPipelineAssetType] = upgradersForPipeline;
}
return upgradersForPipeline;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f118938a043d65c4cbecc1878576e305
@@ -0,0 +1,217 @@
using UnityEngine;
namespace UnityEditor.Rendering
{
/// <summary>
/// Material upgrader and relevant utilities for SpeedTree 8.
/// </summary>
public class SpeedTree8MaterialUpgrader : MaterialUpgrader
{
private enum WindQuality
{
None = 0,
Fastest,
Fast,
Better,
Best,
Palm,
Count
}
private static string[] WindQualityString =
{
"_WINDQUALITY_NONE",
"_WINDQUALITY_FASTEST",
"_WINDQUALITY_FAST",
"_WINDQUALITY_BETTER",
"_WINDQUALITY_BEST",
"_WINDQUALITY_PALM"
};
static private class Uniforms
{
internal static int _WINDQUALITY = Shader.PropertyToID("_WINDQUALITY");
internal static int EFFECT_BILLBOARD = Shader.PropertyToID("EFFECT_BILLBOARD");
internal static int EFFECT_EXTRA_TEX = Shader.PropertyToID("EFFECT_EXTRA_TEX");
internal static int _TwoSided = Shader.PropertyToID("_TwoSided");
internal static int _WindQuality = Shader.PropertyToID("_WindQuality");
}
/// <summary>
/// Returns true if the material contains a SpeedTree Wind keyword.
/// </summary>
/// <param name="material">Material to check</param>
/// <returns> true if the material has a SpeedTree wind keyword that enables Vertex Shader wind animation </returns>
public static bool DoesMaterialHaveSpeedTreeWindKeyword(Material material)
{
foreach(string keyword in WindQualityString)
if(material.IsKeywordEnabled(keyword))
return true;
return false;
}
/// <summary>
/// Checks the material for SpeedTree keywords to determine if the wind is enabled.
/// </summary>
/// <param name="material">Material to check</param>
/// <returns> true if the material has a SpeedTree wind keyword that enables Vertex Shader wind animation and WindQuality other than None (0) </returns>
public static bool IsWindEnabled(Material material)
{
return HasWindEnabledKeyword(material) && HasWindQualityPropertyEnabled(material);
}
private static bool HasWindEnabledKeyword(Material material)
{
for(int i=1/*skip NONE*/; i<WindQualityString.Length; ++i)
{
if(material.IsKeywordEnabled(WindQualityString[i]))
return true;
}
return false;
}
private static bool HasWindQualityPropertyEnabled(Material material)
{
return material.HasProperty("_WindQuality") && material.GetFloat(Uniforms._WindQuality) > 0.0f;
}
/// <summary>
/// Creates a material upgrader that handles the property renames that HD and Universal have in common when upgrading
/// from the built-in SpeedTree 8 shader.
/// </summary>
/// <param name="sourceShaderName">Original SpeedTree8 shader name.</param>
/// <param name="destShaderName">New SpeedTree 8 shader name.</param>
/// <param name="finalizer">A delegate that postprocesses the material for the render pipeline in use.</param>
public SpeedTree8MaterialUpgrader(string sourceShaderName, string destShaderName, MaterialFinalizer finalizer = null)
{
RenameShader(sourceShaderName, destShaderName, finalizer);
RenameFloat("_WindQuality", "_WINDQUALITY");
RenameFloat("_BillboardKwToggle", "EFFECT_BILLBOARD");
RenameKeywordToFloat("EFFECT_EXTRA_TEX", "EFFECT_EXTRA_TEX", 1, 0);
RenameKeywordToFloat("EFFECT_SUBSURFACE", "_SubsurfaceKwToggle", 1, 0);
RenameKeywordToFloat("EFFECT_BUMP", "_NormalMapKwToggle", 1, 0);
RenameKeywordToFloat("EFFECT_HUE_VARIATION", "_HueVariationKwToggle", 1, 0);
}
/// <summary>
/// Postprocesses materials while you are importing a SpeedTree 8 asset. Call from OnPostprocessSpeedTree in a MaterialPostprocessor.
/// </summary>
/// <param name="speedtree">The GameObject Unity creates from this imported SpeedTree.</param>
/// <param name="stImporter">The asset importer used to import this SpeedTree asset.</param>
/// <param name="finalizer">Render pipeline-specific material finalizer.</param>
public static void PostprocessSpeedTree8Materials(GameObject speedtree, SpeedTreeImporter stImporter, MaterialFinalizer finalizer = null)
{
LODGroup lg = speedtree.GetComponent<LODGroup>();
LOD[] lods = lg.GetLODs();
for (int l = 0; l < lods.Length; l++)
{
LOD lod = lods[l];
bool isBillboard = stImporter.hasBillboard && (l == lods.Length - 1);
int wq = Mathf.Min(stImporter.windQualities[l], stImporter.bestWindQuality);
foreach (Renderer r in lod.renderers)
{
foreach (Material m in r.sharedMaterials)
{
if (m == null)
continue;
float cutoff = stImporter.alphaTestRef;
int cullmode = isBillboard ? 2 : 0;
m.SetFloat(Uniforms._WINDQUALITY, wq);
if (isBillboard)
{
m.SetFloat(Uniforms.EFFECT_BILLBOARD, 1.0f);
}
m.SetFloat(Uniforms._TwoSided, cullmode); // Temporary; Finalizer should read from this and apply the value to a pipeline-specific cull property
if (m.IsKeywordEnabled("EFFECT_EXTRA_TEX"))
m.SetFloat(Uniforms.EFFECT_EXTRA_TEX, 1.0f);
if (finalizer != null)
finalizer(m);
}
}
}
}
/// <summary>
/// Preserves wind quality and billboard settings while you are upgrading a SpeedTree 8 material from previous versions of SpeedTree 8.
/// Wind priority order is _WindQuality float value > enabled keyword.
/// Should work for upgrading versions within a pipeline and from standard to current pipeline.
/// </summary>
/// <param name="material">SpeedTree 8 material to upgrade.</param>
public static void SpeedTree8MaterialFinalizer(Material material)
{
UpgradeWindQuality(material);
}
private static void UpgradeWindQuality(Material material, int windQuality = -1)
{
int wq = GetWindQuality(material, windQuality);
SetWindQuality(material, wq);
}
private static int GetWindQuality(Material material, int windQuality = -1)
{
// Conservative wind quality priority:
// input WindQuality > enabled keyword > _WindQuality float value
if (!WindIntValid(windQuality))
{
windQuality = material.HasProperty(Uniforms._WindQuality) ? (int)material.GetFloat(Uniforms._WindQuality) : 0;
if (!WindIntValid(windQuality))
{
windQuality = GetWindQualityFromKeywords(material.shaderKeywords);
if (!WindIntValid(windQuality))
windQuality = 0;
}
}
return windQuality;
}
private static void ClearWindKeywords(Material material)
{
if (material == null)
return;
for (int i = 0; i < (int)WindQuality.Count; i++)
{
material.DisableKeyword(WindQualityString[i]);
}
}
private static void SetWindQuality(Material material, int windQuality)
{
Debug.Assert(WindIntValid(windQuality), "Attempting to set invalid wind quality on material " + material.name);
if (material == null)
return;
if (windQuality != GetWindQualityFromKeywords(material.shaderKeywords))
{
ClearWindKeywords(material);
}
material.EnableKeyword(WindQualityString[windQuality]);
material.SetFloat(Uniforms._WindQuality, windQuality); // A legacy float used in native code to apply wind data
if (material.HasProperty("_WINDQUALITY"))
material.SetFloat(Uniforms._WINDQUALITY, windQuality); // The actual name of the keyword enum for the shadergraph
}
private static int GetWindQualityFromKeywords(string[] matKws)
{
foreach (string kw in matKws)
{
if (kw.StartsWith("_WINDQUALITY_"))
{
for (int i = 0; i < (int)WindQuality.Count; i++)
{
if (kw.EndsWith(WindQualityString[i]))
return i;
}
}
}
return -1;
}
private static bool WindIntValid(int windInt)
{
return ((int)WindQuality.None <= windInt) && (windInt < (int)WindQuality.Count);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d24fb80a63f172749b7076ac6f006fe9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,36 @@
using UnityEngine;
namespace UnityEditor.Rendering
{
/// <summary>
/// Material upgrader and relevant utilities for SpeedTree 9.
/// </summary>
public class SpeedTree9MaterialUpgrader : MaterialUpgrader
{
/// <summary>
/// Postprocesses materials while you are importing a SpeedTree 9 asset. Call from OnPostprocessSpeedTree in a MaterialPostprocessor.
/// </summary>
/// <param name="speedtree">The GameObject Unity creates from this imported SpeedTree.</param>
/// <param name="finalizer">Render pipeline-specific material finalizer.</param>
protected static void PostprocessSpeedTree9Materials(GameObject speedtree, MaterialFinalizer finalizer = null)
{
LODGroup lg = speedtree.GetComponent<LODGroup>();
LOD[] lods = lg.GetLODs();
for (int l = 0; l < lods.Length; l++)
{
LOD lod = lods[l];
foreach (Renderer r in lod.renderers)
{
foreach (Material m in r.sharedMaterials)
{
if (m == null)
continue;
if (finalizer != null)
finalizer(m);
}
}
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 55968f107cad0c249a1e365a3982f164