Bloom.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. using System;
  2. using UnityEngine;
  3. namespace UnityStandardAssets.ImageEffects
  4. {
  5. [ExecuteInEditMode]
  6. [RequireComponent (typeof(Camera))]
  7. [AddComponentMenu ("Image Effects/Bloom and Glow/Bloom")]
  8. public class Bloom : PostEffectsBase
  9. {
  10. public enum LensFlareStyle
  11. {
  12. Ghosting = 0,
  13. Anamorphic = 1,
  14. Combined = 2,
  15. }
  16. public enum TweakMode
  17. {
  18. Basic = 0,
  19. Complex = 1,
  20. }
  21. public enum HDRBloomMode
  22. {
  23. Auto = 0,
  24. On = 1,
  25. Off = 2,
  26. }
  27. public enum BloomScreenBlendMode
  28. {
  29. Screen = 0,
  30. Add = 1,
  31. }
  32. public enum BloomQuality
  33. {
  34. Cheap = 0,
  35. High = 1,
  36. }
  37. public TweakMode tweakMode = 0;
  38. public BloomScreenBlendMode screenBlendMode = BloomScreenBlendMode.Add;
  39. public HDRBloomMode hdr = HDRBloomMode.Auto;
  40. private bool doHdr = false;
  41. public float sepBlurSpread = 2.5f;
  42. public BloomQuality quality = BloomQuality.High;
  43. public float bloomIntensity = 0.5f;
  44. public float bloomThreshold = 0.5f;
  45. public Color bloomThresholdColor = Color.white;
  46. public int bloomBlurIterations = 2;
  47. public int hollywoodFlareBlurIterations = 2;
  48. public float flareRotation = 0.0f;
  49. public LensFlareStyle lensflareMode = (LensFlareStyle) 1;
  50. public float hollyStretchWidth = 2.5f;
  51. public float lensflareIntensity = 0.0f;
  52. public float lensflareThreshold = 0.3f;
  53. public float lensFlareSaturation = 0.75f;
  54. public Color flareColorA = new Color (0.4f, 0.4f, 0.8f, 0.75f);
  55. public Color flareColorB = new Color (0.4f, 0.8f, 0.8f, 0.75f);
  56. public Color flareColorC = new Color (0.8f, 0.4f, 0.8f, 0.75f);
  57. public Color flareColorD = new Color (0.8f, 0.4f, 0.0f, 0.75f);
  58. public Texture2D lensFlareVignetteMask;
  59. public Shader lensFlareShader;
  60. private Material lensFlareMaterial;
  61. public Shader screenBlendShader;
  62. private Material screenBlend;
  63. public Shader blurAndFlaresShader;
  64. private Material blurAndFlaresMaterial;
  65. public Shader brightPassFilterShader;
  66. private Material brightPassFilterMaterial;
  67. public override bool CheckResources ()
  68. {
  69. CheckSupport (false);
  70. screenBlend = CheckShaderAndCreateMaterial (screenBlendShader, screenBlend);
  71. lensFlareMaterial = CheckShaderAndCreateMaterial(lensFlareShader,lensFlareMaterial);
  72. blurAndFlaresMaterial = CheckShaderAndCreateMaterial (blurAndFlaresShader, blurAndFlaresMaterial);
  73. brightPassFilterMaterial = CheckShaderAndCreateMaterial(brightPassFilterShader, brightPassFilterMaterial);
  74. if (!isSupported)
  75. ReportAutoDisable ();
  76. return isSupported;
  77. }
  78. public void OnRenderImage (RenderTexture source, RenderTexture destination)
  79. {
  80. if (CheckResources()==false)
  81. {
  82. Graphics.Blit (source, destination);
  83. return;
  84. }
  85. // screen blend is not supported when HDR is enabled (will cap values)
  86. doHdr = false;
  87. if (hdr == HDRBloomMode.Auto)
  88. doHdr = source.format == RenderTextureFormat.ARGBHalf && GetComponent<Camera>().allowHDR;
  89. else {
  90. doHdr = hdr == HDRBloomMode.On;
  91. }
  92. doHdr = doHdr && supportHDRTextures;
  93. BloomScreenBlendMode realBlendMode = screenBlendMode;
  94. if (doHdr)
  95. realBlendMode = BloomScreenBlendMode.Add;
  96. var rtFormat= (doHdr) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.Default;
  97. var rtW2= source.width/2;
  98. var rtH2= source.height/2;
  99. var rtW4= source.width/4;
  100. var rtH4= source.height/4;
  101. float widthOverHeight = (1.0f * source.width) / (1.0f * source.height);
  102. float oneOverBaseSize = 1.0f / 512.0f;
  103. // downsample
  104. RenderTexture quarterRezColor = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat);
  105. RenderTexture halfRezColorDown = RenderTexture.GetTemporary (rtW2, rtH2, 0, rtFormat);
  106. if (quality > BloomQuality.Cheap) {
  107. Graphics.Blit (source, halfRezColorDown, screenBlend, 2);
  108. RenderTexture rtDown4 = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat);
  109. Graphics.Blit (halfRezColorDown, rtDown4, screenBlend, 2);
  110. Graphics.Blit (rtDown4, quarterRezColor, screenBlend, 6);
  111. RenderTexture.ReleaseTemporary(rtDown4);
  112. }
  113. else {
  114. Graphics.Blit (source, halfRezColorDown);
  115. Graphics.Blit (halfRezColorDown, quarterRezColor, screenBlend, 6);
  116. }
  117. RenderTexture.ReleaseTemporary (halfRezColorDown);
  118. // cut colors (thresholding)
  119. RenderTexture secondQuarterRezColor = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat);
  120. BrightFilter (bloomThreshold * bloomThresholdColor, quarterRezColor, secondQuarterRezColor);
  121. // blurring
  122. if (bloomBlurIterations < 1) bloomBlurIterations = 1;
  123. else if (bloomBlurIterations > 10) bloomBlurIterations = 10;
  124. for (int iter = 0; iter < bloomBlurIterations; iter++)
  125. {
  126. float spreadForPass = (1.0f + (iter * 0.25f)) * sepBlurSpread;
  127. // vertical blur
  128. RenderTexture blur4 = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat);
  129. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (0.0f, spreadForPass * oneOverBaseSize, 0.0f, 0.0f));
  130. Graphics.Blit (secondQuarterRezColor, blur4, blurAndFlaresMaterial, 4);
  131. RenderTexture.ReleaseTemporary(secondQuarterRezColor);
  132. secondQuarterRezColor = blur4;
  133. // horizontal blur
  134. blur4 = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat);
  135. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 ((spreadForPass / widthOverHeight) * oneOverBaseSize, 0.0f, 0.0f, 0.0f));
  136. Graphics.Blit (secondQuarterRezColor, blur4, blurAndFlaresMaterial, 4);
  137. RenderTexture.ReleaseTemporary (secondQuarterRezColor);
  138. secondQuarterRezColor = blur4;
  139. if (quality > BloomQuality.Cheap)
  140. {
  141. if (iter == 0)
  142. {
  143. Graphics.SetRenderTarget(quarterRezColor);
  144. GL.Clear(false, true, Color.black); // Clear to avoid RT restore
  145. Graphics.Blit (secondQuarterRezColor, quarterRezColor);
  146. }
  147. else
  148. {
  149. Graphics.Blit (secondQuarterRezColor, quarterRezColor, screenBlend, 10);
  150. }
  151. }
  152. }
  153. if (quality > BloomQuality.Cheap)
  154. {
  155. Graphics.SetRenderTarget(secondQuarterRezColor);
  156. GL.Clear(false, true, Color.black); // Clear to avoid RT restore
  157. Graphics.Blit (quarterRezColor, secondQuarterRezColor, screenBlend, 6);
  158. }
  159. // lens flares: ghosting, anamorphic or both (ghosted anamorphic flares)
  160. if (lensflareIntensity > Mathf.Epsilon)
  161. {
  162. RenderTexture rtFlares4 = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat);
  163. if (lensflareMode == 0)
  164. {
  165. // ghosting only
  166. BrightFilter (lensflareThreshold, secondQuarterRezColor, rtFlares4);
  167. if (quality > BloomQuality.Cheap)
  168. {
  169. // smooth a little
  170. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (0.0f, (1.5f) / (1.0f * quarterRezColor.height), 0.0f, 0.0f));
  171. Graphics.SetRenderTarget(quarterRezColor);
  172. GL.Clear(false, true, Color.black); // Clear to avoid RT restore
  173. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 4);
  174. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 ((1.5f) / (1.0f * quarterRezColor.width), 0.0f, 0.0f, 0.0f));
  175. Graphics.SetRenderTarget(rtFlares4);
  176. GL.Clear(false, true, Color.black); // Clear to avoid RT restore
  177. Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 4);
  178. }
  179. // no ugly edges!
  180. Vignette (0.975f, rtFlares4, rtFlares4);
  181. BlendFlares (rtFlares4, secondQuarterRezColor);
  182. }
  183. else
  184. {
  185. //Vignette (0.975ff, rtFlares4, rtFlares4);
  186. //DrawBorder(rtFlares4, screenBlend, 8);
  187. float flareXRot = 1.0f * Mathf.Cos(flareRotation);
  188. float flareyRot = 1.0f * Mathf.Sin(flareRotation);
  189. float stretchWidth = (hollyStretchWidth * 1.0f / widthOverHeight) * oneOverBaseSize;
  190. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (flareXRot, flareyRot, 0.0f, 0.0f));
  191. blurAndFlaresMaterial.SetVector ("_Threshhold", new Vector4 (lensflareThreshold, 1.0f, 0.0f, 0.0f));
  192. blurAndFlaresMaterial.SetVector ("_TintColor", new Vector4 (flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * flareColorA.a * lensflareIntensity);
  193. blurAndFlaresMaterial.SetFloat ("_Saturation", lensFlareSaturation);
  194. // "pre and cut"
  195. quarterRezColor.DiscardContents();
  196. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 2);
  197. // "post"
  198. rtFlares4.DiscardContents();
  199. Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 3);
  200. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (flareXRot * stretchWidth, flareyRot * stretchWidth, 0.0f, 0.0f));
  201. // stretch 1st
  202. blurAndFlaresMaterial.SetFloat ("_StretchWidth", hollyStretchWidth);
  203. quarterRezColor.DiscardContents();
  204. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 1);
  205. // stretch 2nd
  206. blurAndFlaresMaterial.SetFloat ("_StretchWidth", hollyStretchWidth * 2.0f);
  207. rtFlares4.DiscardContents();
  208. Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 1);
  209. // stretch 3rd
  210. blurAndFlaresMaterial.SetFloat ("_StretchWidth", hollyStretchWidth * 4.0f);
  211. quarterRezColor.DiscardContents();
  212. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 1);
  213. // additional blur passes
  214. for (int iter = 0; iter < hollywoodFlareBlurIterations; iter++)
  215. {
  216. stretchWidth = (hollyStretchWidth * 2.0f / widthOverHeight) * oneOverBaseSize;
  217. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (stretchWidth * flareXRot, stretchWidth * flareyRot, 0.0f, 0.0f));
  218. rtFlares4.DiscardContents();
  219. Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 4);
  220. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (stretchWidth * flareXRot, stretchWidth * flareyRot, 0.0f, 0.0f));
  221. quarterRezColor.DiscardContents();
  222. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 4);
  223. }
  224. if (lensflareMode == (LensFlareStyle) 1)
  225. // anamorphic lens flares
  226. AddTo (1.0f, quarterRezColor, secondQuarterRezColor);
  227. else
  228. {
  229. // "combined" lens flares
  230. Vignette (1.0f, quarterRezColor, rtFlares4);
  231. BlendFlares (rtFlares4, quarterRezColor);
  232. AddTo (1.0f, quarterRezColor, secondQuarterRezColor);
  233. }
  234. }
  235. RenderTexture.ReleaseTemporary (rtFlares4);
  236. }
  237. int blendPass = (int) realBlendMode;
  238. //if (Mathf.Abs(chromaticBloom) < Mathf.Epsilon)
  239. // blendPass += 4;
  240. screenBlend.SetFloat ("_Intensity", bloomIntensity);
  241. screenBlend.SetTexture ("_ColorBuffer", source);
  242. if (quality > BloomQuality.Cheap)
  243. {
  244. RenderTexture halfRezColorUp = RenderTexture.GetTemporary (rtW2, rtH2, 0, rtFormat);
  245. Graphics.Blit (secondQuarterRezColor, halfRezColorUp);
  246. Graphics.Blit (halfRezColorUp, destination, screenBlend, blendPass);
  247. RenderTexture.ReleaseTemporary (halfRezColorUp);
  248. }
  249. else
  250. Graphics.Blit (secondQuarterRezColor, destination, screenBlend, blendPass);
  251. RenderTexture.ReleaseTemporary (quarterRezColor);
  252. RenderTexture.ReleaseTemporary (secondQuarterRezColor);
  253. }
  254. private void AddTo (float intensity_, RenderTexture from, RenderTexture to)
  255. {
  256. screenBlend.SetFloat ("_Intensity", intensity_);
  257. Graphics.Blit (from, to, screenBlend, 9);
  258. }
  259. private void BlendFlares (RenderTexture from, RenderTexture to)
  260. {
  261. lensFlareMaterial.SetVector ("colorA", new Vector4 (flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * lensflareIntensity);
  262. lensFlareMaterial.SetVector ("colorB", new Vector4 (flareColorB.r, flareColorB.g, flareColorB.b, flareColorB.a) * lensflareIntensity);
  263. lensFlareMaterial.SetVector ("colorC", new Vector4 (flareColorC.r, flareColorC.g, flareColorC.b, flareColorC.a) * lensflareIntensity);
  264. lensFlareMaterial.SetVector ("colorD", new Vector4 (flareColorD.r, flareColorD.g, flareColorD.b, flareColorD.a) * lensflareIntensity);
  265. Graphics.Blit (from, to, lensFlareMaterial);
  266. }
  267. private void BrightFilter (float thresh, RenderTexture from, RenderTexture to)
  268. {
  269. brightPassFilterMaterial.SetVector ("_Threshhold", new Vector4 (thresh, thresh, thresh, thresh));
  270. Graphics.Blit (from, to, brightPassFilterMaterial, 0);
  271. }
  272. private void BrightFilter (Color threshColor, RenderTexture from, RenderTexture to)
  273. {
  274. brightPassFilterMaterial.SetVector ("_Threshhold", threshColor);
  275. Graphics.Blit (from, to, brightPassFilterMaterial, 1);
  276. }
  277. private void Vignette (float amount, RenderTexture from, RenderTexture to)
  278. {
  279. if (lensFlareVignetteMask)
  280. {
  281. screenBlend.SetTexture ("_ColorBuffer", lensFlareVignetteMask);
  282. Graphics.Blit (from == to ? null : from, to, screenBlend, from == to ? 7 : 3);
  283. }
  284. else if (from != to)
  285. {
  286. Graphics.SetRenderTarget (to);
  287. GL.Clear(false, true, Color.black); // clear destination to avoid RT restore
  288. Graphics.Blit (from, to);
  289. }
  290. }
  291. }
  292. }