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.
99 lines
3.8 KiB
99 lines
3.8 KiB
#if UNITY_EDITOR
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering.HighDefinition;
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using System;
|
|
|
|
namespace UnityEditor.Rendering.HighDefinition
|
|
{
|
|
// This class keep track of every diffusion profile in the project so it can generate unique uint hashes
|
|
// for every asset, which are used to differentiate diffusion profiles in the shader
|
|
[InitializeOnLoad]
|
|
class DiffusionProfileHashTable
|
|
{
|
|
[System.NonSerialized]
|
|
static Dictionary<int, uint> diffusionProfileHashes = new Dictionary<int, uint>();
|
|
|
|
// Stable hash to avoid having different result after upgrading mono
|
|
// Source: https://github.com/Unity-Technologies/mono/blob/unity-2021.2-mbe-pre-upgrade/mcs/class/referencesource/mscorlib/system/string.cs#L824
|
|
unsafe static int MonoStringHash(string guid)
|
|
{
|
|
fixed(char *src = guid)
|
|
{
|
|
int hash1 = 5381;
|
|
int hash2 = hash1;
|
|
|
|
int c;
|
|
char *s = src;
|
|
while ((c = s[0]) != 0)
|
|
{
|
|
hash1 = ((hash1 << 5) + hash1) ^ c;
|
|
c = s[1];
|
|
if (c == 0)
|
|
break;
|
|
hash2 = ((hash2 << 5) + hash2) ^ c;
|
|
s += 2;
|
|
}
|
|
|
|
return hash1 + (hash2 * 1566083941);
|
|
}
|
|
}
|
|
|
|
static uint GetDiffusionProfileHash(DiffusionProfileSettings asset)
|
|
{
|
|
string assetPath = AssetDatabase.GetAssetPath(asset);
|
|
|
|
// In case the diffusion profile is not yet saved on the disk, we don't generate the hash
|
|
if (String.IsNullOrEmpty(assetPath))
|
|
return 0;
|
|
|
|
uint hash32 = (uint)MonoStringHash(AssetDatabase.AssetPathToGUID(assetPath));
|
|
uint mantissa = hash32 & 0x7FFFFF;
|
|
uint exponent = 0b10000000; // 0 as exponent
|
|
|
|
// only store the first 23 bits so when the hash is converted to float, it doesn't write into
|
|
// the exponent part of the float (which avoids having NaNs, inf or precisions issues)
|
|
return (exponent << 23) | mantissa;
|
|
}
|
|
|
|
static internal uint GenerateUniqueHash(DiffusionProfileSettings asset)
|
|
{
|
|
uint hash = GetDiffusionProfileHash(asset);
|
|
|
|
while (diffusionProfileHashes.ContainsValue(hash))
|
|
{
|
|
Debug.LogWarning("Collision found in asset: " + asset + ", generating a new hash, previous hash: " + hash);
|
|
hash++;
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
public static void UpdateDiffusionProfileHashNow(DiffusionProfileSettings profile)
|
|
{
|
|
uint hash = profile.profile.hash;
|
|
|
|
// If the hash is 0, then we need to generate a new one (it means that the profile was just created)
|
|
if (hash == 0)
|
|
{
|
|
profile.profile.hash = GenerateUniqueHash(profile);
|
|
EditorUtility.SetDirty(profile);
|
|
// We can't move the asset
|
|
}
|
|
// If the asset is not in the list, we regenerate it's hash using the GUID (which leads to the same result every time)
|
|
else if (!diffusionProfileHashes.ContainsKey(profile.GetInstanceID()))
|
|
{
|
|
uint newHash = GenerateUniqueHash(profile);
|
|
if (newHash != profile.profile.hash)
|
|
{
|
|
profile.profile.hash = newHash;
|
|
EditorUtility.SetDirty(profile);
|
|
}
|
|
}
|
|
else // otherwise, no issue, we don't change the hash and we keep it to check for collisions
|
|
diffusionProfileHashes.Add(profile.GetInstanceID(), profile.profile.hash);
|
|
}
|
|
}
|
|
}
|
|
#endif
|