EnviroFogModule.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System.Runtime.InteropServices;
  5. using System;
  6. namespace Enviro
  7. {
  8. [Serializable]
  9. public class EnviroFogSettings
  10. {
  11. /// Volumetrics Settings
  12. public bool volumetrics = true;
  13. public enum Quality
  14. {
  15. Low,
  16. Medium,
  17. High
  18. }
  19. public int steps = 32;
  20. public Quality quality;
  21. [Range(0f,2f)]
  22. public float scattering;
  23. [Range(0f,1f)]
  24. public float extinction;
  25. [Range(0f,1f)]
  26. public float anistropy;
  27. public float maxRange;
  28. [Range(0f,1f)]
  29. public float noiseIntensity;
  30. [Range(0f,0.01f)]
  31. public float noiseScale;
  32. public Vector3 windDirection;
  33. public Texture3D noise;
  34. public Texture2D ditheringTex;
  35. //Height Fog Settings
  36. public bool fog = true;
  37. [Range(0.0f,1f)]
  38. public float fogDensity = 0.02f; // This is the global density factor, which can be thought of as the fog layer's thickness.
  39. [Range(0.001f, 0.1f)]
  40. public float fogHeightFalloff = 0.2f; // Height density factor, controls how the density increases as height decreases. Smaller values make the transition larger.
  41. public float fogHeight = 0.0f;
  42. [Range(0.0f, 1f)]
  43. public float fogDensity2 = 0.02f;
  44. [Range(0.001f, 0.1f)]
  45. public float fogHeightFalloff2 = 0.2f;
  46. public float fogHeight2;
  47. [Range(0.0f,1.0f)]
  48. public float fogMaxOpacity = 1.0f;
  49. [Range(0.0f,5000.0f)]
  50. public float startDistance = 0.0f;
  51. [Range(0.0f,1.0f)]
  52. public float fogColorBlend = 0.5f;
  53. [GradientUsage(true)]
  54. public Gradient ambientColorGradient;
  55. /// 3D Type
  56. /*public float fogRange = 2000f;
  57. public float lightIntensityMult = 0.1f;
  58. public float constantFog = 100f;
  59. public float heightFogExponent = 0f;
  60. public float heightFogAmount = 0f;
  61. public float noiseFogAmount = 0f;
  62. public float noiseFogScale = 0f;
  63. public float reprojectionFactor = 0.0f;
  64. public float depthBias = 0.0f;
  65. */
  66. #if ENVIRO_HDRP
  67. //HDRP Fog
  68. public bool controlHDRPFog;
  69. public float fogAttenuationDistance = 400f;
  70. public float baseHeight = 0f;
  71. public float maxHeight = 50f;
  72. [GradientUsage(true)]
  73. public Gradient fogColorTint;
  74. //HDRP Volumetrics
  75. public bool controlHDRPVolumetrics;
  76. [GradientUsage(true)]
  77. public Gradient volumetricsColorTint;
  78. [Range(0f,1f)]
  79. public float ambientDimmer = 1f;
  80. [Range(0f,10f)]
  81. public float directLightMultiplier = 1f;
  82. [Range(0f,1f)]
  83. public float directLightShadowdimmer = 1f;
  84. #endif
  85. }
  86. [Serializable]
  87. public class EnviroFogModule : EnviroModule
  88. {
  89. //Settings
  90. public Enviro.EnviroFogSettings Settings;
  91. public EnviroFogModule preset;
  92. public bool showFogControls;
  93. public bool showVolumetricsControls;
  94. #if ENVIRO_HDRP
  95. public bool showHDRPFogControls;
  96. #endif
  97. //Fog Zones and Lights
  98. public List<EnviroVolumetricFogLight> fogLights = new List<EnviroVolumetricFogLight>();
  99. private Light myLight;
  100. //Materials
  101. public Material fogMat;
  102. public Material volumetricsMat;
  103. public Material blurMat;
  104. // Textures
  105. public RenderTexture volumetricsRenderTexture;
  106. private Texture2D blackTex;
  107. //Point Lights
  108. struct PointLightParams
  109. {
  110. public Vector3 pos;
  111. public float range;
  112. public Vector3 color;
  113. float padding;
  114. }
  115. PointLightParams[] m_PointLightParams;
  116. ComputeBuffer m_PointLightParamsCB;
  117. //Spot Lights
  118. struct SpotLightParams
  119. {
  120. public Vector3 pos;
  121. public float range;
  122. public Vector3 color;
  123. public Vector3 lightDirection;
  124. public float lightCosHalfAngle;
  125. float padding;
  126. }
  127. SpotLightParams[] m_SpotLightParams;
  128. ComputeBuffer m_SpotLightParamsCB;
  129. #if ENVIRO_HDRP
  130. public UnityEngine.Rendering.HighDefinition.Fog fogHDRP;
  131. #endif
  132. /// 3D Type
  133. //public List<EnviroFogLight> vFogLights = new List<EnviroFogLight>();
  134. //
  135. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  136. /// Update Functions
  137. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  138. public override void Enable()
  139. {
  140. #if !ENVIRO_HDRP
  141. if(EnviroManager.instance.Objects.directionalLight != null)
  142. {
  143. if(EnviroManager.instance.Objects.directionalLight.gameObject.GetComponent<EnviroVolumetricFogLight>() == null)
  144. EnviroManager.instance.Objects.directionalLight.gameObject.AddComponent<EnviroVolumetricFogLight>();
  145. }
  146. if(EnviroManager.instance.Objects.additionalDirectionalLight != null)
  147. {
  148. if(EnviroManager.instance.Objects.additionalDirectionalLight.gameObject.GetComponent<EnviroVolumetricFogLight>() == null)
  149. EnviroManager.instance.Objects.additionalDirectionalLight.gameObject.AddComponent<EnviroVolumetricFogLight>();
  150. }
  151. #endif
  152. if(blackTex == null)
  153. blackTex = Resources.Load("tex_enviro_black") as Texture2D;
  154. }
  155. public override void Disable()
  156. {
  157. CleanupHeightFog();
  158. CleanupVolumetrics();
  159. if(EnviroManager.instance.Objects.directionalLight != null)
  160. {
  161. if(EnviroManager.instance.Objects.directionalLight.gameObject.GetComponent<EnviroVolumetricFogLight>() != null)
  162. DestroyImmediate(EnviroManager.instance.Objects.directionalLight.gameObject.GetComponent<EnviroVolumetricFogLight>());
  163. }
  164. if(EnviroManager.instance.Objects.additionalDirectionalLight != null)
  165. {
  166. if(EnviroManager.instance.Objects.additionalDirectionalLight.gameObject.GetComponent<EnviroVolumetricFogLight>() != null)
  167. DestroyImmediate(EnviroManager.instance.Objects.additionalDirectionalLight.gameObject.GetComponent<EnviroVolumetricFogLight>());
  168. }
  169. }
  170. // Update Method
  171. public override void UpdateModule ()
  172. {
  173. //Somehow this texture might get lost in runtime. Make sure to load it in this case.
  174. if(blackTex == null)
  175. blackTex = Resources.Load("tex_enviro_black") as Texture2D;
  176. #if ENVIRO_HDRP
  177. UpdateFogHDRP ();
  178. #endif
  179. }
  180. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. /// Public general functions
  182. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. public bool AddLight (EnviroVolumetricFogLight light)
  184. {
  185. fogLights.Add(light);
  186. return true;
  187. }
  188. public void RemoveLight (EnviroVolumetricFogLight light)
  189. {
  190. if(fogLights.Contains(light))
  191. fogLights.Remove(light);
  192. }
  193. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  194. /// HDRP
  195. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  196. #if ENVIRO_HDRP
  197. private void UpdateFogHDRP ()
  198. {
  199. if(EnviroManager.instance.volumeHDRP != null)
  200. {
  201. if(fogHDRP == null)
  202. {
  203. UnityEngine.Rendering.HighDefinition.Fog TempFog;
  204. if (EnviroManager.instance.volumeHDRP.sharedProfile != null && EnviroManager.instance.volumeHDRP.sharedProfile.TryGet<UnityEngine.Rendering.HighDefinition.Fog>(out TempFog))
  205. {
  206. fogHDRP = TempFog;
  207. }
  208. else
  209. {
  210. EnviroManager.instance.volumeHDRP.sharedProfile.Add<UnityEngine.Rendering.HighDefinition.Fog>();
  211. if (EnviroManager.instance.volumeHDRP.sharedProfile.TryGet<UnityEngine.Rendering.HighDefinition.Fog>(out TempFog))
  212. {
  213. fogHDRP = TempFog;
  214. }
  215. }
  216. }
  217. else
  218. {
  219. if(Settings.controlHDRPFog)
  220. {
  221. fogHDRP.active = true;
  222. fogHDRP.enabled.overrideState = true;
  223. fogHDRP.enabled.value = Settings.controlHDRPFog;
  224. fogHDRP.meanFreePath.overrideState = true;
  225. fogHDRP.meanFreePath.value = Settings.fogAttenuationDistance;
  226. fogHDRP.baseHeight.overrideState = true;
  227. fogHDRP.baseHeight.value = Settings.baseHeight;
  228. fogHDRP.maximumHeight.overrideState = true;
  229. fogHDRP.maximumHeight.value = Settings.maxHeight;
  230. fogHDRP.tint.overrideState = true;
  231. fogHDRP.tint.value = Settings.fogColorTint.Evaluate(EnviroManager.instance.solarTime);
  232. }
  233. else
  234. {
  235. fogHDRP.active = false;
  236. }
  237. if(Settings.controlHDRPVolumetrics)
  238. {
  239. fogHDRP.enableVolumetricFog.overrideState = true;
  240. fogHDRP.enableVolumetricFog.value = true;
  241. fogHDRP.albedo.overrideState = true;
  242. fogHDRP.albedo.value = Settings.volumetricsColorTint.Evaluate(EnviroManager.instance.solarTime);
  243. fogHDRP.globalLightProbeDimmer.overrideState = true;
  244. fogHDRP.globalLightProbeDimmer.value = Settings.ambientDimmer;
  245. if(EnviroManager.instance.Lighting != null && EnviroManager.instance.Lighting.directionalLightHDRP != null)
  246. {
  247. EnviroManager.instance.Lighting.directionalLightHDRP.volumetricDimmer = Settings.directLightMultiplier;
  248. EnviroManager.instance.Lighting.directionalLightHDRP.volumetricShadowDimmer = Settings.directLightShadowdimmer;
  249. }
  250. if(EnviroManager.instance.Lighting != null && EnviroManager.instance.Lighting.additionalLightHDRP != null)
  251. {
  252. EnviroManager.instance.Lighting.additionalLightHDRP.volumetricDimmer = Settings.directLightMultiplier;
  253. EnviroManager.instance.Lighting.additionalLightHDRP.volumetricShadowDimmer = Settings.directLightShadowdimmer;
  254. }
  255. }
  256. else
  257. {
  258. fogHDRP.enableVolumetricFog.value = false;
  259. }
  260. }
  261. }
  262. }
  263. #endif
  264. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  265. /// Height Fog
  266. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  267. public float RayOriginTerm(float density, float heightFalloff, float heightOffset, Camera cam)
  268. {
  269. float exponent = heightFalloff * (cam.transform.position.y - heightOffset);
  270. return density * Mathf.Pow(2.0f, - exponent);
  271. }
  272. public void UpdateFogShader (Camera cam)
  273. {
  274. Shader.SetGlobalVector("_EnviroFogParameters", new Vector4(RayOriginTerm(Settings.fogDensity * 0.01f, Settings.fogHeightFalloff, Settings.fogHeight,cam), Settings.fogHeightFalloff, Settings.fogDensity, Settings.fogHeight));
  275. Shader.SetGlobalVector("_EnviroFogParameters2", new Vector4(RayOriginTerm(Settings.fogDensity2 * 0.01f, Settings.fogHeightFalloff2, Settings.fogHeight2,cam), Settings.fogHeightFalloff2, Settings.fogDensity2, Settings.fogHeight2));
  276. Shader.SetGlobalVector("_EnviroFogParameters3",new Vector4(1.0f - Settings.fogMaxOpacity,Settings.startDistance,0f,Settings.fogColorBlend));
  277. Shader.SetGlobalColor("_EnviroFogColor", Settings.ambientColorGradient.Evaluate(EnviroManager.instance.solarTime));
  278. }
  279. public void RenderHeightFog(Camera cam, RenderTexture source, RenderTexture destination)
  280. {
  281. UnityEngine.Profiling.Profiler.BeginSample("Enviro Fog Rendering");
  282. if(fogMat == null)
  283. fogMat = new Material(Shader.Find("Hidden/EnviroHeightFog"));
  284. UpdateFogShader(cam);
  285. fogMat.SetTexture("_MainTex",source);
  286. Graphics.Blit(source, destination, fogMat);
  287. UnityEngine.Profiling.Profiler.EndSample();
  288. }
  289. #if ENVIRO_URP
  290. public void RenderHeightFogURP(Camera cam,EnviroURPRenderPass pass,UnityEngine.Rendering.CommandBuffer cmd, RenderTexture source, UnityEngine.Rendering.RenderTargetIdentifier destination)
  291. {
  292. if(fogMat == null)
  293. fogMat = new Material(Shader.Find("Hidden/EnviroHeightFog"));
  294. UpdateFogShader(cam);
  295. fogMat.EnableKeyword("ENVIROURP");
  296. pass.CustomBlit(cmd,cam.cameraToWorldMatrix,source,destination,fogMat);
  297. }
  298. #endif
  299. #if ENVIRO_HDRP
  300. public void RenderHeightFogHDRP(Camera cam,UnityEngine.Rendering.CommandBuffer cmd, UnityEngine.Rendering.RTHandle source, UnityEngine.Rendering.RTHandle destination)
  301. {
  302. if(fogMat == null)
  303. fogMat = new Material(Shader.Find("Hidden/EnviroHeightFogHDRP"));
  304. UpdateFogShader(cam);
  305. fogMat.SetTexture("_MainTex",source);
  306. cmd.Blit(source, destination, fogMat);
  307. }
  308. #endif
  309. private void CleanupHeightFog()
  310. {
  311. if(fogMat != null)
  312. DestroyImmediate(fogMat);
  313. if(EnviroManager.instance.removeZoneParamsCB != null)
  314. EnviroHelper.ReleaseComputeBuffer(ref EnviroManager.instance.removeZoneParamsCB);
  315. if(EnviroManager.instance.clearZoneCB != null)
  316. EnviroHelper.ReleaseComputeBuffer(ref EnviroManager.instance.clearZoneCB);
  317. if(EnviroManager.instance.clearCB != null)
  318. EnviroHelper.ReleaseComputeBuffer(ref EnviroManager.instance.clearCB);
  319. }
  320. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  321. /// Volumetrics
  322. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  323. public void RenderVolumetrics(Camera camera, RenderTexture source)
  324. {
  325. UnityEngine.Profiling.Profiler.BeginSample("Enviro Volumetrics Rendering");
  326. if(Settings.volumetrics == false || camera.cameraType == CameraType.Reflection)
  327. {
  328. Shader.SetGlobalTexture("_EnviroVolumetricFogTex", blackTex);
  329. return;
  330. }
  331. if(volumetricsMat == null)
  332. volumetricsMat = new Material(Shader.Find("Hidden/Volumetrics"));
  333. if(blurMat == null)
  334. blurMat = new Material(Shader.Find("Hidden/EnviroBlur"));
  335. CreateVolumetricsBuffers();
  336. SetUpPointLightBuffers();
  337. SetUpSpotLightBuffers();
  338. UpdateVolumetricsShader(volumetricsMat);
  339. //if(cloudsTex != null)
  340. // volumetricsMat.SetTexture("_CloudsTex", cloudsTex);
  341. RenderTextureDescriptor desc = source.descriptor;
  342. if(volumetricsRenderTexture == null)
  343. volumetricsRenderTexture = new RenderTexture(desc);
  344. if(Settings.quality == EnviroFogSettings.Quality.High)
  345. {
  346. RenderTexture target = RenderTexture.GetTemporary(desc);
  347. volumetricsMat.SetTexture("_MainTex",source);
  348. Graphics.Blit(source,target,volumetricsMat);
  349. RenderTexture temp = RenderTexture.GetTemporary(desc);
  350. // horizontal bilateral blur at full res
  351. blurMat.SetTexture("_MainTex",target);
  352. Graphics.Blit(target, temp, blurMat, 0);
  353. // vertical bilateral blur at full res
  354. blurMat.SetTexture("_MainTex",temp);
  355. Graphics.Blit(temp, target, blurMat, 1);
  356. Graphics.Blit(target, volumetricsRenderTexture);
  357. RenderTexture.ReleaseTemporary(temp);
  358. RenderTexture.ReleaseTemporary(target);
  359. }
  360. else if(Settings.quality == EnviroFogSettings.Quality.Medium)
  361. {
  362. desc.width = source.width / 2;
  363. desc.height = source.height / 2;
  364. RenderTexture target = RenderTexture.GetTemporary(desc);
  365. RenderTexture depth = RenderTexture.GetTemporary(desc);
  366. depth.filterMode = FilterMode.Point;
  367. volumetricsMat.SetTexture("_MainTex",source);
  368. Graphics.Blit(source,target,volumetricsMat);
  369. blurMat.SetTexture("_MainTex",source);
  370. Graphics.Blit(source, depth, blurMat, 4);
  371. blurMat.SetTexture("_HalfResDepthBuffer", depth);
  372. blurMat.SetTexture("_HalfResColor", target);
  373. RenderTexture temp = RenderTexture.GetTemporary(desc);
  374. // horizontal bilateral blur at half res
  375. blurMat.SetTexture("_MainTex",target);
  376. Graphics.Blit(target, temp, blurMat, 2);
  377. // vertical bilateral blur at half res
  378. blurMat.SetTexture("_MainTex",temp);
  379. Graphics.Blit(temp, target, blurMat, 3);
  380. // upscale to full res
  381. blurMat.SetTexture("_MainTex",target);
  382. Graphics.Blit(target, volumetricsRenderTexture, blurMat, 5);
  383. RenderTexture.ReleaseTemporary(temp);
  384. RenderTexture.ReleaseTemporary(target);
  385. RenderTexture.ReleaseTemporary(depth);
  386. }
  387. else if (Settings.quality == EnviroFogSettings.Quality.Low)
  388. {
  389. desc.width = source.width / 2;
  390. desc.height = source.height / 2;
  391. RenderTexture depthHalf = RenderTexture.GetTemporary(desc);
  392. depthHalf.filterMode = FilterMode.Point;
  393. desc.width = source.width / 4;
  394. desc.height = source.height / 4;
  395. RenderTexture target = RenderTexture.GetTemporary(desc);
  396. RenderTexture depthQuarter = RenderTexture.GetTemporary(desc);
  397. depthQuarter.filterMode = FilterMode.Point;
  398. volumetricsMat.SetTexture("_MainTex",source);
  399. Graphics.Blit(source,target,volumetricsMat);
  400. blurMat.SetTexture("_MainTex",source);
  401. Graphics.Blit(source, depthHalf, blurMat,4);
  402. Graphics.Blit(source, depthQuarter, blurMat,6);
  403. blurMat.SetTexture("_HalfResDepthBuffer", depthHalf);
  404. blurMat.SetTexture("_QuarterResDepthBuffer", depthQuarter);
  405. //blurMat.SetTexture("_HalfResColor", target);
  406. blurMat.SetTexture("_QuarterResColor", target);
  407. RenderTexture temp = RenderTexture.GetTemporary(desc);
  408. // horizontal bilateral blur at half res
  409. blurMat.SetTexture("_MainTex",target);
  410. Graphics.Blit(target, temp, blurMat, 8);
  411. // vertical bilateral blur at half res
  412. blurMat.SetTexture("_MainTex",temp);
  413. Graphics.Blit(temp, target, blurMat, 9);
  414. // upscale to full res
  415. blurMat.SetTexture("_MainTex",target);
  416. Graphics.Blit(target, volumetricsRenderTexture, blurMat, 7);
  417. RenderTexture.ReleaseTemporary(temp);
  418. RenderTexture.ReleaseTemporary(target);
  419. RenderTexture.ReleaseTemporary(depthHalf);
  420. RenderTexture.ReleaseTemporary(depthQuarter);
  421. }
  422. Shader.SetGlobalTexture("_EnviroVolumetricFogTex", volumetricsRenderTexture);
  423. UnityEngine.Profiling.Profiler.EndSample();
  424. }
  425. #if ENVIRO_URP
  426. public void RenderVolumetricsURP(Camera camera, EnviroURPRenderPass pass, UnityEngine.Rendering.CommandBuffer cmd, RenderTexture source)
  427. {
  428. if(Settings.volumetrics == false || camera.cameraType == CameraType.Reflection)
  429. {
  430. Shader.SetGlobalTexture("_EnviroVolumetricFogTex", blackTex);
  431. return;
  432. }
  433. if(volumetricsMat == null)
  434. volumetricsMat = new Material(Shader.Find("Hidden/VolumetricsURP"));
  435. if(blurMat == null)
  436. blurMat = new Material(Shader.Find("Hidden/EnviroBlur"));
  437. CreateVolumetricsBuffers();
  438. SetUpPointLightBuffers();
  439. SetUpSpotLightBuffers();
  440. UpdateVolumetricsShader(volumetricsMat);
  441. volumetricsMat.EnableKeyword("ENVIROURP");
  442. blurMat.EnableKeyword("ENVIROURP");
  443. //if(cloudsTex != null)
  444. // volumetricsMat.SetTexture("_CloudsTex", cloudsTex);
  445. RenderTextureDescriptor desc = source.descriptor;
  446. desc.colorFormat = RenderTextureFormat.ARGBHalf;
  447. if(volumetricsRenderTexture == null)
  448. volumetricsRenderTexture = new RenderTexture(desc);
  449. if(Settings.quality == EnviroFogSettings.Quality.High)
  450. {
  451. RenderTexture target = RenderTexture.GetTemporary(desc);
  452. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,source,target,volumetricsMat);
  453. RenderTexture temp = RenderTexture.GetTemporary(desc);
  454. // horizontal bilateral blur at full res
  455. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,target,temp,blurMat,0);
  456. // vertical bilateral blur at full res
  457. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,temp,target,blurMat,1);
  458. //Graphics.Blit(target, volumetricsRenderTexture);
  459. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,target,volumetricsRenderTexture);
  460. RenderTexture.ReleaseTemporary(temp);
  461. RenderTexture.ReleaseTemporary(target);
  462. }
  463. else if(Settings.quality == EnviroFogSettings.Quality.Medium)
  464. {
  465. desc.width = source.width / 2;
  466. desc.height = source.height / 2;
  467. RenderTexture target = RenderTexture.GetTemporary(desc);
  468. RenderTexture depth = RenderTexture.GetTemporary(desc);
  469. depth.filterMode = FilterMode.Point;
  470. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,source,target,volumetricsMat);
  471. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,source,depth,blurMat,4);
  472. blurMat.SetTexture("_HalfResDepthBuffer", depth);
  473. blurMat.SetTexture("_HalfResColor", target);
  474. RenderTexture temp = RenderTexture.GetTemporary(desc);
  475. // horizontal bilateral blur at half res
  476. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,target,temp,blurMat,2);
  477. // vertical bilateral blur at half res
  478. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,temp,target,blurMat,3);
  479. // upscale to full res
  480. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,target,volumetricsRenderTexture,blurMat,5);
  481. RenderTexture.ReleaseTemporary(temp);
  482. RenderTexture.ReleaseTemporary(target);
  483. RenderTexture.ReleaseTemporary(depth);
  484. }
  485. else if (Settings.quality == EnviroFogSettings.Quality.Low)
  486. {
  487. desc.width = source.width / 2;
  488. desc.height = source.height / 2;
  489. RenderTexture depthHalf = RenderTexture.GetTemporary(desc);
  490. depthHalf.filterMode = FilterMode.Point;
  491. desc.width = source.width / 4;
  492. desc.height = source.height / 4;
  493. RenderTexture target = RenderTexture.GetTemporary(desc);
  494. RenderTexture depthQuarter = RenderTexture.GetTemporary(desc);
  495. depthQuarter.filterMode = FilterMode.Point;
  496. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,source,target,volumetricsMat);
  497. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,source,depthHalf,blurMat,4);
  498. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,source,depthQuarter,blurMat,6);
  499. blurMat.SetTexture("_HalfResDepthBuffer", depthHalf);
  500. blurMat.SetTexture("_QuarterResDepthBuffer", depthQuarter);
  501. //blurMat.SetTexture("_HalfResColor", target);
  502. blurMat.SetTexture("_QuarterResColor", target);
  503. RenderTexture temp = RenderTexture.GetTemporary(desc);
  504. // horizontal bilateral blur at half res
  505. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,target,temp,blurMat,8);
  506. // vertical bilateral blur at half res
  507. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,temp,target,blurMat,9);
  508. // upscale to full res
  509. pass.CustomBlit(cmd,camera.cameraToWorldMatrix,target,volumetricsRenderTexture,blurMat,7);
  510. RenderTexture.ReleaseTemporary(temp);
  511. RenderTexture.ReleaseTemporary(target);
  512. RenderTexture.ReleaseTemporary(depthHalf);
  513. RenderTexture.ReleaseTemporary(depthQuarter);
  514. }
  515. Shader.SetGlobalTexture("_EnviroVolumetricFogTex", volumetricsRenderTexture);
  516. }
  517. #endif
  518. private void UpdateVolumetricsShader(Material mat)
  519. {
  520. if(myLight == null)
  521. myLight = EnviroHelper.GetDirectionalLight();
  522. mat.SetInt("_Steps", Settings.steps);
  523. if(myLight == null)
  524. {
  525. mat.SetVector("_DirLightDir", new Vector4(0f, 0f, 0f, 1.0f / 2.0f));
  526. Shader.SetGlobalColor("_EnviroDirLightColor", Color.white * 1.0f);
  527. }
  528. else
  529. {
  530. mat.SetVector("_DirLightDir", new Vector4(myLight.transform.forward.x, myLight.transform.forward.y, myLight.transform.forward.z, 1.0f / (myLight.range * myLight.range)));
  531. Shader.SetGlobalColor("_EnviroDirLightColor", myLight.color * myLight.intensity);
  532. }
  533. mat.SetFloat("_MaxRayLength", Settings.maxRange);
  534. mat.SetVector("_WindDirection", new Vector4(Settings.windDirection.x, Settings.windDirection.y,Settings.windDirection.z));
  535. mat.SetVector("_NoiseData", new Vector4(Settings.noiseScale, Settings.noiseIntensity));
  536. mat.SetVector("_MieG", new Vector4(Settings.anistropy, 1 + (Settings.anistropy * Settings.anistropy), 2 * Settings.anistropy, 1.0f / (4.0f * Mathf.PI)));
  537. mat.SetVector("_VolumetricLight", new Vector4(Settings.scattering, Settings.extinction, 1f, 0f));// - SkyboxExtinctionCoef));
  538. mat.SetTexture("_NoiseTexture",Settings.noise);
  539. mat.SetTexture("_DitherTexture",Settings.ditheringTex);
  540. mat.SetVector("_Randomness", new Vector4(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value));
  541. }
  542. private void CreateVolumetricsBuffers()
  543. {
  544. int pointLightCount = 0, spotLightCount = 0;
  545. for(int i = 0; i < fogLights.Count; i++)
  546. {
  547. Enviro.EnviroVolumetricFogLight fogLight = fogLights[i];
  548. if (fogLight == null)
  549. continue;
  550. bool isOn = fogLight.isOn;
  551. switch(fogLight.light.type)
  552. {
  553. case LightType.Point: if (isOn) pointLightCount++; break;
  554. case LightType.Spot: if (isOn) spotLightCount++; break;
  555. }
  556. }
  557. EnviroHelper.CreateBuffer(ref m_PointLightParamsCB, pointLightCount, Marshal.SizeOf(typeof(PointLightParams)));
  558. EnviroHelper.CreateBuffer(ref m_SpotLightParamsCB, spotLightCount, Marshal.SizeOf(typeof(SpotLightParams)));
  559. EnviroHelper.CreateBuffer(ref EnviroManager.instance.clearCB, 1, 4);
  560. }
  561. private void CleanupVolumetrics()
  562. {
  563. if(volumetricsMat != null)
  564. DestroyImmediate(volumetricsMat);
  565. if(blurMat != null)
  566. DestroyImmediate(blurMat);
  567. if(volumetricsRenderTexture != null)
  568. DestroyImmediate(volumetricsRenderTexture);
  569. EnviroHelper.ReleaseComputeBuffer(ref m_PointLightParamsCB);
  570. EnviroHelper.ReleaseComputeBuffer(ref m_SpotLightParamsCB);
  571. EnviroHelper.ReleaseComputeBuffer(ref EnviroManager.instance.clearCB);
  572. }
  573. void SetUpPointLightBuffers()
  574. {
  575. int count = m_PointLightParamsCB == null ? 0 : m_PointLightParamsCB.count;
  576. volumetricsMat.SetFloat("_PointLightsCount", count);
  577. if (count == 0)
  578. {
  579. // Can't not set the buffer
  580. volumetricsMat.SetBuffer("_PointLights", EnviroManager.instance.clearCB);
  581. return;
  582. }
  583. if (m_PointLightParams == null || m_PointLightParams.Length != count)
  584. m_PointLightParams = new PointLightParams[count];
  585. int lightID = 0;
  586. for (int i = 0; i < fogLights.Count; i++)
  587. {
  588. Enviro.EnviroVolumetricFogLight fl = fogLights[i];
  589. if (fl == null || fl.light.type != LightType.Point || !fl.isOn)
  590. continue;
  591. Light light = fl.light;
  592. m_PointLightParams[lightID].pos = light.transform.position;
  593. float range = light.range * fl.range;
  594. m_PointLightParams[lightID].range = 1.0f / (range * range);
  595. m_PointLightParams[lightID].color = new Vector3(light.color.r, light.color.g, light.color.b) * light.intensity * fl.intensity;
  596. lightID++;
  597. }
  598. // TODO: try a constant buffer with setfloats instead for perf
  599. m_PointLightParamsCB.SetData(m_PointLightParams);
  600. volumetricsMat.SetBuffer("_PointLights", m_PointLightParamsCB);
  601. }
  602. void SetUpSpotLightBuffers()
  603. {
  604. int count = m_SpotLightParamsCB == null ? 0 : m_SpotLightParamsCB.count;
  605. volumetricsMat.SetFloat("_SpotLightsCount", count);
  606. if (count == 0)
  607. {
  608. // Can't not set the buffer
  609. volumetricsMat.SetBuffer("_SpotLights", EnviroManager.instance.clearCB);
  610. return;
  611. }
  612. if (m_SpotLightParams == null || m_SpotLightParams.Length != count)
  613. m_SpotLightParams = new SpotLightParams[count];
  614. int lightID = 0;
  615. for (int i = 0; i < fogLights.Count; i++)
  616. {
  617. Enviro.EnviroVolumetricFogLight fl = fogLights[i];
  618. if (fl == null || fl.light.type != LightType.Spot || !fl.isOn)
  619. continue;
  620. Light light = fl.light;
  621. m_SpotLightParams[lightID].pos = light.transform.position;
  622. float range = light.range * fl.range;
  623. m_SpotLightParams[lightID].range = 1.0f / (range * range);
  624. m_SpotLightParams[lightID].color = new Vector3(light.color.r, light.color.g, light.color.b) * light.intensity * fl.intensity;
  625. m_SpotLightParams[lightID].lightDirection = light.transform.forward;
  626. m_SpotLightParams[lightID].lightCosHalfAngle = Mathf.Cos(light.spotAngle * 0.5f * Mathf.Deg2Rad);
  627. lightID++;
  628. }
  629. // TODO: try a constant buffer with setfloats instead for perf
  630. m_SpotLightParamsCB.SetData(m_SpotLightParams);
  631. volumetricsMat.SetBuffer("_SpotLights", m_SpotLightParamsCB);
  632. }
  633. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  634. /// Save and Load
  635. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  636. public void LoadModuleValues ()
  637. {
  638. if(preset != null)
  639. {
  640. Settings = JsonUtility.FromJson<Enviro.EnviroFogSettings>(JsonUtility.ToJson(preset.Settings));
  641. }
  642. else
  643. {
  644. Debug.Log("Please assign a saved module to load from!");
  645. }
  646. }
  647. public void SaveModuleValues ()
  648. {
  649. #if UNITY_EDITOR
  650. EnviroFogModule t = ScriptableObject.CreateInstance<EnviroFogModule>();
  651. t.name = "Fog Module";
  652. t.Settings = JsonUtility.FromJson<Enviro.EnviroFogSettings>(JsonUtility.ToJson(Settings));
  653. string assetPathAndName = UnityEditor.AssetDatabase.GenerateUniqueAssetPath("Assets/Enviro 3" + "/New " + t.name + ".asset");
  654. UnityEditor.AssetDatabase.CreateAsset(t, assetPathAndName);
  655. UnityEditor.AssetDatabase.SaveAssets();
  656. UnityEditor.AssetDatabase.Refresh();
  657. #endif
  658. }
  659. public void SaveModuleValues (EnviroFogModule module)
  660. {
  661. module.Settings = JsonUtility.FromJson<Enviro.EnviroFogSettings>(JsonUtility.ToJson(Settings));
  662. #if UNITY_EDITOR
  663. UnityEditor.EditorUtility.SetDirty(module);
  664. UnityEditor.AssetDatabase.SaveAssets();
  665. #endif
  666. }
  667. }
  668. }