您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

334 行
11 KiB

//#define _SNAPPERS_TEXTURE_ARRAYS
using System;
using UnityEngine;
using UnityEngine.Serialization;
using Unity.DemoTeam.Attributes;
namespace Unity.DemoTeam.DigitalHuman
{
[ExecuteAlways, RequireComponent(typeof(SkinnedMeshRenderer))]
public class SnappersHeadRenderer : MonoBehaviour
{
private SkinnedMeshRenderer smr;
private MaterialPropertyBlock smrProps;
[Header("Facial rig")]
public SnappersHeadDefinition headDefinition;
public SnappersHeadDefinition.InstanceData headInstance;
[FormerlySerializedAs("headController")] public Transform headControllers;
[EnumFlag] public SnappersHeadDefinition.Warnings warnings;
[Header("Material setup")]
public TextureSet[] materials = new TextureSet[0];
[Serializable]
public struct TextureSet
{
[Header("Identifier")]
public int materialIndex;
public MaterialPropertyBlock materialProps;
[Header("Activation masks")]
public Texture2D mask1;
public Texture2D mask2;
public Texture2D mask3;
public Texture2D mask4;
public Texture2D mask5;
public Texture2D mask6;
public Texture2D mask7;
public Texture2D mask8;
public Texture2D mask9;
public Texture2D mask10;
public Texture2D mask11;
public Texture2D mask12;
#if _SNAPPERS_TEXTURE_ARRAYS
public Texture2DArray maskArray;
#endif
[Header("Activation maps")]
public Texture2D albedo1;
public Texture2D albedo2;
public Texture2D albedo3;
public Texture2D albedo4;
#if _SNAPPERS_TEXTURE_ARRAYS
public Texture2DArray albedoArray;
#endif
[Space]
public Texture2D normal1;
public Texture2D normal2;
public Texture2D normal3;
public Texture2D normal4;
#if _SNAPPERS_TEXTURE_ARRAYS
public Texture2DArray normalArray;
#endif
[Space]
public Texture2D cavity1;
public Texture2D cavity2;
public Texture2D cavity3;
public Texture2D cavity4;
#if _SNAPPERS_TEXTURE_ARRAYS
public Texture2DArray cavityArray;
#endif
public void ApplyTextureSet()
{
#if _SNAPPERS_TEXTURE_ARRAYS
SetTextureChecked(materialProps, "_SnappersMask", maskArray);
SetTextureChecked(materialProps, "_SnappersAlbedo", albedoArray);
SetTextureChecked(materialProps, "_SnappersNormal", normalArray);
SetTextureChecked(materialProps, "_SnappersCavity", cavityArray);
#else
SetTextureChecked(materialProps, "_SnappersMask1", mask1);
SetTextureChecked(materialProps, "_SnappersMask2", mask2);
SetTextureChecked(materialProps, "_SnappersMask3", mask3);
SetTextureChecked(materialProps, "_SnappersMask4", mask4);
SetTextureChecked(materialProps, "_SnappersMask5", mask5);
SetTextureChecked(materialProps, "_SnappersMask6", mask6);
SetTextureChecked(materialProps, "_SnappersMask7", mask7);
SetTextureChecked(materialProps, "_SnappersMask8", mask8);
SetTextureChecked(materialProps, "_SnappersMask9", mask9);
SetTextureChecked(materialProps, "_SnappersMask10", mask10);
SetTextureChecked(materialProps, "_SnappersMask11", mask11);
SetTextureChecked(materialProps, "_SnappersMask12", mask12);
SetTextureChecked(materialProps, "_SnappersAlbedo1", albedo1);
SetTextureChecked(materialProps, "_SnappersAlbedo2", albedo2);
SetTextureChecked(materialProps, "_SnappersAlbedo3", albedo3);
SetTextureChecked(materialProps, "_SnappersAlbedo4", albedo4);
SetTextureChecked(materialProps, "_SnappersNormal1", normal1);
SetTextureChecked(materialProps, "_SnappersNormal2", normal2);
SetTextureChecked(materialProps, "_SnappersNormal3", normal3);
SetTextureChecked(materialProps, "_SnappersNormal4", normal4);
SetTextureChecked(materialProps, "_SnappersCavity1", cavity1);
SetTextureChecked(materialProps, "_SnappersCavity2", cavity2);
SetTextureChecked(materialProps, "_SnappersCavity3", cavity3);
SetTextureChecked(materialProps, "_SnappersCavity4", cavity4);
#endif
}
}
[Header("-> SkinDeformationRenderer (if avail.)")]
public bool injectFittedWeights;
[Range(1.0f, 10.0f)]
public float injectFittedWeightsScale = 1.0f;
#region Deprecated material setup
[HideInInspector, SerializeField] private Texture2D mask1;
[HideInInspector, SerializeField] private Texture2D mask2;
[HideInInspector, SerializeField] private Texture2D mask3;
[HideInInspector, SerializeField] private Texture2D mask4;
[HideInInspector, SerializeField] private Texture2D mask5;
[HideInInspector, SerializeField] private Texture2D mask6;
[HideInInspector, SerializeField] private Texture2D mask7;
[HideInInspector, SerializeField] private Texture2D mask8;
[HideInInspector, SerializeField] private Texture2D mask9;
[HideInInspector, SerializeField] private Texture2D mask10;
[HideInInspector, SerializeField] private Texture2D mask11;
[HideInInspector, SerializeField] private Texture2D mask12;
[HideInInspector, SerializeField] private Texture2D albedo1;
[HideInInspector, SerializeField] private Texture2D albedo2;
[HideInInspector, SerializeField] private Texture2D albedo3;
[HideInInspector, SerializeField] private Texture2D albedo4;
[HideInInspector, SerializeField] private Texture2D normal1;
[HideInInspector, SerializeField] private Texture2D normal2;
[HideInInspector, SerializeField] private Texture2D normal3;
[HideInInspector, SerializeField] private Texture2D normal4;
[HideInInspector, SerializeField] private Texture2D cavity1;
[HideInInspector, SerializeField] private Texture2D cavity2;
[HideInInspector, SerializeField] private Texture2D cavity3;
[HideInInspector, SerializeField] private Texture2D cavity4;
bool TransferMaterial(ref Texture2D src, ref Texture2D dst)
{
dst = src;
src = null;
return (dst != null);
}
#endregion
void OnEnable()
{
#region Deprecated material transfer
if (materials.Length == 0)
{
var setPopulated = false;
var set = new TextureSet();
set.materialIndex = 0;
setPopulated |= TransferMaterial(ref mask1, ref set.mask1);
setPopulated |= TransferMaterial(ref mask2, ref set.mask2);
setPopulated |= TransferMaterial(ref mask3, ref set.mask3);
setPopulated |= TransferMaterial(ref mask4, ref set.mask4);
setPopulated |= TransferMaterial(ref mask5, ref set.mask5);
setPopulated |= TransferMaterial(ref mask6, ref set.mask6);
setPopulated |= TransferMaterial(ref mask7, ref set.mask7);
setPopulated |= TransferMaterial(ref mask8, ref set.mask8);
setPopulated |= TransferMaterial(ref mask9, ref set.mask9);
setPopulated |= TransferMaterial(ref mask10, ref set.mask10);
setPopulated |= TransferMaterial(ref mask11, ref set.mask11);
setPopulated |= TransferMaterial(ref mask12, ref set.mask12);
setPopulated |= TransferMaterial(ref albedo1, ref set.albedo1);
setPopulated |= TransferMaterial(ref albedo2, ref set.albedo2);
setPopulated |= TransferMaterial(ref albedo3, ref set.albedo3);
setPopulated |= TransferMaterial(ref albedo4, ref set.albedo4);
setPopulated |= TransferMaterial(ref normal1, ref set.normal1);
setPopulated |= TransferMaterial(ref normal2, ref set.normal2);
setPopulated |= TransferMaterial(ref normal3, ref set.normal3);
setPopulated |= TransferMaterial(ref normal4, ref set.normal4);
setPopulated |= TransferMaterial(ref cavity1, ref set.cavity1);
setPopulated |= TransferMaterial(ref cavity2, ref set.cavity2);
setPopulated |= TransferMaterial(ref cavity3, ref set.cavity3);
setPopulated |= TransferMaterial(ref cavity4, ref set.cavity4);
if (setPopulated)
{
materials = new TextureSet[1];
materials[0] = set;
}
}
#endregion
smr = GetComponent<SkinnedMeshRenderer>();
for (int i = 0; i != materials.Length; i++)
{
if (materials[i].materialProps == null)
materials[i].materialProps = new MaterialPropertyBlock();
}
}
void OnDisable()
{
FetchPropertyBlocks();
{
if (headInstance.shaderParamFloats != null)//TODO introduce IsCreated() or similar?
{
SnappersHeadDefinition.ResetShaderParam(ref headInstance);
for (int i = 0; i != materials.Length; i++)
{
SnappersHeadDefinition.ApplyShaderParam(ref headInstance, materials[i].materialProps);
}
}
}
ApplyPropertyBlocks();
}
void FetchPropertyBlocks()
{
for (int i = 0; i != materials.Length; i++)
{
if (materials[i].materialProps == null)
materials[i].materialProps = new MaterialPropertyBlock();
smr.GetPropertyBlock(materials[i].materialProps, materials[i].materialIndex);
}
}
void ApplyPropertyBlocks()
{
for (int i = 0; i != materials.Length; i++)
{
smr.SetPropertyBlock(materials[i].materialProps, materials[i].materialIndex);
}
}
void LateUpdate()
{
FetchPropertyBlocks();
{
if (headDefinition != null)
{
headDefinition.PrepareInstance(ref headInstance, smr, headControllers, warnings);
headDefinition.ResolveControllers(ref headInstance);
headDefinition.ResolveBlendShapes(ref headInstance, smr);
if (injectFittedWeights)
{
var skinDeform = GetComponent<SkinDeformationRenderer>();
if (skinDeform != null && skinDeform.fittedWeightsAvailable)
{
var fittedWeights = skinDeform.fittedWeights;
var inputIndices = headInstance.blendShapeIndices;
var inputWeights = headInstance.blendShapeWeights;
for (int i = 0; i != headInstance.blendShapeIndices.Length; i++)
{
inputWeights[i] = Mathf.Clamp01(Mathf.Max(injectFittedWeightsScale * fittedWeights[inputIndices[i]], inputWeights[i]));
}
}
headDefinition.ResolveShaderParam(ref headInstance);
headDefinition.ResolveBlendShapes(ref headInstance, smr);// done again to avoid factoring in fitted weights
}
else
{
headDefinition.ResolveShaderParam(ref headInstance);
}
SnappersHeadDefinition.ApplyControllers(ref headInstance);
SnappersHeadDefinition.ApplyBlendShapes(ref headInstance, smr);
}
else
{
SnappersHeadDefinition.ResetShaderParam(ref headInstance);
}
for (int i = 0; i != materials.Length; i++)
{
SnappersHeadDefinition.ApplyShaderParam(ref headInstance, materials[i].materialProps);
materials[i].ApplyTextureSet();
}
}
ApplyPropertyBlocks();
}
static void SetTextureChecked(MaterialPropertyBlock props, string textureId, Texture texture)
{
if (texture != null)
props.SetTexture(textureId, texture);
else
props.SetTexture(textureId, Texture2D.blackTexture);
}
#if _SNAPPERS_TEXTURE_ARRAYS
static void UpdateTextureArray(ref Texture2DArray array, Texture2D[] slices, bool linear)
{
if (array != null && array.depth != slices.Length)
{
Texture2DArray.Destroy(array);
array = null;
}
if (array == null)
{
array = new Texture2DArray(slices[0].width, slices[0].height, slices.Length, slices[0].format, true, linear);
array.hideFlags |= HideFlags.HideAndDontSave;
}
if (slices.Length > 0 && slices[0] != null)
{
array.wrapMode = slices[0].wrapMode;
array.anisoLevel = slices[0].anisoLevel;
array.filterMode = slices[0].filterMode;
}
for (int i = 0; i != slices.Length; i++)
{
if (slices[i] != null)
{
int mipCount = slices[i].mipmapCount;
for (int mip = 0; mip != mipCount; mip++)
{
Graphics.CopyTexture(slices[i], 0, mip, array, i, mip);
}
}
}
}
#endif
}
}