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