|
|
- // author : Saber
- // date : 2020/12/8
- // desc : 将当前项目中的后处理集中处理
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using System;
- using LuaInterface;
- using UnityStandardAssets.ImageEffects;
- public enum Resolution
- {
- Low = 0,
- High = 1,
- }
-
- public enum BlurType
- {
- Standard = 0,
- Sgx = 1,
- }
-
- // [ExecuteInEditMode, ImageEffectAllowedInSceneView]
- [RequireComponent (typeof(Camera))]
- public class PostEffect : PostEffectsBase
- {
-
- #region FXAA参数
- public bool EnableFXAA = false; // FXAA总开关
- const int fxaaPass = 1;
- [Range(0.0312f, 0.0833f)]
- public float contrastThreshold = 0.0312f;
- [Range(0.063f, 0.333f)]
- public float relativeThreshold = 0.063f;
- [Range(0f, 1f)]
- public float subpixelBlending = 1f;
- public Shader FXAAShader;
- public bool lowQuality;
- Material fxaaMaterial;
- #endregion
-
- #region bloom效果参数
- public bool EnableBloom = false;
- [Range(0.0f, 1.5f)]
- public float threshold = 0.47f;
- [Range(0.0f, 3f)]
- public float intensity = 0.75f;
- [Range(0.25f, 5.5f)]
- public float blurSize = 0.46f;
- int bloomDowmSample = 1;
- float bloomBlurAmount = 0.5f;
- int passOffset = 0;
- Resolution resolution = Resolution.Low;
- [Range(1, 4)]
- public int blurIterations = 1;
- public BlurType blurType= BlurType.Standard;
- public Shader fastBloomShader = null;
- public Shader dualBloomShader = null;
- private Material fastBloomMaterial = null;
- private Material dualBloomMaterial = null;
- public bool use_dual_bloom = false;
-
- const int DUAL_BLOOM_RENDER_PASS = 0;
- const int DUAL_BLOOM_DOWNSAMPLE_PASS = 1;
- const int DUAL_BLOOM_UPSAMPLE_PASS = 2;
- const int DUAL_BLOOM_LUMINACE_PASS = 3;
- #endregion
-
- #region 高斯模糊/双重模糊后处理效果参数
- public bool EnableBlur = false;
- public bool use_dual_blur = false; // 使用双面模糊
-
- #region 高斯模糊相关参数
- const int BLUR_PASS_HOR = 0; // 水平模糊pass
- const int BLUR_PASS_VER = 1; // 垂直模糊pass
- public Shader blurShader; // 高斯模糊shader
- Material blurMaterial; // 高速模糊材质
- [HideInInspector]
- public bool render_blur_effect = false; // 高斯模糊关键参数,设置为true时会开始渲染高斯模糊纹理
- public bool get_screen_shot = false; // 与上面的功能区分,只截图,并不会改变原先的渲染
- // 高斯模糊缓存纹理(不要在渲染时动态创建,会消耗很多内存,这里先生成引用)
- public float blurSpread = 0.4f; // 模糊散值
- public float blur_amount = 1f; // 模糊插值,0:初始效果,1:完全模糊效果
- private int recurveNum = 1; // 当前迭代的渲染次数
- public int recurveMaxNum = 1; // 最大迭代渲染次数
- public int downSample = 4; // 降低采样率比率(降低采样率可以提高性能,但肯定会让效果变差)
- LuaFunction screenshot_callback; // 模糊截图回调
- #endregion
-
- #region 双面模糊相关参数
- const int DOWN_SAMPLE_PASS = 0; // 降采样pass
- const int UP_SAMPLE_PASS = 1; // 升采样pass
- public Shader dualBlurShader; // 双面模糊shader
- Material dual_blur_mat; // 双面模糊材质球
- RenderTextureFormat format;
- #endregion
- #endregion
- private RenderTexture final_renderTexture; // 最终渲染出来的画面RT缓存
- private RenderTexture temp_rt1;
- private RenderTexture temp_rt2;
- private bool final_rt_rendered = false; // 最终画面是否被渲染到了
-
- // 检查资源
- public bool GetSupported()
- {
- return CheckSupport(false);
- }
- public override bool CheckResources()
- {
- CheckSupport (false);
-
- if (!isSupported){
- ReportAutoDisable ();
- return isSupported;
- }
-
- // 创建对应shader的材质球
- fxaaMaterial = CheckShaderAndCreateMaterial (FXAAShader, fxaaMaterial); // FXAA效果
- fastBloomMaterial = CheckShaderAndCreateMaterial (fastBloomShader, fastBloomMaterial); // Bloom效果(高斯模糊)
- dualBloomMaterial = CheckShaderAndCreateMaterial (dualBloomShader, dualBloomMaterial); // Bloom效果(双重模糊)
- blurMaterial = CheckShaderAndCreateMaterial (blurShader, blurMaterial); // 高斯模糊效果
- dual_blur_mat = CheckShaderAndCreateMaterial (dualBlurShader, dual_blur_mat); // 双面模糊效果
-
- return isSupported;
- }
-
- // 非迭代的material参数修改,统一做成接口调用以一次性修改,而不要在渲染逻辑内重复执行
- // FXAA属性值应用
- public void ApplyFXAAMaterialProperties()
- {
- if (fxaaMaterial != null)
- {
- fxaaMaterial.SetFloat("_ContrastThreshold", contrastThreshold);
- fxaaMaterial.SetFloat("_RelativeThreshold", relativeThreshold);
- fxaaMaterial.SetFloat("_SubpixelBlending", subpixelBlending);
-
- if (lowQuality) {
- fxaaMaterial.EnableKeyword("LOW_QUALITY");
- }
- else {
- fxaaMaterial.DisableKeyword("LOW_QUALITY");
- }
- }
- }
- // Bloom泛光属性值应用
- public void ApplyBloomMaterialProperties()
- {
- bloomDowmSample = resolution == Resolution.Low ? 4 : 2;
- bloomBlurAmount = resolution == Resolution.Low ? 0.5f : 1.0f;
- passOffset = blurType == BlurType.Standard ? 0 : 2;
-
- // 双面模糊的参数直接设置
- if (dualBloomMaterial)
- {
- dualBloomMaterial.SetFloat("_Threshold", threshold);
- dualBloomMaterial.SetFloat("_Intensity", intensity);
- }
- }
-
- // 高斯/双面模糊属性值应用
- public void ApplyBlurMaterialProperties()
- {
-
- }
-
- // 根据当前的项目渲染顺序,预设的渲染顺序分别是 Bloom泛光效果 -> FXAA抗锯齿效果 -> 模糊效果(采集模糊背景用,很少用于即时渲染)
- // 将所有的效果整合成OnRenderImage中处理,不拆分,尽可能减少Graphics.Blit次数
- void OnRenderImage(RenderTexture src, RenderTexture dest)
- {
- if (isSupported) // 支持后处理
- {
- final_rt_rendered = false;
- final_renderTexture = RenderTexture.GetTemporary(src.width, src.height, 0, src.format);
- format = src.format;
- // 1.处理Bloom泛光效果
- if (EnableBloom && fastBloomMaterial != null && dualBloomMaterial != null)
- {
- // 使用双面模糊算法来处理模糊部分
- if(use_dual_bloom)
- {
- int width = src.width;
- int height = src.height;
- // 根据亮度阈值获取亮度图
- temp_rt1 = RenderTexture.GetTemporary(width / bloomDowmSample, height / bloomDowmSample, 0, format);
- temp_rt2 = RenderTexture.GetTemporary(width / bloomDowmSample, height / bloomDowmSample, 0, format);
- Graphics.Blit(src, temp_rt1, dualBloomMaterial, DUAL_BLOOM_LUMINACE_PASS);
- for(int i = 0; i < blurIterations; i++)
- {
- dualBloomMaterial.SetFloat("_Offset", (1.0f + i * blurSize) * bloomBlurAmount); // 设置模糊扩散uv偏移
- // 降采样渲染
- Graphics.Blit(temp_rt1, temp_rt2, dualBloomMaterial, DUAL_BLOOM_DOWNSAMPLE_PASS);
- // 升采样渲染
- Graphics.Blit(temp_rt2, temp_rt1, dualBloomMaterial, DUAL_BLOOM_UPSAMPLE_PASS);
- }
- dualBloomMaterial.SetTexture("_Bloom", temp_rt1);
- }
- // 使用高斯模糊算法处理模糊部分
- else
- {
- fastBloomMaterial.SetVector("_Parameter", new Vector4 (blurSize * bloomBlurAmount, 0.0f, threshold, intensity));
- // src.filterMode = FilterMode.Bilinear;
- int rtW = src.width / bloomDowmSample;
- int rtH = src.height / bloomDowmSample;
- // downsample
- temp_rt1 = RenderTexture.GetTemporary(rtW, rtH, 0, format);
- temp_rt2 = RenderTexture.GetTemporary(rtW, rtH, 0, format);
- // temp_rt1.filterMode = FilterMode.Bilinear;
- // temp_rt2.filterMode = FilterMode.Bilinear;
- Graphics.Blit(src, temp_rt1, fastBloomMaterial, 1);
-
- for(int i = 0; i < blurIterations; i++)
- {
- fastBloomMaterial.SetVector("_Parameter", new Vector4 (blurSize * bloomBlurAmount + (i*1.0f), 0.0f, threshold, intensity));
- // vertical blur
- Graphics.Blit(temp_rt1, temp_rt2, fastBloomMaterial, 2 + passOffset);
- Graphics.Blit(temp_rt2, temp_rt1, fastBloomMaterial, 3 + passOffset);
- }
- fastBloomMaterial.SetTexture("_Bloom", temp_rt1);
- }
- ReleaseTemporary(temp_rt2);
-
- // 这边就判断是否使用FXAA
- if (EnableFXAA && fxaaMaterial != null)
- {
- temp_rt2 = RenderTexture.GetTemporary(src.width, src.height, 0, format);
- if(use_dual_bloom) // 使用双面模糊算法来处理合并部分
- {
- Graphics.Blit(src, temp_rt2, dualBloomMaterial, DUAL_BLOOM_RENDER_PASS);
- }
- else
- {
- Graphics.Blit(src, temp_rt2, fastBloomMaterial, 0);
- }
-
- Graphics.Blit(temp_rt2, final_renderTexture, fxaaMaterial, fxaaPass);
- ReleaseTemporary(temp_rt2);
- }
- else
- {
- if(use_dual_bloom) // 使用双面模糊算法来处理合并部分
- {
- Graphics.Blit(src, final_renderTexture, dualBloomMaterial, DUAL_BLOOM_RENDER_PASS);
- }
- else
- {
- Graphics.Blit(src, final_renderTexture, fastBloomMaterial, 0);
- }
- }
- final_rt_rendered = true;
- //source.filterMode = FilterMode.Point;
- ReleaseTemporary(temp_rt1);
- }
- else
- {
- // 当不适用Bloom的情况,处理FXAA抗锯齿效果
- if (EnableFXAA && fxaaMaterial != null)
- {
- Graphics.Blit(src, final_renderTexture, fxaaMaterial, fxaaPass);
- final_rt_rendered = true;
- }
- }
- // 3.处理模糊需求
- if (EnableBlur && blurMaterial != null && dual_blur_mat != null && (render_blur_effect || get_screen_shot))
- {
- // 使用双面模糊算法
- if(use_dual_blur){
- int width = src.width;
- int height = src.height;
- recurveNum = 1; // 初始化迭代
- // RT初始化
- temp_rt1 = RenderTexture.GetTemporary(width / downSample, height / downSample, 0, format);
-
- if(get_screen_shot && !render_blur_effect) // 当只是渲染截图,就使用临时rt2
- temp_rt2 = RenderTexture.GetTemporary(width / downSample, height / downSample, 0, format);
-
- while(recurveNum <= recurveMaxNum)
- {
- dual_blur_mat.SetFloat("_Offset", (1.0f + recurveNum * blurSpread) * blur_amount); // 设置模糊扩散uv偏移
- if (get_screen_shot && !render_blur_effect) // 只渲染截屏
- {
- // 降采样渲染
- if(recurveNum == 1 && !final_rt_rendered) // 当首次降采样且最终RT没有处理过,就使用源RT
- Graphics.Blit(src, temp_rt1, dual_blur_mat, DOWN_SAMPLE_PASS);
- else
- Graphics.Blit(temp_rt2, temp_rt1, dual_blur_mat, DOWN_SAMPLE_PASS);
-
- // 升采样渲染
- // 使用temp_rt2,不要影响最终画面
- Graphics.Blit(temp_rt1, temp_rt2, dual_blur_mat, UP_SAMPLE_PASS);
- }
- else // 需要实时模糊
- {
- // 降采样渲染
- if(recurveNum == 1 && !final_rt_rendered) // 当首次降采样且最终RT没有处理过,就使用源RT
- Graphics.Blit(src, temp_rt1, dual_blur_mat, DOWN_SAMPLE_PASS);
- else
- Graphics.Blit(final_renderTexture, temp_rt1, dual_blur_mat, DOWN_SAMPLE_PASS);
-
- // 升采样渲染,输出模糊的final_renderTexture
- Graphics.Blit(temp_rt1, final_renderTexture, dual_blur_mat, UP_SAMPLE_PASS);
- }
-
- recurveNum ++;
- }
- RenderTexture.ReleaseTemporary(temp_rt1); // 释放临时RT
- // 仅当使用持续模糊渲染才会置为true,否则由之前的效果来决定
- final_rt_rendered = final_rt_rendered || render_blur_effect;
- }
- else
- {
- recurveNum = 1;
- //缩小要模糊的图片,减少处理压力
- int width = src.width / downSample;
- int height = src.height / downSample;
- // 由于高斯模糊需要将最终纹理降采样,所以这边做一个标志量
- // 如果经过了上面的处理后还需要高斯模糊处理,则需要在迭代渲染过程中进行一次降采样缓存
- bool need_redownSample = true;
-
- if(get_screen_shot && !render_blur_effect) // 当只是渲染截图,就使用临时rt2
- {
- temp_rt2 = RenderTexture.GetTemporary(width, height, 0, format);
- Graphics.Blit(src, temp_rt2);
- need_redownSample = false;
- }
- else
- {
- if(!final_rt_rendered)
- {
- // 这边如果原RT未采样也要释放缓存,不然直接获取缓存会存在泄露问题
- ReleaseTemporary(final_renderTexture);
- final_renderTexture = RenderTexture.GetTemporary(width, height, 0);
- // final_renderTexture.filterMode = FilterMode.Bilinear;
- Graphics.Blit(src, final_renderTexture);
-
- need_redownSample = false;
- }
- }
-
- temp_rt1 = RenderTexture.GetTemporary(width, height, 0);
- while(recurveNum <= recurveMaxNum){
- recurveNum ++;
- blurMaterial.SetFloat("_BlurSize", (1.0f + recurveNum * blurSpread) * blur_amount);
-
- if(get_screen_shot && !render_blur_effect)
- {
- Graphics.Blit(temp_rt2, temp_rt1, blurMaterial, BLUR_PASS_HOR);
- if(need_redownSample)
- {
- temp_rt2 = RenderTexture.GetTemporary(width, height, 0, format);
- need_redownSample = false;
- }
- Graphics.Blit(temp_rt1, temp_rt2, blurMaterial, BLUR_PASS_VER);
- }
- else
- {
- Graphics.Blit(final_renderTexture, temp_rt1, blurMaterial, BLUR_PASS_HOR);
- if(need_redownSample)
- {
- ReleaseTemporary(final_renderTexture);
- final_renderTexture = RenderTexture.GetTemporary(width, height, 0);
- need_redownSample = false;
- }
- Graphics.Blit(temp_rt1, final_renderTexture, blurMaterial, BLUR_PASS_VER);
- }
- }
- RenderTexture.ReleaseTemporary(temp_rt1);
- // 仅当使用持续模糊渲染才会置为true,否则由之前的效果来决定
- final_rt_rendered = final_rt_rendered || render_blur_effect;
- }
- }
- if(get_screen_shot && !render_blur_effect){
- GetBlurScreenShot();
- get_screen_shot = false; // 截图生成之后就停止运作
- }
- if(final_rt_rendered)
- {
- Graphics.Blit(final_renderTexture, dest);
- }
- else
- {
- Graphics.Blit(src, dest);
- }
- RenderTexture.ReleaseTemporary(final_renderTexture);
- }
- else
- {
- Graphics.Blit(src, dest); // 不支持后处理,则直接输出最终画面
- }
- }
-
- // 设置开始处理模糊效果的截图
- public void RenderBlurScreenShot(float blur_amount, int downSample, LuaFunction func)
- {
- get_screen_shot = true;
- this.blur_amount = blur_amount;
- this.downSample = downSample;
- screenshot_callback = func;
- }
- void GetBlurScreenShot()
- {
- // RenderTexture temp_screen_shot = RenderTexture.GetTemporary(final_renderTexture.width, final_renderTexture.height, 0);
- // Graphics.Blit(final_renderTexture, temp_screen_shot);
- RenderTexture temp_screen_shot = RenderTexture.GetTemporary(temp_rt2.width, temp_rt2.height, 0);
- Graphics.Blit(temp_rt2, temp_screen_shot);
- if (screenshot_callback != null)
- {
- List<UnityEngine.Object> list = new List<UnityEngine.Object>();
- list.Add(temp_screen_shot);
- object[] args = new object[] { list.ToArray() };
- screenshot_callback.Call(args);
- screenshot_callback.Dispose();
- screenshot_callback = null;
- }
- // 释放掉临时RT2
- ReleaseTemporary(temp_rt2);
- }
- // 销毁渲染纹理缓存
- public void ReleaseRenderTexCache()
- {
- if (!render_blur_effect) {
- ReleaseTemporary(final_renderTexture);
- }
- }
- void ReleaseTemporary(RenderTexture rt)
- {
- if (rt != null)
- {
- RenderTexture.ReleaseTemporary(rt);
- }
- }
- void OnDisable()
- {
- // // 销毁已有的材质球
- // if (fastBloomMaterial)
- // DestroyImmediate (fastBloomMaterial);
- // if (dualBloomMaterial)
- // DestroyImmediate (dualBloomMaterial);
- // if (fxaaMaterial)
- // DestroyImmediate (fxaaMaterial);
- // if (blurMaterial)
- // DestroyImmediate (blurMaterial);
- // if (dual_blur_mat)
- // DestroyImmediate (dual_blur_mat);
-
- // ReleaseTemporary(final_renderTexture);
- // ReleaseTemporary(temp_rt1);
- // ReleaseTemporary(temp_rt2);
- }
- }
|