LiquidURPRenderComponent.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. #if UNITY_PIPELINE_URP
  2. using UnityEngine;
  3. using UnityEngine.Rendering;
  4. using UnityEngine.Rendering.Universal;
  5. using com.zibra.liquid.Solver;
  6. using com.zibra.liquid.Bridge;
  7. namespace com.zibra.liquid
  8. {
  9. /// <summary>
  10. /// Component responsible for rendering liquid in case of URP.
  11. /// </summary>
  12. /// <remarks>
  13. /// This is not used in case liquid's
  14. /// <see cref="Solver::ZibraLiquid::CurrentRenderingMode">ZibraLiquid.CurrentRenderingMode</see>
  15. /// is set to Unity Render.
  16. /// </remarks>
  17. public class LiquidURPRenderComponent : ScriptableRendererFeature
  18. {
  19. #region Public Interface
  20. /// <summary>
  21. /// URP specific liquid rendering settings.
  22. /// </summary>
  23. [System.Serializable]
  24. public class LiquidURPRenderSettings
  25. {
  26. /// <summary>
  27. /// Globally defines whether liquid renders in URP.
  28. /// </summary>
  29. public bool IsEnabled = true;
  30. /// <summary>
  31. /// Injection point where we will insert liquid rendering.
  32. /// </summary>
  33. /// <remarks>
  34. /// In case of URP, this parameter will be used instead of
  35. /// <see cref="Solver::ZibraLiquid::CurrentInjectionPoint">ZibraLiquid.CurrentInjectionPoint</see>.
  36. /// </remarks>
  37. public RenderPassEvent InjectionPoint = RenderPassEvent.AfterRenderingSkybox;
  38. }
  39. /// <summary>
  40. /// See <see cref="LiquidURPRenderSettings"/>.
  41. /// </summary>
  42. // Must be called exactly "settings" so Unity shows this as render feature settings in editor
  43. public LiquidURPRenderSettings settings = new LiquidURPRenderSettings();
  44. /// <summary>
  45. /// Creates URP ScriptableRendererFeature.
  46. /// </summary>
  47. public override void Create()
  48. {
  49. handleSystem.Initialize(0, 0);
  50. }
  51. /// <summary>
  52. /// Adds scriptable render passes.
  53. /// </summary>
  54. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
  55. {
  56. if (!settings.IsEnabled)
  57. {
  58. return;
  59. }
  60. if (renderingData.cameraData.cameraType != CameraType.Game &&
  61. renderingData.cameraData.cameraType != CameraType.SceneView)
  62. {
  63. return;
  64. }
  65. Camera camera = renderingData.cameraData.camera;
  66. camera.depthTextureMode = DepthTextureMode.Depth;
  67. int liquidsToRenderCount = 0;
  68. int backgroundsToCopyCount = 0;
  69. int liquidsToVisualizeSDFCount = 0;
  70. int liquidsToUpscaleCount = 0;
  71. foreach (var liquid in ZibraLiquid.AllFluids)
  72. {
  73. if (liquid != null && liquid.Initialized)
  74. {
  75. liquidsToRenderCount++;
  76. if (liquid.EnableDownscale)
  77. {
  78. liquidsToUpscaleCount++;
  79. }
  80. if (liquid.IsBackgroundCopyNeeded(camera))
  81. {
  82. backgroundsToCopyCount++;
  83. }
  84. if (liquid.VisualizeSceneSDF)
  85. {
  86. liquidsToVisualizeSDFCount++;
  87. }
  88. }
  89. }
  90. if (copyPasses == null || copyPasses.Length != backgroundsToCopyCount)
  91. {
  92. copyPasses = new CopyBackgroundURPRenderPass[backgroundsToCopyCount];
  93. for (int i = 0; i < backgroundsToCopyCount; ++i)
  94. {
  95. copyPasses[i] = new CopyBackgroundURPRenderPass(settings.InjectionPoint);
  96. }
  97. }
  98. if (liquidNativePasses == null || liquidNativePasses.Length != liquidsToRenderCount)
  99. {
  100. liquidNativePasses = new LiquidNativeRenderPass[liquidsToRenderCount];
  101. for (int i = 0; i < liquidsToRenderCount; ++i)
  102. {
  103. liquidNativePasses[i] = new LiquidNativeRenderPass(settings.InjectionPoint);
  104. }
  105. }
  106. if (liquidURPPasses == null || liquidURPPasses.Length != liquidsToRenderCount)
  107. {
  108. liquidURPPasses = new LiquidURPRenderPass[liquidsToRenderCount];
  109. for (int i = 0; i < liquidsToRenderCount; ++i)
  110. {
  111. liquidURPPasses[i] = new LiquidURPRenderPass(settings.InjectionPoint);
  112. }
  113. }
  114. if (liquidVisualizeSDFPasses == null || liquidVisualizeSDFPasses.Length != liquidsToVisualizeSDFCount)
  115. {
  116. liquidVisualizeSDFPasses = new LiquidVisualizeSDFPass[liquidsToVisualizeSDFCount];
  117. for (int i = 0; i < liquidsToVisualizeSDFCount; ++i)
  118. {
  119. liquidVisualizeSDFPasses[i] = new LiquidVisualizeSDFPass(settings.InjectionPoint);
  120. }
  121. }
  122. if (upscalePasses == null || upscalePasses.Length != liquidsToUpscaleCount)
  123. {
  124. upscalePasses = new LiquidUpscaleURPRenderPass[liquidsToUpscaleCount];
  125. for (int i = 0; i < liquidsToUpscaleCount; ++i)
  126. {
  127. upscalePasses[i] = new LiquidUpscaleURPRenderPass(settings.InjectionPoint);
  128. }
  129. }
  130. int currentCopyPass = 0;
  131. int currentLiquidPass = 0;
  132. int currentVisualizeSDFPass = 0;
  133. int currentUpscalePass = 0;
  134. foreach (var liquid in ZibraLiquid.AllFluids)
  135. {
  136. if (liquid != null && liquid.IsRenderingEnabled() &&
  137. ((camera.cullingMask & (1 << liquid.gameObject.layer)) != 0))
  138. {
  139. if (liquid.IsBackgroundCopyNeeded(camera))
  140. {
  141. copyPasses[currentCopyPass].liquid = liquid;
  142. copyPasses[currentCopyPass].handleSystem = handleSystem;
  143. copyPasses[currentCopyPass].ConfigureInput(ScriptableRenderPassInput.Color |
  144. ScriptableRenderPassInput.Depth);
  145. copyPasses[currentCopyPass].renderPassEvent = settings.InjectionPoint;
  146. renderer.EnqueuePass(copyPasses[currentCopyPass]);
  147. currentCopyPass++;
  148. }
  149. liquidNativePasses[currentLiquidPass].liquid = liquid;
  150. liquidNativePasses[currentLiquidPass].handleSystem = handleSystem;
  151. liquidNativePasses[currentLiquidPass].renderPassEvent = settings.InjectionPoint;
  152. renderer.EnqueuePass(liquidNativePasses[currentLiquidPass]);
  153. liquidURPPasses[currentLiquidPass].liquid = liquid;
  154. liquidURPPasses[currentLiquidPass].handleSystem = handleSystem;
  155. liquidURPPasses[currentLiquidPass].ConfigureInput(ScriptableRenderPassInput.Color |
  156. ScriptableRenderPassInput.Depth);
  157. liquidURPPasses[currentLiquidPass].renderPassEvent = settings.InjectionPoint;
  158. renderer.EnqueuePass(liquidURPPasses[currentLiquidPass]);
  159. currentLiquidPass++;
  160. if (liquid.VisualizeSceneSDF)
  161. {
  162. liquidVisualizeSDFPasses[currentVisualizeSDFPass].ConfigureInput(
  163. ScriptableRenderPassInput.Color | ScriptableRenderPassInput.Depth);
  164. liquidVisualizeSDFPasses[currentVisualizeSDFPass].liquid = liquid;
  165. liquidVisualizeSDFPasses[currentVisualizeSDFPass].handleSystem = handleSystem;
  166. liquidVisualizeSDFPasses[currentVisualizeSDFPass].renderPassEvent = settings.InjectionPoint;
  167. renderer.EnqueuePass(liquidVisualizeSDFPasses[currentVisualizeSDFPass]);
  168. currentVisualizeSDFPass++;
  169. }
  170. if (liquid.EnableDownscale)
  171. {
  172. upscalePasses[currentUpscalePass].liquid = liquid;
  173. upscalePasses[currentUpscalePass].handleSystem = handleSystem;
  174. upscalePasses[currentUpscalePass].renderPassEvent = settings.InjectionPoint;
  175. renderer.EnqueuePass(upscalePasses[currentUpscalePass]);
  176. currentUpscalePass++;
  177. }
  178. }
  179. }
  180. }
  181. #endregion
  182. #region Implementation details
  183. private class CopyBackgroundURPRenderPass : ScriptableRenderPass
  184. {
  185. public ZibraLiquid liquid;
  186. public RTHandleSystem handleSystem;
  187. RTHandle cameraColorTarget;
  188. public CopyBackgroundURPRenderPass(RenderPassEvent injectionPoint)
  189. {
  190. renderPassEvent = injectionPoint;
  191. }
  192. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
  193. {
  194. #if UNITY_PIPELINE_URP_13_1_OR_HIGHER
  195. cameraColorTarget = renderingData.cameraData.renderer.cameraColorTargetHandle;
  196. #else
  197. cameraColorTarget = handleSystem.Alloc(renderingData.cameraData.renderer.cameraColorTarget);
  198. #endif
  199. }
  200. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  201. {
  202. Camera camera = renderingData.cameraData.camera;
  203. CommandBuffer cmd = CommandBufferPool.Get("ZibraLiquid.Render");
  204. if (liquid.CameraResourcesMap.ContainsKey(camera))
  205. {
  206. RTHandle background = handleSystem.Alloc(liquid.CameraResourcesMap[camera].Background);
  207. Blit(cmd, cameraColorTarget, background);
  208. }
  209. context.ExecuteCommandBuffer(cmd);
  210. CommandBufferPool.Release(cmd);
  211. }
  212. }
  213. private class LiquidNativeRenderPass : ScriptableRenderPass
  214. {
  215. public ZibraLiquid liquid;
  216. public RTHandleSystem handleSystem;
  217. public LiquidNativeRenderPass(RenderPassEvent injectionPoint)
  218. {
  219. renderPassEvent = injectionPoint;
  220. }
  221. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  222. {
  223. Camera camera = renderingData.cameraData.camera;
  224. camera.depthTextureMode = DepthTextureMode.Depth;
  225. CommandBuffer cmd = CommandBufferPool.Get("ZibraLiquid.Render");
  226. liquid.RenderCallBack(renderingData.cameraData.camera, renderingData.cameraData.renderScale);
  227. // set initial parameters in the native plugin
  228. LiquidBridge.SubmitInstanceEvent(cmd, liquid.CurrentInstanceID, LiquidBridge.EventID.SetCameraParams,
  229. liquid.CamNativeParams[camera]);
  230. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan)
  231. {
  232. cmd.SetRenderTarget(liquid.Color0, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store,
  233. liquid.Depth, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
  234. cmd.ClearRenderTarget(true, true, Color.clear);
  235. }
  236. liquid.RenderLiquidNative(cmd, renderingData.cameraData.camera);
  237. context.ExecuteCommandBuffer(cmd);
  238. CommandBufferPool.Release(cmd);
  239. }
  240. }
  241. private class LiquidURPRenderPass : ScriptableRenderPass
  242. {
  243. public ZibraLiquid liquid;
  244. public RTHandleSystem handleSystem;
  245. RTHandle cameraColorTarget;
  246. static int UpscaleColorTextureID = Shader.PropertyToID("ZibraLiquid_LiquidTempColorTexture");
  247. static int UpscaleDepthTextureID = Shader.PropertyToID("ZibraLiquid_LiquidTempDepthTexture");
  248. RTHandle UpscaleColorTexture;
  249. RTHandle UpscaleDepthTexture;
  250. public LiquidURPRenderPass(RenderPassEvent injectionPoint)
  251. {
  252. renderPassEvent = injectionPoint;
  253. }
  254. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
  255. {
  256. #if UNITY_PIPELINE_URP_13_1_OR_HIGHER
  257. cameraColorTarget = renderingData.cameraData.renderer.cameraColorTargetHandle;
  258. #else
  259. cameraColorTarget = handleSystem.Alloc(renderingData.cameraData.renderer.cameraColorTarget);
  260. #endif
  261. }
  262. public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
  263. {
  264. if (liquid.EnableDownscale)
  265. {
  266. RenderTextureDescriptor descriptor = cameraTextureDescriptor;
  267. Vector2Int dimensions = new Vector2Int(descriptor.width, descriptor.height);
  268. dimensions = liquid.ApplyDownscaleFactor(dimensions);
  269. descriptor.width = dimensions.x;
  270. descriptor.height = dimensions.y;
  271. descriptor.msaaSamples = 1;
  272. descriptor.colorFormat = RenderTextureFormat.ARGBHalf;
  273. descriptor.depthBufferBits = 0;
  274. cmd.GetTemporaryRT(UpscaleColorTextureID, descriptor, FilterMode.Bilinear);
  275. descriptor.colorFormat = RenderTextureFormat.Depth;
  276. descriptor.depthBufferBits = 32;
  277. cmd.GetTemporaryRT(UpscaleDepthTextureID, descriptor, FilterMode.Bilinear);
  278. UpscaleColorTexture = handleSystem.Alloc(new RenderTargetIdentifier(UpscaleColorTextureID));
  279. UpscaleDepthTexture = handleSystem.Alloc(new RenderTargetIdentifier(UpscaleDepthTextureID));
  280. ConfigureTarget(UpscaleColorTexture, UpscaleDepthTexture);
  281. ConfigureClear(ClearFlag.All, new Color(0, 0, 0, 0));
  282. }
  283. else
  284. {
  285. ConfigureTarget(cameraColorTarget);
  286. // ConfigureClear seems to be persistent, so need to reset it
  287. ConfigureClear(ClearFlag.None, new Color(0, 0, 0, 0));
  288. }
  289. }
  290. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  291. {
  292. Camera camera = renderingData.cameraData.camera;
  293. camera.depthTextureMode = DepthTextureMode.Depth;
  294. CommandBuffer cmd = CommandBufferPool.Get("ZibraLiquid.Render");
  295. if (!liquid.EnableDownscale)
  296. {
  297. cmd.SetRenderTarget(cameraColorTarget);
  298. }
  299. liquid.RenderLiquidMain(cmd, camera);
  300. context.ExecuteCommandBuffer(cmd);
  301. CommandBufferPool.Release(cmd);
  302. }
  303. public override void OnCameraCleanup(CommandBuffer cmd)
  304. {
  305. if (liquid.EnableDownscale)
  306. {
  307. cmd.ReleaseTemporaryRT(UpscaleColorTextureID);
  308. cmd.ReleaseTemporaryRT(UpscaleDepthTextureID);
  309. }
  310. }
  311. }
  312. private class LiquidVisualizeSDFPass : ScriptableRenderPass
  313. {
  314. public ZibraLiquid liquid;
  315. public RTHandleSystem handleSystem;
  316. RTHandle cameraColorTarget;
  317. static int UpscaleColorTextureID = Shader.PropertyToID("ZibraLiquid_LiquidTempColorTexture");
  318. static int UpscaleDepthTextureID = Shader.PropertyToID("ZibraLiquid_LiquidTempDepthTexture");
  319. RTHandle UpscaleColorTexture;
  320. RTHandle UpscaleDepthTexture;
  321. public LiquidVisualizeSDFPass(RenderPassEvent injectionPoint)
  322. {
  323. renderPassEvent = injectionPoint;
  324. }
  325. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
  326. {
  327. #if UNITY_PIPELINE_URP_13_1_OR_HIGHER
  328. cameraColorTarget = renderingData.cameraData.renderer.cameraColorTargetHandle;
  329. #else
  330. cameraColorTarget = handleSystem.Alloc(renderingData.cameraData.renderer.cameraColorTarget);
  331. #endif
  332. }
  333. public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
  334. {
  335. if (liquid.EnableDownscale)
  336. {
  337. UpscaleColorTexture = handleSystem.Alloc(new RenderTargetIdentifier(UpscaleColorTextureID));
  338. UpscaleDepthTexture = handleSystem.Alloc(new RenderTargetIdentifier(UpscaleDepthTextureID));
  339. ConfigureTarget(UpscaleColorTexture, UpscaleDepthTexture);
  340. }
  341. else
  342. {
  343. ConfigureTarget(cameraColorTarget);
  344. }
  345. }
  346. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  347. {
  348. Camera camera = renderingData.cameraData.camera;
  349. camera.depthTextureMode = DepthTextureMode.Depth;
  350. CommandBuffer cmd = CommandBufferPool.Get("ZibraLiquid.Render");
  351. LiquidBridge.SubmitInstanceEvent(cmd, liquid.CurrentInstanceID, LiquidBridge.EventID.RenderSDF);
  352. if (liquid.EnableDownscale)
  353. {
  354. cmd.SetRenderTarget(UpscaleColorTexture, UpscaleDepthTexture);
  355. }
  356. else
  357. {
  358. cmd.SetRenderTarget(cameraColorTarget);
  359. }
  360. liquid.RenderSDFVisualization(cmd, camera);
  361. context.ExecuteCommandBuffer(cmd);
  362. CommandBufferPool.Release(cmd);
  363. }
  364. }
  365. private class LiquidUpscaleURPRenderPass : ScriptableRenderPass
  366. {
  367. public ZibraLiquid liquid;
  368. public RTHandleSystem handleSystem;
  369. static int UpscaleColorTextureID = Shader.PropertyToID("ZibraLiquid_LiquidTempColorTexture");
  370. static int UpscaleDepthTextureID = Shader.PropertyToID("ZibraLiquid_LiquidTempDepthTexture");
  371. RTHandle UpscaleColorTexture;
  372. RTHandle UpscaleDepthTexture;
  373. public LiquidUpscaleURPRenderPass(RenderPassEvent injectionPoint)
  374. {
  375. renderPassEvent = injectionPoint;
  376. }
  377. public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
  378. {
  379. UpscaleColorTexture = handleSystem.Alloc(new RenderTargetIdentifier(UpscaleColorTextureID));
  380. UpscaleDepthTexture = handleSystem.Alloc(new RenderTargetIdentifier(UpscaleDepthTextureID));
  381. }
  382. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  383. {
  384. Camera camera = renderingData.cameraData.camera;
  385. camera.depthTextureMode = DepthTextureMode.Depth;
  386. CommandBuffer cmd = CommandBufferPool.Get("ZibraLiquid.Render");
  387. liquid.UpscaleLiquidDirect(cmd, camera, UpscaleColorTexture, UpscaleDepthTexture);
  388. context.ExecuteCommandBuffer(cmd);
  389. CommandBufferPool.Release(cmd);
  390. }
  391. }
  392. RTHandleSystem handleSystem = new RTHandleSystem();
  393. // 1 pass per rendered liquid that requires background copy
  394. CopyBackgroundURPRenderPass[] copyPasses;
  395. // 1 pass per rendered liquid
  396. LiquidNativeRenderPass[] liquidNativePasses;
  397. // 1 pass per rendered liquid
  398. LiquidURPRenderPass[] liquidURPPasses;
  399. // 1 pass per rendered liquid with VisualizeSceneSDF enabled
  400. LiquidVisualizeSDFPass[] liquidVisualizeSDFPasses;
  401. // 1 pass per rendered liquid that have downscale enabled
  402. LiquidUpscaleURPRenderPass[] upscalePasses;
  403. #endregion
  404. }
  405. }
  406. #endif // UNITY_PIPELINE_URP