源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

448 lines
19 KiB

// 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);
}
}