using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; public class OvrAvatarMaterialManager : MonoBehaviour { public enum TextureType { DiffuseTextures = 0, NormalMaps = 1, RoughnessMaps = 2, Count = 3 } [Serializable] public struct AvatarComponentMaterialProperties { public ovrAvatarBodyPartType TypeIndex; public Color Color; public Texture2D[] Textures; [Range(0f, 1f)] public float DiffuseIntensity; [Range(0f, 10f)] public float RimIntensity; [Range(0f, 1f)] public float ReflectionIntensity; } [Serializable] public struct AvatarTextureArrayProperties { public Texture2D[] Textures; public Texture2DArray TextureArray; } [Serializable] public struct AvatarMaterialPropertyBlock { public Vector4[] Colors; public float[] DiffuseIntensities; public float[] RimIntensities; public float[] ReflectionIntensities; } [Serializable] public class AvatarMaterialConfig { public AvatarComponentMaterialProperties[] ComponentMaterialProperties; public AvatarMaterialPropertyBlock MaterialPropertyBlock; } public Texture2D[] DiffuseFallbacks; public Texture2D[] NormalFallbacks; private Renderer TargetRenderer; private AvatarTextureArrayProperties[] TextureArrays; private OvrAvatarTextureCopyManager TextureCopyManager; private readonly string[] TextureTypeToShaderProperties = new string[3] { "_MainTex", "_NormalMap", "_RoughnessMap" }; public List ReflectionProbes = new List(); public AvatarMaterialConfig LocalAvatarConfig; public AvatarMaterialConfig DefaultAvatarConfig; private AvatarMaterialPropertyBlock LocalAvatarMaterialPropertyBlock; private Shader CombinedShader; public static string AVATAR_SHADER_LOADER = "OvrAvatar/Avatar_Mobile_Loader"; public static string AVATAR_SHADER_MAINTEX = "_MainTex"; public static string AVATAR_SHADER_NORMALMAP = "_NormalMap"; public static string AVATAR_SHADER_ROUGHNESSMAP = "_RoughnessMap"; public static string AVATAR_SHADER_COLOR = "_BaseColor"; public static string AVATAR_SHADER_DIFFUSEINTENSITY = "_DiffuseIntensity"; public static string AVATAR_SHADER_RIMINTENSITY = "_RimIntensity"; public static string AVATAR_SHADER_REFLECTIONINTENSITY = "_ReflectionIntensity"; public static string AVATAR_SHADER_CUBEMAP = "_Cubemap"; public static string AVATAR_SHADER_ALPHA = "_Alpha"; public static string AVATAR_SHADER_LOADING_DIMMER = "_LoadingDimmer"; public static string AVATAR_SHADER_IRIS_COLOR = "_MaskColorIris"; public static string AVATAR_SHADER_LIP_COLOR = "_MaskColorLips"; public static string AVATAR_SHADER_BROW_COLOR = "_MaskColorBrows"; public static string AVATAR_SHADER_LASH_COLOR = "_MaskColorLashes"; public static string AVATAR_SHADER_SCLERA_COLOR = "_MaskColorSclera"; public static string AVATAR_SHADER_GUM_COLOR = "_MaskColorGums"; public static string AVATAR_SHADER_TEETH_COLOR = "_MaskColorTeeth"; public static string AVATAR_SHADER_LIP_SMOOTHNESS = "_LipSmoothness"; private const float LOADING_ANIMATION_AMPLITUDE = 0.5f; private const float LOADING_ANIMATION_PERIOD = 0.35f; private const float LOADING_ANIMATION_CURVE_SCALE = 0.25f; private const float LOADING_ANIMATION_DIMMER_MIN = 0.3f; private void Awake() { TextureCopyManager = base.gameObject.AddComponent(); } public void CreateTextureArrays() { for (int i = 0; i < 5; i++) { LocalAvatarConfig.ComponentMaterialProperties[i].Textures = new Texture2D[3]; DefaultAvatarConfig.ComponentMaterialProperties[i].Textures = new Texture2D[3]; } TextureArrays = new AvatarTextureArrayProperties[3]; } public void SetRenderer(Renderer renderer) { TargetRenderer = renderer; TargetRenderer.GetClosestReflectionProbes(ReflectionProbes); } public void OnCombinedMeshReady() { InitTextureArrays(); SetMaterialPropertyBlock(); StartCoroutine(RunLoadingAnimation()); } public void InitTextureArrays() { AvatarComponentMaterialProperties avatarComponentMaterialProperties = LocalAvatarConfig.ComponentMaterialProperties[0]; for (int i = 0; i < TextureArrays.Length && i < avatarComponentMaterialProperties.Textures.Length; i++) { TextureArrays[i].TextureArray = new Texture2DArray(avatarComponentMaterialProperties.Textures[0].height, avatarComponentMaterialProperties.Textures[0].width, LocalAvatarConfig.ComponentMaterialProperties.Length, avatarComponentMaterialProperties.Textures[0].format, true, (QualitySettings.activeColorSpace != ColorSpace.Gamma) ? true : false) { filterMode = FilterMode.Trilinear }; TextureArrays[i].Textures = new Texture2D[LocalAvatarConfig.ComponentMaterialProperties.Length]; for (int j = 0; j < LocalAvatarConfig.ComponentMaterialProperties.Length; j++) { TextureArrays[i].Textures[j] = LocalAvatarConfig.ComponentMaterialProperties[j].Textures[i]; } ProcessTexturesWithMips(TextureArrays[i].Textures, avatarComponentMaterialProperties.Textures[i].height, TextureArrays[i].TextureArray); } } private void ProcessTexturesWithMips(Texture2D[] textures, int texArrayResolution, Texture2DArray texArray) { for (int i = 0; i < textures.Length; i++) { int num = texArrayResolution; int num2 = textures[i].mipmapCount - 1; for (int num3 = num2; num3 >= 0; num3--) { int mipSize = texArrayResolution / num; TextureCopyManager.CopyTexture(textures[i], texArray, num3, mipSize, i); num /= 2; } } } private void SetMaterialPropertyBlock() { if (TargetRenderer != null) { for (int i = 0; i < LocalAvatarConfig.ComponentMaterialProperties.Length; i++) { LocalAvatarConfig.MaterialPropertyBlock.Colors[i] = LocalAvatarConfig.ComponentMaterialProperties[i].Color; LocalAvatarConfig.MaterialPropertyBlock.DiffuseIntensities[i] = LocalAvatarConfig.ComponentMaterialProperties[i].DiffuseIntensity; LocalAvatarConfig.MaterialPropertyBlock.RimIntensities[i] = LocalAvatarConfig.ComponentMaterialProperties[i].RimIntensity; LocalAvatarConfig.MaterialPropertyBlock.ReflectionIntensities[i] = LocalAvatarConfig.ComponentMaterialProperties[i].ReflectionIntensity; } } } private void ApplyMaterialPropertyBlock() { MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock(); materialPropertyBlock.SetVectorArray(AVATAR_SHADER_COLOR, LocalAvatarConfig.MaterialPropertyBlock.Colors); materialPropertyBlock.SetFloatArray(AVATAR_SHADER_DIFFUSEINTENSITY, LocalAvatarConfig.MaterialPropertyBlock.DiffuseIntensities); materialPropertyBlock.SetFloatArray(AVATAR_SHADER_RIMINTENSITY, LocalAvatarConfig.MaterialPropertyBlock.RimIntensities); materialPropertyBlock.SetFloatArray(AVATAR_SHADER_REFLECTIONINTENSITY, LocalAvatarConfig.MaterialPropertyBlock.ReflectionIntensities); TargetRenderer.GetClosestReflectionProbes(ReflectionProbes); if (ReflectionProbes != null && ReflectionProbes.Count > 0 && ReflectionProbes[0].probe.texture != null) { materialPropertyBlock.SetTexture(AVATAR_SHADER_CUBEMAP, ReflectionProbes[0].probe.texture); } for (int i = 0; i < TextureArrays.Length; i++) { materialPropertyBlock.SetTexture(TextureTypeToShaderProperties[i], TextureArrays[i].TextureArray); } TargetRenderer.SetPropertyBlock(materialPropertyBlock); } public static ovrAvatarBodyPartType GetComponentType(string objectName) { if (objectName.Contains("0")) { return ovrAvatarBodyPartType.Body; } if (objectName.Contains("1")) { return ovrAvatarBodyPartType.Clothing; } if (objectName.Contains("2")) { return ovrAvatarBodyPartType.Eyewear; } if (objectName.Contains("3")) { return ovrAvatarBodyPartType.Hair; } if (objectName.Contains("4")) { return ovrAvatarBodyPartType.Beard; } return ovrAvatarBodyPartType.Count; } public void ValidateTextures() { AvatarComponentMaterialProperties[] componentMaterialProperties = LocalAvatarConfig.ComponentMaterialProperties; int[] array = new int[3]; TextureFormat[] array2 = new TextureFormat[3]; for (int i = 0; i < componentMaterialProperties.Length; i++) { for (int j = 0; j < componentMaterialProperties[i].Textures.Length; j++) { if (componentMaterialProperties[i].Textures[j] == null) { string text = componentMaterialProperties[i].TypeIndex.ToString(); TextureType textureType = (TextureType)j; throw new Exception(text + "Invalid: " + textureType); } array[j] = componentMaterialProperties[i].Textures[j].height; array2[j] = componentMaterialProperties[i].Textures[j].format; } } for (int k = 0; k < 3; k++) { for (int l = 1; l < componentMaterialProperties.Length; l++) { if (componentMaterialProperties[l - 1].Textures[k].height != componentMaterialProperties[l].Textures[k].height) { object[] obj = new object[8] { componentMaterialProperties[l].TypeIndex.ToString(), " Mismatching Resolutions: ", null, null, null, null, null, null }; TextureType textureType2 = (TextureType)k; obj[2] = textureType2.ToString(); obj[3] = " "; obj[4] = componentMaterialProperties[l - 1].Textures[k].height; obj[5] = " vs "; obj[6] = componentMaterialProperties[l].Textures[k].height; obj[7] = " Ensure you are using ASTC texture compression on Android or turn off CombineMeshes"; throw new Exception(string.Concat(obj)); } if (componentMaterialProperties[l - 1].Textures[k].format != componentMaterialProperties[l].Textures[k].format) { string text2 = componentMaterialProperties[l].TypeIndex.ToString(); TextureType textureType3 = (TextureType)k; throw new Exception(text2 + " Mismatching Formats: " + textureType3.ToString() + " Ensure you are using ASTC texture compression on Android or turn off CombineMeshes"); } } } } private IEnumerator RunLoadingAnimation() { CombinedShader = TargetRenderer.sharedMaterial.shader; int srcBlend = TargetRenderer.sharedMaterial.GetInt("_SrcBlend"); int dstBlend = TargetRenderer.sharedMaterial.GetInt("_DstBlend"); bool transparentQueue = TargetRenderer.sharedMaterial.IsKeywordEnabled("_ALPHATEST_ON"); int renderQueue = TargetRenderer.sharedMaterial.renderQueue; string renderTag = TargetRenderer.sharedMaterial.GetTag("RenderType", false); TargetRenderer.sharedMaterial.shader = Shader.Find(AVATAR_SHADER_LOADER); TargetRenderer.sharedMaterial.SetColor(AVATAR_SHADER_COLOR, Color.white); while (TextureCopyManager.GetTextureCount() > 0) { float distance = (0.5f * Mathf.Sin(Time.timeSinceLevelLoad / 0.35f) + 0.5f) * 0.25f + 0.3f; TargetRenderer.sharedMaterial.SetFloat(AVATAR_SHADER_LOADING_DIMMER, distance); yield return null; } TargetRenderer.sharedMaterial.SetFloat(AVATAR_SHADER_LOADING_DIMMER, 1f); TargetRenderer.sharedMaterial.shader = CombinedShader; TargetRenderer.sharedMaterial.SetOverrideTag("RenderType", renderTag); TargetRenderer.sharedMaterial.SetInt("_SrcBlend", srcBlend); TargetRenderer.sharedMaterial.SetInt("_DstBlend", dstBlend); if (transparentQueue) { TargetRenderer.sharedMaterial.EnableKeyword("_ALPHATEST_ON"); TargetRenderer.sharedMaterial.EnableKeyword("_ALPHABLEND_ON"); TargetRenderer.sharedMaterial.EnableKeyword("_ALPHAPREMULTIPLY_ON"); } else { TargetRenderer.sharedMaterial.DisableKeyword("_ALPHATEST_ON"); TargetRenderer.sharedMaterial.DisableKeyword("_ALPHABLEND_ON"); TargetRenderer.sharedMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON"); } TargetRenderer.sharedMaterial.renderQueue = renderQueue; ApplyMaterialPropertyBlock(); } }