DynamicFog.cs 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. #if UNITY_EDITOR
  6. using UnityEditor;
  7. #endif
  8. namespace DynamicFogAndMist {
  9. public enum FOG_TYPE {
  10. DesktopFogWithSkyHaze = 0,
  11. MobileFogWithSkyHaze = 1,
  12. MobileFogOnlyGround = 2,
  13. DesktopFogPlusWithSkyHaze = 3,
  14. MobileFogSimple = 4,
  15. MobileFogBasic = 5,
  16. MobileFogOrthogonal = 6,
  17. DesktopFogPlusOrthogonal = 7
  18. }
  19. static class FOG_TYPE_Ext {
  20. public static bool isPlus (this FOG_TYPE fogType) {
  21. return fogType == FOG_TYPE.DesktopFogPlusWithSkyHaze || fogType == FOG_TYPE.MobileFogSimple || fogType == FOG_TYPE.MobileFogBasic || fogType == FOG_TYPE.MobileFogOrthogonal || fogType == FOG_TYPE.DesktopFogPlusOrthogonal;
  22. }
  23. }
  24. public enum FOG_PRESET {
  25. Clear,
  26. Mist,
  27. WindyMist,
  28. GroundFog,
  29. Fog,
  30. HeavyFog,
  31. SandStorm,
  32. Custom
  33. }
  34. [ExecuteInEditMode]
  35. [RequireComponent (typeof(Camera))]
  36. [HelpURL ("http://kronnect.com/taptapgo")]
  37. #if UNITY_5_4_OR_NEWER
  38. [ImageEffectAllowedInSceneView]
  39. #endif
  40. public class DynamicFog : MonoBehaviour {
  41. [SerializeField]
  42. FOG_TYPE _effectType = FOG_TYPE.DesktopFogPlusWithSkyHaze;
  43. public FOG_TYPE effectType {
  44. get { return _effectType; }
  45. set {
  46. if (value != _effectType) {
  47. _effectType = value;
  48. _preset = FOG_PRESET.Custom;
  49. UpdateMaterialProperties ();
  50. }
  51. }
  52. }
  53. [SerializeField]
  54. FOG_PRESET _preset = FOG_PRESET.Mist;
  55. public FOG_PRESET preset {
  56. get { return _preset; }
  57. set {
  58. if (value != _preset) {
  59. _preset = value;
  60. UpdateMaterialProperties ();
  61. }
  62. }
  63. }
  64. [SerializeField]
  65. DynamicFogProfile _profile;
  66. public DynamicFogProfile profile {
  67. get { return _profile; }
  68. set {
  69. if (value != _profile) {
  70. _profile = value;
  71. if (_profile != null) {
  72. _profile.Load (this);
  73. _preset = FOG_PRESET.Custom;
  74. UpdateMaterialProperties ();
  75. }
  76. }
  77. }
  78. }
  79. [SerializeField]
  80. bool _useFogVolumes = false;
  81. public bool useFogVolumes {
  82. get { return _useFogVolumes; }
  83. set {
  84. if (value != _useFogVolumes) {
  85. _useFogVolumes = value;
  86. }
  87. }
  88. }
  89. [SerializeField]
  90. bool _enableDithering = false;
  91. public bool enableDithering {
  92. get { return _enableDithering; }
  93. set {
  94. if (value != _enableDithering) {
  95. _enableDithering = value;
  96. UpdateMaterialProperties ();
  97. }
  98. }
  99. }
  100. [SerializeField, Range (0, 0.2f)]
  101. float _ditherStrength = 0.03f;
  102. public float ditherStrength {
  103. get { return _ditherStrength; }
  104. set {
  105. if (value != _ditherStrength) {
  106. _ditherStrength = value;
  107. UpdateMaterialProperties ();
  108. }
  109. }
  110. }
  111. [SerializeField, Range (0, 1)]
  112. float _alpha = 1.0f;
  113. public float alpha {
  114. get { return _alpha; }
  115. set {
  116. if (value != _alpha) {
  117. _alpha = value;
  118. UpdateMaterialProperties ();
  119. }
  120. }
  121. }
  122. [SerializeField, Range (0, 1)]
  123. float _noiseStrength = 0.5f;
  124. public float noiseStrength {
  125. get { return _noiseStrength; }
  126. set {
  127. if (value != _noiseStrength) {
  128. _noiseStrength = value;
  129. UpdateMaterialProperties ();
  130. }
  131. }
  132. }
  133. [SerializeField, Range (0.01f, 1)]
  134. float _noiseScale = 0.1f;
  135. public float noiseScale {
  136. get { return _noiseScale; }
  137. set {
  138. if (value != _noiseScale) {
  139. _noiseScale = value;
  140. UpdateMaterialProperties ();
  141. }
  142. }
  143. }
  144. [SerializeField, Range (0, 0.999f)]
  145. float _distance = 0.1f;
  146. public float distance {
  147. get { return _distance; }
  148. set {
  149. if (value != _distance) {
  150. _distance = value;
  151. UpdateMaterialProperties ();
  152. }
  153. }
  154. }
  155. [SerializeField, Range (0.0001f, 2f)]
  156. float _distanceFallOff = 0.01f;
  157. public float distanceFallOff {
  158. get { return _distanceFallOff; }
  159. set {
  160. if (value != _distanceFallOff) {
  161. _distanceFallOff = value;
  162. UpdateMaterialProperties ();
  163. }
  164. }
  165. }
  166. [SerializeField, Range (0, 1.2f)]
  167. float _maxDistance = 0.999f;
  168. public float maxDistance {
  169. get { return _maxDistance; }
  170. set {
  171. if (value != _maxDistance) {
  172. _maxDistance = value;
  173. UpdateMaterialProperties ();
  174. }
  175. }
  176. }
  177. [SerializeField, Range (0.0001f, 0.5f)]
  178. float _maxDistanceFallOff = 0f;
  179. public float maxDistanceFallOff {
  180. get { return _maxDistanceFallOff; }
  181. set {
  182. if (value != _maxDistanceFallOff) {
  183. _maxDistanceFallOff = value;
  184. UpdateMaterialProperties ();
  185. }
  186. }
  187. }
  188. [SerializeField, Range (0, 500)]
  189. float _height = 1f;
  190. public float height {
  191. get { return _height; }
  192. set {
  193. if (value != _height) {
  194. _height = value;
  195. UpdateMaterialProperties ();
  196. }
  197. }
  198. }
  199. [SerializeField, Range (0, 500)]
  200. float _maxHeight = 100f;
  201. public float maxHeight {
  202. get { return _maxHeight; }
  203. set {
  204. if (value != _maxHeight) {
  205. _maxHeight = value;
  206. UpdateMaterialProperties ();
  207. }
  208. }
  209. }
  210. // used in orthogonal fog
  211. [SerializeField, Range (0.0001f, 1)]
  212. float _heightFallOff = 0.1f;
  213. public float heightFallOff {
  214. get { return _heightFallOff; }
  215. set {
  216. if (value != _heightFallOff) {
  217. _heightFallOff = value;
  218. UpdateMaterialProperties ();
  219. }
  220. }
  221. }
  222. [SerializeField]
  223. float _baselineHeight = 0;
  224. public float baselineHeight {
  225. get { return _baselineHeight; }
  226. set {
  227. if (value != _baselineHeight) {
  228. _baselineHeight = value;
  229. UpdateMaterialProperties ();
  230. }
  231. }
  232. }
  233. [SerializeField]
  234. bool _clipUnderBaseline = false;
  235. public bool clipUnderBaseline {
  236. get { return _clipUnderBaseline; }
  237. set {
  238. if (value != _clipUnderBaseline) {
  239. _clipUnderBaseline = value;
  240. UpdateMaterialProperties ();
  241. }
  242. }
  243. }
  244. [SerializeField, Range (0, 15)]
  245. float _turbulence = 0.1f;
  246. public float turbulence {
  247. get { return _turbulence; }
  248. set {
  249. if (value != _turbulence) {
  250. _turbulence = value;
  251. UpdateMaterialProperties ();
  252. }
  253. }
  254. }
  255. [SerializeField, Range (0, 5.0f)]
  256. float _speed = 0.1f;
  257. public float speed {
  258. get { return _speed; }
  259. set {
  260. if (value != _speed) {
  261. _speed = value;
  262. UpdateMaterialProperties ();
  263. }
  264. }
  265. }
  266. [SerializeField]
  267. Vector3 _windDirection = new Vector3(1,0,1);
  268. public Vector3 windDirection {
  269. get { return _windDirection; }
  270. set {
  271. if (value != _windDirection) {
  272. _windDirection = value;
  273. UpdateMaterialProperties ();
  274. }
  275. }
  276. }
  277. [SerializeField]
  278. Color _color = Color.white;
  279. public Color color {
  280. get { return _color; }
  281. set {
  282. if (value != _color) {
  283. _color = value;
  284. UpdateMaterialProperties ();
  285. }
  286. }
  287. }
  288. [SerializeField]
  289. Color _color2 = Color.gray;
  290. public Color color2 {
  291. get { return _color2; }
  292. set {
  293. if (value != _color2) {
  294. _color2 = value;
  295. UpdateMaterialProperties ();
  296. }
  297. }
  298. }
  299. [SerializeField, Range (0, 500)]
  300. float _skyHaze = 50f;
  301. public float skyHaze {
  302. get { return _skyHaze; }
  303. set {
  304. if (value != _skyHaze) {
  305. _skyHaze = value;
  306. UpdateMaterialProperties ();
  307. }
  308. }
  309. }
  310. [SerializeField, Range (0, 1)]
  311. float _skySpeed = 0.3f;
  312. public float skySpeed {
  313. get { return _skySpeed; }
  314. set {
  315. if (value != _skySpeed) {
  316. _skySpeed = value;
  317. UpdateMaterialProperties ();
  318. }
  319. }
  320. }
  321. [SerializeField, Range (0, 1)]
  322. float _skyNoiseStrength = 0.1f;
  323. public float skyNoiseStrength {
  324. get { return _skyNoiseStrength; }
  325. set {
  326. if (value != _skyNoiseStrength) {
  327. _skyNoiseStrength = value;
  328. UpdateMaterialProperties ();
  329. }
  330. }
  331. }
  332. [SerializeField, Range (0, 1)]
  333. float _skyAlpha = 1.0f;
  334. public float skyAlpha {
  335. get { return _skyAlpha; }
  336. set {
  337. if (value != _skyAlpha) {
  338. _skyAlpha = value;
  339. UpdateMaterialProperties ();
  340. }
  341. }
  342. }
  343. [SerializeField]
  344. GameObject _sun;
  345. public GameObject sun {
  346. get { return _sun; }
  347. set {
  348. if (value != _sun) {
  349. _sun = value;
  350. UpdateMaterialProperties ();
  351. }
  352. }
  353. }
  354. [SerializeField]
  355. bool _fogOfWarEnabled = false;
  356. public bool fogOfWarEnabled {
  357. get { return _fogOfWarEnabled; }
  358. set {
  359. if (value != _fogOfWarEnabled) {
  360. _fogOfWarEnabled = value;
  361. UpdateMaterialProperties ();
  362. }
  363. }
  364. }
  365. [SerializeField]
  366. Vector3 _fogOfWarCenter;
  367. public Vector3 fogOfWarCenter {
  368. get { return _fogOfWarCenter; }
  369. set {
  370. if (value != _fogOfWarCenter) {
  371. _fogOfWarCenter = value;
  372. UpdateMaterialProperties ();
  373. }
  374. }
  375. }
  376. [SerializeField]
  377. Vector3 _fogOfWarSize = new Vector3 (1024, 0, 1024);
  378. public Vector3 fogOfWarSize {
  379. get { return _fogOfWarSize; }
  380. set {
  381. if (value != _fogOfWarSize) {
  382. _fogOfWarSize = value;
  383. UpdateMaterialProperties ();
  384. }
  385. }
  386. }
  387. [SerializeField]
  388. int _fogOfWarTextureSize = 256;
  389. public int fogOfWarTextureSize {
  390. get { return _fogOfWarTextureSize; }
  391. set {
  392. if (value != _fogOfWarTextureSize) {
  393. _fogOfWarTextureSize = value;
  394. UpdateMaterialProperties ();
  395. }
  396. }
  397. }
  398. [SerializeField]
  399. bool _useSinglePassStereoRenderingMatrix = false;
  400. public bool useSinglePassStereoRenderingMatrix {
  401. get { return _useSinglePassStereoRenderingMatrix; }
  402. set {
  403. if (value != _useSinglePassStereoRenderingMatrix) {
  404. _useSinglePassStereoRenderingMatrix = value;
  405. UpdateMaterialProperties ();
  406. }
  407. }
  408. }
  409. [SerializeField]
  410. bool _useXZDistance = false;
  411. public bool useXZDistance {
  412. get { return _useXZDistance; }
  413. set {
  414. if (value != _useXZDistance) {
  415. _useXZDistance = value;
  416. UpdateMaterialProperties ();
  417. }
  418. }
  419. }
  420. [SerializeField, Range (0, 1)]
  421. float _scattering = 0.7f;
  422. public float scattering {
  423. get { return _scattering; }
  424. set {
  425. if (value != _scattering) {
  426. _scattering = value;
  427. UpdateMaterialProperties ();
  428. }
  429. }
  430. }
  431. [SerializeField]
  432. Color _scatteringColor = new Color (1, 1, 0.8f);
  433. public Color scatteringColor {
  434. get { return _scatteringColor; }
  435. set {
  436. if (value != _scatteringColor) {
  437. _scatteringColor = value;
  438. UpdateMaterialProperties ();
  439. }
  440. }
  441. }
  442. Material fogMatAdv, fogMatFogSky, fogMatOnlyFog, fogMatVol, fogMatSimple, fogMatBasic, fogMatOrthogonal, fogMatDesktopPlusOrthogonal;
  443. [SerializeField]
  444. Material
  445. fogMat;
  446. float initialFogAlpha, targetFogAlpha;
  447. float initialSkyHazeAlpha, targetSkyHazeAlpha;
  448. bool targetFogColors;
  449. Color initialFogColor1, targetFogColor1;
  450. Color initialFogColor2, targetFogColor2;
  451. float transitionDuration;
  452. float transitionStartTime;
  453. float currentFogAlpha, currentSkyHazeAlpha;
  454. bool transitionAlpha, transitionColor, transitionProfile;
  455. DynamicFogProfile initialProfile, targetProfile;
  456. Color currentFogColor1, currentFogColor2;
  457. Camera currentCamera;
  458. Texture2D fogOfWarTexture;
  459. Color32[] fogOfWarColorBuffer;
  460. Light sunLight;
  461. Vector3 sunDirection = Vector3.zero;
  462. Color sunColor = Color.white;
  463. float sunIntensity = 1f;
  464. static DynamicFog _fog;
  465. List<string> shaderKeywords;
  466. bool matOrtho;
  467. bool shouldUpdateMaterialProperties;
  468. public static DynamicFog instance {
  469. get {
  470. if (_fog == null) {
  471. foreach (Camera camera in Camera.allCameras) {
  472. _fog = camera.GetComponent<DynamicFog> ();
  473. if (_fog != null)
  474. break;
  475. }
  476. }
  477. return _fog;
  478. }
  479. }
  480. public string GetCurrentPresetName () {
  481. return Enum.GetName (typeof(FOG_PRESET), preset);
  482. }
  483. public Camera fogCamera {
  484. get {
  485. return currentCamera;
  486. }
  487. }
  488. // Creates a private material used to the effect
  489. void OnEnable () {
  490. Init ();
  491. UpdateMaterialPropertiesNow ();
  492. }
  493. void Reset () {
  494. UpdateMaterialPropertiesNow ();
  495. }
  496. void OnDestroy () {
  497. fogMat = null;
  498. if (fogMatVol != null) {
  499. DestroyImmediate (fogMatVol);
  500. fogMatVol = null;
  501. if (fogMatDesktopPlusOrthogonal != null) {
  502. DestroyImmediate (fogMatDesktopPlusOrthogonal);
  503. fogMatDesktopPlusOrthogonal = null;
  504. }
  505. }
  506. if (fogMatAdv != null) {
  507. DestroyImmediate (fogMatAdv);
  508. fogMatAdv = null;
  509. }
  510. if (fogMatFogSky != null) {
  511. DestroyImmediate (fogMatFogSky);
  512. fogMatFogSky = null;
  513. }
  514. if (fogMatOnlyFog != null) {
  515. DestroyImmediate (fogMatOnlyFog);
  516. fogMatOnlyFog = null;
  517. }
  518. if (fogMatSimple != null) {
  519. DestroyImmediate (fogMatSimple);
  520. fogMatSimple = null;
  521. }
  522. if (fogMatBasic != null) {
  523. DestroyImmediate (fogMatBasic);
  524. fogMatBasic = null;
  525. }
  526. if (fogMatOrthogonal != null) {
  527. DestroyImmediate (fogMatOrthogonal);
  528. fogMatOrthogonal = null;
  529. }
  530. if (fogMatDesktopPlusOrthogonal != null) {
  531. DestroyImmediate (fogMatDesktopPlusOrthogonal);
  532. fogMatOrthogonal = null;
  533. }
  534. if (fogOfWarTexture != null) {
  535. DestroyImmediate (fogOfWarTexture);
  536. fogOfWarTexture = null;
  537. }
  538. }
  539. void Init () {
  540. targetFogAlpha = -1;
  541. targetSkyHazeAlpha = -1;
  542. currentCamera = GetComponent<Camera> ();
  543. UpdateFogOfWarTexture ();
  544. if (_profile != null)
  545. _profile.Load (this);
  546. #if UNITY_EDITOR
  547. if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.Android)
  548. {
  549. #if UNITY_5_5_OR_NEWER
  550. _useSinglePassStereoRenderingMatrix = PlayerSettings.stereoRenderingPath == StereoRenderingPath.SinglePass;
  551. #else
  552. _useSinglePassStereoRenderingMatrix = PlayerSettings.singlePassStereoRendering;
  553. #endif
  554. }
  555. #endif
  556. }
  557. // Check possible alpha transition
  558. void Update () {
  559. if (fogMat == null)
  560. return;
  561. // Check profile transition
  562. if (transitionProfile) {
  563. float t = (Time.time - transitionStartTime) / transitionDuration;
  564. if (t > 1)
  565. t = 1;
  566. DynamicFogProfile.Lerp (initialProfile, targetProfile, t, this);
  567. if (t >= 1f) {
  568. transitionProfile = false;
  569. }
  570. }
  571. // Check alpha transitions
  572. if (transitionAlpha) {
  573. if (targetFogAlpha >= 0) {
  574. if (targetFogAlpha != currentFogAlpha || targetSkyHazeAlpha != currentSkyHazeAlpha) {
  575. if (transitionDuration > 0) {
  576. currentFogAlpha = Mathf.Lerp (initialFogAlpha, targetFogAlpha, (Time.time - transitionStartTime) / transitionDuration);
  577. currentSkyHazeAlpha = Mathf.Lerp (initialSkyHazeAlpha, targetSkyHazeAlpha, (Time.time - transitionStartTime) / transitionDuration);
  578. } else {
  579. currentFogAlpha = targetFogAlpha;
  580. currentSkyHazeAlpha = targetSkyHazeAlpha;
  581. transitionAlpha = false;
  582. }
  583. fogMat.SetFloat ("_FogAlpha", currentFogAlpha);
  584. SetSkyData ();
  585. }
  586. } else if (currentFogAlpha != alpha || targetSkyHazeAlpha != currentSkyHazeAlpha) {
  587. if (transitionDuration > 0) {
  588. currentFogAlpha = Mathf.Lerp (initialFogAlpha, alpha, (Time.time - transitionStartTime) / transitionDuration);
  589. currentSkyHazeAlpha = Mathf.Lerp (initialSkyHazeAlpha, alpha, (Time.time - transitionStartTime) / transitionDuration);
  590. } else {
  591. currentFogAlpha = alpha;
  592. currentSkyHazeAlpha = skyAlpha;
  593. transitionAlpha = false;
  594. }
  595. fogMat.SetFloat ("_FogAlpha", currentFogAlpha);
  596. SetSkyData ();
  597. }
  598. }
  599. // Check color transitions
  600. if (transitionColor) {
  601. if (targetFogColors) {
  602. if (targetFogColor1 != currentFogColor1 || targetFogColor2 != currentFogColor2) {
  603. if (transitionDuration > 0) {
  604. currentFogColor1 = Color.Lerp (initialFogColor1, targetFogColor1, (Time.time - transitionStartTime) / transitionDuration);
  605. currentFogColor2 = Color.Lerp (initialFogColor2, targetFogColor2, (Time.time - transitionStartTime) / transitionDuration);
  606. } else {
  607. currentFogColor1 = targetFogColor1;
  608. currentFogColor2 = targetFogColor2;
  609. transitionColor = false;
  610. }
  611. fogMat.SetColor ("_FogColor", currentFogColor1);
  612. fogMat.SetColor ("_FogColor2", currentFogColor2);
  613. }
  614. } else if (currentFogColor1 != color || currentFogColor2 != color2) {
  615. if (transitionDuration > 0) {
  616. currentFogColor1 = Color.Lerp (initialFogColor1, color, (Time.time - transitionStartTime) / transitionDuration);
  617. currentFogColor2 = Color.Lerp (initialFogColor2, color2, (Time.time - transitionStartTime) / transitionDuration);
  618. } else {
  619. currentFogColor1 = color;
  620. currentFogColor2 = color2;
  621. transitionColor = false;
  622. }
  623. fogMat.SetColor ("_FogColor", currentFogColor1);
  624. fogMat.SetColor ("_FogColor2", currentFogColor2);
  625. }
  626. }
  627. // Updates sun illumination
  628. if (sun != null) {
  629. bool needFogColorUpdate = false;
  630. if (sun.transform.forward != sunDirection) {
  631. needFogColorUpdate = true;
  632. }
  633. if (sunLight != null) {
  634. if (sunLight.color != sunColor || sunLight.intensity != sunIntensity) {
  635. needFogColorUpdate = true;
  636. }
  637. }
  638. if (needFogColorUpdate)
  639. UpdateFogColor ();
  640. }
  641. }
  642. void OnDidApplyAnimationProperties () { // support for animating property based fields
  643. shouldUpdateMaterialProperties = true;
  644. }
  645. public void CheckPreset () {
  646. if (_preset != FOG_PRESET.Custom) {
  647. _effectType = FOG_TYPE.DesktopFogWithSkyHaze;
  648. }
  649. switch (preset) {
  650. case FOG_PRESET.Clear:
  651. alpha = 0;
  652. break;
  653. case FOG_PRESET.Mist:
  654. alpha = 0.75f;
  655. skySpeed = 0.11f;
  656. skyHaze = 15;
  657. skyNoiseStrength = 1;
  658. skyAlpha = 0.33f;
  659. distance = 0;
  660. distanceFallOff = 0.07f;
  661. height = 4.4f;
  662. heightFallOff = 1;
  663. turbulence = 0;
  664. noiseStrength = 0.6f;
  665. speed = 0.01f;
  666. color = new Color (0.89f, 0.89f, 0.89f, 1);
  667. color2 = color;
  668. maxDistance = 0.999f;
  669. maxDistanceFallOff = 0f;
  670. break;
  671. case FOG_PRESET.WindyMist:
  672. alpha = 0.75f;
  673. skySpeed = 0.3f;
  674. skyHaze = 35;
  675. skyNoiseStrength = 0.32f;
  676. skyAlpha = 0.33f;
  677. distance = 0;
  678. distanceFallOff = 0.07f;
  679. height = 2f;
  680. heightFallOff = 1;
  681. turbulence = 2;
  682. noiseStrength = 0.6f;
  683. speed = 0.06f;
  684. color = new Color (0.89f, 0.89f, 0.89f, 1);
  685. color2 = color;
  686. maxDistance = 0.999f;
  687. maxDistanceFallOff = 0f;
  688. break;
  689. case FOG_PRESET.GroundFog:
  690. alpha = 1;
  691. skySpeed = 0.3f;
  692. skyHaze = 35;
  693. skyNoiseStrength = 0.32f;
  694. skyAlpha = 0.33f;
  695. distance = 0;
  696. distanceFallOff = 0;
  697. height = 1f;
  698. heightFallOff = 1;
  699. turbulence = 0.4f;
  700. noiseStrength = 0.7f;
  701. speed = 0.005f;
  702. color = new Color (0.89f, 0.89f, 0.89f, 1);
  703. color2 = color;
  704. maxDistance = 0.999f;
  705. maxDistanceFallOff = 0f;
  706. break;
  707. case FOG_PRESET.Fog:
  708. alpha = 0.96f;
  709. skySpeed = 0.3f;
  710. skyHaze = 155;
  711. skyNoiseStrength = 0.6f;
  712. skyAlpha = 0.93f;
  713. distance = effectType.isPlus () ? 0.2f : 0.01f;
  714. distanceFallOff = 0.04f;
  715. height = 20f;
  716. heightFallOff = 1;
  717. turbulence = 0.4f;
  718. noiseStrength = 0.4f;
  719. speed = 0.005f;
  720. color = new Color (0.89f, 0.89f, 0.89f, 1);
  721. color2 = color;
  722. maxDistance = 0.999f;
  723. maxDistanceFallOff = 0f;
  724. break;
  725. case FOG_PRESET.HeavyFog:
  726. alpha = 1;
  727. skySpeed = 0.05f;
  728. skyHaze = 350;
  729. skyNoiseStrength = 0.8f;
  730. skyAlpha = 0.97f;
  731. distance = effectType.isPlus () ? 0.1f : 0f;
  732. distanceFallOff = 0.045f;
  733. height = 35f;
  734. heightFallOff = 0.88f;
  735. turbulence = 0.4f;
  736. noiseStrength = 0.24f;
  737. speed = 0.003f;
  738. color = new Color (0.86f, 0.847f, 0.847f, 1);
  739. color2 = color;
  740. maxDistance = 0.999f;
  741. maxDistanceFallOff = 0f;
  742. break;
  743. case FOG_PRESET.SandStorm:
  744. alpha = 1;
  745. skySpeed = 0.49f;
  746. skyHaze = 333;
  747. skyNoiseStrength = 0.72f;
  748. skyAlpha = 0.97f;
  749. distance = effectType.isPlus () ? 0.15f : 0f;
  750. distanceFallOff = 0.028f;
  751. height = 83f;
  752. heightFallOff = 0;
  753. turbulence = 15;
  754. noiseStrength = 0.45f;
  755. speed = 0.2f;
  756. color = new Color (0.364f, 0.36f, 0.36f, 1);
  757. color2 = color;
  758. maxDistance = 0.999f;
  759. maxDistanceFallOff = 0f;
  760. break;
  761. }
  762. }
  763. void OnPreCull () {
  764. if (currentCamera != null && currentCamera.depthTextureMode == DepthTextureMode.None) {
  765. currentCamera.depthTextureMode = DepthTextureMode.Depth;
  766. }
  767. }
  768. // Postprocess the image
  769. void OnRenderImage (RenderTexture source, RenderTexture destination) {
  770. if (fogMat == null || _alpha == 0 || currentCamera == null) {
  771. Graphics.Blit (source, destination);
  772. return;
  773. }
  774. if (shouldUpdateMaterialProperties) {
  775. shouldUpdateMaterialProperties = false;
  776. UpdateMaterialPropertiesNow ();
  777. }
  778. if (currentCamera.orthographic) {
  779. if (!matOrtho)
  780. ResetMaterial ();
  781. fogMat.SetVector ("_ClipDir", currentCamera.transform.forward);
  782. } else {
  783. if (matOrtho)
  784. ResetMaterial ();
  785. }
  786. if (_useSinglePassStereoRenderingMatrix && UnityEngine.XR.XRSettings.enabled) {
  787. fogMat.SetMatrix ("_ClipToWorld", currentCamera.cameraToWorldMatrix);
  788. } else {
  789. fogMat.SetMatrix ("_ClipToWorld", currentCamera.cameraToWorldMatrix * currentCamera.projectionMatrix.inverse);
  790. }
  791. Graphics.Blit (source, destination, fogMat);
  792. }
  793. void ResetMaterial () {
  794. fogMat = null;
  795. fogMatAdv = null;
  796. fogMatFogSky = null;
  797. fogMatOnlyFog = null;
  798. fogMatSimple = null;
  799. fogMatBasic = null;
  800. fogMatVol = null;
  801. fogMatDesktopPlusOrthogonal = null;
  802. fogMatOrthogonal = null;
  803. UpdateMaterialProperties ();
  804. }
  805. public void UpdateMaterialProperties () {
  806. if (Application.isPlaying) {
  807. shouldUpdateMaterialProperties = true;
  808. } else {
  809. UpdateMaterialPropertiesNow ();
  810. }
  811. }
  812. void UpdateMaterialPropertiesNow () {
  813. CheckPreset ();
  814. CopyTransitionValues ();
  815. string matName;
  816. switch (effectType) {
  817. case FOG_TYPE.MobileFogOnlyGround:
  818. if (fogMatOnlyFog == null) {
  819. if (currentCamera.orthographic) {
  820. matOrtho = true;
  821. matName = "Materials/DFOOnlyFog";
  822. } else {
  823. matOrtho = false;
  824. matName = "Materials/DFGOnlyFog";
  825. }
  826. fogMatOnlyFog = Instantiate (Resources.Load<Material> (matName)) as Material;
  827. fogMatOnlyFog.hideFlags = HideFlags.DontSave;
  828. }
  829. fogMat = fogMatOnlyFog;
  830. break;
  831. case FOG_TYPE.MobileFogWithSkyHaze:
  832. if (fogMatFogSky == null) {
  833. if (currentCamera.orthographic) {
  834. matOrtho = true;
  835. matName = "Materials/DFOWithSky";
  836. } else {
  837. matOrtho = false;
  838. matName = "Materials/DFGWithSky";
  839. }
  840. fogMatFogSky = Instantiate (Resources.Load<Material> (matName)) as Material;
  841. fogMatFogSky.hideFlags = HideFlags.DontSave;
  842. }
  843. fogMat = fogMatFogSky;
  844. break;
  845. case FOG_TYPE.DesktopFogPlusWithSkyHaze:
  846. if (fogMatVol == null) {
  847. if (currentCamera.orthographic) {
  848. matOrtho = true;
  849. matName = "Materials/DFODesktopPlus";
  850. } else {
  851. matOrtho = false;
  852. matName = "Materials/DFGDesktopPlus";
  853. }
  854. fogMatVol = Instantiate (Resources.Load<Material> (matName)) as Material;
  855. fogMatVol.hideFlags = HideFlags.DontSave;
  856. }
  857. fogMat = fogMatVol;
  858. break;
  859. case FOG_TYPE.MobileFogSimple:
  860. if (fogMatSimple == null) {
  861. if (currentCamera.orthographic) {
  862. matOrtho = true;
  863. matName = "Materials/DFOSimple";
  864. } else {
  865. matOrtho = false;
  866. matName = "Materials/DFGSimple";
  867. }
  868. fogMatSimple = Instantiate (Resources.Load<Material> (matName)) as Material;
  869. fogMatSimple.hideFlags = HideFlags.DontSave;
  870. }
  871. fogMat = fogMatSimple;
  872. break;
  873. case FOG_TYPE.MobileFogBasic:
  874. if (fogMatBasic == null) {
  875. if (currentCamera.orthographic) {
  876. matOrtho = true;
  877. matName = "Materials/DFOBasic";
  878. } else {
  879. matOrtho = false;
  880. matName = "Materials/DFGBasic";
  881. }
  882. fogMatBasic = Instantiate (Resources.Load<Material> (matName)) as Material;
  883. fogMatBasic.hideFlags = HideFlags.DontSave;
  884. }
  885. fogMat = fogMatBasic;
  886. break;
  887. case FOG_TYPE.MobileFogOrthogonal:
  888. if (fogMatOrthogonal == null) {
  889. if (currentCamera.orthographic) {
  890. matOrtho = true;
  891. matName = "Materials/DFOOrthogonal";
  892. } else {
  893. matOrtho = false;
  894. matName = "Materials/DFGOrthogonal";
  895. }
  896. fogMatOrthogonal = Instantiate (Resources.Load<Material> (matName)) as Material;
  897. fogMatOrthogonal.hideFlags = HideFlags.DontSave;
  898. }
  899. fogMat = fogMatOrthogonal;
  900. break;
  901. case FOG_TYPE.DesktopFogPlusOrthogonal:
  902. if (fogMatDesktopPlusOrthogonal == null) {
  903. if (currentCamera.orthographic) {
  904. matOrtho = true;
  905. matName = "Materials/DFODesktopPlusOrthogonal";
  906. } else {
  907. matOrtho = false;
  908. matName = "Materials/DFGDesktopPlusOrthogonal";
  909. }
  910. fogMatDesktopPlusOrthogonal = Instantiate (Resources.Load<Material> (matName)) as Material;
  911. fogMatDesktopPlusOrthogonal.hideFlags = HideFlags.DontSave;
  912. }
  913. fogMat = fogMatDesktopPlusOrthogonal;
  914. break;
  915. default:
  916. if (fogMatAdv == null) {
  917. if (currentCamera.orthographic) {
  918. matOrtho = true;
  919. matName = "Materials/DFODesktop";
  920. } else {
  921. matOrtho = false;
  922. matName = "Materials/DFGDesktop";
  923. }
  924. fogMatAdv = Instantiate (Resources.Load<Material> (matName)) as Material;
  925. fogMatAdv.hideFlags = HideFlags.DontSave;
  926. }
  927. fogMat = fogMatAdv;
  928. break;
  929. }
  930. if (fogMat == null)
  931. return;
  932. if (currentCamera == null)
  933. currentCamera = GetComponent<Camera> ();
  934. float sp = effectType == FOG_TYPE.DesktopFogPlusWithSkyHaze ? _speed * 5f : _speed;
  935. fogMat.SetVector ("_FogSpeed", -_windDirection.normalized * sp);
  936. Vector4 noiseData = new Vector4 (_noiseStrength, _turbulence, currentCamera.farClipPlane * 15.0f / 1000f, _noiseScale);
  937. fogMat.SetVector ("_FogNoiseData", noiseData);
  938. Vector4 heightData = new Vector4 (_height + 0.001f, _baselineHeight, _clipUnderBaseline ? -0.01f : -10000, _heightFallOff);
  939. if (_effectType == FOG_TYPE.MobileFogOrthogonal || _effectType == FOG_TYPE.DesktopFogPlusOrthogonal) {
  940. heightData.z = maxHeight;
  941. }
  942. fogMat.SetVector ("_FogHeightData", heightData);
  943. fogMat.SetFloat ("_FogAlpha", currentFogAlpha);
  944. Vector4 distanceData = new Vector4 (_distance, _distanceFallOff, _maxDistance, _maxDistanceFallOff);
  945. if (effectType.isPlus ()) {
  946. distanceData.x = currentCamera.farClipPlane * _distance;
  947. distanceData.y = distanceFallOff * distanceData.x + 0.0001f;
  948. distanceData.z *= currentCamera.farClipPlane;
  949. }
  950. fogMat.SetVector ("_FogDistance", distanceData);
  951. UpdateFogColor ();
  952. SetSkyData ();
  953. if (shaderKeywords == null) {
  954. shaderKeywords = new List<string> ();
  955. } else {
  956. shaderKeywords.Clear ();
  957. }
  958. if (fogOfWarEnabled) {
  959. if (fogOfWarTexture == null) {
  960. UpdateFogOfWarTexture ();
  961. }
  962. fogMat.SetTexture ("_FogOfWar", fogOfWarTexture);
  963. fogMat.SetVector ("_FogOfWarCenter", _fogOfWarCenter);
  964. fogMat.SetVector ("_FogOfWarSize", _fogOfWarSize);
  965. Vector3 ca = fogOfWarCenter - 0.5f * _fogOfWarSize;
  966. fogMat.SetVector ("_FogOfWarCenterAdjusted", new Vector3 (ca.x / _fogOfWarSize.x, 1f, ca.z / _fogOfWarSize.z));
  967. shaderKeywords.Add ("FOG_OF_WAR_ON");
  968. }
  969. if (_enableDithering) {
  970. fogMat.SetFloat ("_FogDither", _ditherStrength);
  971. shaderKeywords.Add ("DITHER_ON");
  972. }
  973. fogMat.shaderKeywords = shaderKeywords.ToArray ();
  974. }
  975. void CopyTransitionValues () {
  976. currentFogAlpha = _alpha;
  977. currentSkyHazeAlpha = _skyAlpha;
  978. currentFogColor1 = _color;
  979. currentFogColor2 = _color2;
  980. }
  981. void SetSkyData () {
  982. // x = haze, y = speed, z = noise, w = alpha
  983. Vector4 skyData = new Vector4 (_skyHaze, _skySpeed, _skyNoiseStrength, currentSkyHazeAlpha);
  984. fogMat.SetVector ("_FogSkyData", skyData);
  985. }
  986. void UpdateFogColor () {
  987. if (fogMat == null)
  988. return;
  989. if (_sun != null) {
  990. if (sunLight == null)
  991. sunLight = _sun.GetComponent<Light> ();
  992. if (sunLight != null && sunLight.transform != _sun.transform) {
  993. sunLight = _sun.GetComponent<Light> ();
  994. }
  995. sunDirection = _sun.transform.forward;
  996. if (sunLight != null) {
  997. sunColor = sunLight.color;
  998. sunIntensity = sunLight.intensity;
  999. }
  1000. }
  1001. float fogIntensity = sunIntensity * Mathf.Clamp01 (1.0f - sunDirection.y);
  1002. fogMat.SetColor ("_FogColor", fogIntensity * currentFogColor1 * sunColor);
  1003. fogMat.SetColor ("_FogColor2", fogIntensity * currentFogColor2 * sunColor);
  1004. Color sColor = fogIntensity * scatteringColor;
  1005. fogMat.SetColor ("_SunColor", new Vector4 (sColor.r, sColor.g, sColor.b, scattering));
  1006. fogMat.SetVector ("_SunDir", -sunDirection);
  1007. }
  1008. #region Fog Volume
  1009. public void SetTargetProfile (DynamicFogProfile targetProfile, float duration) {
  1010. if (!_useFogVolumes)
  1011. return;
  1012. this.preset = FOG_PRESET.Custom;
  1013. this.initialProfile = ScriptableObject.CreateInstance<DynamicFogProfile> ();
  1014. this.initialProfile.Save (this);
  1015. this.targetProfile = targetProfile;
  1016. this.transitionDuration = duration;
  1017. this.transitionStartTime = Time.time;
  1018. this.transitionProfile = true;
  1019. }
  1020. public void ClearTargetProfile (float duration) {
  1021. SetTargetProfile (initialProfile, duration);
  1022. }
  1023. public void SetTargetAlpha (float newFogAlpha, float newSkyHazeAlpha, float duration) {
  1024. if (!useFogVolumes)
  1025. return;
  1026. this.preset = FOG_PRESET.Custom;
  1027. this.initialFogAlpha = currentFogAlpha;
  1028. this.initialSkyHazeAlpha = currentSkyHazeAlpha;
  1029. this.targetFogAlpha = newFogAlpha;
  1030. this.targetSkyHazeAlpha = newSkyHazeAlpha;
  1031. this.transitionDuration = duration;
  1032. this.transitionStartTime = Time.time;
  1033. this.transitionAlpha = true;
  1034. }
  1035. public void ClearTargetAlpha (float duration) {
  1036. SetTargetAlpha (-1, -1, duration);
  1037. }
  1038. public void SetTargetColors (Color color1, Color color2, float duration) {
  1039. if (!useFogVolumes)
  1040. return;
  1041. this.preset = FOG_PRESET.Custom;
  1042. this.initialFogColor1 = currentFogColor1;
  1043. this.initialFogColor2 = currentFogColor2;
  1044. this.targetFogColor1 = color1;
  1045. this.targetFogColor2 = color2;
  1046. this.transitionDuration = duration;
  1047. this.transitionStartTime = Time.time;
  1048. this.targetFogColors = true;
  1049. this.transitionColor = true;
  1050. }
  1051. public void ClearTargetColors (float duration) {
  1052. this.targetFogColors = false;
  1053. SetTargetColors (color, color2, duration);
  1054. }
  1055. #endregion
  1056. #region Fog of War stuff
  1057. void UpdateFogOfWarTexture () {
  1058. if (!fogOfWarEnabled)
  1059. return;
  1060. int size = GetScaledSize (fogOfWarTextureSize, 1.0f);
  1061. // fogOfWarTexture = new Texture2D(size, size, TextureFormat.Alpha8, false);
  1062. fogOfWarTexture = new Texture2D (size, size, TextureFormat.ARGB32, false);
  1063. fogOfWarTexture.hideFlags = HideFlags.DontSave;
  1064. fogOfWarTexture.filterMode = FilterMode.Bilinear;
  1065. fogOfWarTexture.wrapMode = TextureWrapMode.Clamp;
  1066. ResetFogOfWar ();
  1067. }
  1068. /// <summary>
  1069. /// Changes the alpha value of the fog of war at world position. It takes into account FogOfWarCenter and FogOfWarSize.
  1070. /// Note that only x and z coordinates are used. Y (vertical) coordinate is ignored.
  1071. /// </summary>
  1072. /// <param name="worldPosition">in world space coordinates.</param>
  1073. /// <param name="radius">radius of application in world units.</param>
  1074. public void SetFogOfWarAlpha (Vector3 worldPosition, float radius, float fogNewAlpha) {
  1075. if (fogOfWarTexture == null)
  1076. return;
  1077. float tx = (worldPosition.x - fogOfWarCenter.x) / fogOfWarSize.x + 0.5f;
  1078. if (tx < 0 || tx > 1f)
  1079. return;
  1080. float tz = (worldPosition.z - fogOfWarCenter.z) / fogOfWarSize.z + 0.5f;
  1081. if (tz < 0 || tz > 1f)
  1082. return;
  1083. int tw = fogOfWarTexture.width;
  1084. int th = fogOfWarTexture.height;
  1085. int px = (int)(tx * tw);
  1086. int pz = (int)(tz * th);
  1087. int colorBufferPos = pz * tw + px;
  1088. byte newAlpha8 = (byte)(fogNewAlpha * 255);
  1089. Color32 existingColor = fogOfWarColorBuffer [colorBufferPos];
  1090. if (newAlpha8 != existingColor.a) { // just to avoid over setting the texture in an Update() loop
  1091. float tr = radius / fogOfWarSize.z;
  1092. int delta = Mathf.FloorToInt (th * tr);
  1093. for (int r = pz - delta; r <= pz + delta; r++) {
  1094. if (r > 0 && r < th - 1) {
  1095. for (int c = px - delta; c <= px + delta; c++) {
  1096. if (c > 0 && c < tw - 1) {
  1097. int distance = Mathf.FloorToInt (Mathf.Sqrt ((pz - r) * (pz - r) + (px - c) * (px - c)));
  1098. if (distance <= delta) {
  1099. colorBufferPos = r * tw + c;
  1100. Color32 colorBuffer = fogOfWarColorBuffer [colorBufferPos];
  1101. colorBuffer.a = (byte)Mathf.Lerp (newAlpha8, colorBuffer.a, (float)distance / delta);
  1102. fogOfWarColorBuffer [colorBufferPos] = colorBuffer;
  1103. fogOfWarTexture.SetPixel (c, r, colorBuffer);
  1104. }
  1105. }
  1106. }
  1107. }
  1108. }
  1109. fogOfWarTexture.Apply ();
  1110. }
  1111. }
  1112. public void ResetFogOfWarAlpha (Vector3 worldPosition, float radius) {
  1113. if (fogOfWarTexture == null)
  1114. return;
  1115. float tx = (worldPosition.x - fogOfWarCenter.x) / fogOfWarSize.x + 0.5f;
  1116. if (tx < 0 || tx > 1f)
  1117. return;
  1118. float tz = (worldPosition.z - fogOfWarCenter.z) / fogOfWarSize.z + 0.5f;
  1119. if (tz < 0 || tz > 1f)
  1120. return;
  1121. int tw = fogOfWarTexture.width;
  1122. int th = fogOfWarTexture.height;
  1123. int px = (int)(tx * tw);
  1124. int pz = (int)(tz * th);
  1125. int colorBufferPos = pz * tw + px;
  1126. float tr = radius / fogOfWarSize.z;
  1127. int delta = Mathf.FloorToInt (th * tr);
  1128. for (int r = pz - delta; r <= pz + delta; r++) {
  1129. if (r > 0 && r < th - 1) {
  1130. for (int c = px - delta; c <= px + delta; c++) {
  1131. if (c > 0 && c < tw - 1) {
  1132. int distance = Mathf.FloorToInt (Mathf.Sqrt ((pz - r) * (pz - r) + (px - c) * (px - c)));
  1133. if (distance <= delta) {
  1134. colorBufferPos = r * tw + c;
  1135. Color32 colorBuffer = fogOfWarColorBuffer [colorBufferPos];
  1136. colorBuffer.a = 255;
  1137. fogOfWarColorBuffer [colorBufferPos] = colorBuffer;
  1138. fogOfWarTexture.SetPixel (c, r, colorBuffer);
  1139. }
  1140. }
  1141. }
  1142. }
  1143. fogOfWarTexture.Apply ();
  1144. }
  1145. }
  1146. public void ResetFogOfWar () {
  1147. if (fogOfWarTexture == null)
  1148. return;
  1149. int h = fogOfWarTexture.height;
  1150. int w = fogOfWarTexture.width;
  1151. int newLength = h * w;
  1152. if (fogOfWarColorBuffer == null || fogOfWarColorBuffer.Length != newLength) {
  1153. fogOfWarColorBuffer = new Color32[newLength];
  1154. }
  1155. Color32 opaque = new Color32 (255, 255, 255, 255);
  1156. for (int k = 0; k < newLength; k++)
  1157. fogOfWarColorBuffer [k] = opaque;
  1158. fogOfWarTexture.SetPixels32 (fogOfWarColorBuffer);
  1159. fogOfWarTexture.Apply ();
  1160. }
  1161. int GetScaledSize (int size, float factor) {
  1162. size = (int)(size / factor);
  1163. size /= 4;
  1164. if (size < 1)
  1165. size = 1;
  1166. return size * 4;
  1167. }
  1168. #endregion
  1169. }
  1170. }