178 lines
4.7 KiB
C#
Raw Permalink Normal View History

2025-09-08 17:37:12 +08:00
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]
2025-09-09 17:30:50 +08:00
private Renderer Target;
2025-09-08 17:37:12 +08:00
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;
2025-09-09 17:30:50 +08:00
public float Density = 1;
2025-09-08 17:37:12 +08:00
[Header("是否使用GPU实例化")]
public bool isInStance = false;
2025-09-09 17:30:50 +08:00
public bool ZWrite = true;
public int RenderSort = 0;
2025-09-08 17:37:12 +08:00
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();
}
//更新毛发渲染
void LateUpdate()
{
//目标为空就不渲染
2025-09-09 17:30:50 +08:00
if (TargetChange() == false)
{
Debug.Log("返回");
return;
}
isInStance = false;
if (isInStance) UpDateInstance();
2025-09-08 17:37:12 +08:00
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<MeshFilter>().sharedMesh;
skinHasValue = false;
}
else
{
skinnedMeshRenderer = target.gameObject.GetComponent<SkinnedMeshRenderer>();
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);
2025-09-09 17:30:50 +08:00
layerMat.SetInt("_ZWrite",ZWrite? 1:0);
layerMat.SetFloat("_Density",Density);
layerMat.renderQueue = 3000+RenderSort;
2025-09-08 17:37:12 +08:00
mpb = new MaterialPropertyBlock();
}
void MeshInstancedData()
{
instanceMatrices = new Matrix4x4[LayerCount];
layerMat.enableInstancing = true;
// 随机生成实例的位置和旋转
for (int i = 0; i < LayerCount; i++)
{
2025-09-09 17:30:50 +08:00
//Vector3 position = target.transform.position;
//Quaternion rotation = target.transform.rotation;
//Vector3 scale = Vector3.one;
2025-09-08 17:37:12 +08:00
2025-09-09 17:30:50 +08:00
instanceMatrices[i] = target.transform.localToWorldMatrix;// //Matrix4x4.TRS(position, rotation, scale);
2025-09-08 17:37:12 +08:00
}
}
//使用GPU实例化
void UpDateInstance()
{
if (skinHasValue)
{
skinnedMeshRenderer.BakeMesh(mesh);
}
2025-09-09 17:30:50 +08:00
for (int i = 0; i < LayerCount; i++)
{
instanceMatrices[i] = target.transform.localToWorldMatrix;
}
2025-09-08 17:37:12 +08:00
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);
}
}
}