UnityMol  0.9.6-875
UnityMol viewer / In developement
DepthOfFieldDeprecated.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/Camera/Depth of Field (deprecated)") ]
10  {
11  public enum Dof34QualitySetting
12  {
13  OnlyBackground = 1,
14  BackgroundAndForeground = 2,
15  }
16 
17  public enum DofResolution
18  {
19  High = 2,
20  Medium = 3,
21  Low = 4,
22  }
23 
24  public enum DofBlurriness
25  {
26  Low = 1,
27  High = 2,
28  VeryHigh = 4,
29  }
30 
31  public enum BokehDestination
32  {
33  Background = 0x1,
34  Foreground = 0x2,
35  BackgroundAndForeground = 0x3,
36  }
37 
38  static private int SMOOTH_DOWNSAMPLE_PASS = 6;
39  static private float BOKEH_EXTRA_BLUR = 2.0f;
40 
41  public Dof34QualitySetting quality = Dof34QualitySetting.OnlyBackground;
42  public DofResolution resolution = DofResolution.Low;
43  public bool simpleTweakMode = true;
44 
45  public float focalPoint = 1.0f;
46  public float smoothness = 0.5f;
47 
48  public float focalZDistance = 0.0f;
49  public float focalZStartCurve = 1.0f;
50  public float focalZEndCurve = 1.0f;
51 
52  private float focalStartCurve = 2.0f;
53  private float focalEndCurve = 2.0f;
54  private float focalDistance01 = 0.1f;
55 
56  public Transform objectFocus = null;
57  public float focalSize = 0.0f;
58 
59  public DofBlurriness bluriness = DofBlurriness.High;
60  public float maxBlurSpread = 1.75f;
61 
62  public float foregroundBlurExtrude = 1.15f;
63 
64  public Shader dofBlurShader;
65  private Material dofBlurMaterial = null;
66 
67  public Shader dofShader;
68  private Material dofMaterial = null;
69 
70  public bool visualize = false;
71  public BokehDestination bokehDestination = BokehDestination.Background;
72 
73  private float widthOverHeight = 1.25f;
74  private float oneOverBaseSize = 1.0f / 512.0f;
75 
76  public bool bokeh = false;
77  public bool bokehSupport = true;
78  public Shader bokehShader;
79  public Texture2D bokehTexture;
80  public float bokehScale = 2.4f;
81  public float bokehIntensity = 0.15f;
82  public float bokehThresholdContrast = 0.1f;
83  public float bokehThresholdLuminance = 0.55f;
84  public int bokehDownsample = 1;
85  private Material bokehMaterial;
86 
87  private Camera _camera;
88 
89  void CreateMaterials () {
90  dofBlurMaterial = CheckShaderAndCreateMaterial (dofBlurShader, dofBlurMaterial);
91  dofMaterial = CheckShaderAndCreateMaterial (dofShader,dofMaterial);
92  bokehSupport = bokehShader.isSupported;
93 
94  if (bokeh && bokehSupport && bokehShader)
95  bokehMaterial = CheckShaderAndCreateMaterial (bokehShader, bokehMaterial);
96  }
97 
98 
99  public override bool CheckResources () {
100  CheckSupport (true);
101 
102  dofBlurMaterial = CheckShaderAndCreateMaterial (dofBlurShader, dofBlurMaterial);
103  dofMaterial = CheckShaderAndCreateMaterial (dofShader,dofMaterial);
104  bokehSupport = bokehShader.isSupported;
105 
106  if (bokeh && bokehSupport && bokehShader)
107  bokehMaterial = CheckShaderAndCreateMaterial (bokehShader, bokehMaterial);
108 
109  if (!isSupported)
110  ReportAutoDisable ();
111  return isSupported;
112  }
113 
114  void OnDisable () {
115  Quads.Cleanup ();
116  }
117 
118  void OnEnable () {
119  _camera = GetComponent<Camera>();
120  _camera.depthTextureMode |= DepthTextureMode.Depth;
121  }
122 
123  float FocalDistance01 ( float worldDist) {
124  return _camera.WorldToViewportPoint((worldDist-_camera.nearClipPlane) * _camera.transform.forward + _camera.transform.position).z / (_camera.farClipPlane-_camera.nearClipPlane);
125  }
126 
128  int divider = 1;
129  if (resolution == DofResolution.Medium)
130  divider = 2;
131  else if (resolution == DofResolution.Low)
132  divider = 2;
133  return divider;
134  }
135 
136  int GetLowResolutionDividerBasedOnQuality ( int baseDivider) {
137  int lowTexDivider = baseDivider;
138  if (resolution == DofResolution.High)
139  lowTexDivider *= 2;
140  if (resolution == DofResolution.Low)
141  lowTexDivider *= 2;
142  return lowTexDivider;
143  }
144 
145  private RenderTexture foregroundTexture = null;
146  private RenderTexture mediumRezWorkTexture = null;
147  private RenderTexture finalDefocus = null;
148  private RenderTexture lowRezWorkTexture = null;
149  private RenderTexture bokehSource = null;
150  private RenderTexture bokehSource2 = null;
151 
152  void OnRenderImage (RenderTexture source, RenderTexture destination) {
153  if (CheckResources()==false) {
154  Graphics.Blit (source, destination);
155  return;
156  }
157 
158  if (smoothness < 0.1f)
159  smoothness = 0.1f;
160 
161  // update needed focal & rt size parameter
162 
163  bokeh = bokeh && bokehSupport;
164  float bokehBlurAmplifier = bokeh ? BOKEH_EXTRA_BLUR : 1.0f;
165 
166  bool blurForeground = quality > Dof34QualitySetting.OnlyBackground;
167  float focal01Size = focalSize / (_camera.farClipPlane - _camera.nearClipPlane);;
168 
169  if (simpleTweakMode) {
170  focalDistance01 = objectFocus ? (_camera.WorldToViewportPoint (objectFocus.position)).z / (_camera.farClipPlane) : FocalDistance01 (focalPoint);
171  focalStartCurve = focalDistance01 * smoothness;
172  focalEndCurve = focalStartCurve;
173  blurForeground = blurForeground && (focalPoint > (_camera.nearClipPlane + Mathf.Epsilon));
174  }
175  else {
176  if (objectFocus) {
177  var vpPoint= _camera.WorldToViewportPoint (objectFocus.position);
178  vpPoint.z = (vpPoint.z) / (_camera.farClipPlane);
179  focalDistance01 = vpPoint.z;
180  }
181  else
182  focalDistance01 = FocalDistance01 (focalZDistance);
183 
184  focalStartCurve = focalZStartCurve;
185  focalEndCurve = focalZEndCurve;
186  blurForeground = blurForeground && (focalPoint > (_camera.nearClipPlane + Mathf.Epsilon));
187  }
188 
189  widthOverHeight = (1.0f * source.width) / (1.0f * source.height);
190  oneOverBaseSize = 1.0f / 512.0f;
191 
192  dofMaterial.SetFloat ("_ForegroundBlurExtrude", foregroundBlurExtrude);
193  dofMaterial.SetVector ("_CurveParams", new Vector4 (simpleTweakMode ? 1.0f / focalStartCurve : focalStartCurve, simpleTweakMode ? 1.0f / focalEndCurve : focalEndCurve, focal01Size * 0.5f, focalDistance01));
194  dofMaterial.SetVector ("_InvRenderTargetSize", new Vector4 (1.0f / (1.0f * source.width), 1.0f / (1.0f * source.height),0.0f,0.0f));
195 
196  int divider = GetDividerBasedOnQuality ();
197  int lowTexDivider = GetLowResolutionDividerBasedOnQuality (divider);
198 
199  AllocateTextures (blurForeground, source, divider, lowTexDivider);
200 
201  // WRITE COC to alpha channel
202  // source is only being bound to detect y texcoord flip
203  Graphics.Blit (source, source, dofMaterial, 3);
204 
205  // better DOWNSAMPLE (could actually be weighted for higher quality)
206  Downsample (source, mediumRezWorkTexture);
207 
208  // BLUR A LITTLE first, which has two purposes
209  // 1.) reduce jitter, noise, aliasing
210  // 2.) produce the little-blur buffer used in composition later
211  Blur (mediumRezWorkTexture, mediumRezWorkTexture, DofBlurriness.Low, 4, maxBlurSpread);
212 
213  if ((bokeh) && ((BokehDestination.Foreground & bokehDestination) != 0))
214  {
215  dofMaterial.SetVector ("_Threshhold", new Vector4(bokehThresholdContrast, bokehThresholdLuminance, 0.95f, 0.0f));
216 
217  // add and mark the parts that should end up as bokeh shapes
218  Graphics.Blit (mediumRezWorkTexture, bokehSource2, dofMaterial, 11);
219 
220  // remove those parts (maybe even a little tittle bittle more) from the regurlarly blurred buffer
221  //Graphics.Blit (mediumRezWorkTexture, lowRezWorkTexture, dofMaterial, 10);
222  Graphics.Blit (mediumRezWorkTexture, lowRezWorkTexture);//, dofMaterial, 10);
223 
224  // maybe you want to reblur the small blur ... but not really needed.
225  //Blur (mediumRezWorkTexture, mediumRezWorkTexture, DofBlurriness.Low, 4, maxBlurSpread);
226 
227  // bigger BLUR
228  Blur (lowRezWorkTexture, lowRezWorkTexture, bluriness, 0, maxBlurSpread * bokehBlurAmplifier);
229  }
230  else {
231  // bigger BLUR
232  Downsample (mediumRezWorkTexture, lowRezWorkTexture);
233  Blur (lowRezWorkTexture, lowRezWorkTexture, bluriness, 0, maxBlurSpread);
234  }
235 
236  dofBlurMaterial.SetTexture ("_TapLow", lowRezWorkTexture);
237  dofBlurMaterial.SetTexture ("_TapMedium", mediumRezWorkTexture);
238  Graphics.Blit (null, finalDefocus, dofBlurMaterial, 3);
239 
240  // we are only adding bokeh now if the background is the only part we have to deal with
241  if ((bokeh) && ((BokehDestination.Foreground & bokehDestination) != 0))
242  AddBokeh (bokehSource2, bokehSource, finalDefocus);
243 
244  dofMaterial.SetTexture ("_TapLowBackground", finalDefocus);
245  dofMaterial.SetTexture ("_TapMedium", mediumRezWorkTexture); // needed for debugging/visualization
246 
247  // FINAL DEFOCUS (background)
248  Graphics.Blit (source, blurForeground ? foregroundTexture : destination, dofMaterial, visualize ? 2 : 0);
249 
250  // FINAL DEFOCUS (foreground)
251  if (blurForeground) {
252  // WRITE COC to alpha channel
253  Graphics.Blit (foregroundTexture, source, dofMaterial, 5);
254 
255  // DOWNSAMPLE (unweighted)
256  Downsample (source, mediumRezWorkTexture);
257 
258  // BLUR A LITTLE first, which has two purposes
259  // 1.) reduce jitter, noise, aliasing
260  // 2.) produce the little-blur buffer used in composition later
261  BlurFg (mediumRezWorkTexture, mediumRezWorkTexture, DofBlurriness.Low, 2, maxBlurSpread);
262 
263  if ((bokeh) && ((BokehDestination.Foreground & bokehDestination) != 0))
264  {
265  dofMaterial.SetVector ("_Threshhold", new Vector4(bokehThresholdContrast * 0.5f, bokehThresholdLuminance, 0.0f, 0.0f));
266 
267  // add and mark the parts that should end up as bokeh shapes
268  Graphics.Blit (mediumRezWorkTexture, bokehSource2, dofMaterial, 11);
269 
270  // remove the parts (maybe even a little tittle bittle more) that will end up in bokeh space
271  //Graphics.Blit (mediumRezWorkTexture, lowRezWorkTexture, dofMaterial, 10);
272  Graphics.Blit (mediumRezWorkTexture, lowRezWorkTexture);//, dofMaterial, 10);
273 
274  // big BLUR
275  BlurFg (lowRezWorkTexture, lowRezWorkTexture, bluriness, 1, maxBlurSpread * bokehBlurAmplifier);
276  }
277  else {
278  // big BLUR
279  BlurFg (mediumRezWorkTexture, lowRezWorkTexture, bluriness, 1, maxBlurSpread);
280  }
281 
282  // simple upsample once
283  Graphics.Blit (lowRezWorkTexture, finalDefocus);
284 
285  dofMaterial.SetTexture ("_TapLowForeground", finalDefocus);
286  Graphics.Blit (source, destination, dofMaterial, visualize ? 1 : 4);
287 
288  if ((bokeh) && ((BokehDestination.Foreground & bokehDestination) != 0))
289  AddBokeh (bokehSource2, bokehSource, destination);
290  }
291 
292  ReleaseTextures ();
293  }
294 
295  void Blur ( RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread) {
296  RenderTexture tmp = RenderTexture.GetTemporary (to.width, to.height);
297  if ((int)iterations > 1) {
298  BlurHex (from, to, blurPass, spread, tmp);
299  if ((int)iterations > 2) {
300  dofBlurMaterial.SetVector ("offsets", new Vector4 (0.0f, spread * oneOverBaseSize, 0.0f, 0.0f));
301  Graphics.Blit (to, tmp, dofBlurMaterial, blurPass);
302  dofBlurMaterial.SetVector ("offsets", new Vector4 (spread / widthOverHeight * oneOverBaseSize, 0.0f, 0.0f, 0.0f));
303  Graphics.Blit (tmp, to, dofBlurMaterial, blurPass);
304  }
305  }
306  else {
307  dofBlurMaterial.SetVector ("offsets", new Vector4 (0.0f, spread * oneOverBaseSize, 0.0f, 0.0f));
308  Graphics.Blit (from, tmp, dofBlurMaterial, blurPass);
309  dofBlurMaterial.SetVector ("offsets", new Vector4 (spread / widthOverHeight * oneOverBaseSize, 0.0f, 0.0f, 0.0f));
310  Graphics.Blit (tmp, to, dofBlurMaterial, blurPass);
311  }
312  RenderTexture.ReleaseTemporary (tmp);
313  }
314 
315  void BlurFg ( RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread) {
316  // we want a nice, big coc, hence we need to tap once from this (higher resolution) texture
317  dofBlurMaterial.SetTexture ("_TapHigh", from);
318 
319  RenderTexture tmp = RenderTexture.GetTemporary (to.width, to.height);
320  if ((int)iterations > 1) {
321  BlurHex (from, to, blurPass, spread, tmp);
322  if ((int)iterations > 2) {
323  dofBlurMaterial.SetVector ("offsets", new Vector4 (0.0f, spread * oneOverBaseSize, 0.0f, 0.0f));
324  Graphics.Blit (to, tmp, dofBlurMaterial, blurPass);
325  dofBlurMaterial.SetVector ("offsets", new Vector4 (spread / widthOverHeight * oneOverBaseSize, 0.0f, 0.0f, 0.0f));
326  Graphics.Blit (tmp, to, dofBlurMaterial, blurPass);
327  }
328  }
329  else {
330  dofBlurMaterial.SetVector ("offsets", new Vector4 (0.0f, spread * oneOverBaseSize, 0.0f, 0.0f));
331  Graphics.Blit (from, tmp, dofBlurMaterial, blurPass);
332  dofBlurMaterial.SetVector ("offsets", new Vector4 (spread / widthOverHeight * oneOverBaseSize, 0.0f, 0.0f, 0.0f));
333  Graphics.Blit (tmp, to, dofBlurMaterial, blurPass);
334  }
335  RenderTexture.ReleaseTemporary (tmp);
336  }
337 
338  void BlurHex ( RenderTexture from, RenderTexture to, int blurPass, float spread, RenderTexture tmp) {
339  dofBlurMaterial.SetVector ("offsets", new Vector4 (0.0f, spread * oneOverBaseSize, 0.0f, 0.0f));
340  Graphics.Blit (from, tmp, dofBlurMaterial, blurPass);
341  dofBlurMaterial.SetVector ("offsets", new Vector4 (spread / widthOverHeight * oneOverBaseSize, 0.0f, 0.0f, 0.0f));
342  Graphics.Blit (tmp, to, dofBlurMaterial, blurPass);
343  dofBlurMaterial.SetVector ("offsets", new Vector4 (spread / widthOverHeight * oneOverBaseSize, spread * oneOverBaseSize, 0.0f, 0.0f));
344  Graphics.Blit (to, tmp, dofBlurMaterial, blurPass);
345  dofBlurMaterial.SetVector ("offsets", new Vector4 (spread / widthOverHeight * oneOverBaseSize, -spread * oneOverBaseSize, 0.0f, 0.0f));
346  Graphics.Blit (tmp, to, dofBlurMaterial, blurPass);
347  }
348 
349  void Downsample ( RenderTexture from, RenderTexture to) {
350  dofMaterial.SetVector ("_InvRenderTargetSize", new Vector4 (1.0f / (1.0f * to.width), 1.0f / (1.0f * to.height), 0.0f, 0.0f));
351  Graphics.Blit (from, to, dofMaterial, SMOOTH_DOWNSAMPLE_PASS);
352  }
353 
354  void AddBokeh ( RenderTexture bokehInfo, RenderTexture tempTex, RenderTexture finalTarget) {
355  if (bokehMaterial) {
356  var meshes = Quads.GetMeshes (tempTex.width, tempTex.height); // quads: exchanging more triangles with less overdraw
357 
358  RenderTexture.active = tempTex;
359  GL.Clear (false, true, new Color (0.0f, 0.0f, 0.0f, 0.0f));
360 
361  GL.PushMatrix ();
362  GL.LoadIdentity ();
363 
364  // point filter mode is important, otherwise we get bokeh shape & size artefacts
365  bokehInfo.filterMode = FilterMode.Point;
366 
367  float arW = (bokehInfo.width * 1.0f) / (bokehInfo.height * 1.0f);
368  float sc = 2.0f / (1.0f * bokehInfo.width);
369  sc += bokehScale * maxBlurSpread * BOKEH_EXTRA_BLUR * oneOverBaseSize;
370 
371  bokehMaterial.SetTexture ("_Source", bokehInfo);
372  bokehMaterial.SetTexture ("_MainTex", bokehTexture);
373  bokehMaterial.SetVector ("_ArScale",new Vector4 (sc, sc * arW, 0.5f, 0.5f * arW));
374  bokehMaterial.SetFloat ("_Intensity", bokehIntensity);
375  bokehMaterial.SetPass (0);
376 
377  foreach(Mesh m in meshes)
378  if (m) Graphics.DrawMeshNow (m, Matrix4x4.identity);
379 
380  GL.PopMatrix ();
381 
382  Graphics.Blit (tempTex, finalTarget, dofMaterial, 8);
383 
384  // important to set back as we sample from this later on
385  bokehInfo.filterMode = FilterMode.Bilinear;
386  }
387  }
388 
389 
390  void ReleaseTextures () {
391  if (foregroundTexture) RenderTexture.ReleaseTemporary (foregroundTexture);
392  if (finalDefocus) RenderTexture.ReleaseTemporary (finalDefocus);
393  if (mediumRezWorkTexture) RenderTexture.ReleaseTemporary (mediumRezWorkTexture);
394  if (lowRezWorkTexture) RenderTexture.ReleaseTemporary (lowRezWorkTexture);
395  if (bokehSource) RenderTexture.ReleaseTemporary (bokehSource);
396  if (bokehSource2) RenderTexture.ReleaseTemporary (bokehSource2);
397  }
398 
399  void AllocateTextures ( bool blurForeground, RenderTexture source, int divider, int lowTexDivider) {
400  foregroundTexture = null;
401  if (blurForeground)
402  foregroundTexture = RenderTexture.GetTemporary (source.width, source.height, 0);
403  mediumRezWorkTexture = RenderTexture.GetTemporary (source.width / divider, source.height / divider, 0);
404  finalDefocus = RenderTexture.GetTemporary (source.width / divider, source.height / divider, 0);
405  lowRezWorkTexture = RenderTexture.GetTemporary (source.width / lowTexDivider, source.height / lowTexDivider, 0);
406  bokehSource = null;
407  bokehSource2 = null;
408  if (bokeh) {
409  bokehSource = RenderTexture.GetTemporary (source.width / (lowTexDivider * bokehDownsample), source.height / (lowTexDivider * bokehDownsample), 0, RenderTextureFormat.ARGBHalf);
410  bokehSource2 = RenderTexture.GetTemporary (source.width / (lowTexDivider * bokehDownsample), source.height / (lowTexDivider * bokehDownsample), 0, RenderTextureFormat.ARGBHalf);
411  bokehSource.filterMode = FilterMode.Bilinear;
412  bokehSource2.filterMode = FilterMode.Bilinear;
413  RenderTexture.active = bokehSource2;
414  GL.Clear (false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f));
415  }
416 
417  // to make sure: always use bilinear filter setting
418 
419  source.filterMode = FilterMode.Bilinear;
420  finalDefocus.filterMode = FilterMode.Bilinear;
421  mediumRezWorkTexture.filterMode = FilterMode.Bilinear;
422  lowRezWorkTexture.filterMode = FilterMode.Bilinear;
423  if (foregroundTexture)
424  foregroundTexture.filterMode = FilterMode.Bilinear;
425  }
426  }
427 }
void BlurHex(RenderTexture from, RenderTexture to, int blurPass, float spread, RenderTexture tmp)
void Blur(RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread)
static Mesh[] GetMeshes(int totalWidth, int totalHeight)
Definition: Quads.cs:42
void AddBokeh(RenderTexture bokehInfo, RenderTexture tempTex, RenderTexture finalTarget)
void AllocateTextures(bool blurForeground, RenderTexture source, int divider, int lowTexDivider)
void Downsample(RenderTexture from, RenderTexture to)
void BlurFg(RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread)
void OnRenderImage(RenderTexture source, RenderTexture destination)