/// author:Saber
|
|
/// desc:角色相机泛光效果脚本
|
|
/// 2020年2月21日优化:参考了catlikecoding的模糊思路优化逻辑提升效果,模糊rt使用局部摄像机获取到的画面进行处理
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
[ExecuteInEditMode]
|
|
[RequireComponent(typeof(Camera))]
|
|
public class RoleCameraBloom : MonoBehaviour
|
|
{
|
|
public RenderTexture cullRenderTexture; // 用来接收泛光相机的裁剪RT
|
|
private ChangeShaderRender scr_script; // 泛光摄像机上的渲染脚本
|
|
#region 泛光特效相关参数
|
|
//模糊散值
|
|
public Material bloomMaterial; // 泛光特效相关材质
|
|
public bool render_bloom_effect = false; // 泛光特效关键参数,设置为true时会开始渲染泛光特效
|
|
|
|
#endregion
|
|
private bool isSupported; // 设备支持变量
|
|
// 模糊摄像机获取到的画面依然需要做阈值处理,不过初始默认值为0
|
|
[Range(0, 10)]
|
|
public float threshold = 1;
|
|
// 避免阈值附近的画面忽然点亮,这里设置一个软阈值处理阈值附近的颜色值的泛光效果
|
|
[Range(0, 1)]
|
|
public float softThreshold = 0.5f;
|
|
[Range(0, 10)]
|
|
public float intensity = 1;
|
|
#region 渲染pass常量
|
|
const int BoxDownPrefilterPass = 0; // 对泛光部分降采样的pass
|
|
const int BoxDownPass = 1; // 降序采样pass
|
|
const int BoxUpPass = 2; // 升序采样pass,最大限度利用到所有的像素颜色贡献
|
|
const int ApplyBloomPass = 3; // 泛光颜色叠加pass
|
|
const int DebugBloomPass = 4; // 测试pass,不叠加原颜色,只渲染泛光处理的效果
|
|
#endregion
|
|
[Range(1, 8)]
|
|
public int iterations = 4; // 泛光迭代次数
|
|
RenderTexture[] textures = new RenderTexture[8]; // 临时纹理链表
|
|
RenderTexture currentDestination;
|
|
RenderTexture currentSource;
|
|
Vector4 filter; // 膝盖曲线过滤值
|
|
public bool debug = false;
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
// 检查平台支持,不支持则直接禁用
|
|
isSupported = CheckSupport();
|
|
this.enabled = isSupported;
|
|
if(scr_script != null){
|
|
scr_script.enabled = isSupported;
|
|
}
|
|
// 测试逻辑
|
|
// TestLogic();
|
|
}
|
|
#region 测试逻辑
|
|
private void TestLogic()
|
|
{
|
|
RenderTexture temp_render = new RenderTexture(1280, 600, 0);
|
|
GameObject child = this.transform.GetChild(0).gameObject;
|
|
Camera temp_camera = child.GetComponent<Camera>();
|
|
child.AddComponent<ChangeShaderRender>();
|
|
ChangeShaderRender temp_scr = child.GetComponent<ChangeShaderRender>();
|
|
Shader shader = Shader.Find("SaberShader/BloomClipShader");
|
|
temp_scr.target_shader = shader;
|
|
SetBloomCameraData(temp_camera, temp_render, temp_scr);
|
|
}
|
|
#endregion
|
|
private bool CheckSupport()
|
|
{
|
|
if (SystemInfo.supportsImageEffects == false)
|
|
{
|
|
Debug.LogWarning("当前平台不支持!");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
// Lua接口,将泛光摄像机和泛光摄像机输出的rt交给本类来控制
|
|
public void SetBloomCameraData(Camera camera, RenderTexture rt, ChangeShaderRender change_shader_render){
|
|
cullRenderTexture = rt;
|
|
camera.targetTexture = cullRenderTexture;
|
|
render_bloom_effect = true;
|
|
scr_script = change_shader_render;
|
|
// 效果运行与否还要看设备支不支持特效
|
|
scr_script.enabled = isSupported;
|
|
}
|
|
// 正式渲染
|
|
// 这个方法要注意在退出游戏的时候把渲染逻辑门关闭,一般情况下把render_bloom_effect置false
|
|
void OnRenderImage(RenderTexture src, RenderTexture dest)
|
|
{
|
|
if (bloomMaterial != null && render_bloom_effect && cullRenderTexture != null)
|
|
{
|
|
// 膝盖曲线的值可以在这里预先算好
|
|
float knee = threshold * softThreshold;
|
|
filter.x = threshold;
|
|
filter.y = filter.x - knee;
|
|
filter.z = 2f * knee;
|
|
filter.w = 0.25f / (knee + 0.00001f);
|
|
bloomMaterial.SetVector("_Filter", filter);
|
|
bloomMaterial.SetFloat("_Intensity", Mathf.GammaToLinearSpace(intensity));
|
|
// 降低一次采样,将剧目摄像机的内容传递到临时的最终画面RT中
|
|
int width = src.width / 4;
|
|
int height = src.height / 4;
|
|
currentDestination = textures[0] = RenderTexture.GetTemporary(width, height, 0, src.format);
|
|
Graphics.Blit(cullRenderTexture, currentDestination, bloomMaterial, BoxDownPrefilterPass);
|
|
currentSource = currentDestination;
|
|
|
|
// 循环降采样,并将结果保存
|
|
int i = 1;
|
|
for (; i < iterations; i++) {
|
|
width /= 2;
|
|
height /= 2;
|
|
if (height < 2) {
|
|
break;
|
|
}
|
|
currentDestination = textures[i] =
|
|
RenderTexture.GetTemporary(width, height, 0, src.format);
|
|
Graphics.Blit(currentSource, currentDestination, bloomMaterial, BoxDownPass);
|
|
currentSource = currentDestination;
|
|
}
|
|
// 再对降采样后的画面继续宁升采样,将每个像素的颜色平均出去
|
|
for (i -= 2; i >= 0; i--) {
|
|
currentDestination = textures[i];
|
|
textures[i] = null;
|
|
Graphics.Blit(currentSource, currentDestination, bloomMaterial, BoxUpPass);
|
|
RenderTexture.ReleaseTemporary(currentSource);
|
|
currentSource = currentDestination;
|
|
}
|
|
|
|
if (debug) {
|
|
Graphics.Blit(currentSource, dest, bloomMaterial, DebugBloomPass);
|
|
}
|
|
else {
|
|
bloomMaterial.SetTexture("_SourceTex", src);
|
|
Graphics.Blit(currentSource, dest, bloomMaterial, ApplyBloomPass);
|
|
}
|
|
RenderTexture.ReleaseTemporary(currentSource);
|
|
}
|
|
else
|
|
{
|
|
Graphics.Blit(src, dest);
|
|
}
|
|
}
|
|
public void ReleaseTempRes()
|
|
{
|
|
render_bloom_effect = false;
|
|
if(scr_script != null)
|
|
{
|
|
scr_script.enabled = false;
|
|
}
|
|
}
|
|
void OnDestroy(){
|
|
ReleaseTempRes();
|
|
}
|
|
}
|