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

153 lines
6.3 KiB

  1. /// author:Saber
  2. /// desc:角色相机泛光效果脚本
  3. /// 2020年2月21日优化:参考了catlikecoding的模糊思路优化逻辑提升效果,模糊rt使用局部摄像机获取到的画面进行处理
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. [ExecuteInEditMode]
  8. [RequireComponent(typeof(Camera))]
  9. public class RoleCameraBloom : MonoBehaviour
  10. {
  11. public RenderTexture cullRenderTexture; // 用来接收泛光相机的裁剪RT
  12. private ChangeShaderRender scr_script; // 泛光摄像机上的渲染脚本
  13. #region 泛光特效相关参数
  14. //模糊散值
  15. public Material bloomMaterial; // 泛光特效相关材质
  16. public bool render_bloom_effect = false; // 泛光特效关键参数,设置为true时会开始渲染泛光特效
  17. #endregion
  18. private bool isSupported; // 设备支持变量
  19. // 模糊摄像机获取到的画面依然需要做阈值处理,不过初始默认值为0
  20. [Range(0, 10)]
  21. public float threshold = 1;
  22. // 避免阈值附近的画面忽然点亮,这里设置一个软阈值处理阈值附近的颜色值的泛光效果
  23. [Range(0, 1)]
  24. public float softThreshold = 0.5f;
  25. [Range(0, 10)]
  26. public float intensity = 1;
  27. #region 渲染pass常量
  28. const int BoxDownPrefilterPass = 0; // 对泛光部分降采样的pass
  29. const int BoxDownPass = 1; // 降序采样pass
  30. const int BoxUpPass = 2; // 升序采样pass,最大限度利用到所有的像素颜色贡献
  31. const int ApplyBloomPass = 3; // 泛光颜色叠加pass
  32. const int DebugBloomPass = 4; // 测试pass,不叠加原颜色,只渲染泛光处理的效果
  33. #endregion
  34. [Range(1, 8)]
  35. public int iterations = 4; // 泛光迭代次数
  36. RenderTexture[] textures = new RenderTexture[8]; // 临时纹理链表
  37. RenderTexture currentDestination;
  38. RenderTexture currentSource;
  39. Vector4 filter; // 膝盖曲线过滤值
  40. public bool debug = false;
  41. // Start is called before the first frame update
  42. void Start()
  43. {
  44. // 检查平台支持,不支持则直接禁用
  45. isSupported = CheckSupport();
  46. this.enabled = isSupported;
  47. if(scr_script != null){
  48. scr_script.enabled = isSupported;
  49. }
  50. // 测试逻辑
  51. // TestLogic();
  52. }
  53. #region 测试逻辑
  54. private void TestLogic()
  55. {
  56. RenderTexture temp_render = new RenderTexture(1280, 600, 0);
  57. GameObject child = this.transform.GetChild(0).gameObject;
  58. Camera temp_camera = child.GetComponent<Camera>();
  59. child.AddComponent<ChangeShaderRender>();
  60. ChangeShaderRender temp_scr = child.GetComponent<ChangeShaderRender>();
  61. Shader shader = Shader.Find("SaberShader/BloomClipShader");
  62. temp_scr.target_shader = shader;
  63. SetBloomCameraData(temp_camera, temp_render, temp_scr);
  64. }
  65. #endregion
  66. private bool CheckSupport()
  67. {
  68. if (SystemInfo.supportsImageEffects == false)
  69. {
  70. Debug.LogWarning("当前平台不支持!");
  71. return false;
  72. }
  73. return true;
  74. }
  75. // Lua接口,将泛光摄像机和泛光摄像机输出的rt交给本类来控制
  76. public void SetBloomCameraData(Camera camera, RenderTexture rt, ChangeShaderRender change_shader_render){
  77. cullRenderTexture = rt;
  78. camera.targetTexture = cullRenderTexture;
  79. render_bloom_effect = true;
  80. scr_script = change_shader_render;
  81. // 效果运行与否还要看设备支不支持特效
  82. scr_script.enabled = isSupported;
  83. }
  84. // 正式渲染
  85. // 这个方法要注意在退出游戏的时候把渲染逻辑门关闭,一般情况下把render_bloom_effect置false
  86. void OnRenderImage(RenderTexture src, RenderTexture dest)
  87. {
  88. if (bloomMaterial != null && render_bloom_effect && cullRenderTexture != null)
  89. {
  90. // 膝盖曲线的值可以在这里预先算好
  91. float knee = threshold * softThreshold;
  92. filter.x = threshold;
  93. filter.y = filter.x - knee;
  94. filter.z = 2f * knee;
  95. filter.w = 0.25f / (knee + 0.00001f);
  96. bloomMaterial.SetVector("_Filter", filter);
  97. bloomMaterial.SetFloat("_Intensity", Mathf.GammaToLinearSpace(intensity));
  98. // 降低一次采样,将剧目摄像机的内容传递到临时的最终画面RT中
  99. int width = src.width / 4;
  100. int height = src.height / 4;
  101. currentDestination = textures[0] = RenderTexture.GetTemporary(width, height, 0, src.format);
  102. Graphics.Blit(cullRenderTexture, currentDestination, bloomMaterial, BoxDownPrefilterPass);
  103. currentSource = currentDestination;
  104. // 循环降采样,并将结果保存
  105. int i = 1;
  106. for (; i < iterations; i++) {
  107. width /= 2;
  108. height /= 2;
  109. if (height < 2) {
  110. break;
  111. }
  112. currentDestination = textures[i] =
  113. RenderTexture.GetTemporary(width, height, 0, src.format);
  114. Graphics.Blit(currentSource, currentDestination, bloomMaterial, BoxDownPass);
  115. currentSource = currentDestination;
  116. }
  117. // 再对降采样后的画面继续宁升采样,将每个像素的颜色平均出去
  118. for (i -= 2; i >= 0; i--) {
  119. currentDestination = textures[i];
  120. textures[i] = null;
  121. Graphics.Blit(currentSource, currentDestination, bloomMaterial, BoxUpPass);
  122. RenderTexture.ReleaseTemporary(currentSource);
  123. currentSource = currentDestination;
  124. }
  125. if (debug) {
  126. Graphics.Blit(currentSource, dest, bloomMaterial, DebugBloomPass);
  127. }
  128. else {
  129. bloomMaterial.SetTexture("_SourceTex", src);
  130. Graphics.Blit(currentSource, dest, bloomMaterial, ApplyBloomPass);
  131. }
  132. RenderTexture.ReleaseTemporary(currentSource);
  133. }
  134. else
  135. {
  136. Graphics.Blit(src, dest);
  137. }
  138. }
  139. public void ReleaseTempRes()
  140. {
  141. render_bloom_effect = false;
  142. if(scr_script != null)
  143. {
  144. scr_script.enabled = false;
  145. }
  146. }
  147. void OnDestroy(){
  148. ReleaseTempRes();
  149. }
  150. }