IMHOTEP Framework
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Pages
DepthOfFieldDeprecated.cs
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 
127  int GetDividerBasedOnQuality () {
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 }