256 lines
8.8 KiB
C#
256 lines
8.8 KiB
C#
|
|
using Thousandto.Launcher.ExternalLibs;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace Thousandto.Launcher.ExternalLibs
|
|
{
|
|
/// <summary>
|
|
/// 不透明对象的曝光处理.
|
|
/// 描述: 利用渲染图片的alpha通道,来判断哪些需要曝光哪些不需要,这个只针对不透明的对象(Opaque).
|
|
/// </summary>
|
|
public class OpaqueBloom
|
|
{
|
|
|
|
|
|
//命令缓存
|
|
private CommandBuffer _processCmds;
|
|
//当前挂载的摄像机
|
|
private Camera _camera;
|
|
//材质球
|
|
private Material _mat;
|
|
//触发事件2
|
|
private CameraEvent _triggerEvent = CameraEvent.BeforeImageEffects;
|
|
//参数:x,y表示偏移处理,z:表示曝光强度
|
|
private Vector4 _Params = Vector4.zero;
|
|
//阈值相关:x:threshold,y:threshold-knee,z:knee*2,w:1/(knee*4)
|
|
private Vector4 _Threshold = Vector4.zero;
|
|
private bool _isInited = false;
|
|
|
|
//是否可用
|
|
private bool _enabled = true;
|
|
public bool Enabled
|
|
{
|
|
get
|
|
{
|
|
return _enabled;
|
|
}
|
|
set
|
|
{
|
|
if (_enabled != value)
|
|
{
|
|
_enabled = value && SystemInfo.supportsImageEffects;
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool IsInited
|
|
{
|
|
get
|
|
{
|
|
return _isInited;
|
|
}
|
|
}
|
|
|
|
//初始化
|
|
public void Initialize()
|
|
{
|
|
if (!_isInited)
|
|
{
|
|
//判断是否支持
|
|
_enabled = _enabled && SystemInfo.supportsImageEffects;
|
|
InitMat();
|
|
Debug.Log("Initialize:" + _enabled + ";;;SystemInfo.supportsImageEffects:" + SystemInfo.supportsImageEffects + ";;(_mat != null):" + (_mat != null).ToString());
|
|
if (_mat != null)
|
|
{
|
|
InitCmd();
|
|
_isInited = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//反初始化
|
|
public void UnInitialize()
|
|
{
|
|
if (_processCmds != null)
|
|
{
|
|
if (_camera != null)
|
|
{
|
|
_camera.RemoveCommandBuffer(_triggerEvent, _processCmds);
|
|
}
|
|
_processCmds.Release();
|
|
_processCmds = null;
|
|
}
|
|
|
|
if (_mat != null)
|
|
{
|
|
GameObject.Destroy(_mat);
|
|
_mat = null;
|
|
}
|
|
}
|
|
|
|
//绑定摄像机
|
|
public void BindCamera(Camera cam)
|
|
{
|
|
if (_processCmds != null)
|
|
{
|
|
if (_camera != null)
|
|
{
|
|
_camera.forceIntoRenderTexture = false;
|
|
_camera.RemoveCommandBuffer(_triggerEvent, _processCmds);
|
|
}
|
|
|
|
|
|
if (cam != null && Enabled)
|
|
{
|
|
cam.forceIntoRenderTexture = true;
|
|
cam.AddCommandBuffer(_triggerEvent, _processCmds);
|
|
}
|
|
}
|
|
_camera = cam;
|
|
|
|
}
|
|
|
|
//设置偏移和强度
|
|
public void SetOffsetAndStrength(Vector2 offset, float strength)
|
|
{
|
|
_Params = new Vector4(offset.x, offset.y, strength);
|
|
RefreshMat();
|
|
}
|
|
|
|
//设置阈值
|
|
public void SeThreshold(float threshold, float knee)
|
|
{
|
|
_Threshold = new Vector4(threshold, threshold - knee, knee * 2, 1 / ((knee + 0.0001f) * 4));
|
|
RefreshMat();
|
|
}
|
|
|
|
//刷新材质球
|
|
public void RefreshMat()
|
|
{
|
|
if (_mat != null)
|
|
{
|
|
_mat.SetVector("_Params", _Params);
|
|
_mat.SetVector("_Threshold", _Threshold);
|
|
}
|
|
}
|
|
|
|
//初始化渲染命令
|
|
private void InitCmd()
|
|
{
|
|
var mainTexID = CmdBufferUtils.MainTexID;
|
|
var bloomTexID = Shader.PropertyToID("_BloomTex");
|
|
|
|
if (_processCmds == null)
|
|
{
|
|
_processCmds = new CommandBuffer();
|
|
_processCmds.name = "OpaqueBloomCmd";
|
|
|
|
//准备
|
|
_processCmds.GetTemporaryRT(CmdBufferUtils.FullScreenTexID, -1,-1, 0, FilterMode.Bilinear);
|
|
|
|
int tw = Screen.width / 2;
|
|
int th = Screen.height / 2;
|
|
int iterations = Mathf.Clamp(Mathf.FloorToInt(Mathf.Log(Mathf.Max(tw, th), 2)), 1, 3);
|
|
int[] dids = new int[iterations];
|
|
int[] uids = new int[iterations];
|
|
for (int i = 0; i < iterations; i++)
|
|
{
|
|
dids[i] = (Shader.PropertyToID("_CameraBloomEffectTexD" + i));
|
|
uids[i] = (Shader.PropertyToID("_CameraBloomEffectTexU" + i));
|
|
_processCmds.GetTemporaryRT(dids[i], tw, th, 0, FilterMode.Bilinear);
|
|
_processCmds.GetTemporaryRT(uids[i], tw, th, 0, FilterMode.Bilinear);
|
|
tw = tw / 2;
|
|
th = th / 2;
|
|
}
|
|
|
|
//0.摄像机的数据读取出来
|
|
_processCmds.SetRenderTarget(CmdBufferUtils.FullScreenTexID);
|
|
_processCmds.SetGlobalTexture(mainTexID, BuiltinRenderTextureType.CameraTarget);
|
|
_processCmds.DrawMesh(CmdBufferUtils.QuadMesh, Matrix4x4.identity, _mat, 0, 3);
|
|
|
|
//1.过滤一下
|
|
_processCmds.SetRenderTarget(dids[0]);
|
|
_processCmds.SetGlobalTexture(mainTexID, CmdBufferUtils.FullScreenTexID);
|
|
_processCmds.DrawMesh(CmdBufferUtils.QuadMesh, Matrix4x4.identity, _mat, 0, 0);
|
|
|
|
//2.进行采样处理
|
|
for (int i = 0; i < iterations; i++)
|
|
{
|
|
//2.1 处理行
|
|
_processCmds.SetRenderTarget(uids[i]);
|
|
_processCmds.SetGlobalTexture(mainTexID, dids[0]);
|
|
_processCmds.DrawMesh(CmdBufferUtils.QuadMesh, Matrix4x4.identity, _mat, 0, 1);
|
|
|
|
//2.2 处理列
|
|
_processCmds.SetRenderTarget(dids[i]);
|
|
_processCmds.SetGlobalTexture(mainTexID, uids[i]);
|
|
_processCmds.DrawMesh(CmdBufferUtils.QuadMesh, Matrix4x4.identity, _mat, 0, 2);
|
|
}
|
|
|
|
|
|
//4.先把最后一个复制了
|
|
_processCmds.SetRenderTarget(uids[iterations - 1]);
|
|
_processCmds.SetGlobalTexture(mainTexID, dids[iterations - 1]);
|
|
_processCmds.DrawMesh(CmdBufferUtils.QuadMesh, Matrix4x4.identity, _mat, 0, 3);
|
|
|
|
//5.把bloom纹理给组合起来
|
|
for (int i = iterations - 2; i >= 0; i--)
|
|
{
|
|
_processCmds.SetRenderTarget(uids[i]);
|
|
_processCmds.SetGlobalTexture(mainTexID, uids[i + 1]);
|
|
_processCmds.SetGlobalTexture(bloomTexID, dids[i]);
|
|
_processCmds.DrawMesh(CmdBufferUtils.QuadMesh, Matrix4x4.identity, _mat, 0, 4);
|
|
}
|
|
|
|
|
|
|
|
//6.把bloom纹理与显示帧的数据给组合起来
|
|
_processCmds.SetRenderTarget(BuiltinRenderTextureType.CameraTarget);
|
|
_processCmds.SetGlobalTexture(mainTexID, CmdBufferUtils.FullScreenTexID);
|
|
_processCmds.SetGlobalTexture(bloomTexID, uids[0]);
|
|
_processCmds.DrawMesh(CmdBufferUtils.QuadMesh, Matrix4x4.identity, _mat, 0, 4);
|
|
|
|
_processCmds.SetRenderTarget(uids[0]);
|
|
//7.释放RT资源
|
|
for (int i = 0; i < iterations; i++)
|
|
{
|
|
_processCmds.ReleaseTemporaryRT(dids[i]);
|
|
_processCmds.ReleaseTemporaryRT(uids[i]);
|
|
}
|
|
_processCmds.ReleaseTemporaryRT(CmdBufferUtils.FullScreenTexID);
|
|
|
|
if (_camera != null && Enabled)
|
|
{
|
|
_camera.forceIntoRenderTexture = true;
|
|
_camera.AddCommandBuffer(_triggerEvent, _processCmds);
|
|
}
|
|
}
|
|
}
|
|
|
|
//初始化材质球
|
|
private void InitMat()
|
|
{
|
|
if (_mat == null)
|
|
{
|
|
var sh = RuntimeUtilities.FindShader("Hidden/Ares/PostEffect/BloomCmd");
|
|
if (sh != null)
|
|
{
|
|
_mat = new Material(sh);
|
|
_mat.hideFlags = HideFlags.DontSave;
|
|
|
|
//初始化材质球
|
|
SetOffsetAndStrength(new Vector2(4, 4), 1.5f);
|
|
SeThreshold(0.9f, 0.5f);
|
|
RefreshMat();
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("没有找到Shader:Hidden/Ares/PostEffect/BloomCmd,OpaqueBloom无效!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|