Files
JJBB/Assets/Project/Script/Shader/XRayRenderer.cs
2024-08-23 15:49:34 +08:00

157 lines
6.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}