EnviroVolumetricCloudsModule.cs 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System;
  5. namespace Enviro
  6. {
  7. [Serializable]
  8. public class EnviroVolumetricCloudsQuality
  9. {
  10. public bool volumetricClouds = true;
  11. [Range(1,6)]
  12. public int downsampling = 4;
  13. [Range(32,256)]
  14. public int stepsLayer1 = 128;
  15. [Range(32,256)]
  16. public int stepsLayer2 = 64;
  17. [Range(0f,2f)]
  18. public float blueNoiseIntensity = 1f;
  19. [Range(0f,10f)]
  20. public float reprojectionBlendTime = 10f;
  21. [Range(0f,1f)]
  22. public float lodDistance = 0.25f;
  23. }
  24. [Serializable]
  25. public class EnviroCloudGlobalSettings
  26. {
  27. public bool dualLayer = false;
  28. public Gradient sunLightColorGradient;
  29. public Gradient moonLightColorGradient;
  30. public Gradient ambientColorGradient;
  31. public Color sunLightColor;
  32. public Color moonLightColor;
  33. public Color ambientColor;
  34. public bool depthBlending = false;
  35. public Texture3D noise;
  36. public Texture3D detailNoise;
  37. public Texture2D curlTex;
  38. public Texture2D blueNoise;
  39. public float cloudsWorldScale = 5000000f;
  40. public float atmosphereColorSaturateDistance = 25000f;
  41. [Range(0.0f, 2.0f)]
  42. public float ambientLighIntensity = 1f;
  43. public bool cloudShadows = true;
  44. [Range(0.0f, 2.0f)]
  45. public float cloudShadowsIntensity = 1f;
  46. }
  47. [Serializable]
  48. public class EnviroCloudLayerSettings
  49. {
  50. public float cloudsWindDirectionX = 0f;
  51. public float cloudsWindDirectionY = 1f;
  52. public float windIntensity = 0.001f;
  53. [Range(-1f,1f)]
  54. public float coverage = 1f;
  55. public float worleyFreq2 = 4f;
  56. public float worleyFreq1 = 1f;
  57. [Range(0f,1f)]
  58. public float dilateCoverage = 0.5f;
  59. [Range(0f,1f)]
  60. public float dilateType = 0.5f;
  61. [Range(0f,1f)]
  62. public float cloudsTypeModifier = 0.5f;
  63. public Vector2 locationOffset;
  64. public float bottomCloudsHeight = 2000f;
  65. public float topCloudsHeight = 8000f;
  66. [Range(0f,2f)]
  67. public float density = 0.3f;
  68. [Range(0f,2f)]
  69. public float scatteringIntensity = 1f;
  70. [Range(0f,1f)]
  71. public float silverLiningSpread = 0.8f;
  72. [Range(0f,1f)]
  73. public float powderIntensity = 0.5f;
  74. [Range(0f,1f)]
  75. public float curlIntensity = 0.25f;
  76. [Range(0f,0.25f)]
  77. public float lightStepModifier = 0.05f;
  78. [Range(0f,2f)]
  79. public float lightAbsorbtion = 0.5f;
  80. [Range(0f,1f)]
  81. public float multiScatteringA = 0.5f;
  82. [Range(0f,1f)]
  83. public float multiScatteringB = 0.5f;
  84. [Range(0f,1f)]
  85. public float multiScatteringC = 0.5f;
  86. public float baseNoiseUV = 15f;
  87. public float detailNoiseUV = 50f;
  88. [Range(0.0f, 1.0f)]
  89. public float baseErosionIntensity = 0f;
  90. [Range(0.0f, 1.0f)]
  91. public float detailErosionIntensity = 0.3f;
  92. [Range(0.0f, 1.0f)]
  93. public float anvilBias = 0.0f;
  94. }
  95. public class EnviroVolumetricCloudRenderer
  96. {
  97. // Clouds Rendering
  98. public Camera camera;
  99. public Material raymarchMat;
  100. public Material reprojectMat;
  101. public Material depthMat;
  102. public Material blendAndLightingMat;
  103. public Material shadowMat;
  104. public RenderTexture[] fullBuffer;
  105. public int fullBufferIndex;
  106. public RenderTexture undersampleBuffer;
  107. public RenderTexture downsampledDepth;
  108. public Matrix4x4 prevV;
  109. public int frame = 0;
  110. public bool firstFrame = true;
  111. #if ENVIRO_HDRP
  112. public UnityEngine.Rendering.RTHandle[] fullBufferHandles;
  113. public UnityEngine.Rendering.RTHandle undersampleBufferHandle;
  114. public UnityEngine.Rendering.RTHandle downsampledDepthHandle;
  115. #endif
  116. }
  117. [Serializable]
  118. [ExecuteInEditMode]
  119. public class EnviroVolumetricCloudsModule : EnviroModule
  120. {
  121. //Base
  122. public Enviro.EnviroCloudLayerSettings settingsLayer1;
  123. public Enviro.EnviroCloudLayerSettings settingsLayer2;
  124. public Enviro.EnviroCloudGlobalSettings settingsGlobal;
  125. public Enviro.EnviroVolumetricCloudsQuality settingsQuality;
  126. public EnviroVolumetricCloudsModule preset;
  127. //Inspector
  128. public bool showGlobalControls;
  129. public bool showLayer1Controls;
  130. public bool showLayer2Controls;
  131. public bool showCoverageControls;
  132. public bool showLightingControls;
  133. public bool showDensityControls;
  134. public bool showTextureControls;
  135. public bool showWindControls;
  136. //Wind
  137. public Vector3 cloudAnimLayer1;
  138. public Vector3 cloudAnimLayer2;
  139. public Vector3 cloudAnimNonScaled;
  140. //Weather Map
  141. public RenderTexture weatherMap;
  142. private Material weatherMapMat;
  143. private ComputeShader weatherMapCS;
  144. private Light dirLight;
  145. //Update Method
  146. public override void UpdateModule ()
  147. {
  148. UpdateWind();
  149. UnityEngine.Profiling.Profiler.BeginSample("Enviro Clouds Weather Map");
  150. weatherMap = EnviroManager.instance.VolumetricClouds.RenderWeatherMap();
  151. UnityEngine.Profiling.Profiler.EndSample();
  152. }
  153. public override void Enable()
  154. {
  155. }
  156. public override void Disable()
  157. {
  158. if(weatherMapMat != null)
  159. DestroyImmediate(weatherMapMat);
  160. if(weatherMap != null)
  161. DestroyImmediate(weatherMap);
  162. }
  163. public void RenderCloudsShadows(RenderTexture source, RenderTexture destination, EnviroVolumetricCloudRenderer renderer)
  164. {
  165. if(renderer.shadowMat == null)
  166. renderer.shadowMat = new Material(Shader.Find("Hidden/EnviroApplyShadows"));
  167. renderer.shadowMat.SetTexture("_CloudsTex",renderer.undersampleBuffer);
  168. renderer.shadowMat.SetFloat("_Intensity",EnviroManager.instance.VolumetricClouds.settingsGlobal.cloudShadowsIntensity);
  169. renderer.shadowMat.SetTexture("_MainTex",source);
  170. Graphics.Blit(source,destination,renderer.shadowMat);
  171. }
  172. #if ENVIRO_URP
  173. public void RenderCloudsShadowsURP(EnviroURPRenderPass pass,Camera cam, UnityEngine.Rendering.CommandBuffer cmd, RenderTexture source, UnityEngine.Rendering.RenderTargetIdentifier destination, EnviroVolumetricCloudRenderer renderer)
  174. {
  175. if(renderer.shadowMat == null)
  176. renderer.shadowMat = new Material(Shader.Find("Hidden/EnviroApplyShadows"));
  177. renderer.shadowMat.SetTexture("_CloudsTex",renderer.undersampleBuffer);
  178. renderer.shadowMat.SetFloat("_Intensity",EnviroManager.instance.VolumetricClouds.settingsGlobal.cloudShadowsIntensity);
  179. renderer.shadowMat.EnableKeyword("ENVIROURP");
  180. pass.CustomBlit(cmd,cam.cameraToWorldMatrix,source,destination,renderer.shadowMat);
  181. }
  182. #endif
  183. #if ENVIRO_HDRP
  184. public void RenderCloudsShadowsHDRP(Camera cam, UnityEngine.Rendering.CommandBuffer cmd, UnityEngine.Rendering.RTHandle source, UnityEngine.Rendering.RTHandle destination, EnviroVolumetricCloudRenderer renderer)
  185. {
  186. if(renderer.shadowMat == null)
  187. renderer.shadowMat = new Material(Shader.Find("Hidden/EnviroApplyShadowsHDRP"));
  188. renderer.shadowMat.SetTexture("_MainTex",source);
  189. renderer.shadowMat.SetTexture("_CloudsTex",renderer.undersampleBufferHandle);
  190. renderer.shadowMat.SetVector("_HandleScales", new Vector4(1/renderer.undersampleBufferHandle.rtHandleProperties.rtHandleScale.x,1/renderer.undersampleBufferHandle.rtHandleProperties.rtHandleScale.y,1,1));
  191. renderer.shadowMat.SetFloat("_Intensity",EnviroManager.instance.VolumetricClouds.settingsGlobal.cloudShadowsIntensity);
  192. cmd.Blit(source,destination,renderer.shadowMat);
  193. }
  194. #endif
  195. /// Render Clouds
  196. public void RenderVolumetricClouds(Camera cam, RenderTexture source, RenderTexture destination, EnviroVolumetricCloudRenderer renderer, EnviroQuality quality)
  197. {
  198. UnityEngine.Profiling.Profiler.BeginSample("Enviro Clouds Rendering");
  199. int downsampling = settingsQuality.downsampling;
  200. if(quality != null)
  201. downsampling = quality.volumetricCloudsOverride.downsampling;
  202. int width = cam.pixelWidth / downsampling;
  203. int height = cam.pixelHeight / downsampling;
  204. if(cam.cameraType != CameraType.Reflection)
  205. {
  206. if (renderer.fullBuffer == null || renderer.fullBuffer.Length != 2)
  207. {
  208. renderer.fullBuffer = new RenderTexture[2];
  209. }
  210. renderer.fullBufferIndex = (renderer.fullBufferIndex + 1) % 2;
  211. renderer.firstFrame |= CreateRenderTexture(ref renderer.fullBuffer[0], width, height, RenderTextureFormat.ARGBHalf, FilterMode.Bilinear,source.descriptor);
  212. renderer.firstFrame |= CreateRenderTexture(ref renderer.fullBuffer[1], width, height, RenderTextureFormat.ARGBHalf, FilterMode.Bilinear,source.descriptor);
  213. }
  214. renderer.firstFrame |= CreateRenderTexture(ref renderer.undersampleBuffer, width , height, RenderTextureFormat.ARGBHalf, FilterMode.Bilinear,source.descriptor);
  215. renderer.frame++;
  216. if(renderer.frame > 64)
  217. renderer.frame = 0;
  218. if(renderer.depthMat == null)
  219. renderer.depthMat = new Material(Shader.Find("Hidden/EnviroVolumetricCloudsDepth"));
  220. CreateRenderTexture(ref renderer.downsampledDepth, width, height, RenderTextureFormat.RFloat, FilterMode.Point, source.descriptor);
  221. renderer.depthMat.SetTexture("_MainTex", source);
  222. if (downsampling > 1)
  223. {
  224. Graphics.Blit(source, renderer.downsampledDepth, renderer.depthMat, 0); //Downsample the texture.
  225. }
  226. else
  227. {
  228. Graphics.Blit(source, renderer.downsampledDepth, renderer.depthMat, 1); //Just copy it.
  229. }
  230. //1. Raymarch
  231. SetRaymarchShader(cam,renderer, quality);
  232. renderer.raymarchMat.SetTexture("_MainTex", source);
  233. Graphics.Blit(source,renderer.undersampleBuffer,renderer.raymarchMat);
  234. //Pass 2: Reprojection
  235. if(cam.cameraType != CameraType.Reflection)
  236. {
  237. if(renderer.reprojectMat == null)
  238. renderer.reprojectMat = new Material(Shader.Find("Hidden/EnviroVolumetricCloudsReproject"));
  239. SetReprojectShader(cam, renderer, quality);
  240. if (renderer.firstFrame)
  241. {
  242. Graphics.Blit(renderer.undersampleBuffer, renderer.fullBuffer[renderer.fullBufferIndex]);
  243. }
  244. renderer.reprojectMat.SetTexture("_MainTex", renderer.fullBuffer[renderer.fullBufferIndex]);
  245. Graphics.Blit(renderer.fullBuffer[renderer.fullBufferIndex], renderer.fullBuffer[renderer.fullBufferIndex ^ 1], renderer.reprojectMat);
  246. }
  247. //Pass 3: Lighting and Blending
  248. if(renderer.blendAndLightingMat == null)
  249. renderer.blendAndLightingMat = new Material(Shader.Find("Hidden/EnviroVolumetricCloudsBlend"));
  250. SetBlendShader(cam,renderer);
  251. renderer.blendAndLightingMat.SetTexture("_MainTex", source);
  252. Graphics.Blit(source, destination, renderer.blendAndLightingMat);
  253. renderer.prevV = cam.worldToCameraMatrix;
  254. renderer.firstFrame = false;
  255. UnityEngine.Profiling.Profiler.EndSample();
  256. }
  257. #if ENVIRO_URP
  258. public void RenderVolumetricCloudsURP(UnityEngine.Rendering.Universal.RenderingData renderingData, EnviroURPRenderPass pass, UnityEngine.Rendering.CommandBuffer cmd, RenderTexture source, UnityEngine.Rendering.RenderTargetIdentifier destination, EnviroVolumetricCloudRenderer renderer, EnviroQuality quality)
  259. {
  260. UnityEngine.Profiling.Profiler.BeginSample("Enviro Clouds Rendering");
  261. int downsampling = settingsQuality.downsampling;
  262. if(quality != null)
  263. downsampling = quality.volumetricCloudsOverride.downsampling;
  264. int width = renderingData.cameraData.camera.pixelWidth / downsampling;
  265. int height = renderingData.cameraData.camera.pixelHeight / downsampling;
  266. if(renderingData.cameraData.camera.cameraType != CameraType.Reflection)
  267. {
  268. if (renderer.fullBuffer == null || renderer.fullBuffer.Length != 2)
  269. {
  270. renderer.fullBuffer = new RenderTexture[2];
  271. }
  272. renderer.fullBufferIndex = (renderer.fullBufferIndex + 1) % 2;
  273. renderer.firstFrame |= CreateRenderTexture(ref renderer.fullBuffer[0], width, height, RenderTextureFormat.ARGBHalf, FilterMode.Bilinear,source.descriptor);
  274. renderer.firstFrame |= CreateRenderTexture(ref renderer.fullBuffer[1], width, height, RenderTextureFormat.ARGBHalf, FilterMode.Bilinear,source.descriptor);
  275. }
  276. renderer.firstFrame |= CreateRenderTexture(ref renderer.undersampleBuffer, width , height, RenderTextureFormat.ARGBHalf, FilterMode.Bilinear,source.descriptor);
  277. renderer.frame++;
  278. if(renderer.frame > 64)
  279. renderer.frame = 0;
  280. if(renderer.depthMat == null)
  281. renderer.depthMat = new Material(Shader.Find("Hidden/EnviroVolumetricCloudsDepth"));
  282. SetToURP(renderer.depthMat);
  283. CreateRenderTexture(ref renderer.downsampledDepth, width, height, RenderTextureFormat.RFloat, FilterMode.Point, source.descriptor);
  284. if (downsampling > 1)
  285. {
  286. pass.CustomBlit(cmd,renderingData.cameraData.camera.cameraToWorldMatrix,source,renderer.downsampledDepth,renderer.depthMat,0);
  287. }
  288. else
  289. {
  290. pass.CustomBlit(cmd,renderingData.cameraData.camera.cameraToWorldMatrix,source,renderer.downsampledDepth,renderer.depthMat,1);
  291. }
  292. //1. Raymarch
  293. SetRaymarchShader(renderingData.cameraData.camera,renderer, quality);
  294. SetToURP(renderer.raymarchMat);
  295. pass.CustomBlit(cmd,renderingData.cameraData.camera.cameraToWorldMatrix,source,renderer.undersampleBuffer,renderer.raymarchMat);
  296. //Pass 2: Reprojection
  297. if(renderingData.cameraData.camera.cameraType != CameraType.Reflection)
  298. {
  299. if(renderer.reprojectMat == null)
  300. renderer.reprojectMat = new Material(Shader.Find("Hidden/EnviroVolumetricCloudsReproject"));
  301. SetReprojectShader(renderingData.cameraData.camera, renderer, quality);
  302. SetToURP(renderer.reprojectMat);
  303. if (renderer.firstFrame)
  304. pass.CustomBlit(cmd,renderingData.cameraData.camera.cameraToWorldMatrix,renderer.undersampleBuffer,renderer.fullBuffer[renderer.fullBufferIndex]);
  305. pass.CustomBlit(cmd,renderingData.cameraData.camera.cameraToWorldMatrix,renderer.fullBuffer[renderer.fullBufferIndex],renderer.fullBuffer[renderer.fullBufferIndex ^ 1],renderer.reprojectMat);
  306. }
  307. //Pass 3: Lighting and Blending
  308. if(renderer.blendAndLightingMat == null)
  309. renderer.blendAndLightingMat = new Material(Shader.Find("Hidden/EnviroVolumetricCloudsBlend"));
  310. SetBlendShader(renderingData.cameraData.camera,renderer);
  311. SetToURP(renderer.blendAndLightingMat);
  312. pass.CustomBlit(cmd,renderingData.cameraData.camera.cameraToWorldMatrix,source,destination,renderer.blendAndLightingMat);
  313. renderer.prevV = renderingData.cameraData.camera.worldToCameraMatrix;
  314. renderer.firstFrame = false;
  315. UnityEngine.Profiling.Profiler.EndSample();
  316. }
  317. #endif
  318. #if ENVIRO_HDRP
  319. public void RenderVolumetricCloudsHDRP(Camera cam, UnityEngine.Rendering.CommandBuffer cmd, UnityEngine.Rendering.RTHandle source, UnityEngine.Rendering.RTHandle destination, EnviroVolumetricCloudRenderer renderer, EnviroQuality quality)
  320. {
  321. //UnityEngine.Profiling.Profiler.BeginSample("Enviro Clouds Rendering");
  322. int downsampling = settingsQuality.downsampling;
  323. if(quality != null)
  324. downsampling = quality.volumetricCloudsOverride.downsampling;
  325. int width = cam.pixelWidth / downsampling;
  326. int height = cam.pixelHeight / downsampling;
  327. RenderTextureDescriptor desc = source.rt.descriptor;
  328. desc.dimension = UnityEngine.Rendering.TextureDimension.Tex2D;
  329. if(cam.cameraType != CameraType.Reflection)
  330. {
  331. if (renderer.fullBuffer == null || renderer.fullBuffer.Length != 2)
  332. {
  333. renderer.fullBuffer = new RenderTexture[2];
  334. renderer.fullBufferHandles = new UnityEngine.Rendering.RTHandle[2];
  335. }
  336. renderer.fullBufferIndex = (renderer.fullBufferIndex + 1) % 2;
  337. renderer.firstFrame |= CreateRenderTexture(ref renderer.fullBuffer[0], width, height, RenderTextureFormat.ARGBHalf, FilterMode.Bilinear,desc);
  338. renderer.firstFrame |= CreateRenderTexture(ref renderer.fullBuffer[1], width, height, RenderTextureFormat.ARGBHalf, FilterMode.Bilinear,desc);
  339. renderer.fullBufferHandles[0] = UnityEngine.Rendering.RTHandles.Alloc(renderer.fullBuffer[0]);
  340. renderer.fullBufferHandles[1] = UnityEngine.Rendering.RTHandles.Alloc(renderer.fullBuffer[1]);
  341. }
  342. renderer.firstFrame |= CreateRenderTexture(ref renderer.undersampleBuffer, width , height, RenderTextureFormat.ARGBHalf, FilterMode.Bilinear,desc);
  343. renderer.undersampleBufferHandle = UnityEngine.Rendering.RTHandles.Alloc(renderer.undersampleBuffer);
  344. renderer.frame++;
  345. if(renderer.frame > 64)
  346. renderer.frame = 0;
  347. if(renderer.depthMat == null)
  348. renderer.depthMat = new Material(Shader.Find("Hidden/EnviroVolumetricCloudsDepthHDRP"));
  349. CreateRenderTexture(ref renderer.downsampledDepth, width, height, RenderTextureFormat.RFloat, FilterMode.Point, desc);
  350. renderer.downsampledDepthHandle = UnityEngine.Rendering.RTHandles.Alloc(renderer.downsampledDepth);
  351. renderer.depthMat.SetTexture("_MainTex", source);
  352. if (downsampling > 1)
  353. {
  354. cmd.Blit(source, renderer.downsampledDepthHandle, renderer.depthMat, 0); //Downsample the texture.
  355. }
  356. else
  357. {
  358. cmd.Blit(source, renderer.downsampledDepthHandle, renderer.depthMat, 1); //Just copy it.
  359. }
  360. //1. Raymarch
  361. SetRaymarchShader(cam,renderer, quality);
  362. renderer.raymarchMat.SetTexture("_MainTex", source);
  363. cmd.Blit(source,renderer.undersampleBufferHandle,renderer.raymarchMat);
  364. //Pass 2: Reprojection
  365. if(cam.cameraType != CameraType.Reflection)
  366. {
  367. if(renderer.reprojectMat == null)
  368. renderer.reprojectMat = new Material(Shader.Find("Hidden/EnviroVolumetricCloudsReproject"));
  369. SetReprojectShader(cam, renderer, quality);
  370. if (renderer.firstFrame)
  371. {
  372. cmd.Blit(renderer.undersampleBufferHandle, renderer.fullBufferHandles[renderer.fullBufferIndex]);
  373. }
  374. renderer.reprojectMat.SetTexture("_MainTex", renderer.fullBufferHandles[renderer.fullBufferIndex]);
  375. cmd.Blit(renderer.fullBufferHandles[renderer.fullBufferIndex], renderer.fullBufferHandles[renderer.fullBufferIndex ^ 1], renderer.reprojectMat);
  376. }
  377. //Pass 3: Lighting and Blending
  378. if(renderer.blendAndLightingMat == null)
  379. renderer.blendAndLightingMat = new Material(Shader.Find("Hidden/EnviroVolumetricCloudsBlendHDRP"));
  380. SetBlendShader(cam,renderer);
  381. renderer.blendAndLightingMat.SetTexture("_MainTex", source);
  382. cmd.Blit(source, destination, renderer.blendAndLightingMat);
  383. renderer.prevV = cam.worldToCameraMatrix;
  384. renderer.firstFrame = false;
  385. //UnityEngine.Profiling.Profiler.EndSample();
  386. }
  387. #endif
  388. void SetRaymarchShader (Camera cam, EnviroVolumetricCloudRenderer renderer, EnviroQuality quality)
  389. {
  390. if(renderer.raymarchMat == null)
  391. renderer.raymarchMat = new Material(Shader.Find("Hidden/EnviroCloudsRaymarch"));
  392. if(dirLight == null)
  393. {
  394. dirLight = EnviroHelper.GetDirectionalLight();
  395. }
  396. //Check if we use dual lightmode and change the light only in that case. Otherwise keep it to the cached one.
  397. else if (EnviroManager.instance.Lighting != null && EnviroManager.instance.Lighting.Settings.lightingMode == EnviroLighting.LightingMode.Dual)
  398. {
  399. dirLight = EnviroHelper.GetDirectionalLight();
  400. }
  401. EnviroCloudLayerSettings layer1 = settingsLayer1;
  402. EnviroCloudLayerSettings layer2 = settingsLayer2;
  403. EnviroCloudGlobalSettings global = settingsGlobal;
  404. float blueNoiseIntensity = settingsQuality.blueNoiseIntensity;
  405. float lodDistance = settingsQuality.lodDistance;
  406. Vector4 steps = new Vector4(settingsQuality.stepsLayer1,settingsQuality.stepsLayer1,settingsQuality.stepsLayer2,settingsQuality.stepsLayer2);
  407. int downsample = settingsQuality.downsampling;
  408. if(quality != null)
  409. {
  410. blueNoiseIntensity = quality.volumetricCloudsOverride.blueNoiseIntensity;
  411. steps = new Vector4(quality.volumetricCloudsOverride.stepsLayer1,quality.volumetricCloudsOverride.stepsLayer1,quality.volumetricCloudsOverride.stepsLayer2,quality.volumetricCloudsOverride.stepsLayer2);
  412. lodDistance = quality.volumetricCloudsOverride.lodDistance;
  413. downsample = quality.volumetricCloudsOverride.downsampling;
  414. }
  415. //Textures
  416. renderer.raymarchMat.SetTexture("_Noise", settingsGlobal.noise);
  417. renderer.raymarchMat.SetTexture("_DetailNoise", settingsGlobal.detailNoise);
  418. renderer.raymarchMat.SetTexture("_CurlNoise", settingsGlobal.curlTex);
  419. if(weatherMap != null)
  420. renderer.raymarchMat.SetTexture("_WeatherMap",weatherMap);
  421. //Matrix
  422. if(UnityEngine.XR.XRSettings.enabled && UnityEngine.XR.XRSettings.stereoRenderingMode == UnityEngine.XR.XRSettings.StereoRenderingMode.SinglePassInstanced)
  423. {
  424. renderer.raymarchMat.SetMatrix("_InverseProjection", cam.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left).inverse);
  425. renderer.raymarchMat.SetMatrix("_InverseRotation", cam.GetStereoViewMatrix(Camera.StereoscopicEye.Left).inverse);
  426. renderer.raymarchMat.SetMatrix("_InverseProjectionRight", cam.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right).inverse);
  427. renderer.raymarchMat.SetMatrix("_InverseRotationRight", cam.GetStereoViewMatrix(Camera.StereoscopicEye.Right).inverse);
  428. }
  429. else
  430. {
  431. renderer.raymarchMat.SetMatrix("_InverseProjection", cam.projectionMatrix.inverse);
  432. renderer.raymarchMat.SetMatrix("_InverseRotation", cam.cameraToWorldMatrix);
  433. }
  434. renderer.raymarchMat.SetVector("_CameraPosition", cam.transform.position);
  435. renderer.raymarchMat.SetVector("_Steps", steps);
  436. if(dirLight != null)
  437. renderer.raymarchMat.SetVector("_LightDir", -dirLight.transform.forward);
  438. else
  439. renderer.raymarchMat.SetVector("_LightDir", Vector3.zero);
  440. renderer.raymarchMat.SetVector("_CloudsNoiseSettings", new Vector4(layer1.baseNoiseUV, layer1.detailNoiseUV, layer2.baseNoiseUV, layer2.detailNoiseUV));
  441. renderer.raymarchMat.SetVector("_CloudsLighting", new Vector4(layer1.scatteringIntensity, 0f, 0f, layer1.silverLiningSpread));
  442. renderer.raymarchMat.SetVector("_CloudsLighting2", new Vector4(layer2.scatteringIntensity, 0f, 0f, layer2.silverLiningSpread));
  443. renderer.raymarchMat.SetVector("_CloudsLightingExtended", new Vector4(layer1.powderIntensity, layer1.curlIntensity, layer1.lightStepModifier, layer1.lightAbsorbtion));
  444. renderer.raymarchMat.SetVector("_CloudsLightingExtended2", new Vector4(layer2.powderIntensity, layer2.curlIntensity, layer2.lightStepModifier, layer2.lightAbsorbtion));
  445. renderer.raymarchMat.SetVector("_CloudsMultiScattering", new Vector4(layer1.multiScatteringA, layer1.multiScatteringB, layer1.multiScatteringC, 0));
  446. renderer.raymarchMat.SetVector("_CloudsMultiScattering2", new Vector4(layer2.multiScatteringA, layer2.multiScatteringB, layer2.multiScatteringC, 0));
  447. renderer.raymarchMat.SetVector("_CloudsParameter", new Vector4(layer1.bottomCloudsHeight, layer1.topCloudsHeight, 1 / (layer1.topCloudsHeight - layer1.bottomCloudsHeight), settingsGlobal.cloudsWorldScale));
  448. renderer.raymarchMat.SetVector("_CloudsParameter2", new Vector4(layer2.bottomCloudsHeight, layer2.topCloudsHeight, 1 / (layer2.topCloudsHeight - layer2.bottomCloudsHeight), settingsGlobal.cloudsWorldScale));
  449. renderer.raymarchMat.SetVector("_CloudDensityScale", new Vector4(layer1.density, layer2.density, blueNoiseIntensity, 0f));
  450. renderer.raymarchMat.SetVector("_CloudsCoverageSettings", new Vector4(layer1.coverage, 0f, layer1.anvilBias, layer2.anvilBias));
  451. renderer.raymarchMat.SetVector("_CloudsAnimation", new Vector4(cloudAnimLayer1.x, cloudAnimLayer1.y, cloudAnimLayer1.z, 0f));
  452. renderer.raymarchMat.SetVector("_CloudsWindDirection", new Vector4(settingsLayer1.cloudsWindDirectionX, settingsLayer1.cloudsWindDirectionY, cloudAnimNonScaled.x,cloudAnimNonScaled.y));
  453. renderer.raymarchMat.SetVector("_CloudsErosionIntensity", new Vector4(1f - layer1.baseErosionIntensity, layer1.detailErosionIntensity,1f - layer2.baseErosionIntensity, layer2.detailErosionIntensity));
  454. renderer.raymarchMat.SetFloat("_LODDistance", lodDistance);
  455. renderer.raymarchMat.SetTexture("_DownsampledDepth", renderer.downsampledDepth);
  456. renderer.raymarchMat.SetInt("_Frame", renderer.frame);
  457. renderer.raymarchMat.SetTexture("_BlueNoise",settingsGlobal.blueNoise);
  458. renderer.raymarchMat.SetVector("_Randomness", new Vector4(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value));
  459. renderer.raymarchMat.SetVector("_Resolution", new Vector4(renderer.undersampleBuffer.width,renderer.undersampleBuffer.height,downsample,0f));
  460. if(settingsGlobal.dualLayer)
  461. renderer.raymarchMat.EnableKeyword("ENVIRO_DUAL_LAYER");
  462. else
  463. renderer.raymarchMat.DisableKeyword("ENVIRO_DUAL_LAYER");
  464. if(settingsGlobal.cloudShadows)
  465. renderer.raymarchMat.EnableKeyword("ENVIRO_CLOUD_SHADOWS");
  466. else
  467. renderer.raymarchMat.DisableKeyword("ENVIRO_CLOUD_SHADOWS");
  468. SetDepthBlending(renderer.raymarchMat);
  469. }
  470. void SetReprojectShader (Camera cam, EnviroVolumetricCloudRenderer renderer, EnviroQuality quality)
  471. {
  472. float reprojectionBlendTime = settingsQuality.reprojectionBlendTime;
  473. if(quality != null)
  474. {
  475. reprojectionBlendTime = quality.volumetricCloudsOverride.reprojectionBlendTime;
  476. }
  477. SetDepthBlending(renderer.reprojectMat);
  478. #if ENVIRO_HDRP
  479. renderer.reprojectMat.SetTexture("_DownsampledDepth", renderer.downsampledDepthHandle);
  480. renderer.reprojectMat.SetTexture("_UndersampleCloudTex", renderer.undersampleBufferHandle);
  481. #else
  482. renderer.reprojectMat.SetTexture("_DownsampledDepth", renderer.downsampledDepth);
  483. renderer.reprojectMat.SetTexture("_UndersampleCloudTex", renderer.undersampleBuffer);
  484. #endif
  485. if(UnityEngine.XR.XRSettings.enabled && UnityEngine.XR.XRSettings.stereoRenderingMode == UnityEngine.XR.XRSettings.StereoRenderingMode.SinglePassInstanced)
  486. {
  487. renderer.reprojectMat.SetMatrix("_PrevVP", renderer.prevV);
  488. renderer.reprojectMat.SetVector("_ProjectionExtents", EnviroHelper.GetProjectionExtents(cam,Camera.StereoscopicEye.Left));
  489. renderer.reprojectMat.SetVector("_ProjectionExtentsRight", EnviroHelper.GetProjectionExtents(cam,Camera.StereoscopicEye.Right));
  490. }
  491. else
  492. {
  493. renderer.reprojectMat.SetMatrix("_PrevVP", renderer.prevV);
  494. renderer.reprojectMat.SetVector("_ProjectionExtents", EnviroHelper.GetProjectionExtents(cam));
  495. }
  496. renderer.reprojectMat.SetFloat("_BlendTime", reprojectionBlendTime);
  497. Matrix4x4 camtowolrd = Matrix4x4.TRS(cam.transform.position, cam.transform.rotation, Vector3.one);
  498. renderer.reprojectMat.SetMatrix("_CamToWorld", camtowolrd);
  499. }
  500. void SetBlendShader (Camera cam, EnviroVolumetricCloudRenderer renderer)
  501. {
  502. SetDepthBlending(renderer.blendAndLightingMat);
  503. if(UnityEngine.XR.XRSettings.enabled && UnityEngine.XR.XRSettings.stereoRenderingMode == UnityEngine.XR.XRSettings.StereoRenderingMode.SinglePassInstanced)
  504. {
  505. renderer.blendAndLightingMat.SetVector("_ProjectionExtents", EnviroHelper.GetProjectionExtents(cam,Camera.StereoscopicEye.Left));
  506. renderer.blendAndLightingMat.SetVector("_ProjectionExtentsRight", EnviroHelper.GetProjectionExtents(cam,Camera.StereoscopicEye.Right));
  507. }
  508. else
  509. {
  510. renderer.blendAndLightingMat.SetVector("_ProjectionExtents", EnviroHelper.GetProjectionExtents(cam));
  511. }
  512. #if ENVIRO_HDRP
  513. renderer.blendAndLightingMat.SetTexture("_DownsampledDepth", renderer.downsampledDepthHandle);
  514. renderer.blendAndLightingMat.SetVector("_DepthHandleScale", new Vector4(1/renderer.downsampledDepthHandle.rtHandleProperties.rtHandleScale.x,1/renderer.downsampledDepthHandle.rtHandleProperties.rtHandleScale.y,1,1));
  515. #else
  516. renderer.blendAndLightingMat.SetTexture("_DownsampledDepth", renderer.downsampledDepth);
  517. #endif
  518. Matrix4x4 camtowolrd = Matrix4x4.TRS(cam.transform.position, cam.transform.rotation, Vector3.one);
  519. renderer.blendAndLightingMat.SetMatrix("_CamToWorld", camtowolrd);
  520. Color directLightColor;
  521. if(!EnviroManager.instance.isNight)
  522. {
  523. directLightColor = settingsGlobal.sunLightColorGradient.Evaluate(EnviroManager.instance.solarTime);
  524. }
  525. else
  526. {
  527. directLightColor = settingsGlobal.moonLightColorGradient.Evaluate(EnviroManager.instance.lunarTime);
  528. }
  529. renderer.blendAndLightingMat.SetColor("_DirectLightColor", directLightColor);
  530. renderer.blendAndLightingMat.SetColor("_AmbientColor", settingsGlobal.ambientColorGradient.Evaluate(EnviroManager.instance.solarTime) * settingsGlobal.ambientLighIntensity);
  531. renderer.blendAndLightingMat.SetFloat("_AtmosphereColorSaturateDistance",settingsGlobal.atmosphereColorSaturateDistance);
  532. //We don't use reprojection pass for reflections.
  533. #if ENVIRO_HDRP
  534. if(cam.cameraType == CameraType.Reflection)
  535. {
  536. renderer.blendAndLightingMat.SetTexture("_CloudTex", renderer.undersampleBufferHandle);
  537. renderer.blendAndLightingMat.SetVector("_HandleScales", new Vector4(1 / renderer.undersampleBufferHandle.rtHandleProperties.rtHandleScale.x, 1 / renderer.undersampleBufferHandle.rtHandleProperties.rtHandleScale.y,1,1));
  538. }
  539. else
  540. {
  541. renderer.blendAndLightingMat.SetTexture("_CloudTex", renderer.fullBufferHandles[renderer.fullBufferIndex ^ 1]);
  542. renderer.blendAndLightingMat.SetVector("_HandleScales", new Vector4(1/ renderer.fullBufferHandles[renderer.fullBufferIndex ^ 1].rtHandleProperties.rtHandleScale.x, 1/ renderer.fullBufferHandles[renderer.fullBufferIndex ^ 1].rtHandleProperties.rtHandleScale.y,1,1));
  543. }
  544. #else
  545. if(cam.cameraType == CameraType.Reflection)
  546. {
  547. renderer.blendAndLightingMat.SetTexture("_CloudTex", renderer.undersampleBuffer);
  548. }
  549. else
  550. {
  551. renderer.blendAndLightingMat.SetTexture("_CloudTex", renderer.fullBuffer[renderer.fullBufferIndex ^ 1]);
  552. }
  553. #endif
  554. }
  555. private void SetDepthBlending(Material mat)
  556. {
  557. if(settingsGlobal.depthBlending)
  558. mat.EnableKeyword("ENVIRO_DEPTH_BLENDING");
  559. else
  560. mat.DisableKeyword("ENVIRO_DEPTH_BLENDING");
  561. }
  562. private void SetToURP(Material mat)
  563. {
  564. mat.EnableKeyword("ENVIROURP");
  565. }
  566. public bool CreateRenderTexture(ref RenderTexture texture, int width, int height, RenderTextureFormat format, FilterMode filterMode, RenderTextureDescriptor dsc)
  567. {
  568. if(texture != null && (texture.width != width || texture.height != height || texture.vrUsage != dsc.vrUsage))
  569. {
  570. DestroyImmediate(texture);
  571. texture = null;
  572. }
  573. if(texture == null)
  574. {
  575. RenderTextureDescriptor d = dsc;
  576. d.width = width;
  577. d.height = height;
  578. d.colorFormat = format;
  579. d.depthBufferBits = 0;
  580. texture = new RenderTexture(d);
  581. texture.antiAliasing = 1;
  582. texture.useMipMap = false;
  583. texture.filterMode = filterMode;
  584. texture.Create();
  585. return true;
  586. }
  587. else
  588. {
  589. return false;
  590. }
  591. }
  592. public RenderTexture RenderWeatherMap()
  593. {
  594. if(weatherMapMat == null)
  595. weatherMapMat = new Material(Shader.Find("Enviro3/Standard/WeatherTexture"));
  596. if (weatherMap == null)
  597. {
  598. weatherMap = new RenderTexture(512, 512, 0, RenderTextureFormat.ARGBFloat);
  599. weatherMap.wrapMode = TextureWrapMode.Repeat;
  600. }
  601. weatherMapMat.SetFloat("_CoverageLayer1",settingsLayer1.coverage);
  602. weatherMapMat.SetFloat("_WorleyFreq1Layer1", settingsLayer1.worleyFreq1);
  603. weatherMapMat.SetFloat("_WorleyFreq2Layer1",settingsLayer1.worleyFreq2);
  604. weatherMapMat.SetFloat("_DilateCoverageLayer1",settingsLayer1.dilateCoverage);
  605. weatherMapMat.SetFloat("_DilateTypeLayer1",settingsLayer1.dilateType);
  606. weatherMapMat.SetFloat("_CloudsTypeModifierLayer1",settingsLayer1.cloudsTypeModifier);
  607. if(settingsGlobal.dualLayer)
  608. {
  609. weatherMapMat.EnableKeyword("ENVIRO_DUAL_LAYER");
  610. weatherMapMat.SetFloat("_CoverageLayer2",settingsLayer2.coverage);
  611. weatherMapMat.SetFloat("_WorleyFreq1Layer2",settingsLayer2.worleyFreq1);
  612. weatherMapMat.SetFloat("_WorleyFreq2Layer2", settingsLayer2.worleyFreq2);
  613. weatherMapMat.SetFloat("_DilateCoverageLayer2",settingsLayer2.dilateCoverage);
  614. weatherMapMat.SetFloat("_DilateTypeLayer2",settingsLayer2.dilateType);
  615. weatherMapMat.SetFloat("_CloudsTypeModifierLayer2",settingsLayer2.cloudsTypeModifier);
  616. }
  617. else
  618. {
  619. weatherMapMat.DisableKeyword("ENVIRO_DUAL_LAYER");
  620. }
  621. weatherMapMat.SetVector("_LocationOffset",new Vector4(settingsLayer1.locationOffset.x,settingsLayer1.locationOffset.y,settingsLayer2.locationOffset.x,settingsLayer2.locationOffset.y));
  622. //weatherMapMat.SetVector("_WindDirection", cloudAnimNonScaled);
  623. //weatherMapMat.SetFloat("_WindSpeed",settingsLayer1.windIntensity);
  624. Graphics.Blit(null,weatherMap,weatherMapMat);
  625. return weatherMap;
  626. }
  627. public RenderTexture RenderWeatherMapCS()
  628. {
  629. if(weatherMapMat == null)
  630. weatherMapMat = new Material(Shader.Find("Enviro3/Standard/WeatherMap"));
  631. if(weatherMapCS == null)
  632. weatherMapCS = (ComputeShader)Resources.Load("Shader/Clouds/EnviroWeatherMapCS");
  633. if (weatherMap == null)
  634. {
  635. weatherMap = new RenderTexture(512, 512, 0, RenderTextureFormat.ARGBFloat);
  636. weatherMap.wrapMode = TextureWrapMode.Repeat;
  637. weatherMap.enableRandomWrite = true;
  638. }
  639. weatherMap.enableRandomWrite = true;
  640. weatherMapCS.SetFloat("_CoverageLayer1",settingsLayer1.coverage);
  641. weatherMapCS.SetFloat("_WorleyFreq1Layer1", settingsLayer1.worleyFreq1);
  642. weatherMapCS.SetFloat("_WorleyFreq2Layer1",settingsLayer1.worleyFreq2);
  643. weatherMapCS.SetFloat("_DilateCoverageLayer1",settingsLayer1.dilateCoverage);
  644. weatherMapCS.SetFloat("_DilateTypeLayer1",settingsLayer1.dilateType);
  645. weatherMapCS.SetFloat("_CloudsTypeModifierLayer1",settingsLayer1.cloudsTypeModifier);
  646. if(settingsGlobal.dualLayer)
  647. {
  648. weatherMapCS.SetFloat("_CoverageLayer2",settingsLayer2.coverage);
  649. weatherMapCS.SetFloat("_WorleyFreq1Layer2",settingsLayer2.worleyFreq1);
  650. weatherMapCS.SetFloat("_WorleyFreq2Layer2", settingsLayer2.worleyFreq2);
  651. weatherMapCS.SetFloat("_DilateCoverageLayer2",settingsLayer2.dilateCoverage);
  652. weatherMapCS.SetFloat("_DilateTypeLayer2",settingsLayer2.dilateType);
  653. weatherMapCS.SetFloat("_CloudsTypeModifierLayer2",settingsLayer2.cloudsTypeModifier);
  654. }
  655. weatherMapCS.SetVector("_LocationOffset",new Vector4(settingsLayer1.locationOffset.x,settingsLayer1.locationOffset.y,settingsLayer2.locationOffset.x,settingsLayer2.locationOffset.y));
  656. weatherMapCS.SetVector("_WindDirection", cloudAnimNonScaled);
  657. weatherMapCS.SetFloat("_WindSpeed",settingsLayer1.windIntensity);
  658. weatherMapCS.SetTexture(0,"Result",weatherMap);
  659. weatherMapCS.Dispatch(0, 512/16, 512/16, 1);
  660. return weatherMap;
  661. }
  662. private void UpdateWind()
  663. {
  664. cloudAnimLayer1 += new Vector3((settingsLayer1.windIntensity * settingsLayer1.cloudsWindDirectionX) * Time.deltaTime, (settingsLayer1.windIntensity * settingsLayer1.cloudsWindDirectionY) * Time.deltaTime, -1f * settingsLayer1.windIntensity * Time.deltaTime);
  665. cloudAnimLayer1 = EnviroHelper.PingPong(cloudAnimLayer1);
  666. if(settingsGlobal.dualLayer)
  667. {
  668. cloudAnimLayer2 += new Vector3((settingsLayer2.windIntensity * settingsLayer2.cloudsWindDirectionX) * Time.deltaTime, (settingsLayer2.windIntensity * settingsLayer2.cloudsWindDirectionY) * Time.deltaTime, -1f * settingsLayer2.windIntensity * Time.deltaTime);
  669. cloudAnimLayer2 = EnviroHelper.PingPong(cloudAnimLayer2);
  670. }
  671. cloudAnimNonScaled += new Vector3((settingsLayer1.windIntensity * settingsLayer1.cloudsWindDirectionX) * Time.deltaTime, (settingsLayer1.windIntensity * settingsLayer1.cloudsWindDirectionY) * Time.deltaTime, -1f * settingsLayer1.windIntensity * Time.deltaTime) * 0.1f;
  672. }
  673. //Save and Load
  674. public void LoadModuleValues ()
  675. {
  676. if(preset != null)
  677. {
  678. settingsLayer1 = JsonUtility.FromJson<Enviro.EnviroCloudLayerSettings>(JsonUtility.ToJson(preset.settingsLayer1));
  679. settingsLayer2 = JsonUtility.FromJson<Enviro.EnviroCloudLayerSettings>(JsonUtility.ToJson(preset.settingsLayer2));
  680. settingsGlobal = JsonUtility.FromJson<Enviro.EnviroCloudGlobalSettings>(JsonUtility.ToJson(preset.settingsGlobal));
  681. }
  682. else
  683. {
  684. Debug.Log("Please assign a saved module to load from!");
  685. }
  686. }
  687. public void SaveModuleValues ()
  688. {
  689. #if UNITY_EDITOR
  690. EnviroVolumetricCloudsModule t = ScriptableObject.CreateInstance<EnviroVolumetricCloudsModule>();
  691. t.name = "Cloud Module";
  692. t.settingsLayer1 = JsonUtility.FromJson<Enviro.EnviroCloudLayerSettings>(JsonUtility.ToJson(settingsLayer1));
  693. t.settingsLayer2 = JsonUtility.FromJson<Enviro.EnviroCloudLayerSettings>(JsonUtility.ToJson(settingsLayer2));
  694. t.settingsGlobal = JsonUtility.FromJson<Enviro.EnviroCloudGlobalSettings>(JsonUtility.ToJson(settingsGlobal));
  695. string assetPathAndName = UnityEditor.AssetDatabase.GenerateUniqueAssetPath("Assets/Enviro 3" + "/New " + t.name + ".asset");
  696. UnityEditor.AssetDatabase.CreateAsset(t, assetPathAndName);
  697. UnityEditor.AssetDatabase.SaveAssets();
  698. UnityEditor.AssetDatabase.Refresh();
  699. #endif
  700. }
  701. public void SaveModuleValues (EnviroVolumetricCloudsModule module)
  702. {
  703. module.settingsLayer1 = JsonUtility.FromJson<Enviro.EnviroCloudLayerSettings>(JsonUtility.ToJson(settingsLayer1));
  704. module.settingsLayer2 = JsonUtility.FromJson<Enviro.EnviroCloudLayerSettings>(JsonUtility.ToJson(settingsLayer2));
  705. module.settingsGlobal = JsonUtility.FromJson<Enviro.EnviroCloudGlobalSettings>(JsonUtility.ToJson(settingsGlobal));
  706. #if UNITY_EDITOR
  707. UnityEditor.EditorUtility.SetDirty(module);
  708. UnityEditor.AssetDatabase.SaveAssets();
  709. #endif
  710. }
  711. }
  712. }