using System; using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.Rendering; //[ExecuteAlways] public class RongMaoSkinMesh : MonoBehaviour { public int Count = 0; //public Shader shader; [Header("渲染目标")] [SerializeField] private Renderer Target; public Shader BaseShader; [Header("皮毛物理")] public int LayerCount = 10; public float FurLength = 0.5f; public Vector3 FurFore; public Texture2D Noise; public Texture2D Noise2; public Texture2D MainTex;//毛发颜色 public Texture2D Mask;//不产生毛发区域的灰度遮罩 [Header("皮毛渲染")] //毛发染色 public Color FurColor = Color.white; public Color ShadowColor = Color.white; [Range(0, 1)] public float ShadowStrength = 0.3f; [Range(0.01f, 1)] public float R = 0.5f; [Range(0, 3)] public float _LengthMut = 1; public float Density = 1; [Header("是否使用GPU实例化")] public bool isInStance = false; public bool ZWrite = true; public int RenderSort = 0; private bool skinHasValue = false; private Renderer target; //创建毛发 private Mesh mesh; private Material layerMat; private SkinnedMeshRenderer skinnedMeshRenderer; private MaterialPropertyBlock mpb; private ComputeBuffer instanceBuffer; private Matrix4x4[] instanceMatrices; private bool isInit; void OnEnable() { isInit = Init(); } //更新毛发渲染 private void Update() { if (skinHasValue) { skinnedMeshRenderer.BakeMesh(mesh); } } void LateUpdate() { //目标为空就不渲染 if (TargetChange() == false) { Debug.Log("返回"); return; } isInStance = false; if (isInStance) UpDateInstance(); else UpDateMesh(); } bool TargetChange() { if (Target != target) { target = Target; isInit = Init(); } return isInit; } //初始化毛发,返回是否初始化成功 bool Init() { if (target.IsUnityNull()) return false; CreateFur(); MeshInstancedData(); if (target.GetType() == typeof(MeshRenderer)) { mesh = target.GetComponent().sharedMesh; skinHasValue = false; } else { skinnedMeshRenderer = target.gameObject.GetComponent(); skinHasValue = true; } return true; } //初始化网格、材质、SkinnedMeshRenderer void CreateFur() { mesh = new Mesh(); layerMat = new Material(BaseShader); layerMat.SetTexture("_MainTex", MainTex); layerMat.SetColor("_Color", FurColor); layerMat.SetFloat("_FurLength", FurLength); layerMat.SetTexture("_Noise", Noise); layerMat.SetTexture("_Noise2", Noise2); layerMat.SetTexture("_Mask", Mask); layerMat.SetColor("_ShadowColor", ShadowColor); layerMat.SetFloat("_R", R); layerMat.SetFloat("_LayerCount", LayerCount); layerMat.SetInt("_ZWrite", ZWrite ? 1 : 0); layerMat.SetFloat("_Density", Density); layerMat.renderQueue = 3000 + RenderSort; mpb = new MaterialPropertyBlock(); } void MeshInstancedData() { instanceMatrices = new Matrix4x4[LayerCount]; layerMat.enableInstancing = true; // 随机生成实例的位置和旋转 for (int i = 0; i < LayerCount; i++) { //Vector3 position = target.transform.position; //Quaternion rotation = target.transform.rotation; //Vector3 scale = Vector3.one; instanceMatrices[i] = target.transform.localToWorldMatrix;// //Matrix4x4.TRS(position, rotation, scale); } } //使用GPU实例化 void UpDateInstance() { for (int i = 0; i < LayerCount; i++) { instanceMatrices[i] = target.transform.localToWorldMatrix; } layerMat.EnableKeyword("INSTANCE"); Graphics.DrawMeshInstanced(mesh, 0, layerMat, instanceMatrices, LayerCount); } //未使用GPU实例化 void UpDateMesh() { //if (skinHasValue) //{ // skinnedMeshRenderer.BakeMesh(mesh); //} layerMat.DisableKeyword("INSTANCE"); float furOffset = 1.0f / LayerCount; for (int i = 0; i < LayerCount; i++) { mpb.SetFloat("_LayerOffset", i * furOffset); Graphics.DrawMesh(mesh, target.transform.localToWorldMatrix, layerMat, 0, Camera.main, 0, mpb); } } }