Files
JJBB/Assets/Project/Script/Shader/XRayRenderer.cs

157 lines
6.2 KiB
C#
Raw Normal View History

2024-08-23 15:49:34 +08:00
using System.Collections.Generic;
using Games.LogicObj;
using Module.Log;
using UnityEngine;
using UnityEngine.Rendering;
/// <summary>
/// 用于渲染透视效果的特殊渲染器
/// </summary>
public class XRayRenderer : MonoBehaviour
{
private static Material _xRayMaterial;
private const string _xRayMaterialName = "PlayerXRay";
private List<MyTuple<SkinnedMeshRenderer, SkinnedMeshRenderer>> _skinnedMeshRendererList;
private List<MeshRenderer> _meshRendererList;
// 注不要修改为Start需要保证在有子节点绑定前配置完成
public void Init(List<RendererInfo> rendererInfos)
{
for (var i = 0; i < rendererInfos.Count; i++)
{
var cachedRenderer = rendererInfos[i].CachedRenderer;
if (cachedRenderer == null ||
cachedRenderer.sharedMaterial == null ||
cachedRenderer.sharedMaterial.shader == null ||
!cachedRenderer.sharedMaterial.shader.IsCharacterShader())
continue;
var meshRenderer = rendererInfos[i].CachedRenderer as MeshRenderer;
if (meshRenderer == null)
{
var skinRenderer = rendererInfos[i].CachedRenderer as SkinnedMeshRenderer;
if (skinRenderer != null)
{
if (_skinnedMeshRendererList == null)
_skinnedMeshRendererList = new List<MyTuple<SkinnedMeshRenderer, SkinnedMeshRenderer>>();
_skinnedMeshRendererList.Add(
new MyTuple<SkinnedMeshRenderer, SkinnedMeshRenderer>(skinRenderer,
CreateFromSkinnedRenderer(skinRenderer)));
}
}
else
{
var meshFilter = meshRenderer.GetComponent<MeshFilter>();
if (meshFilter != null)
{
if (_meshRendererList == null)
_meshRendererList = new List<MeshRenderer>();
_meshRendererList.Add(CreateFromMeshRenderer(meshRenderer, meshFilter));
}
#if UNITY_EDITOR
else
LogModule.ErrorLog(string.Format("MeshRenderer没有对应的MeshFilter于物体{0}", meshRenderer.transform.GetHierarchyName()));
#endif
}
}
}
public void TrimXRaRenderer(Transform root)
{
if (root != null)
{
if (_skinnedMeshRendererList != null)
{
for (var i = _skinnedMeshRendererList.Count - 1; i >= 0; i--)
{
if (_skinnedMeshRendererList[i].first == null ||
_skinnedMeshRendererList[i].first.transform.IsChildOf(root))
_skinnedMeshRendererList.RemoveAt(i);
}
}
if (_meshRendererList != null)
{
for (var i = _meshRendererList.Count - 1; i >= 0; i--)
{
if (_meshRendererList[i] == null || _meshRendererList[i].transform.IsChildOf(root))
_meshRendererList.RemoveAt(i);
}
}
}
}
public void ResetBones()
{
if (_skinnedMeshRendererList != null)
for (var i = _skinnedMeshRendererList.Count - 1; i >= 0; i--)
{
SetBones(_skinnedMeshRendererList[i].first, _skinnedMeshRendererList[i].second);
_skinnedMeshRendererList[i].second.gameObject.SetActive(true);
}
if (_meshRendererList != null)
for (var i = 0; i < _meshRendererList.Count; i++)
_meshRendererList[i].gameObject.SetActive(true);
}
public void Hide()
{
if (_skinnedMeshRendererList != null)
for (var i = 0; i < _skinnedMeshRendererList.Count; i++)
_skinnedMeshRendererList[i].second.gameObject.SetActive(false);
if (_meshRendererList != null)
for (var i = 0; i < _meshRendererList.Count; i++)
_meshRendererList[i].gameObject.SetActive(false);
}
private static MeshRenderer CreateFromMeshRenderer(MeshRenderer sourceRenderer, MeshFilter sourceFilter)
{
// 注:可能有些物体会拥有初始动画
var xRayObject = BuildXRayObject(sourceRenderer);
var targetFilter = xRayObject.AddComponent<MeshFilter>();
var targetRenderer = xRayObject.AddComponent<MeshRenderer>();
targetFilter.sharedMesh = sourceFilter.sharedMesh;
SetRendererParameters(sourceRenderer, targetRenderer);
return targetRenderer;
}
private static SkinnedMeshRenderer CreateFromSkinnedRenderer(SkinnedMeshRenderer sourceRenderer)
{
var xRayObject = BuildXRayObject(sourceRenderer);
var targetRenderer = xRayObject.AddComponent<SkinnedMeshRenderer>();
SetBones(sourceRenderer, targetRenderer);
targetRenderer.sharedMesh = sourceRenderer.sharedMesh;
SetRendererParameters(sourceRenderer, targetRenderer);
return targetRenderer;
}
private static void SetBones(SkinnedMeshRenderer sourceRenderer, SkinnedMeshRenderer targetRenderer)
{
targetRenderer.rootBone = sourceRenderer.rootBone;
targetRenderer.bones = sourceRenderer.bones;
}
private static GameObject BuildXRayObject(Component root)
{
var xRayObject = new GameObject("XRayObject");
xRayObject.transform.SetParent(root.transform);
xRayObject.transform.localPosition = Vector3.zero;
xRayObject.transform.localRotation = Quaternion.identity;
xRayObject.transform.localScale = Vector3.one;
return xRayObject;
}
private static void SetRendererParameters(Renderer source, Renderer target)
{
if (_xRayMaterial == null)
_xRayMaterial = CommonUtility.LoadSharedMaterial(_xRayMaterialName);
target.shadowCastingMode = ShadowCastingMode.Off;
target.receiveShadows = false;
var materials = new Material[source.sharedMaterials.Length];
for (var i = 0; i < materials.Length; i++)
materials[i] = _xRayMaterial;
target.sharedMaterials = materials;
target.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
}
}