DepthOfFieldDeprecated.cs 20 KB

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