264 lines
7.6 KiB
C#
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,
|
|
}
|
|
|
|
}
|
|
}
|