Bloom.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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. quarterRezColor.MarkRestoreExpected(); // using max blending, RT restore expected
  150. Graphics.Blit (secondQuarterRezColor, quarterRezColor, screenBlend, 10);
  151. }
  152. }
  153. }
  154. if (quality > BloomQuality.Cheap)
  155. {
  156. Graphics.SetRenderTarget(secondQuarterRezColor);
  157. GL.Clear(false, true, Color.black); // Clear to avoid RT restore
  158. Graphics.Blit (quarterRezColor, secondQuarterRezColor, screenBlend, 6);
  159. }
  160. // lens flares: ghosting, anamorphic or both (ghosted anamorphic flares)
  161. if (lensflareIntensity > Mathf.Epsilon)
  162. {
  163. RenderTexture rtFlares4 = RenderTexture.GetTemporary (rtW4, rtH4, 0, rtFormat);
  164. if (lensflareMode == 0)
  165. {
  166. // ghosting only
  167. BrightFilter (lensflareThreshold, secondQuarterRezColor, rtFlares4);
  168. if (quality > BloomQuality.Cheap)
  169. {
  170. // smooth a little
  171. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (0.0f, (1.5f) / (1.0f * quarterRezColor.height), 0.0f, 0.0f));
  172. Graphics.SetRenderTarget(quarterRezColor);
  173. GL.Clear(false, true, Color.black); // Clear to avoid RT restore
  174. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 4);
  175. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 ((1.5f) / (1.0f * quarterRezColor.width), 0.0f, 0.0f, 0.0f));
  176. Graphics.SetRenderTarget(rtFlares4);
  177. GL.Clear(false, true, Color.black); // Clear to avoid RT restore
  178. Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 4);
  179. }
  180. // no ugly edges!
  181. Vignette (0.975f, rtFlares4, rtFlares4);
  182. BlendFlares (rtFlares4, secondQuarterRezColor);
  183. }
  184. else
  185. {
  186. //Vignette (0.975ff, rtFlares4, rtFlares4);
  187. //DrawBorder(rtFlares4, screenBlend, 8);
  188. float flareXRot = 1.0f * Mathf.Cos(flareRotation);
  189. float flareyRot = 1.0f * Mathf.Sin(flareRotation);
  190. float stretchWidth = (hollyStretchWidth * 1.0f / widthOverHeight) * oneOverBaseSize;
  191. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (flareXRot, flareyRot, 0.0f, 0.0f));
  192. blurAndFlaresMaterial.SetVector ("_Threshhold", new Vector4 (lensflareThreshold, 1.0f, 0.0f, 0.0f));
  193. blurAndFlaresMaterial.SetVector ("_TintColor", new Vector4 (flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * flareColorA.a * lensflareIntensity);
  194. blurAndFlaresMaterial.SetFloat ("_Saturation", lensFlareSaturation);
  195. // "pre and cut"
  196. quarterRezColor.DiscardContents();
  197. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 2);
  198. // "post"
  199. rtFlares4.DiscardContents();
  200. Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 3);
  201. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (flareXRot * stretchWidth, flareyRot * stretchWidth, 0.0f, 0.0f));
  202. // stretch 1st
  203. blurAndFlaresMaterial.SetFloat ("_StretchWidth", hollyStretchWidth);
  204. quarterRezColor.DiscardContents();
  205. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 1);
  206. // stretch 2nd
  207. blurAndFlaresMaterial.SetFloat ("_StretchWidth", hollyStretchWidth * 2.0f);
  208. rtFlares4.DiscardContents();
  209. Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 1);
  210. // stretch 3rd
  211. blurAndFlaresMaterial.SetFloat ("_StretchWidth", hollyStretchWidth * 4.0f);
  212. quarterRezColor.DiscardContents();
  213. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 1);
  214. // additional blur passes
  215. for (int iter = 0; iter < hollywoodFlareBlurIterations; iter++)
  216. {
  217. stretchWidth = (hollyStretchWidth * 2.0f / widthOverHeight) * oneOverBaseSize;
  218. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (stretchWidth * flareXRot, stretchWidth * flareyRot, 0.0f, 0.0f));
  219. rtFlares4.DiscardContents();
  220. Graphics.Blit (quarterRezColor, rtFlares4, blurAndFlaresMaterial, 4);
  221. blurAndFlaresMaterial.SetVector ("_Offsets", new Vector4 (stretchWidth * flareXRot, stretchWidth * flareyRot, 0.0f, 0.0f));
  222. quarterRezColor.DiscardContents();
  223. Graphics.Blit (rtFlares4, quarterRezColor, blurAndFlaresMaterial, 4);
  224. }
  225. if (lensflareMode == (LensFlareStyle) 1)
  226. // anamorphic lens flares
  227. AddTo (1.0f, quarterRezColor, secondQuarterRezColor);
  228. else
  229. {
  230. // "combined" lens flares
  231. Vignette (1.0f, quarterRezColor, rtFlares4);
  232. BlendFlares (rtFlares4, quarterRezColor);
  233. AddTo (1.0f, quarterRezColor, secondQuarterRezColor);
  234. }
  235. }
  236. RenderTexture.ReleaseTemporary (rtFlares4);
  237. }
  238. int blendPass = (int) realBlendMode;
  239. //if (Mathf.Abs(chromaticBloom) < Mathf.Epsilon)
  240. // blendPass += 4;
  241. screenBlend.SetFloat ("_Intensity", bloomIntensity);
  242. screenBlend.SetTexture ("_ColorBuffer", source);
  243. if (quality > BloomQuality.Cheap)
  244. {
  245. RenderTexture halfRezColorUp = RenderTexture.GetTemporary (rtW2, rtH2, 0, rtFormat);
  246. Graphics.Blit (secondQuarterRezColor, halfRezColorUp);
  247. Graphics.Blit (halfRezColorUp, destination, screenBlend, blendPass);
  248. RenderTexture.ReleaseTemporary (halfRezColorUp);
  249. }
  250. else
  251. Graphics.Blit (secondQuarterRezColor, destination, screenBlend, blendPass);
  252. RenderTexture.ReleaseTemporary (quarterRezColor);
  253. RenderTexture.ReleaseTemporary (secondQuarterRezColor);
  254. }
  255. private void AddTo (float intensity_, RenderTexture from, RenderTexture to)
  256. {
  257. screenBlend.SetFloat ("_Intensity", intensity_);
  258. to.MarkRestoreExpected(); // additive blending, RT restore expected
  259. Graphics.Blit (from, to, screenBlend, 9);
  260. }
  261. private void BlendFlares (RenderTexture from, RenderTexture to)
  262. {
  263. lensFlareMaterial.SetVector ("colorA", new Vector4 (flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * lensflareIntensity);
  264. lensFlareMaterial.SetVector ("colorB", new Vector4 (flareColorB.r, flareColorB.g, flareColorB.b, flareColorB.a) * lensflareIntensity);
  265. lensFlareMaterial.SetVector ("colorC", new Vector4 (flareColorC.r, flareColorC.g, flareColorC.b, flareColorC.a) * lensflareIntensity);
  266. lensFlareMaterial.SetVector ("colorD", new Vector4 (flareColorD.r, flareColorD.g, flareColorD.b, flareColorD.a) * lensflareIntensity);
  267. to.MarkRestoreExpected(); // additive blending, RT restore expected
  268. Graphics.Blit (from, to, lensFlareMaterial);
  269. }
  270. private void BrightFilter (float thresh, RenderTexture from, RenderTexture to)
  271. {
  272. brightPassFilterMaterial.SetVector ("_Threshhold", new Vector4 (thresh, thresh, thresh, thresh));
  273. Graphics.Blit (from, to, brightPassFilterMaterial, 0);
  274. }
  275. private void BrightFilter (Color threshColor, RenderTexture from, RenderTexture to)
  276. {
  277. brightPassFilterMaterial.SetVector ("_Threshhold", threshColor);
  278. Graphics.Blit (from, to, brightPassFilterMaterial, 1);
  279. }
  280. private void Vignette (float amount, RenderTexture from, RenderTexture to)
  281. {
  282. if (lensFlareVignetteMask)
  283. {
  284. screenBlend.SetTexture ("_ColorBuffer", lensFlareVignetteMask);
  285. to.MarkRestoreExpected(); // using blending, RT restore expected
  286. Graphics.Blit (from == to ? null : from, to, screenBlend, from == to ? 7 : 3);
  287. }
  288. else if (from != to)
  289. {
  290. Graphics.SetRenderTarget (to);
  291. GL.Clear(false, true, Color.black); // clear destination to avoid RT restore
  292. Graphics.Blit (from, to);
  293. }
  294. }
  295. }
  296. }