源战役客户端
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

  1. // author : Saber
  2. // date : 2020/12/8
  3. // desc : 将当前项目中的后处理集中处理
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. using System;
  8. using LuaInterface;
  9. using UnityStandardAssets.ImageEffects;
  10. public enum Resolution
  11. {
  12. Low = 0,
  13. High = 1,
  14. }
  15. public enum BlurType
  16. {
  17. Standard = 0,
  18. Sgx = 1,
  19. }
  20. // [ExecuteInEditMode, ImageEffectAllowedInSceneView]
  21. [RequireComponent (typeof(Camera))]
  22. public class PostEffect : PostEffectsBase
  23. {
  24. #region FXAA参数
  25. public bool EnableFXAA = false; // FXAA总开关
  26. const int fxaaPass = 1;
  27. [Range(0.0312f, 0.0833f)]
  28. public float contrastThreshold = 0.0312f;
  29. [Range(0.063f, 0.333f)]
  30. public float relativeThreshold = 0.063f;
  31. [Range(0f, 1f)]
  32. public float subpixelBlending = 1f;
  33. public Shader FXAAShader;
  34. public bool lowQuality;
  35. Material fxaaMaterial;
  36. #endregion
  37. #region bloom效果参数
  38. public bool EnableBloom = false;
  39. [Range(0.0f, 1.5f)]
  40. public float threshold = 0.47f;
  41. [Range(0.0f, 3f)]
  42. public float intensity = 0.75f;
  43. [Range(0.25f, 5.5f)]
  44. public float blurSize = 0.46f;
  45. int bloomDowmSample = 1;
  46. float bloomBlurAmount = 0.5f;
  47. int passOffset = 0;
  48. Resolution resolution = Resolution.Low;
  49. [Range(1, 4)]
  50. public int blurIterations = 1;
  51. public BlurType blurType= BlurType.Standard;
  52. public Shader fastBloomShader = null;
  53. public Shader dualBloomShader = null;
  54. private Material fastBloomMaterial = null;
  55. private Material dualBloomMaterial = null;
  56. public bool use_dual_bloom = false;
  57. const int DUAL_BLOOM_RENDER_PASS = 0;
  58. const int DUAL_BLOOM_DOWNSAMPLE_PASS = 1;
  59. const int DUAL_BLOOM_UPSAMPLE_PASS = 2;
  60. const int DUAL_BLOOM_LUMINACE_PASS = 3;
  61. #endregion
  62. #region 高斯模糊/双重模糊后处理效果参数
  63. public bool EnableBlur = false;
  64. public bool use_dual_blur = false; // 使用双面模糊
  65. #region 高斯模糊相关参数
  66. const int BLUR_PASS_HOR = 0; // 水平模糊pass
  67. const int BLUR_PASS_VER = 1; // 垂直模糊pass
  68. public Shader blurShader; // 高斯模糊shader
  69. Material blurMaterial; // 高速模糊材质
  70. [HideInInspector]
  71. public bool render_blur_effect = false; // 高斯模糊关键参数,设置为true时会开始渲染高斯模糊纹理
  72. public bool get_screen_shot = false; // 与上面的功能区分,只截图,并不会改变原先的渲染
  73. // 高斯模糊缓存纹理(不要在渲染时动态创建,会消耗很多内存,这里先生成引用)
  74. public float blurSpread = 0.4f; // 模糊散值
  75. public float blur_amount = 1f; // 模糊插值,0:初始效果,1:完全模糊效果
  76. private int recurveNum = 1; // 当前迭代的渲染次数
  77. public int recurveMaxNum = 1; // 最大迭代渲染次数
  78. public int downSample = 4; // 降低采样率比率(降低采样率可以提高性能,但肯定会让效果变差)
  79. LuaFunction screenshot_callback; // 模糊截图回调
  80. #endregion
  81. #region 双面模糊相关参数
  82. const int DOWN_SAMPLE_PASS = 0; // 降采样pass
  83. const int UP_SAMPLE_PASS = 1; // 升采样pass
  84. public Shader dualBlurShader; // 双面模糊shader
  85. Material dual_blur_mat; // 双面模糊材质球
  86. RenderTextureFormat format;
  87. #endregion
  88. #endregion
  89. private RenderTexture final_renderTexture; // 最终渲染出来的画面RT缓存
  90. private RenderTexture temp_rt1;
  91. private RenderTexture temp_rt2;
  92. private bool final_rt_rendered = false; // 最终画面是否被渲染到了
  93. // 检查资源
  94. public bool GetSupported()
  95. {
  96. return CheckSupport(false);
  97. }
  98. public override bool CheckResources()
  99. {
  100. CheckSupport (false);
  101. if (!isSupported){
  102. ReportAutoDisable ();
  103. return isSupported;
  104. }
  105. // 创建对应shader的材质球
  106. fxaaMaterial = CheckShaderAndCreateMaterial (FXAAShader, fxaaMaterial); // FXAA效果
  107. fastBloomMaterial = CheckShaderAndCreateMaterial (fastBloomShader, fastBloomMaterial); // Bloom效果(高斯模糊)
  108. dualBloomMaterial = CheckShaderAndCreateMaterial (dualBloomShader, dualBloomMaterial); // Bloom效果(双重模糊)
  109. blurMaterial = CheckShaderAndCreateMaterial (blurShader, blurMaterial); // 高斯模糊效果
  110. dual_blur_mat = CheckShaderAndCreateMaterial (dualBlurShader, dual_blur_mat); // 双面模糊效果
  111. return isSupported;
  112. }
  113. // 非迭代的material参数修改,统一做成接口调用以一次性修改,而不要在渲染逻辑内重复执行
  114. // FXAA属性值应用
  115. public void ApplyFXAAMaterialProperties()
  116. {
  117. if (fxaaMaterial != null)
  118. {
  119. fxaaMaterial.SetFloat("_ContrastThreshold", contrastThreshold);
  120. fxaaMaterial.SetFloat("_RelativeThreshold", relativeThreshold);
  121. fxaaMaterial.SetFloat("_SubpixelBlending", subpixelBlending);
  122. if (lowQuality) {
  123. fxaaMaterial.EnableKeyword("LOW_QUALITY");
  124. }
  125. else {
  126. fxaaMaterial.DisableKeyword("LOW_QUALITY");
  127. }
  128. }
  129. }
  130. // Bloom泛光属性值应用
  131. public void ApplyBloomMaterialProperties()
  132. {
  133. bloomDowmSample = resolution == Resolution.Low ? 4 : 2;
  134. bloomBlurAmount = resolution == Resolution.Low ? 0.5f : 1.0f;
  135. passOffset = blurType == BlurType.Standard ? 0 : 2;
  136. // 双面模糊的参数直接设置
  137. if (dualBloomMaterial)
  138. {
  139. dualBloomMaterial.SetFloat("_Threshold", threshold);
  140. dualBloomMaterial.SetFloat("_Intensity", intensity);
  141. }
  142. }
  143. // 高斯/双面模糊属性值应用
  144. public void ApplyBlurMaterialProperties()
  145. {
  146. }
  147. // 根据当前的项目渲染顺序,预设的渲染顺序分别是 Bloom泛光效果 -> FXAA抗锯齿效果 -> 模糊效果(采集模糊背景用,很少用于即时渲染)
  148. // 将所有的效果整合成OnRenderImage中处理,不拆分,尽可能减少Graphics.Blit次数
  149. void OnRenderImage(RenderTexture src, RenderTexture dest)
  150. {
  151. if (isSupported) // 支持后处理
  152. {
  153. final_rt_rendered = false;
  154. final_renderTexture = RenderTexture.GetTemporary(src.width, src.height, 0, src.format);
  155. format = src.format;
  156. // 1.处理Bloom泛光效果
  157. if (EnableBloom && fastBloomMaterial != null && dualBloomMaterial != null)
  158. {
  159. // 使用双面模糊算法来处理模糊部分
  160. if(use_dual_bloom)
  161. {
  162. int width = src.width;
  163. int height = src.height;
  164. // 根据亮度阈值获取亮度图
  165. temp_rt1 = RenderTexture.GetTemporary(width / bloomDowmSample, height / bloomDowmSample, 0, format);
  166. temp_rt2 = RenderTexture.GetTemporary(width / bloomDowmSample, height / bloomDowmSample, 0, format);
  167. Graphics.Blit(src, temp_rt1, dualBloomMaterial, DUAL_BLOOM_LUMINACE_PASS);
  168. for(int i = 0; i < blurIterations; i++)
  169. {
  170. dualBloomMaterial.SetFloat("_Offset", (1.0f + i * blurSize) * bloomBlurAmount); // 设置模糊扩散uv偏移
  171. // 降采样渲染
  172. Graphics.Blit(temp_rt1, temp_rt2, dualBloomMaterial, DUAL_BLOOM_DOWNSAMPLE_PASS);
  173. // 升采样渲染
  174. Graphics.Blit(temp_rt2, temp_rt1, dualBloomMaterial, DUAL_BLOOM_UPSAMPLE_PASS);
  175. }
  176. dualBloomMaterial.SetTexture("_Bloom", temp_rt1);
  177. }
  178. // 使用高斯模糊算法处理模糊部分
  179. else
  180. {
  181. fastBloomMaterial.SetVector("_Parameter", new Vector4 (blurSize * bloomBlurAmount, 0.0f, threshold, intensity));
  182. // src.filterMode = FilterMode.Bilinear;
  183. int rtW = src.width / bloomDowmSample;
  184. int rtH = src.height / bloomDowmSample;
  185. // downsample
  186. temp_rt1 = RenderTexture.GetTemporary(rtW, rtH, 0, format);
  187. temp_rt2 = RenderTexture.GetTemporary(rtW, rtH, 0, format);
  188. // temp_rt1.filterMode = FilterMode.Bilinear;
  189. // temp_rt2.filterMode = FilterMode.Bilinear;
  190. Graphics.Blit(src, temp_rt1, fastBloomMaterial, 1);
  191. for(int i = 0; i < blurIterations; i++)
  192. {
  193. fastBloomMaterial.SetVector("_Parameter", new Vector4 (blurSize * bloomBlurAmount + (i*1.0f), 0.0f, threshold, intensity));
  194. // vertical blur
  195. Graphics.Blit(temp_rt1, temp_rt2, fastBloomMaterial, 2 + passOffset);
  196. Graphics.Blit(temp_rt2, temp_rt1, fastBloomMaterial, 3 + passOffset);
  197. }
  198. fastBloomMaterial.SetTexture("_Bloom", temp_rt1);
  199. }
  200. ReleaseTemporary(temp_rt2);
  201. // 这边就判断是否使用FXAA
  202. if (EnableFXAA && fxaaMaterial != null)
  203. {
  204. temp_rt2 = RenderTexture.GetTemporary(src.width, src.height, 0, format);
  205. if(use_dual_bloom) // 使用双面模糊算法来处理合并部分
  206. {
  207. Graphics.Blit(src, temp_rt2, dualBloomMaterial, DUAL_BLOOM_RENDER_PASS);
  208. }
  209. else
  210. {
  211. Graphics.Blit(src, temp_rt2, fastBloomMaterial, 0);
  212. }
  213. Graphics.Blit(temp_rt2, final_renderTexture, fxaaMaterial, fxaaPass);
  214. ReleaseTemporary(temp_rt2);
  215. }
  216. else
  217. {
  218. if(use_dual_bloom) // 使用双面模糊算法来处理合并部分
  219. {
  220. Graphics.Blit(src, final_renderTexture, dualBloomMaterial, DUAL_BLOOM_RENDER_PASS);
  221. }
  222. else
  223. {
  224. Graphics.Blit(src, final_renderTexture, fastBloomMaterial, 0);
  225. }
  226. }
  227. final_rt_rendered = true;
  228. //source.filterMode = FilterMode.Point;
  229. ReleaseTemporary(temp_rt1);
  230. }
  231. else
  232. {
  233. // 当不适用Bloom的情况,处理FXAA抗锯齿效果
  234. if (EnableFXAA && fxaaMaterial != null)
  235. {
  236. Graphics.Blit(src, final_renderTexture, fxaaMaterial, fxaaPass);
  237. final_rt_rendered = true;
  238. }
  239. }
  240. // 3.处理模糊需求
  241. if (EnableBlur && blurMaterial != null && dual_blur_mat != null && (render_blur_effect || get_screen_shot))
  242. {
  243. // 使用双面模糊算法
  244. if(use_dual_blur){
  245. int width = src.width;
  246. int height = src.height;
  247. recurveNum = 1; // 初始化迭代
  248. // RT初始化
  249. temp_rt1 = RenderTexture.GetTemporary(width / downSample, height / downSample, 0, format);
  250. if(get_screen_shot && !render_blur_effect) // 当只是渲染截图,就使用临时rt2
  251. temp_rt2 = RenderTexture.GetTemporary(width / downSample, height / downSample, 0, format);
  252. while(recurveNum <= recurveMaxNum)
  253. {
  254. dual_blur_mat.SetFloat("_Offset", (1.0f + recurveNum * blurSpread) * blur_amount); // 设置模糊扩散uv偏移
  255. if (get_screen_shot && !render_blur_effect) // 只渲染截屏
  256. {
  257. // 降采样渲染
  258. if(recurveNum == 1 && !final_rt_rendered) // 当首次降采样且最终RT没有处理过,就使用源RT
  259. Graphics.Blit(src, temp_rt1, dual_blur_mat, DOWN_SAMPLE_PASS);
  260. else
  261. Graphics.Blit(temp_rt2, temp_rt1, dual_blur_mat, DOWN_SAMPLE_PASS);
  262. // 升采样渲染
  263. // 使用temp_rt2,不要影响最终画面
  264. Graphics.Blit(temp_rt1, temp_rt2, dual_blur_mat, UP_SAMPLE_PASS);
  265. }
  266. else // 需要实时模糊
  267. {
  268. // 降采样渲染
  269. if(recurveNum == 1 && !final_rt_rendered) // 当首次降采样且最终RT没有处理过,就使用源RT
  270. Graphics.Blit(src, temp_rt1, dual_blur_mat, DOWN_SAMPLE_PASS);
  271. else
  272. Graphics.Blit(final_renderTexture, temp_rt1, dual_blur_mat, DOWN_SAMPLE_PASS);
  273. // 升采样渲染,输出模糊的final_renderTexture
  274. Graphics.Blit(temp_rt1, final_renderTexture, dual_blur_mat, UP_SAMPLE_PASS);
  275. }
  276. recurveNum ++;
  277. }
  278. RenderTexture.ReleaseTemporary(temp_rt1); // 释放临时RT
  279. // 仅当使用持续模糊渲染才会置为true,否则由之前的效果来决定
  280. final_rt_rendered = final_rt_rendered || render_blur_effect;
  281. }
  282. else
  283. {
  284. recurveNum = 1;
  285. //缩小要模糊的图片,减少处理压力
  286. int width = src.width / downSample;
  287. int height = src.height / downSample;
  288. // 由于高斯模糊需要将最终纹理降采样,所以这边做一个标志量
  289. // 如果经过了上面的处理后还需要高斯模糊处理,则需要在迭代渲染过程中进行一次降采样缓存
  290. bool need_redownSample = true;
  291. if(get_screen_shot && !render_blur_effect) // 当只是渲染截图,就使用临时rt2
  292. {
  293. temp_rt2 = RenderTexture.GetTemporary(width, height, 0, format);
  294. Graphics.Blit(src, temp_rt2);
  295. need_redownSample = false;
  296. }
  297. else
  298. {
  299. if(!final_rt_rendered)
  300. {
  301. // 这边如果原RT未采样也要释放缓存,不然直接获取缓存会存在泄露问题
  302. ReleaseTemporary(final_renderTexture);
  303. final_renderTexture = RenderTexture.GetTemporary(width, height, 0);
  304. // final_renderTexture.filterMode = FilterMode.Bilinear;
  305. Graphics.Blit(src, final_renderTexture);
  306. need_redownSample = false;
  307. }
  308. }
  309. temp_rt1 = RenderTexture.GetTemporary(width, height, 0);
  310. while(recurveNum <= recurveMaxNum){
  311. recurveNum ++;
  312. blurMaterial.SetFloat("_BlurSize", (1.0f + recurveNum * blurSpread) * blur_amount);
  313. if(get_screen_shot && !render_blur_effect)
  314. {
  315. Graphics.Blit(temp_rt2, temp_rt1, blurMaterial, BLUR_PASS_HOR);
  316. if(need_redownSample)
  317. {
  318. temp_rt2 = RenderTexture.GetTemporary(width, height, 0, format);
  319. need_redownSample = false;
  320. }
  321. Graphics.Blit(temp_rt1, temp_rt2, blurMaterial, BLUR_PASS_VER);
  322. }
  323. else
  324. {
  325. Graphics.Blit(final_renderTexture, temp_rt1, blurMaterial, BLUR_PASS_HOR);
  326. if(need_redownSample)
  327. {
  328. ReleaseTemporary(final_renderTexture);
  329. final_renderTexture = RenderTexture.GetTemporary(width, height, 0);
  330. need_redownSample = false;
  331. }
  332. Graphics.Blit(temp_rt1, final_renderTexture, blurMaterial, BLUR_PASS_VER);
  333. }
  334. }
  335. RenderTexture.ReleaseTemporary(temp_rt1);
  336. // 仅当使用持续模糊渲染才会置为true,否则由之前的效果来决定
  337. final_rt_rendered = final_rt_rendered || render_blur_effect;
  338. }
  339. }
  340. if(get_screen_shot && !render_blur_effect){
  341. GetBlurScreenShot();
  342. get_screen_shot = false; // 截图生成之后就停止运作
  343. }
  344. if(final_rt_rendered)
  345. {
  346. Graphics.Blit(final_renderTexture, dest);
  347. }
  348. else
  349. {
  350. Graphics.Blit(src, dest);
  351. }
  352. RenderTexture.ReleaseTemporary(final_renderTexture);
  353. }
  354. else
  355. {
  356. Graphics.Blit(src, dest); // 不支持后处理,则直接输出最终画面
  357. }
  358. }
  359. // 设置开始处理模糊效果的截图
  360. public void RenderBlurScreenShot(float blur_amount, int downSample, LuaFunction func)
  361. {
  362. get_screen_shot = true;
  363. this.blur_amount = blur_amount;
  364. this.downSample = downSample;
  365. screenshot_callback = func;
  366. }
  367. void GetBlurScreenShot()
  368. {
  369. // RenderTexture temp_screen_shot = RenderTexture.GetTemporary(final_renderTexture.width, final_renderTexture.height, 0);
  370. // Graphics.Blit(final_renderTexture, temp_screen_shot);
  371. RenderTexture temp_screen_shot = RenderTexture.GetTemporary(temp_rt2.width, temp_rt2.height, 0);
  372. Graphics.Blit(temp_rt2, temp_screen_shot);
  373. if (screenshot_callback != null)
  374. {
  375. List<UnityEngine.Object> list = new List<UnityEngine.Object>();
  376. list.Add(temp_screen_shot);
  377. object[] args = new object[] { list.ToArray() };
  378. screenshot_callback.Call(args);
  379. screenshot_callback.Dispose();
  380. screenshot_callback = null;
  381. }
  382. // 释放掉临时RT2
  383. ReleaseTemporary(temp_rt2);
  384. }
  385. // 销毁渲染纹理缓存
  386. public void ReleaseRenderTexCache()
  387. {
  388. if (!render_blur_effect) {
  389. ReleaseTemporary(final_renderTexture);
  390. }
  391. }
  392. void ReleaseTemporary(RenderTexture rt)
  393. {
  394. if (rt != null)
  395. {
  396. RenderTexture.ReleaseTemporary(rt);
  397. }
  398. }
  399. void OnDisable()
  400. {
  401. // // 销毁已有的材质球
  402. // if (fastBloomMaterial)
  403. // DestroyImmediate (fastBloomMaterial);
  404. // if (dualBloomMaterial)
  405. // DestroyImmediate (dualBloomMaterial);
  406. // if (fxaaMaterial)
  407. // DestroyImmediate (fxaaMaterial);
  408. // if (blurMaterial)
  409. // DestroyImmediate (blurMaterial);
  410. // if (dual_blur_mat)
  411. // DestroyImmediate (dual_blur_mat);
  412. // ReleaseTemporary(final_renderTexture);
  413. // ReleaseTemporary(temp_rt1);
  414. // ReleaseTemporary(temp_rt2);
  415. }
  416. }