Files
Main/Assets/Launcher/ExternalLibs/CmdBuffer/OffScreenVfx/OffScreenVfxScript.cs
2025-01-25 04:38:09 +08:00

264 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Rendering;
namespace Thousandto.Launcher.ExternalLibs
{
/// <summary>
/// 离屏特效
/// </summary>
public class OffScreenVfxScript :MonoBehaviour
{
private const CameraEvent CN_TRIGGER_EVENT = CameraEvent.AfterForwardAlpha;
private List<Renderer> _renders = new List<Renderer>();
private CommandBuffer _cmd;
private Camera _camera;
private Material _mat;
private int _offScreenTexID;
public BlendOp _bop = BlendOp.Blend;
private void Start()
{
InitPropertyID();
InitMat();
InitCamera();
InitCmd();
}
private void OnEnable()
{
if (_cmd != null && _camera != null)
{
_camera.AddCommandBuffer(CN_TRIGGER_EVENT, _cmd);
}
if (_cmd != null)
{
RefreshCameraOrVfx();
}
}
private void OnDisable()
{
if (_cmd != null && _camera != null)
{
_camera.RemoveCommandBuffer(CN_TRIGGER_EVENT, _cmd);
}
ClearRenderList();
}
private void OnDestroy()
{
if (_cmd != null)
{
if (_camera != null)
{
_camera.RemoveCommandBuffer(CN_TRIGGER_EVENT, _cmd);
}
_cmd.Release();
_cmd = null;
}
if (_mat != null)
{
GameObject.Destroy(_mat);
_mat = null;
}
ClearRenderList();
}
private void OnValidate()
{
RefreshCmd();
}
private void RefreshCameraOrVfx()
{
var camera = GetComponentsInChildren<Camera>(false);
var render = GetComponentsInChildren<Renderer>(true);
if (camera.Length > 0)
{
OnSceneCameraChanged(camera[0]);
}
else
{
OnSceneCameraChanged(null);
}
if (render.Length > 0)
{
OnCameraVfxChanged(new List<Renderer>(render));
}
else
{
OnCameraVfxChanged(null);
}
}
private void InitPropertyID()
{
_offScreenTexID = Shader.PropertyToID("_OffScreenTex");
}
private void InitCamera()
{
_camera = GetComponent<Camera>();
if (_camera != null)
{
_camera.forceIntoRenderTexture = true;
}
}
private void InitCmd()
{
if (_cmd == null)
{
_cmd = new CommandBuffer();
_cmd.name = "OffScreenVfxCmd";
if (_camera != null)
{
_camera.AddCommandBuffer(CN_TRIGGER_EVENT, _cmd);
}
}
}
private void InitMat()
{
var sh = RuntimeUtilities.FindShader("Hidden/Ares/PostEffect/OffScreenVfx");
if (sh != null)
{
_mat = new Material(sh);
_mat.hideFlags = HideFlags.DontSave;
}
else
{
Debug.LogError("Hidden/Ares/PostEffect/OffScreenVfx");
}
}
private void RefreshCmd()
{
if (_cmd != null)
{
_cmd.Clear();
if (_renders.Count > 0)
{
_cmd.GetTemporaryRT(_offScreenTexID, -4, -4, 0, FilterMode.Bilinear);
_cmd.GetTemporaryRT(CmdBufferUtils.FullScreenTexID, -1, -1, 0, FilterMode.Bilinear);
_cmd.SetRenderTarget(_offScreenTexID);
_cmd.ClearRenderTarget(true, true, Color.black);
//0.把需要处理的模型进行处理
for (int i = 0; i < _renders.Count; i++)
{
if (_renders[i] != null)
{
_renders[i].enabled = false;
_cmd.DrawRenderer(_renders[i], _renders[i].sharedMaterial);
}
}
//1.把FrameBuffer中的数据进行组合
_cmd.SetGlobalTexture("_OffScreenTex", _offScreenTexID);
_cmd.SetGlobalTexture(CmdBufferUtils.MainTexID, BuiltinRenderTextureType.CameraTarget);
_cmd.SetRenderTarget(CmdBufferUtils.FullScreenTexID);
_cmd.DrawMesh(CmdBufferUtils.QuadMesh, Matrix4x4.identity, _mat,0, (int)_bop);
//2.把扭曲的页面复制到FrameBuffer中.
_cmd.SetGlobalTexture(CmdBufferUtils.MainTexID, CmdBufferUtils.FullScreenTexID);
_cmd.SetRenderTarget(BuiltinRenderTextureType.CameraTarget);
_cmd.DrawMesh(CmdBufferUtils.QuadMesh, Matrix4x4.identity, CmdBufferUtils.BlitMat, 0, 0);
_cmd.ReleaseTemporaryRT(CmdBufferUtils.FullScreenTexID);
_cmd.ReleaseTemporaryRT(_offScreenTexID);
}
}
}
private void OnPostEffectActive(int val)
{
Debug.LogError("OffScreenVfx:OnPostEffectActive:" + val);
if (_camera != null && _cmd != null)
{
//根据激活状态来处理
if (val > 0)
{
_camera.RemoveCommandBuffer(CN_TRIGGER_EVENT, _cmd);
_camera.AddCommandBuffer(CN_TRIGGER_EVENT, _cmd);
}
else
{
_camera.RemoveCommandBuffer(CN_TRIGGER_EVENT, _cmd);
ClearRenderList();
}
}
}
public void OnSceneCameraChanged()
{
OnSceneCameraChanged(null);
}
public void OnSceneCameraChanged(object obj)
{
Camera cam = obj as Camera;
Debug.LogError("OnSceneCameraChanged:" + (cam != null ? cam.name : "NULL"));
if (_camera != null)
{
if (_cmd != null)
{
_camera.RemoveCommandBuffer(CN_TRIGGER_EVENT, _cmd);
}
}
_camera = cam;
if (_camera != null)
{
_camera.forceIntoRenderTexture = true;
if (_cmd != null)
{
_camera.AddCommandBuffer(CN_TRIGGER_EVENT, _cmd);
}
}
}
public void OnCameraVfxChanged()
{
OnCameraVfxChanged(null);
}
public void OnCameraVfxChanged(object obj)
{
List<Renderer> list = obj as List<Renderer>;
Debug.LogError("OnCameraVfxChanged:" + (list!= null ?list.Count.ToString():"NULL"));
ClearRenderList();
if (list != null && list.Count > 0)
{
_renders.AddRange(list);
}
RefreshCmd();
}
private void ClearRenderList()
{
for (int i = 0; i < _renders.Count; i++)
{
_renders[i].enabled = true;
}
_renders.Clear();
}
public enum BlendOp
{
Blend = 0,
Add = 1,
Skill = 2,
}
}
}