EnviroReflectionProbe.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.Rendering;
  5. #if ENVIRO_HDRP
  6. using UnityEngine.Rendering.HighDefinition;
  7. #endif
  8. namespace Enviro
  9. {
  10. [AddComponentMenu("Enviro 3/Reflection Probe")]
  11. [RequireComponent(typeof(ReflectionProbe)), ExecuteInEditMode]
  12. public class EnviroReflectionProbe : MonoBehaviour
  13. {
  14. #region Public Var
  15. #region Standalone Settings
  16. public bool standalone = false;
  17. public bool updateReflectionOnGameTime = true;
  18. public float reflectionsUpdateTreshhold = 0.025f;
  19. public bool useTimeSlicing = true;
  20. #endregion
  21. public Camera renderCam;
  22. [HideInInspector]
  23. public ReflectionProbe myProbe;
  24. public bool customRendering = false;
  25. #if !ENVIRO_HDRP
  26. private EnviroRenderer enviroRenderer;
  27. #endif
  28. public bool useFog = false;
  29. #endregion
  30. #region Private Var
  31. // Privates
  32. public Camera bakingCam;
  33. public int renderId = -1;
  34. private bool currentMode = false;
  35. private int currentRes;
  36. private RenderTexture cubemap;
  37. private RenderTexture finalCubemap;
  38. private RenderTexture mirrorTexture;
  39. private RenderTexture renderTexture;
  40. private GameObject renderCamObj;
  41. private Material mirror = null;
  42. private Material bakeMat = null;
  43. private Material convolutionMat;
  44. private Coroutine refreshing;
  45. private int renderID;
  46. #if ENVIRO_HDRP
  47. public HDProbe hdprobe;
  48. #endif
  49. private static Quaternion[] orientations = new Quaternion[]
  50. {
  51. Quaternion.LookRotation(Vector3.right, Vector3.down),
  52. Quaternion.LookRotation(Vector3.left, Vector3.down),
  53. Quaternion.LookRotation(Vector3.up, Vector3.forward),
  54. Quaternion.LookRotation(Vector3.down, Vector3.back),
  55. Quaternion.LookRotation(Vector3.forward, Vector3.down),
  56. Quaternion.LookRotation(Vector3.back, Vector3.down)
  57. };
  58. private double lastRelfectionUpdate;
  59. #endregion
  60. ////////
  61. void OnEnable()
  62. {
  63. myProbe = GetComponent<ReflectionProbe>();
  64. #if ENVIRO_HDRP
  65. if (EnviroManager.instance != null)
  66. {
  67. hdprobe = GetComponent<HDProbe>();
  68. if(!standalone && myProbe != null)
  69. myProbe.enabled = true;
  70. if (customRendering)
  71. {
  72. if (hdprobe != null)
  73. {
  74. hdprobe.mode = ProbeSettings.Mode.Custom;
  75. CreateCubemap();
  76. CreateTexturesAndMaterial();
  77. CreateRenderCamera();
  78. currentRes = myProbe.resolution;
  79. StartCoroutine(RefreshFirstTime());
  80. }
  81. }
  82. else
  83. {
  84. if (hdprobe != null)
  85. {
  86. hdprobe.mode = ProbeSettings.Mode.Realtime;
  87. hdprobe.realtimeMode = ProbeSettings.RealtimeMode.OnDemand;
  88. hdprobe.RequestRenderNextUpdate();
  89. }
  90. }
  91. }
  92. #else
  93. if (!standalone && myProbe != null)
  94. myProbe.enabled = true;
  95. if (customRendering)
  96. {
  97. myProbe.mode = ReflectionProbeMode.Custom;
  98. myProbe.refreshMode = ReflectionProbeRefreshMode.ViaScripting;
  99. CreateCubemap();
  100. CreateTexturesAndMaterial();
  101. CreateRenderCamera();
  102. currentRes = myProbe.resolution;
  103. StartCoroutine(RefreshFirstTime());
  104. }
  105. else
  106. {
  107. myProbe.mode = ReflectionProbeMode.Realtime;
  108. myProbe.refreshMode = ReflectionProbeRefreshMode.ViaScripting;
  109. //StartCoroutine(RefreshUnity());
  110. renderId = myProbe.RenderProbe();
  111. }
  112. #endif
  113. }
  114. void OnDisable()
  115. {
  116. Cleanup();
  117. if (!standalone && myProbe != null)
  118. myProbe.enabled = false;
  119. RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Skybox;
  120. }
  121. private void Cleanup()
  122. {
  123. if (refreshing != null)
  124. StopCoroutine(refreshing);
  125. if (cubemap != null)
  126. {
  127. if (renderCam != null)
  128. renderCam.targetTexture = null;
  129. DestroyImmediate(cubemap);
  130. }
  131. if (renderCamObj != null)
  132. DestroyImmediate(renderCamObj);
  133. if (mirrorTexture != null)
  134. DestroyImmediate(mirrorTexture);
  135. if (renderTexture != null)
  136. DestroyImmediate(renderTexture);
  137. }
  138. // Creation
  139. private void CreateRenderCamera()
  140. {
  141. if (renderCamObj == null)
  142. {
  143. renderCamObj = new GameObject();
  144. renderCamObj.name = "Reflection Probe Cam";
  145. renderCamObj.hideFlags = HideFlags.HideAndDontSave;
  146. renderCam = renderCamObj.AddComponent<Camera>();
  147. renderCam.gameObject.SetActive(true);
  148. renderCam.cameraType = CameraType.Reflection;
  149. renderCam.fieldOfView = 90;
  150. renderCam.farClipPlane = myProbe.farClipPlane;
  151. renderCam.nearClipPlane = myProbe.nearClipPlane;
  152. renderCam.clearFlags = (CameraClearFlags)myProbe.clearFlags;
  153. renderCam.backgroundColor = myProbe.backgroundColor;
  154. renderCam.allowHDR = myProbe.hdr;
  155. renderCam.targetTexture = cubemap;
  156. renderCam.enabled = false;
  157. #if VEGETATION_STUDIO_PRO
  158. // VegetationStudioManager.Instance.AddCamera(renderCam);
  159. #endif
  160. #if !ENVIRO_HDRP
  161. if (EnviroManager.instance != null)
  162. {
  163. enviroRenderer = renderCamObj.AddComponent<EnviroRenderer>();
  164. }
  165. #endif
  166. }
  167. }
  168. private void UpdateCameraSettings()
  169. {
  170. if (renderCam != null)
  171. {
  172. renderCam.cullingMask = myProbe.cullingMask;
  173. #if !ENVIRO_HDRP
  174. if (EnviroManager.instance != null)
  175. {
  176. //Update Quality
  177. }
  178. #endif
  179. }
  180. }
  181. private Camera CreateBakingCamera()
  182. {
  183. GameObject tempCam = new GameObject();
  184. tempCam.name = "Reflection Probe Cam";
  185. Camera cam = tempCam.AddComponent<Camera>();
  186. cam.enabled = false;
  187. cam.gameObject.SetActive(true);
  188. cam.cameraType = CameraType.Reflection;
  189. cam.fieldOfView = 90;
  190. cam.farClipPlane = myProbe.farClipPlane;
  191. cam.nearClipPlane = myProbe.nearClipPlane;
  192. cam.cullingMask = myProbe.cullingMask;
  193. cam.clearFlags = (CameraClearFlags)myProbe.clearFlags;
  194. cam.backgroundColor = myProbe.backgroundColor;
  195. cam.allowHDR = myProbe.hdr;
  196. cam.targetTexture = cubemap;
  197. #if !ENVIRO_HDRP
  198. if (EnviroManager.instance != null)
  199. {
  200. enviroRenderer = renderCamObj.AddComponent<EnviroRenderer>();
  201. }
  202. #endif
  203. tempCam.hideFlags = HideFlags.HideAndDontSave;
  204. return cam;
  205. }
  206. private void CreateCubemap()
  207. {
  208. if (cubemap != null && myProbe.resolution == currentRes)
  209. return;
  210. if (cubemap != null)
  211. {
  212. cubemap.Release();
  213. DestroyImmediate(cubemap);
  214. }
  215. if (finalCubemap != null)
  216. {
  217. finalCubemap.Release();
  218. DestroyImmediate(finalCubemap);
  219. }
  220. int resolution = myProbe.resolution;
  221. currentRes = resolution;
  222. RenderTextureFormat format = myProbe.hdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default;
  223. cubemap = new RenderTexture(resolution, resolution, 16, format, RenderTextureReadWrite.Linear);
  224. cubemap.dimension = TextureDimension.Cube;
  225. cubemap.useMipMap = true;
  226. cubemap.autoGenerateMips = false;
  227. cubemap.name = "Enviro Reflection Temp Cubemap";
  228. cubemap.filterMode = FilterMode.Trilinear;
  229. cubemap.Create();
  230. finalCubemap = new RenderTexture(resolution, resolution, 16, format, RenderTextureReadWrite.Linear);
  231. finalCubemap.dimension = TextureDimension.Cube;
  232. finalCubemap.useMipMap = true;
  233. finalCubemap.autoGenerateMips = false;
  234. finalCubemap.name = "Enviro Reflection Final Cubemap";
  235. finalCubemap.filterMode = FilterMode.Trilinear;
  236. finalCubemap.Create();
  237. }
  238. //Create the textures
  239. private void CreateTexturesAndMaterial()
  240. {
  241. if (mirror == null)
  242. mirror = new Material(Shader.Find("Hidden/Enviro/ReflectionProbe"));
  243. if (convolutionMat == null)
  244. convolutionMat = new Material(Shader.Find("Hidden/EnviroCubemapBlur"));
  245. int resolution = myProbe.resolution;
  246. RenderTextureFormat format = myProbe.hdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default;
  247. if (mirrorTexture == null || mirrorTexture.width != resolution || mirrorTexture.height != resolution)
  248. {
  249. if (mirrorTexture != null)
  250. DestroyImmediate(mirrorTexture);
  251. mirrorTexture = new RenderTexture(resolution, resolution, 16, format, RenderTextureReadWrite.Linear);
  252. mirrorTexture.useMipMap = true;
  253. mirrorTexture.autoGenerateMips = false;
  254. mirrorTexture.name = "Enviro Reflection Mirror Texture";
  255. mirrorTexture.Create();
  256. }
  257. if (renderTexture == null || renderTexture.width != resolution || renderTexture.height != resolution)
  258. {
  259. if (renderTexture != null)
  260. DestroyImmediate(renderTexture);
  261. renderTexture = new RenderTexture(resolution, resolution, 16, format, RenderTextureReadWrite.Linear);
  262. renderTexture.useMipMap = true;
  263. renderTexture.autoGenerateMips = false;
  264. renderTexture.name = "Enviro Reflection Target Texture";
  265. renderTexture.Create();
  266. }
  267. }
  268. // Refresh Methods
  269. public void RefreshReflection(bool timeSlice = false)
  270. {
  271. #if ENVIRO_HDRP
  272. if (customRendering)
  273. {
  274. if (refreshing != null)
  275. return;
  276. CreateTexturesAndMaterial();
  277. if (renderCam == null)
  278. CreateRenderCamera();
  279. UpdateCameraSettings();
  280. renderCam.transform.position = transform.position;
  281. renderCam.targetTexture = renderTexture;
  282. if (Application.isPlaying)
  283. {
  284. if (!timeSlice)
  285. refreshing = StartCoroutine(RefreshInstant(renderTexture, mirrorTexture));
  286. else
  287. refreshing = StartCoroutine(RefreshOvertime(renderTexture, mirrorTexture));
  288. }
  289. else
  290. {
  291. refreshing = StartCoroutine(RefreshInstant(renderTexture, mirrorTexture));
  292. }
  293. }
  294. else
  295. {
  296. if(hdprobe != null)
  297. hdprobe.RequestRenderNextUpdate();
  298. }
  299. #else
  300. if (customRendering)
  301. {
  302. if (refreshing != null)
  303. return;
  304. CreateTexturesAndMaterial();
  305. if (renderCam == null)
  306. CreateRenderCamera();
  307. UpdateCameraSettings();
  308. renderCam.transform.position = transform.position;
  309. renderCam.targetTexture = renderTexture;
  310. if (Application.isPlaying)
  311. {
  312. if (!timeSlice)
  313. refreshing = StartCoroutine(RefreshInstant(renderTexture, mirrorTexture));
  314. else
  315. refreshing = StartCoroutine(RefreshOvertime(renderTexture, mirrorTexture));
  316. }
  317. else
  318. {
  319. refreshing = StartCoroutine(RefreshInstant(renderTexture, mirrorTexture));
  320. }
  321. }
  322. else
  323. {
  324. renderId = myProbe.RenderProbe();
  325. }
  326. #endif
  327. }
  328. IEnumerator RefreshFirstTime()
  329. {
  330. yield return null;
  331. RefreshReflection(false);
  332. RefreshReflection(false);
  333. }
  334. public IEnumerator RefreshUnity()
  335. {
  336. yield return null;
  337. renderId = myProbe.RenderProbe();
  338. }
  339. public IEnumerator RefreshInstant(RenderTexture renderTex, RenderTexture mirrorTex)
  340. {
  341. CreateCubemap();
  342. yield return null;
  343. for (int face = 0; face < 6; face++)
  344. {
  345. renderCam.transform.rotation = orientations[face];
  346. renderCam.Render();
  347. if(mirrorTex != null)
  348. {
  349. Graphics.Blit(renderTex, mirrorTex, mirror);
  350. Graphics.CopyTexture(mirrorTex, 0, 0, cubemap, face, 0);
  351. }
  352. }
  353. ConvolutionCubemap();
  354. #if ENVIRO_HDRP
  355. if (hdprobe != null)
  356. hdprobe.SetTexture(ProbeSettings.Mode.Custom, finalCubemap);
  357. #else
  358. myProbe.customBakedTexture = finalCubemap;
  359. #endif
  360. refreshing = null;
  361. }
  362. /// <summary>
  363. /// Update Reflections with Time Slicing
  364. /// </summary>
  365. public IEnumerator RefreshOvertime(RenderTexture renderTex, RenderTexture mirrorTex)
  366. {
  367. CreateCubemap();
  368. for (int face = 0; face < 6; face++)
  369. {
  370. yield return null;
  371. renderCam.transform.rotation = orientations[face];
  372. renderCam.Render();
  373. if(mirrorTex != null)
  374. {
  375. Graphics.Blit(renderTex, mirrorTex, mirror);
  376. Graphics.CopyTexture(mirrorTex, 0, 0, cubemap, face, 0);
  377. }
  378. //ClearTextures();
  379. }
  380. ConvolutionCubemap();
  381. #if ENVIRO_HDRP
  382. if (hdprobe != null)
  383. hdprobe.SetTexture(ProbeSettings.Mode.Custom, finalCubemap);
  384. #else
  385. myProbe.customBakedTexture = finalCubemap;
  386. #endif
  387. refreshing = null;
  388. }
  389. /// <summary>
  390. /// Bakes one face per time into a render texture
  391. /// </summary>
  392. /// <param name="face"></param>
  393. /// <param name="res"></param>
  394. /// <returns></returns>
  395. public RenderTexture BakeCubemapFace(int face, int res)
  396. {
  397. if (bakeMat == null)
  398. bakeMat = new Material(Shader.Find("Hidden/Enviro/BakeCubemap"));
  399. if (bakingCam == null)
  400. bakingCam = CreateBakingCamera();
  401. bakingCam.transform.rotation = orientations[face];
  402. RenderTexture temp = RenderTexture.GetTemporary(res, res, 0, RenderTextureFormat.ARGBFloat);
  403. bakingCam.targetTexture = temp;
  404. bakingCam.Render();
  405. RenderTexture tex = new RenderTexture(res, res, 0, RenderTextureFormat.ARGBFloat);
  406. Graphics.Blit(temp, tex, bakeMat);
  407. RenderTexture.ReleaseTemporary(temp);
  408. return tex;
  409. }
  410. private void ClearTextures()
  411. {
  412. RenderTexture rt = RenderTexture.active;
  413. RenderTexture.active = renderTexture;
  414. GL.Clear(true, true, Color.clear);
  415. RenderTexture.active = mirrorTexture;
  416. GL.Clear(true, true, Color.clear);
  417. RenderTexture.active = rt;
  418. }
  419. //This is not a proper convolution and very hacky to get anywhere near of unity realtime reflection probe mip convolution.
  420. private void ConvolutionCubemap()
  421. {
  422. int mipCount = 7;
  423. GL.PushMatrix();
  424. GL.LoadOrtho();
  425. cubemap.GenerateMips();
  426. float texel = 1f;
  427. switch(finalCubemap.width)
  428. {
  429. case 16:
  430. texel = 1f;
  431. break;
  432. case 32:
  433. texel = 1f;
  434. break;
  435. case 64:
  436. texel = 2f;
  437. break;
  438. case 128:
  439. texel = 4f;
  440. break;
  441. case 256:
  442. texel = 8f;
  443. break;
  444. case 512:
  445. texel = 14f;
  446. break;
  447. case 1024:
  448. texel = 30f;
  449. break;
  450. case 2048:
  451. texel = 60f;
  452. break;
  453. }
  454. float res = finalCubemap.width;
  455. for (int mip = 0; mip < mipCount + 1; mip++)
  456. {
  457. //Copy each face
  458. Graphics.CopyTexture(cubemap, 0, mip, finalCubemap, 0, mip);
  459. Graphics.CopyTexture(cubemap, 1, mip, finalCubemap, 1, mip);
  460. Graphics.CopyTexture(cubemap, 2, mip, finalCubemap, 2, mip);
  461. Graphics.CopyTexture(cubemap, 3, mip, finalCubemap, 3, mip);
  462. Graphics.CopyTexture(cubemap, 4, mip, finalCubemap, 4, mip);
  463. Graphics.CopyTexture(cubemap, 5, mip, finalCubemap, 5, mip);
  464. int dstMip = mip + 1;
  465. if (dstMip == mipCount)
  466. break;
  467. float texelSize = (texel * dstMip) / res;
  468. convolutionMat.SetTexture("_MainTex", finalCubemap);
  469. convolutionMat.SetFloat("_Texel", texelSize);
  470. convolutionMat.SetFloat("_Level", mip);
  471. convolutionMat.SetPass(0);
  472. res *= 0.75f;
  473. // Positive X
  474. Graphics.SetRenderTarget(cubemap, dstMip, CubemapFace.PositiveX);
  475. GL.Begin(GL.QUADS);
  476. GL.TexCoord3(1, 1, 1);
  477. GL.Vertex3(0, 0, 1);
  478. GL.TexCoord3(1, -1, 1);
  479. GL.Vertex3(0, 1, 1);
  480. GL.TexCoord3(1, -1, -1);
  481. GL.Vertex3(1, 1, 1);
  482. GL.TexCoord3(1, 1, -1);
  483. GL.Vertex3(1, 0, 1);
  484. GL.End();
  485. // Negative X
  486. Graphics.SetRenderTarget(cubemap, dstMip, CubemapFace.NegativeX);
  487. GL.Begin(GL.QUADS);
  488. GL.TexCoord3(-1, 1, -1);
  489. GL.Vertex3(0, 0, 1);
  490. GL.TexCoord3(-1, -1, -1);
  491. GL.Vertex3(0, 1, 1);
  492. GL.TexCoord3(-1, -1, 1);
  493. GL.Vertex3(1, 1, 1);
  494. GL.TexCoord3(-1, 1, 1);
  495. GL.Vertex3(1, 0, 1);
  496. GL.End();
  497. // Positive Y
  498. Graphics.SetRenderTarget(cubemap, dstMip, CubemapFace.PositiveY);
  499. GL.Begin(GL.QUADS);
  500. GL.TexCoord3(-1, 1, -1);
  501. GL.Vertex3(0, 0, 1);
  502. GL.TexCoord3(-1, 1, 1);
  503. GL.Vertex3(0, 1, 1);
  504. GL.TexCoord3(1, 1, 1);
  505. GL.Vertex3(1, 1, 1);
  506. GL.TexCoord3(1, 1, -1);
  507. GL.Vertex3(1, 0, 1);
  508. GL.End();
  509. // Negative Y
  510. Graphics.SetRenderTarget(cubemap, dstMip, CubemapFace.NegativeY);
  511. GL.Begin(GL.QUADS);
  512. GL.TexCoord3(-1, -1, 1);
  513. GL.Vertex3(0, 0, 1);
  514. GL.TexCoord3(-1, -1, -1);
  515. GL.Vertex3(0, 1, 1);
  516. GL.TexCoord3(1, -1, -1);
  517. GL.Vertex3(1, 1, 1);
  518. GL.TexCoord3(1, -1, 1);
  519. GL.Vertex3(1, 0, 1);
  520. GL.End();
  521. // Positive Z
  522. Graphics.SetRenderTarget(cubemap, dstMip, CubemapFace.PositiveZ);
  523. GL.Begin(GL.QUADS);
  524. GL.TexCoord3(-1, 1, 1);
  525. GL.Vertex3(0, 0, 1);
  526. GL.TexCoord3(-1, -1, 1);
  527. GL.Vertex3(0, 1, 1);
  528. GL.TexCoord3(1, -1, 1);
  529. GL.Vertex3(1, 1, 1);
  530. GL.TexCoord3(1, 1, 1);
  531. GL.Vertex3(1, 0, 1);
  532. GL.End();
  533. // Negative Z
  534. Graphics.SetRenderTarget(cubemap, dstMip, CubemapFace.NegativeZ);
  535. GL.Begin(GL.QUADS);
  536. GL.TexCoord3(1, 1, -1);
  537. GL.Vertex3(0, 0, 1);
  538. GL.TexCoord3(1, -1, -1);
  539. GL.Vertex3(0, 1, 1);
  540. GL.TexCoord3(-1, -1, -1);
  541. GL.Vertex3(1, 1, 1);
  542. GL.TexCoord3(-1, 1, -1);
  543. GL.Vertex3(1, 0, 1);
  544. GL.End();
  545. }
  546. GL.PopMatrix();
  547. }
  548. private void UpdateStandaloneReflection()
  549. {
  550. if ((EnviroManager.instance.Time.GetDateInHours() > lastRelfectionUpdate + reflectionsUpdateTreshhold ||EnviroManager.instance.Time.GetDateInHours() < lastRelfectionUpdate - reflectionsUpdateTreshhold) && updateReflectionOnGameTime)
  551. {
  552. lastRelfectionUpdate = EnviroManager.instance.Time.GetDateInHours();
  553. RefreshReflection(!useTimeSlicing);
  554. }
  555. }
  556. private void Update()
  557. {
  558. if (currentMode != customRendering)
  559. {
  560. currentMode = customRendering;
  561. if (customRendering)
  562. {
  563. OnEnable();
  564. }
  565. else
  566. {
  567. OnEnable();
  568. Cleanup();
  569. }
  570. }
  571. if (EnviroManager.instance != null && standalone)
  572. {
  573. UpdateStandaloneReflection();
  574. }
  575. }
  576. }
  577. }