OutlineEffect.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.Profiling;
  6. using UnityEngine.Rendering;
  7. namespace EPOOutline
  8. {
  9. public static class OutlineEffect
  10. {
  11. public static readonly int FillRefHash = Shader.PropertyToID("_FillRef");
  12. public static readonly int DilateShiftHash = Shader.PropertyToID("_DilateShift");
  13. public static readonly int ColorMaskHash = Shader.PropertyToID("_ColorMask");
  14. public static readonly int OutlineRefHash = Shader.PropertyToID("_OutlineRef");
  15. public static readonly int RefHash = Shader.PropertyToID("_Ref");
  16. public static readonly int ZWriteHash = Shader.PropertyToID("_ZWrite");
  17. public static readonly int EffectSizeHash = Shader.PropertyToID("_EffectSize");
  18. public static readonly int CullHash = Shader.PropertyToID("_Cull");
  19. public static readonly int ZTestHash = Shader.PropertyToID("_ZTest");
  20. public static readonly int ColorHash = Shader.PropertyToID("_EPOColor");
  21. public static readonly int ScaleHash = Shader.PropertyToID("_Scale");
  22. public static readonly int ShiftHash = Shader.PropertyToID("_Shift");
  23. public static readonly int InitialTexHash = Shader.PropertyToID("_InitialTex");
  24. public static readonly int InfoBufferHash = Shader.PropertyToID("_InfoBuffer");
  25. public static readonly int ComparisonHash = Shader.PropertyToID("_Comparison");
  26. public static readonly int ReadMaskHash = Shader.PropertyToID("_ReadMask");
  27. public static readonly int WriteMaskHash = Shader.PropertyToID("_WriteMask");
  28. public static readonly int OperationHash = Shader.PropertyToID("_Operation");
  29. public static readonly int CutoutThresholdHash = Shader.PropertyToID("_CutoutThreshold");
  30. public static readonly int CutoutMaskHash = Shader.PropertyToID("_CutoutMask");
  31. public static readonly int TextureIndexHash = Shader.PropertyToID("_TextureIndex");
  32. public static readonly int CutoutTextureHash = Shader.PropertyToID("_CutoutTexture");
  33. public static readonly int CutoutTextureSTHash = Shader.PropertyToID("_CutoutTexture_ST");
  34. public static readonly int SrcBlendHash = Shader.PropertyToID("_SrcBlend");
  35. public static readonly int DstBlendHash = Shader.PropertyToID("_DstBlend");
  36. public static readonly int TargetHash = Shader.PropertyToID("ScreenRenderTargetTexture");
  37. public static readonly int InfoTargetHash = Shader.PropertyToID("ScreenInfoRenderTargetTexture");
  38. public static readonly int PrimaryBufferHash = Shader.PropertyToID("PrimaryBuffer");
  39. public static readonly int HelperBufferHash = Shader.PropertyToID("HelperBuffer");
  40. public static readonly int PrimaryInfoBufferHash = Shader.PropertyToID("PrimaryInfoBuffer");
  41. public static readonly int HelperInfoBufferHash = Shader.PropertyToID("HelperInfoBuffer");
  42. private static Material TransparentBlitMaterial;
  43. private static Material EmptyFillMaterial;
  44. private static Material OutlineMaterial;
  45. private static Material PartialBlitMaterial;
  46. private static Material ObstacleMaterial;
  47. private static Material FillMaskMaterial;
  48. private static Material ZPrepassMaterial;
  49. private static Material OutlineMaskMaterial;
  50. private static Material DilateMaterial;
  51. private static Material BlurMaterial;
  52. private static Material FinalBlitMaterial;
  53. private static Material BasicBlitMaterial;
  54. private static Material ClearStencilMaterial;
  55. private struct OutlineTargetGroup
  56. {
  57. public readonly Outlinable Outlinable;
  58. public readonly OutlineTarget Target;
  59. public OutlineTargetGroup(Outlinable outlinable, OutlineTarget target)
  60. {
  61. Outlinable = outlinable;
  62. Target = target;
  63. }
  64. }
  65. private static List<OutlineTargetGroup> targets = new List<OutlineTargetGroup>();
  66. private static List<string> keywords = new List<string>();
  67. public static Material LoadMaterial(string shaderName)
  68. {
  69. var material = new Material(Resources.Load<Shader>(string.Format("Easy performant outline/Shaders/{0}", shaderName)));
  70. if (SystemInfo.supportsInstancing)
  71. material.enableInstancing = true;
  72. return material;
  73. }
  74. [RuntimeInitializeOnLoadMethod]
  75. private static void InitMaterials()
  76. {
  77. if (PartialBlitMaterial == null)
  78. PartialBlitMaterial = LoadMaterial("PartialBlit");
  79. if (ObstacleMaterial == null)
  80. ObstacleMaterial = LoadMaterial("Obstacle");
  81. if (OutlineMaterial == null)
  82. OutlineMaterial = LoadMaterial("Outline");
  83. if (TransparentBlitMaterial == null)
  84. TransparentBlitMaterial = LoadMaterial("TransparentBlit");
  85. if (ZPrepassMaterial == null)
  86. ZPrepassMaterial = LoadMaterial("ZPrepass");
  87. if (OutlineMaskMaterial == null)
  88. OutlineMaskMaterial = LoadMaterial("OutlineMask");
  89. if (DilateMaterial == null)
  90. DilateMaterial = LoadMaterial("Dilate");
  91. if (BlurMaterial == null)
  92. BlurMaterial = LoadMaterial("Blur");
  93. if (FinalBlitMaterial == null)
  94. FinalBlitMaterial = LoadMaterial("FinalBlit");
  95. if (BasicBlitMaterial == null)
  96. BasicBlitMaterial = LoadMaterial("BasicBlit");
  97. if (EmptyFillMaterial == null)
  98. EmptyFillMaterial = LoadMaterial("Fills/EmptyFill");
  99. if (FillMaskMaterial == null)
  100. FillMaskMaterial = LoadMaterial("Fills/FillMask");
  101. if (ClearStencilMaterial == null)
  102. ClearStencilMaterial = LoadMaterial("ClearStencil");
  103. }
  104. private static void Postprocess(OutlineParameters parameters, int first, int second, Material material, int iterations, bool additionalShift, float shiftValue, ref int stencil, Rect viewport, float scale)
  105. {
  106. if (iterations <= 0)
  107. return;
  108. parameters.Buffer.SetGlobalInt(ComparisonHash, (int)CompareFunction.Equal);
  109. for (var index = 1; index <= iterations; index++)
  110. {
  111. parameters.Buffer.SetGlobalInt(RefHash, stencil);
  112. var shift = (additionalShift ? (float)index : 1.0f);
  113. parameters.Buffer.SetGlobalVector(ShiftHash, new Vector4(shift * scale, 0));
  114. Blit(parameters, RenderTargetUtility.ComposeTarget(parameters, first), RenderTargetUtility.ComposeTarget(parameters, second), RenderTargetUtility.ComposeTarget(parameters, first), material, shiftValue, null, -1, viewport);
  115. stencil = (stencil + 1) % 255;
  116. parameters.Buffer.SetGlobalInt(RefHash, stencil);
  117. parameters.Buffer.SetGlobalVector(ShiftHash, new Vector4(0, shift * scale));
  118. Blit(parameters, RenderTargetUtility.ComposeTarget(parameters, second), RenderTargetUtility.ComposeTarget(parameters, first), RenderTargetUtility.ComposeTarget(parameters, first), material, shiftValue, null, -1, viewport);
  119. stencil = (stencil + 1) % 255;
  120. }
  121. }
  122. private static void Blit(OutlineParameters parameters, RenderTargetIdentifier source, RenderTargetIdentifier destination, RenderTargetIdentifier destinationDepth, Material material, float effectSize, CommandBuffer buffer, int pass = -1, Rect? viewport = null)
  123. {
  124. parameters.Buffer.SetGlobalFloat(EffectSizeHash, effectSize);
  125. BlitUtility.Blit(parameters, source, destination, destinationDepth, material, buffer, pass, viewport);
  126. }
  127. private static float GetBlurShift(BlurType blurType, int iterrationsCount)
  128. {
  129. switch (blurType)
  130. {
  131. case BlurType.Anisotropic:
  132. case BlurType.Box:
  133. return (float)(iterrationsCount * 0.65f) + 1.0f;
  134. case BlurType.Gaussian5x5:
  135. return 3.0f * + iterrationsCount;
  136. case BlurType.Gaussian9x9:
  137. return 5.0f + iterrationsCount;
  138. case BlurType.Gaussian13x13:
  139. return 7.0f + iterrationsCount;
  140. default:
  141. throw new ArgumentException("Unknown blur type");
  142. }
  143. }
  144. private static float GetMaskingValueForMode(OutlinableDrawingMode mode)
  145. {
  146. if ((mode & OutlinableDrawingMode.Mask) != 0)
  147. return 0.6f;
  148. else if ((mode & OutlinableDrawingMode.Obstacle) != 0)
  149. return 0.25f;
  150. else
  151. return 1.0f;
  152. }
  153. private static float ComputeEffectShift(OutlineParameters parameters)
  154. {
  155. var effectShift = GetBlurShift(parameters.BlurType, parameters.BlurIterations) * parameters.BlurShift + parameters.DilateIterations * 4.0f * parameters.DilateShift;
  156. return effectShift * 2.0f;
  157. }
  158. private static void PrepareTargets(OutlineParameters parameters)
  159. {
  160. targets.Clear();
  161. foreach (var outlinable in parameters.OutlinablesToRender)
  162. {
  163. foreach (var target in outlinable.OutlineTargets)
  164. {
  165. var renderer = target.Renderer;
  166. if (!target.IsVisible)
  167. {
  168. if ((outlinable.DrawingMode & OutlinableDrawingMode.GenericMask) == 0 || renderer == null)
  169. continue;
  170. }
  171. targets.Add(new OutlineTargetGroup(outlinable, target));
  172. }
  173. }
  174. }
  175. public static void SetupOutline(OutlineParameters parameters)
  176. {
  177. parameters.Buffer.SetGlobalVector(ScaleHash, parameters.Scale);
  178. PrepareTargets(parameters);
  179. Profiler.BeginSample("Setup outline");
  180. Profiler.BeginSample("Check materials");
  181. InitMaterials();
  182. Profiler.EndSample();
  183. var effectShift = ComputeEffectShift(parameters);
  184. var targetWidth = parameters.TargetWidth;
  185. var targetHeight = parameters.TargetHeight;
  186. parameters.Buffer.SetGlobalInt(SrcBlendHash, (int)BlendMode.One);
  187. parameters.Buffer.SetGlobalInt(DstBlendHash, (int)BlendMode.Zero);
  188. var outlineRef = 1;
  189. parameters.Buffer.SetGlobalInt(OutlineRefHash, outlineRef);
  190. SetupDilateKeyword(parameters);
  191. RenderTargetUtility.GetTemporaryRT(parameters, TargetHash, targetWidth, targetHeight, 24, true, false, false);
  192. var scaledWidth = parameters.TargetWidth / 2;
  193. var scaledHeight = parameters.TargetHeight / 2;
  194. switch (parameters.PrimaryBufferSizeMode)
  195. {
  196. case BufferSizeMode.WidthControllsHeight:
  197. scaledWidth = parameters.PrimaryBufferSizeReference;
  198. scaledHeight = (int)((float)parameters.PrimaryBufferSizeReference / ((float)parameters.TargetWidth / (float)parameters.TargetHeight));
  199. break;
  200. case BufferSizeMode.HeightControlsWidth:
  201. scaledWidth = (int)((float)parameters.PrimaryBufferSizeReference / ((float)parameters.TargetHeight / (float)parameters.TargetWidth));
  202. scaledHeight = parameters.PrimaryBufferSizeReference;
  203. break;
  204. case BufferSizeMode.Scaled:
  205. scaledWidth = (int)(targetWidth * parameters.PrimaryBufferScale);
  206. scaledHeight = (int)(targetHeight * parameters.PrimaryBufferScale);
  207. break;
  208. }
  209. if (parameters.EyeMask != StereoTargetEyeMask.None)
  210. {
  211. if (scaledWidth % 2 != 0)
  212. scaledWidth++;
  213. if (scaledHeight % 2 != 0)
  214. scaledHeight++;
  215. }
  216. var scaledViewVector = parameters.MakeScaledVector(scaledWidth, scaledHeight);
  217. RenderTargetUtility.GetTemporaryRT(parameters, PrimaryBufferHash, scaledWidth, scaledHeight, 24, true, false, false);
  218. RenderTargetUtility.GetTemporaryRT(parameters, HelperBufferHash, scaledWidth, scaledHeight, 24, true, false, false);
  219. if (parameters.UseInfoBuffer)
  220. {
  221. var scaledInfoWidth = scaledWidth;
  222. var scaledInfoHeight = scaledHeight;
  223. RenderTargetUtility.GetTemporaryRT(parameters, InfoTargetHash, targetWidth, targetHeight, 0, false, false, false);
  224. RenderTargetUtility.GetTemporaryRT(parameters, PrimaryInfoBufferHash, scaledInfoWidth, scaledInfoHeight, 0, true, true, false);
  225. RenderTargetUtility.GetTemporaryRT(parameters, HelperInfoBufferHash, scaledInfoWidth, scaledInfoHeight, 0, true, true, false);
  226. }
  227. Profiler.BeginSample("Updating blit utility");
  228. BlitUtility.PrepareForRendering(parameters);
  229. Profiler.EndSample();
  230. parameters.Buffer.SetRenderTarget(RenderTargetUtility.ComposeTarget(parameters, TargetHash), RenderTargetUtility.ComposeTarget(parameters, parameters.DepthTarget));
  231. if (parameters.CustomViewport.HasValue)
  232. parameters.Buffer.SetViewport(parameters.CustomViewport.Value);
  233. DrawOutlineables(parameters, CompareFunction.LessEqual, x => true, x => Color.clear, x => ZPrepassMaterial, RenderStyle.FrontBack | RenderStyle.Single, OutlinableDrawingMode.ZOnly);
  234. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetEnabledInfoBufferKeyword());
  235. if (parameters.UseInfoBuffer)
  236. {
  237. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetInfoBufferStageKeyword());
  238. parameters.Buffer.SetRenderTarget(RenderTargetUtility.ComposeTarget(parameters, InfoTargetHash), parameters.DepthTarget);
  239. parameters.Buffer.ClearRenderTarget(false, true, Color.clear);
  240. if (parameters.CustomViewport.HasValue)
  241. parameters.Buffer.SetViewport(parameters.CustomViewport.Value);
  242. DrawOutlineables(parameters, CompareFunction.Always, x => x.OutlineParameters.Enabled, x => new Color(x.OutlineParameters.DilateShift, x.OutlineParameters.BlurShift, 0, 1),
  243. x => OutlineMaterial,
  244. RenderStyle.Single,
  245. OutlinableDrawingMode.Normal);
  246. DrawOutlineables(parameters, CompareFunction.NotEqual, x => x.BackParameters.Enabled, x => new Color(x.BackParameters.DilateShift, x.BackParameters.BlurShift, 0, 1),
  247. x => OutlineMaterial,
  248. RenderStyle.FrontBack);
  249. DrawOutlineables(parameters, CompareFunction.LessEqual, x => x.FrontParameters.Enabled, x => new Color(x.FrontParameters.DilateShift, x.FrontParameters.BlurShift, 0, 1),
  250. x => OutlineMaterial,
  251. RenderStyle.FrontBack,
  252. OutlinableDrawingMode.Normal);
  253. DrawOutlineables(parameters, CompareFunction.LessEqual, x => true, x => new Color(0, 0, GetMaskingValueForMode(x.DrawingMode), 1),
  254. x => ObstacleMaterial,
  255. RenderStyle.Single | RenderStyle.FrontBack,
  256. OutlinableDrawingMode.Obstacle | OutlinableDrawingMode.Mask);
  257. parameters.Buffer.SetGlobalInt(ComparisonHash, (int)CompareFunction.Always);
  258. parameters.Buffer.SetGlobalInt(OperationHash, (int)StencilOp.Keep);
  259. Blit(parameters,
  260. RenderTargetUtility.ComposeTarget(parameters, InfoTargetHash),
  261. RenderTargetUtility.ComposeTarget(parameters, PrimaryInfoBufferHash),
  262. RenderTargetUtility.ComposeTarget(parameters, PrimaryInfoBufferHash),
  263. BasicBlitMaterial, effectShift, null,
  264. -1);
  265. var iterationsCount =
  266. (parameters.DilateQuality == DilateQuality.Base
  267. ? parameters.DilateIterations
  268. : parameters.DilateIterations * 2) + parameters.BlurIterations;
  269. if (iterationsCount > 5)
  270. {
  271. parameters.Buffer.SetGlobalInt(ColorMaskHash, 0);
  272. parameters.Buffer.SetGlobalInt(ComparisonHash, (int)CompareFunction.Always);
  273. parameters.Buffer.SetGlobalInt(RefHash, 255);
  274. parameters.Buffer.SetGlobalInt(OperationHash, (int)StencilOp.Replace);
  275. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetEdgeMaskKeyword());
  276. Blit(parameters,
  277. RenderTargetUtility.ComposeTarget(parameters, InfoTargetHash),
  278. RenderTargetUtility.ComposeTarget(parameters, PrimaryInfoBufferHash),
  279. RenderTargetUtility.ComposeTarget(parameters, PrimaryInfoBufferHash),
  280. BasicBlitMaterial, effectShift, null,
  281. -1);
  282. parameters.Buffer.SetGlobalInt(ColorMaskHash, 255);
  283. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetEdgeMaskKeyword());
  284. parameters.Buffer.SetGlobalInt(OperationHash, (int)StencilOp.Keep);
  285. Blit(parameters,
  286. RenderTargetUtility.ComposeTarget(parameters, InfoTargetHash),
  287. RenderTargetUtility.ComposeTarget(parameters, HelperInfoBufferHash),
  288. RenderTargetUtility.ComposeTarget(parameters, HelperInfoBufferHash),
  289. BasicBlitMaterial, effectShift, null,
  290. -1);
  291. }
  292. var infoRef = 0;
  293. Postprocess(parameters, PrimaryInfoBufferHash, HelperInfoBufferHash, DilateMaterial, iterationsCount,
  294. true,
  295. effectShift, ref infoRef,
  296. new Rect(0, 0, scaledViewVector.x, scaledViewVector.y),
  297. 1.0f);
  298. parameters.Buffer.SetRenderTarget(RenderTargetUtility.ComposeTarget(parameters, InfoTargetHash), parameters.DepthTarget);
  299. if (parameters.CustomViewport.HasValue)
  300. parameters.Buffer.SetViewport(parameters.CustomViewport.Value);
  301. parameters.Buffer.SetGlobalTexture(InfoBufferHash, PrimaryInfoBufferHash);
  302. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetInfoBufferStageKeyword());
  303. }
  304. if (parameters.UseInfoBuffer)
  305. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetEnabledInfoBufferKeyword());
  306. parameters.Buffer.SetRenderTarget(RenderTargetUtility.ComposeTarget(parameters, TargetHash), parameters.DepthTarget);
  307. parameters.Buffer.ClearRenderTarget(false, true, Color.clear);
  308. if (parameters.CustomViewport.HasValue)
  309. parameters.Buffer.SetViewport(parameters.CustomViewport.Value);
  310. var drawnOutlinablesCount = 0;
  311. drawnOutlinablesCount += DrawOutlineables(parameters, CompareFunction.Always, x => x.OutlineParameters.Enabled, x => x.OutlineParameters.Color,
  312. x => OutlineMaterial,
  313. RenderStyle.Single, OutlinableDrawingMode.Normal);
  314. drawnOutlinablesCount += DrawOutlineables(parameters, CompareFunction.NotEqual, x => x.BackParameters.Enabled, x => x.BackParameters.Color,
  315. x => OutlineMaterial,
  316. RenderStyle.FrontBack, OutlinableDrawingMode.Normal);
  317. drawnOutlinablesCount += DrawOutlineables(parameters, CompareFunction.LessEqual, x => x.FrontParameters.Enabled, x => x.FrontParameters.Color,
  318. x => OutlineMaterial,
  319. RenderStyle.FrontBack, OutlinableDrawingMode.Normal);
  320. var postProcessingRef = 0;
  321. if (drawnOutlinablesCount > 0)
  322. {
  323. parameters.Buffer.SetGlobalInt(ComparisonHash, (int)CompareFunction.Always);
  324. parameters.Buffer.SetGlobalInt(OperationHash, (int)StencilOp.Keep);
  325. Blit(parameters, RenderTargetUtility.ComposeTarget(parameters, TargetHash),
  326. RenderTargetUtility.ComposeTarget(parameters, PrimaryBufferHash),
  327. RenderTargetUtility.ComposeTarget(parameters, PrimaryBufferHash),
  328. BasicBlitMaterial, effectShift, null, -1,
  329. new Rect(0, 0, scaledViewVector.x, scaledViewVector.y));
  330. if (parameters.BlurIterations + parameters.DilateIterations > 5)
  331. {
  332. parameters.Buffer.SetGlobalInt(ComparisonHash, (int)CompareFunction.Always);
  333. parameters.Buffer.SetGlobalInt(RefHash, 255);
  334. parameters.Buffer.SetGlobalInt(ColorMaskHash, 0);
  335. parameters.Buffer.SetGlobalInt(OperationHash, (int)StencilOp.Replace);
  336. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetEdgeMaskKeyword());
  337. Blit(parameters, RenderTargetUtility.ComposeTarget(parameters, TargetHash),
  338. RenderTargetUtility.ComposeTarget(parameters, PrimaryBufferHash),
  339. RenderTargetUtility.ComposeTarget(parameters, PrimaryBufferHash),
  340. BasicBlitMaterial, effectShift, null, -1,
  341. new Rect(0, 0, scaledViewVector.x, scaledViewVector.y));
  342. parameters.Buffer.SetGlobalInt(ColorMaskHash, 255);
  343. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetEdgeMaskKeyword());
  344. parameters.Buffer.SetGlobalInt(OperationHash, (int)StencilOp.Keep);
  345. Blit(parameters, RenderTargetUtility.ComposeTarget(parameters, TargetHash),
  346. RenderTargetUtility.ComposeTarget(parameters, HelperBufferHash),
  347. RenderTargetUtility.ComposeTarget(parameters, HelperBufferHash),
  348. BasicBlitMaterial, effectShift, null, -1,
  349. new Rect(0, 0, scaledViewVector.x, scaledViewVector.y));
  350. }
  351. Postprocess(parameters, PrimaryBufferHash, HelperBufferHash, DilateMaterial, parameters.DilateIterations, false, effectShift, ref postProcessingRef,
  352. new Rect(0, 0, scaledViewVector.x, scaledViewVector.y),
  353. parameters.DilateShift);
  354. }
  355. parameters.Buffer.SetRenderTarget(RenderTargetUtility.ComposeTarget(parameters, TargetHash), parameters.DepthTarget);
  356. if (drawnOutlinablesCount > 0)
  357. parameters.Buffer.ClearRenderTarget(false, true, Color.clear);
  358. if (parameters.CustomViewport.HasValue)
  359. parameters.Buffer.SetViewport(parameters.CustomViewport.Value);
  360. if (parameters.BlurIterations > 0)
  361. {
  362. SetupBlurKeyword(parameters);
  363. Postprocess(parameters, PrimaryBufferHash, HelperBufferHash, BlurMaterial, parameters.BlurIterations, false,
  364. effectShift,
  365. ref postProcessingRef,
  366. new Rect(0, 0, scaledViewVector.x, scaledViewVector.y),
  367. parameters.BlurShift);
  368. }
  369. parameters.Buffer.SetGlobalInt(ComparisonHash, (int)CompareFunction.NotEqual);
  370. parameters.Buffer.SetGlobalInt(ReadMaskHash, 255);
  371. parameters.Buffer.SetGlobalInt(OperationHash, (int)StencilOp.Replace);
  372. Blit(parameters,
  373. RenderTargetUtility.ComposeTarget(parameters, PrimaryBufferHash),
  374. parameters.Target,
  375. parameters.DepthTarget,
  376. FinalBlitMaterial,
  377. effectShift, null, -1,
  378. parameters.CustomViewport);
  379. DrawFill(parameters, parameters.Target);
  380. parameters.Buffer.SetGlobalFloat(EffectSizeHash, effectShift);
  381. BlitUtility.Draw(parameters, parameters.Target, parameters.DepthTarget, ClearStencilMaterial, parameters.CustomViewport);
  382. parameters.Buffer.ReleaseTemporaryRT(PrimaryBufferHash);
  383. parameters.Buffer.ReleaseTemporaryRT(HelperBufferHash);
  384. parameters.Buffer.ReleaseTemporaryRT(TargetHash);
  385. if (parameters.UseInfoBuffer)
  386. {
  387. parameters.Buffer.ReleaseTemporaryRT(InfoBufferHash);
  388. parameters.Buffer.ReleaseTemporaryRT(PrimaryInfoBufferHash);
  389. parameters.Buffer.ReleaseTemporaryRT(HelperInfoBufferHash);
  390. }
  391. Profiler.EndSample();
  392. }
  393. private static void SetupDilateKeyword(OutlineParameters parameters)
  394. {
  395. KeywordsUtility.GetAllDilateKeywords(keywords);
  396. foreach (var keyword in keywords)
  397. parameters.Buffer.DisableShaderKeyword(keyword);
  398. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetDilateQualityKeyword(parameters.DilateQuality));
  399. }
  400. private static void SetupBlurKeyword(OutlineParameters parameters)
  401. {
  402. KeywordsUtility.GetAllBlurKeywords(keywords);
  403. foreach (var keyword in keywords)
  404. parameters.Buffer.DisableShaderKeyword(keyword);
  405. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetBlurKeyword(parameters.BlurType));
  406. }
  407. private static int DrawOutlineables(OutlineParameters parameters, CompareFunction function, Func<Outlinable, bool> shouldRender, Func<Outlinable, Color> colorProvider, Func<Outlinable, Material> materialProvider, RenderStyle styleMask, OutlinableDrawingMode modeMask = OutlinableDrawingMode.Normal)
  408. {
  409. var drawnCount = 0;
  410. parameters.Buffer.SetGlobalInt(ZTestHash, (int)function);
  411. foreach (var targetGroup in targets)
  412. {
  413. var outlinable = targetGroup.Outlinable;
  414. if ((int)(outlinable.RenderStyle & styleMask) == 0)
  415. continue;
  416. if ((int)(outlinable.DrawingMode & modeMask) == 0)
  417. continue;
  418. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetBackKeyword(ComplexMaskingMode.MaskingMode));
  419. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetBackKeyword(ComplexMaskingMode.ObstaclesMode));
  420. if (function == CompareFunction.NotEqual && outlinable.ComplexMaskingEnabled)
  421. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetBackKeyword(outlinable.ComplexMaskingMode));
  422. var color = shouldRender(outlinable) ? colorProvider(outlinable) : Color.clear;
  423. parameters.Buffer.SetGlobalColor(ColorHash, color);
  424. var target = targetGroup.Target;
  425. parameters.Buffer.SetGlobalInt(ColorMaskHash, 255);
  426. SetupCutout(parameters, target);
  427. SetupCull(parameters, target);
  428. drawnCount++;
  429. var materialToUse = materialProvider(outlinable);
  430. parameters.Buffer.DrawRenderer(target.Renderer, materialToUse, target.ShiftedSubmeshIndex);
  431. }
  432. return drawnCount;
  433. }
  434. private static void DrawFill(OutlineParameters parameters, RenderTargetIdentifier targetSurface)
  435. {
  436. parameters.Buffer.SetRenderTarget(targetSurface, parameters.DepthTarget);
  437. if (parameters.CustomViewport.HasValue)
  438. parameters.Buffer.SetViewport(parameters.CustomViewport.Value);
  439. var singleMask = 1;
  440. var frontMask = 2;
  441. var backMask = 3;
  442. foreach (var outlinable in parameters.OutlinablesToRender)
  443. {
  444. if ((outlinable.DrawingMode & OutlinableDrawingMode.Normal) == 0)
  445. continue;
  446. parameters.Buffer.SetGlobalInt(ZTestHash, (int)CompareFunction.Greater);
  447. foreach (var target in outlinable.OutlineTargets)
  448. {
  449. if (!target.IsVisible)
  450. continue;
  451. var renderer = target.Renderer;
  452. if (!outlinable.NeedFillMask)
  453. continue;
  454. SetupCutout(parameters, target);
  455. SetupCull(parameters, target);
  456. parameters.Buffer.SetGlobalInt(FillRefHash, backMask);
  457. parameters.Buffer.DrawRenderer(renderer, FillMaskMaterial, target.ShiftedSubmeshIndex);
  458. }
  459. }
  460. foreach (var outlinable in parameters.OutlinablesToRender)
  461. {
  462. if ((outlinable.DrawingMode & OutlinableDrawingMode.Normal) == 0)
  463. continue;
  464. parameters.Buffer.SetGlobalInt(ZTestHash, (int)CompareFunction.LessEqual);
  465. foreach (var target in outlinable.OutlineTargets)
  466. {
  467. if (!target.IsVisible)
  468. continue;
  469. if (!outlinable.NeedFillMask)
  470. continue;
  471. var renderer = target.Renderer;
  472. SetupCutout(parameters, target);
  473. SetupCull(parameters, target);
  474. parameters.Buffer.SetGlobalInt(FillRefHash, frontMask);
  475. parameters.Buffer.DrawRenderer(renderer, FillMaskMaterial, target.ShiftedSubmeshIndex);
  476. }
  477. }
  478. foreach (var outlinable in parameters.OutlinablesToRender)
  479. {
  480. if ((outlinable.DrawingMode & OutlinableDrawingMode.Normal) == 0)
  481. continue;
  482. if (outlinable.RenderStyle == RenderStyle.FrontBack)
  483. {
  484. if ((outlinable.BackParameters.FillPass.Material == null || !outlinable.BackParameters.Enabled) &&
  485. (outlinable.FrontParameters.FillPass.Material == null || !outlinable.FrontParameters.Enabled))
  486. continue;
  487. var frontMaterial = outlinable.FrontParameters.FillPass.Material;
  488. parameters.Buffer.SetGlobalInt(FillRefHash, frontMask);
  489. if (frontMaterial != null && outlinable.FrontParameters.Enabled)
  490. {
  491. foreach (var target in outlinable.OutlineTargets)
  492. {
  493. if (!target.IsVisible)
  494. continue;
  495. var renderer = target.Renderer;
  496. SetupCutout(parameters, target);
  497. SetupCull(parameters, target);
  498. parameters.Buffer.DrawRenderer(renderer, frontMaterial, target.ShiftedSubmeshIndex);
  499. }
  500. }
  501. var backMaterial = outlinable.BackParameters.FillPass.Material;
  502. parameters.Buffer.SetGlobalInt(FillRefHash, backMask);
  503. if (backMaterial == null || !outlinable.BackParameters.Enabled)
  504. continue;
  505. if (outlinable.ComplexMaskingEnabled)
  506. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetBackKeyword(outlinable.ComplexMaskingMode));
  507. foreach (var target in outlinable.OutlineTargets)
  508. {
  509. if (!target.IsVisible)
  510. continue;
  511. var renderer = target.Renderer;
  512. SetupCutout(parameters, target);
  513. SetupCull(parameters, target);
  514. parameters.Buffer.DrawRenderer(renderer, backMaterial, target.ShiftedSubmeshIndex);
  515. }
  516. if (outlinable.ComplexMaskingEnabled)
  517. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetBackKeyword(outlinable.ComplexMaskingMode));
  518. }
  519. else
  520. {
  521. if (outlinable.OutlineParameters.FillPass.Material == null)
  522. continue;
  523. if (!outlinable.OutlineParameters.Enabled)
  524. continue;
  525. parameters.Buffer.SetGlobalInt(FillRefHash, singleMask);
  526. parameters.Buffer.SetGlobalInt(ZTestHash, (int)CompareFunction.Always);
  527. foreach (var target in outlinable.OutlineTargets)
  528. {
  529. if (!target.IsVisible)
  530. continue;
  531. if (!outlinable.NeedFillMask)
  532. continue;
  533. var renderer = target.Renderer;
  534. SetupCutout(parameters, target);
  535. SetupCull(parameters, target);
  536. parameters.Buffer.DrawRenderer(renderer, FillMaskMaterial, target.ShiftedSubmeshIndex);
  537. }
  538. parameters.Buffer.SetGlobalInt(FillRefHash, singleMask);
  539. var fillMaterial = outlinable.OutlineParameters.FillPass.Material;
  540. if (FillMaskMaterial == null)
  541. continue;
  542. foreach (var target in outlinable.OutlineTargets)
  543. {
  544. if (!target.IsVisible)
  545. continue;
  546. var renderer = target.Renderer;
  547. SetupCutout(parameters, target);
  548. SetupCull(parameters, target);
  549. parameters.Buffer.DrawRenderer(renderer, fillMaterial, target.ShiftedSubmeshIndex);
  550. }
  551. }
  552. }
  553. }
  554. private static void SetupCutout(OutlineParameters parameters, OutlineTarget target)
  555. {
  556. if (target.Renderer == null)
  557. return;
  558. var mask = new Vector4(
  559. (target.CutoutMask & ColorMask.R) != ColorMask.None ? 1.0f : 0.0f,
  560. (target.CutoutMask & ColorMask.G) != ColorMask.None ? 1.0f : 0.0f,
  561. (target.CutoutMask & ColorMask.B) != ColorMask.None ? 1.0f : 0.0f,
  562. (target.CutoutMask & ColorMask.A) != ColorMask.None ? 1.0f : 0.0f);
  563. parameters.Buffer.SetGlobalVector(CutoutMaskHash, mask);
  564. if (target.Renderer is SpriteRenderer)
  565. {
  566. var spriteRenderer = target.Renderer as SpriteRenderer;
  567. var sprite = spriteRenderer.sprite;
  568. if (sprite == null)
  569. {
  570. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetCutoutKeyword());
  571. return;
  572. }
  573. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetCutoutKeyword());
  574. parameters.Buffer.SetGlobalFloat(CutoutThresholdHash, target.CutoutThreshold);
  575. parameters.Buffer.SetGlobalTexture(CutoutTextureHash, spriteRenderer.sprite.texture);
  576. return;
  577. }
  578. var materialToGetTextureFrom = target.Renderer.sharedMaterial;
  579. if (target.UsesCutout &&
  580. materialToGetTextureFrom != null &&
  581. materialToGetTextureFrom.HasProperty(target.CutoutTextureId))
  582. {
  583. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetCutoutKeyword());
  584. parameters.Buffer.SetGlobalFloat(CutoutThresholdHash, target.CutoutThreshold);
  585. var offset = materialToGetTextureFrom.GetTextureOffset(target.CutoutTextureId);
  586. var scale = materialToGetTextureFrom.GetTextureScale(target.CutoutTextureId);
  587. parameters.Buffer.SetGlobalVector(CutoutTextureSTHash, new Vector4(scale.x, scale.y, offset.x, offset.y));
  588. var texture = materialToGetTextureFrom.GetTexture(target.CutoutTextureId);
  589. if (texture == null || texture.dimension != TextureDimension.Tex2DArray)
  590. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetTextureArrayCutoutKeyword());
  591. else
  592. {
  593. parameters.Buffer.SetGlobalFloat(TextureIndexHash, target.CutoutTextureIndex);
  594. parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetTextureArrayCutoutKeyword());
  595. }
  596. parameters.Buffer.SetGlobalTexture(CutoutTextureHash, texture);
  597. }
  598. else
  599. parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetCutoutKeyword());
  600. }
  601. private static void SetupCull(OutlineParameters parameters, OutlineTarget target)
  602. {
  603. parameters.Buffer.SetGlobalInt(CullHash, (int)target.CullMode);
  604. }
  605. }
  606. }