ZEDRenderingPlane.cs 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577
  1. //======= Copyright (c) Stereolabs Corporation, All rights reserved. ===============
  2. using UnityEngine;
  3. using UnityEngine.Rendering;
  4. /// <summary>
  5. /// Responsible for actually mixing the real and virtual images, and displaying them in a
  6. /// Frame object within the camera rig.
  7. /// First, it displays the image of the ZED into a quad.
  8. /// Then, it inserts the depth and normals inside the pipeline
  9. /// Third, it computes the data for the light and send it to the shaders.
  10. /// Finally, it post-processes the image, if post-processing is enabled.
  11. /// </summary>
  12. [RequireComponent(typeof(Camera))]
  13. public class ZEDRenderingPlane : MonoBehaviour
  14. {
  15. /// <summary>
  16. /// The rendering mode accepted.
  17. /// </summary>
  18. enum ZED_RENDERING_MODE
  19. {
  20. FORWARD,
  21. DEFERRED,
  22. LAST
  23. };
  24. /// <summary>
  25. /// Which side of the camera (left/right) and whether or not this can be overridden by the camera's stereoTargetEye.
  26. /// </summary>
  27. public enum ZED_CAMERA_SIDE
  28. {
  29. /// <summary>
  30. /// Feed from the ZED's left camera. Can be overridden by the camera's stereoTargetEye value.
  31. /// </summary>
  32. LEFT,
  33. /// <summary>
  34. /// Feed from the ZED's right camera. Can be overridden by the camera's stereoTargetEye value.
  35. /// </summary>
  36. RIGHT,
  37. /// <summary>
  38. /// Feed from the ZED's left camera. Won't be overridden.
  39. /// </summary>
  40. LEFT_FORCE,
  41. /// <summary>
  42. /// Feed from the ZED's right camera. Won't be overridden.
  43. /// </summary>
  44. RIGHT_FORCE
  45. }
  46. /// <summary>
  47. /// The GameGbject that displays the final textures.
  48. /// In the ZED_Rig_Mono and ZED_Rig_Stereo prefabs, this is the Frame object that's a child of each camera.
  49. /// </summary>
  50. [Tooltip("The GameGbject that displays the final textures. " +
  51. "In the ZED_Rig_Mono and ZED_Rig_Stereo prefabs, this is the Frame object that's a child of each camera.")]
  52. public GameObject canvas;
  53. /// <summary>
  54. /// Which camera on the ZED the image/depth/etc. comes from.
  55. /// If set to LEFT or RIGHT, this may be overridden by the camera's stereoTargetEye.
  56. /// If set to LEFT_FORCE or RIGHT_FORCE, it will not be changed.
  57. /// </summary>
  58. [Tooltip("Which camera on the ZED the image/depth/etc. comes from.\r\n" +
  59. "If set to LEFT or RIGHT, this may be overridden by the camera's stereoTargetEye.\r\n" +
  60. "If set to LEFT_FORCE or RIGHT_FORCE, it will not be changed.")]
  61. public ZED_CAMERA_SIDE viewSide = ZED_CAMERA_SIDE.LEFT;
  62. /// <summary>
  63. /// The main material, set to the one on the canvas's MeshRenderer. Used to set the color and depth.
  64. /// </summary>
  65. public Material matRGB { get; private set; }
  66. /// <summary>
  67. /// Aspect ratio of the textures. All the textures displayed should be in 16:9.
  68. /// </summary>
  69. private float aspect = 16.0f / 9.0f;
  70. /// <summary>
  71. /// The Camera component representing an 'eye' of the ZED. Must be on the same GameObject as this component.
  72. /// </summary>
  73. private Camera cam;
  74. /// <summary>
  75. /// The Camera component representing an 'eye' of the ZED. Must be on the same GameObject as this component.
  76. /// </summary>
  77. public Camera renderingCam
  78. {
  79. get
  80. {
  81. return cam;
  82. }
  83. }
  84. /// <summary>
  85. /// zedCamera controlled by ZEDManager (one manager controls one camera)
  86. /// </summary>
  87. private sl.ZEDCamera zedCamera = null;
  88. /// <summary>
  89. /// ZED Manager that controls the zed Camera
  90. /// </summary>
  91. private ZEDManager zedManager = null;
  92. /// <summary>
  93. /// Texture of the real world generated from the ZED. It may be the from the left or right 'eye.'
  94. /// Once created, the ZED SDK automatically updates it with each frame/image the ZED captures.
  95. /// </summary>
  96. private Texture2D textureEye;
  97. public Texture2D TextureEye { get { return textureEye; } }
  98. /// <summary>
  99. /// Depth generated by the ZEDCamera.
  100. /// Once created, the ZED SDK automatically updates it whenever the ZED captures new frames/images.
  101. /// </summary>
  102. Texture2D depth;
  103. /// <summary>
  104. /// Normals generated by the ZEDCamera.
  105. /// Once created, the ZED SDK automatically updates it whenever the ZED captures new frames/images.
  106. /// </summary>
  107. Texture2D normals;
  108. #if !ZED_HDRP && !ZED_URP
  109. /// <summary>
  110. /// CommandBuffer to integrate the depth into Unity's forward or deferred pipeline.
  111. /// </summary>
  112. CommandBuffer[] buffer = new CommandBuffer[(int)ZED_RENDERING_MODE.LAST];
  113. /// <summary>
  114. /// CommandBuffer to create a mask for the virtual objects in forward and deferred rendering.
  115. /// </summary>
  116. CommandBuffer[] postProcessBuffer = new CommandBuffer[(int)ZED_RENDERING_MODE.LAST];
  117. #endif
  118. /// <summary>
  119. /// The material used to integrate the depth in forward mode after the depth texture is created. Mainly used to get the shadows. Not needed for lighting otherwise.
  120. /// </summary>
  121. public Material forwardMat { get; private set; }
  122. /// <summary>
  123. /// The material used to integrate the depth in deferred mode. Always used in deferred regardless of lighting/shadows.
  124. /// </summary>
  125. public Material deferredMat { get; private set; }
  126. /// <summary>
  127. /// The actual rendering path used.
  128. /// To change this, change the settings in Project Settings -> Graphics within the Unity editor.
  129. /// </summary>
  130. private RenderingPath actualRenderingPath = RenderingPath.VertexLit;
  131. public RenderingPath ActualRenderingPath
  132. {
  133. get { return actualRenderingPath; }
  134. }
  135. /// <summary>
  136. /// The MeshFilter component of the canvas object. Used to draw the depth buffer.
  137. /// </summary>
  138. MeshFilter meshCanvas;
  139. /// <summary>
  140. /// A lower resolution of the depth and normals textures from the ZED.
  141. /// </summary>
  142. private sl.Resolution resolution = new sl.Resolution(1280, 720);
  143. /***LIGHTS definitions***/
  144. /// <summary>
  145. /// Point light structure for virtual lights on the real world.
  146. /// Gets sent to the shader via a compute buffer.
  147. /// </summary>
  148. [SerializeField]
  149. public struct PointLight
  150. {
  151. /// <summary>
  152. /// The color, times the intensity.
  153. /// </summary>
  154. public Vector4 color;
  155. /// <summary>
  156. /// The range of the light.
  157. /// </summary>
  158. public float range;
  159. /// <summary>
  160. /// The position of the light.
  161. /// </summary>
  162. public Vector3 position;
  163. }
  164. /// <summary>
  165. /// Maximum number of point lights accepted.
  166. /// </summary>
  167. const int NUMBER_POINT_LIGHT_MAX = 8;
  168. /// <summary>
  169. /// Holds a slot for all point lights that should be cast on the real world.
  170. /// </summary>
  171. [SerializeField]
  172. public PointLight[] pointLights = new PointLight[NUMBER_POINT_LIGHT_MAX];
  173. /// <summary>
  174. /// The size, or 'stride', of each PointLight in bytes. Needed to construct computeBufferPointLight.
  175. /// </summary>
  176. const int SIZE_POINT_LIGHT_BYTES = 32;
  177. /// <summary>
  178. /// Used to pass the pointLights array into matRGB's shader as a buffer.
  179. /// </summary>
  180. ComputeBuffer computeBufferPointLight;
  181. /// <summary>
  182. /// Structure of the spotlight send to the shader
  183. /// </summary>
  184. [SerializeField]
  185. public struct SpotLight
  186. {
  187. /// <summary>
  188. /// The color, times the intensity.
  189. /// </summary>
  190. public Vector4 color;
  191. /// <summary>
  192. /// The position of the light.
  193. /// </summary>
  194. public Vector3 position;
  195. /// <summary>
  196. /// The light's normalized direction and angle.
  197. /// </summary>
  198. public Vector4 direction;
  199. /// <summary>
  200. /// The parameters for the light's falloff.
  201. /// </summary>
  202. public Vector4 parameters;
  203. }
  204. /// <summary>
  205. /// Maximum number of spotlights accepted.
  206. /// </summary>
  207. const int NUMBER_SPOT_LIGHT_MAX = 8;
  208. /// <summary>
  209. /// Holds a slot for all spotlights that should be cast on the real world.
  210. /// </summary>
  211. [SerializeField]
  212. public SpotLight[] spotLights = new SpotLight[NUMBER_SPOT_LIGHT_MAX];
  213. /// <summary>
  214. /// The size, or 'stride', of each SpotLight in bytes. Needed to construct computeBufferSpotLight.
  215. /// </summary>
  216. const int SIZE_SPOT_LIGHT_BYTES = 60;
  217. /// <summary>
  218. /// Maximum number of total lights rendered (point and spot combined).
  219. /// </summary>
  220. const int NUMBER_LIGHTS_MAX = NUMBER_POINT_LIGHT_MAX / 2 + NUMBER_SPOT_LIGHT_MAX / 2;
  221. /// <summary>
  222. /// Data from a directional light. [0] is its direction and [1] is its color.
  223. /// Only one directional light is allowed at once.
  224. /// </summary>
  225. private Vector4[] directionalLightData = new Vector4[2];
  226. /// <summary>
  227. /// Used to pass the spotLights array into matRGB's shader as a buffer.
  228. /// </summary>
  229. ComputeBuffer computeBufferSpotLight;
  230. //Forward ID shader caches.
  231. /// <summary>
  232. /// Property ID of the number of point lights in the ZED_Lighting shader include file.
  233. /// </summary>
  234. private int numberPointLightsID;
  235. /// <summary>
  236. /// Property ID of the number of spotlights in the ZED_Lighting shader include file.
  237. /// </summary>
  238. private int numberSpotLightsID;
  239. /// <summary>
  240. /// Cached property id for _IsTextured. use isTexturedID property instead.
  241. /// </summary>
  242. private int? _istexturedid;
  243. /// <summary>
  244. /// Property id for _IsTextured, which is whether the rendered image has a texture overlay.
  245. /// </summary>
  246. private int isTexturedID
  247. {
  248. get
  249. {
  250. if (_istexturedid == null) _istexturedid = Shader.PropertyToID("_IsTextured");
  251. return (int)_istexturedid;
  252. }
  253. }
  254. /// <summary>
  255. /// Cached property id for _Mask. use maskPropID property instead.
  256. /// </summary>
  257. private int? _maskpropid;
  258. /// <summary>
  259. /// Property id for _Mask, which is the RenderTexture property for an overlay texture.
  260. /// </summary>
  261. private int maskPropID
  262. {
  263. get
  264. {
  265. if (_maskpropid == null) _maskpropid = Shader.PropertyToID("_Mask");
  266. return (int)_maskpropid;
  267. }
  268. }
  269. /*** Post-process definitions***/
  270. /// <summary>
  271. /// The mask used for post-processing. Filled at runtime and updated each frame.
  272. /// </summary>
  273. private RenderTexture mask;
  274. /// <summary>
  275. /// The post process material, used to add noise and change the color.
  276. /// </summary>
  277. private Material postprocessMaterial;
  278. /// <summary>
  279. /// Activate/deactivate post-processing. If false, the mask will not be generated.
  280. /// Set by ZEDManager.setRenderingSettings() based on a checkbox in ZEDManager's custom editor.
  281. /// </summary>
  282. private bool ARpostProcessing = true;
  283. /// <summary>
  284. /// Used to blur the mask.
  285. /// </summary>
  286. private Material blurMaterial;
  287. /// <summary>
  288. /// Used to load a source image's alpha channel into all channels of a destination image.
  289. /// Used during post-processing.
  290. /// </summary>
  291. private Material blitMaterial;
  292. /// <summary>
  293. /// Used to convert the stencil buffer of a rendertexture into a regular texture.
  294. /// </summary>
  295. private Material matStencilToMask;
  296. /// <summary>
  297. /// Used to compose the virtual mask from different textures.
  298. /// </summary>
  299. private Material matComposeMask;
  300. /// <summary>
  301. /// Used to blend the textures from ZEDMeshRenderer, when present.
  302. /// This adds the wireframe effect seen from 3D scanning or plane detection.
  303. /// </summary>
  304. private Material blender;
  305. /// <summary>
  306. /// What kind of image the final result will display. Usually set to View.
  307. /// Set this to VIEW_DEPTH or VIEW_NORMAL to see the live depth or normal maps.
  308. /// </summary>
  309. public sl.VIEW_MODE viewMode = sl.VIEW_MODE.VIEW_IMAGE;
  310. /// <summary>
  311. /// Which side of the camera we render. Left = 0, Right ==1.
  312. /// </summary>
  313. private int side
  314. {
  315. get
  316. {
  317. if (viewSide == ZED_CAMERA_SIDE.LEFT || viewSide == ZED_CAMERA_SIDE.LEFT_FORCE) return 0;
  318. else return 1;
  319. }
  320. }
  321. /// <summary>
  322. /// Default near plane value. Overrides camera's settings on start but will update if camera values change at runtime.
  323. /// </summary>
  324. private float nearplane = 0.1f;
  325. /// <summary>
  326. /// Default far plane value. Overrides camera's settings on start but will update if camera values change at runtime.
  327. /// </summary>
  328. private float farplane = 500.0f;
  329. /// <summary>
  330. /// The target RenderTexture we'll render to if in AR mode.
  331. /// </summary>
  332. [HideInInspector]
  333. private RenderTexture renderTextureTarget;
  334. public RenderTexture target
  335. {
  336. get { return renderTextureTarget; }
  337. }
  338. void Awake()
  339. {
  340. //Get the current camera and set the aspect ratio.
  341. zedManager = gameObject.transform.parent.GetComponent<ZEDManager>();
  342. cam = GetComponent<Camera>();
  343. cam.aspect = aspect;
  344. cam.renderingPath = RenderingPath.UsePlayerSettings; //Assigns the camera's rendering path to be consistent with the project's settings.
  345. //Make the canvas allow rendering this camera.
  346. HideFromWrongCameras.RegisterZEDCam(cam); //Makes all objects with a HideFromWrongCamera hide from this, unless set to this specifc one.
  347. HideFromWrongCameras hider = canvas.GetComponent<HideFromWrongCameras>();
  348. if (!hider)
  349. {
  350. hider = canvas.AddComponent<HideFromWrongCameras>();
  351. }
  352. hider.SetRenderCamera(cam); //This canvas will allow this camera to render it.
  353. }
  354. /// <summary>
  355. /// Whether or not post-processing effects are applied.
  356. /// Usually set by ZEDManager based on the selection in its Inspector.
  357. /// </summary>
  358. /// <param name="c"></param>
  359. public void SetPostProcess(bool c)
  360. {
  361. ARpostProcessing = c;
  362. }
  363. /// <summary>
  364. /// The object that forces the ZED image to be shown at 16:9 aspect ratio, regardless of the target window's resolution.
  365. /// </summary>
  366. private WindowAspectRatio aspectRatio;
  367. /// <summary>
  368. /// Changes the scene's global lighting settings to prevent global illumnation from causing
  369. /// lighting that doesn't match the real world.
  370. /// </summary>
  371. private void SetUpGI()
  372. {
  373. //Only do this if "Hide Skybox" is enabled in ZEDManager, which is is by default.
  374. if (zedManager)
  375. {
  376. if (zedManager.greySkybox)
  377. {
  378. RenderSettings.skybox = null;
  379. Color c;
  380. ColorUtility.TryParseHtmlString("#999999", out c);
  381. RenderSettings.ambientLight = c;
  382. DynamicGI.UpdateEnvironment();
  383. }
  384. }
  385. }
  386. /// <summary>
  387. /// Configures materials/values/settings needed for post-processing and displaying in proper aspect ratio.
  388. /// </summary>
  389. private void Start()
  390. {
  391. //No environmental lighting per default
  392. Shader.SetGlobalFloat("_ZEDExposure", -1);
  393. //Load the materials.
  394. matStencilToMask = new Material(Resources.Load("Materials/PostProcessing/Mat_ZED_Stencil2Mask") as Material);
  395. matComposeMask = new Material(Resources.Load("Materials/PostProcessing/Mat_ZED_MaskCompositor") as Material);
  396. //Load and configure the post-process material.
  397. postprocessMaterial = new Material(Resources.Load("Materials/PostProcessing/Mat_ZED_PostProcessing") as Material);
  398. postprocessMaterial.SetFloat("_gamma", 1.0f / (0.87f * 0.9f));
  399. postprocessMaterial.SetFloat("_MinBlack", 15.0f / 255.0f);
  400. postprocessMaterial.SetInt("_NoiseSize", 2);
  401. //Configure the weights for the blur effect.
  402. float[] weights;
  403. float[] offsets;
  404. ZEDPostProcessingTools.ComputeWeights(0.3f, out weights, out offsets);
  405. //Set the blur config to the shader, should be constant
  406. blurMaterial = new Material(Resources.Load("Materials/PostProcessing/Mat_ZED_Blur") as Material);
  407. blurMaterial.SetFloatArray("weights", weights);
  408. blurMaterial.SetFloatArray("offset", offsets);
  409. //blurMaterial.SetTexture("_Mask", mask);
  410. blurMaterial.SetTexture(maskPropID, mask);
  411. //Force Unity into 16:9 mode to match the ZED's output.
  412. #if UNITY_EDITOR
  413. UnityEditor.PlayerSettings.SetAspectRatio(UnityEditor.AspectRatio.Aspect16by9, true);
  414. UnityEditor.PlayerSettings.SetAspectRatio(UnityEditor.AspectRatio.Aspect16by10, false);
  415. UnityEditor.PlayerSettings.SetAspectRatio(UnityEditor.AspectRatio.Aspect4by3, false);
  416. UnityEditor.PlayerSettings.SetAspectRatio(UnityEditor.AspectRatio.Aspect5by4, false);
  417. #endif
  418. CreateRenderTexture();
  419. //Load the blender for the zedmesher
  420. blender = new Material(Resources.Load("Materials/SpatialMapping/Mat_ZED_PostProcess_Blend") as Material);
  421. SetMeshRenderAvailable(false);
  422. //Set the bounds around the camera, used to detect if a point/spotlight is close enough to be applied.
  423. bounds = new Bounds(transform.position, new Vector3(20, 20, 20));
  424. //IF AR REMOVE
  425. //aspectRatio = new WindowAspectRatio(cam);
  426. #if ZED_LWRP || ZED_HDRP || ZED_URP
  427. RenderPipelineManager.beginFrameRendering += SRPStartFrame;
  428. #endif
  429. }
  430. /// <summary>
  431. /// Configures numerous settings that can't be set until the ZED is fully initialized.
  432. /// Subscribed to ZEDManager.OnZEDReady in OnEnable().
  433. /// </summary>
  434. void ZEDReady()
  435. {
  436. //Add the fade-in effect for when the camera first becomes visible.
  437. if (zedManager.fadeInOnStart)
  438. gameObject.AddComponent<LoadingFade>();
  439. //This cannot happen but just in case...
  440. if (zedManager == null)
  441. return;
  442. zedCamera = zedManager.zedCamera;
  443. SetTextures(zedCamera, viewMode);
  444. canvas.SetActive(true);
  445. canvas.transform.SetParent(cam.transform);
  446. ConfigureLightAndShadow(cam.actualRenderingPath);
  447. //Move the plane with the optical centers.
  448. float plane_distance = 0.15f;
  449. Vector4 opticalCenters = zedCamera.ComputeOpticalCenterOffsets(plane_distance);
  450. if (side == 0)
  451. canvas.transform.localPosition = new Vector3(opticalCenters.x, -1.0f * opticalCenters.y, plane_distance);
  452. else if (side == 1)
  453. canvas.transform.localPosition = new Vector3(opticalCenters.z, -1.0f * opticalCenters.w, plane_distance);
  454. //Set the camera's parameters based on the ZED's, and scale the screen based on its distance.
  455. if (zedCamera.IsCameraReady)
  456. {
  457. //cam.projectionMatrix = zedCamera.Projection;
  458. SetProjection(nearplane, farplane);
  459. cam.nearClipPlane = nearplane;
  460. cam.farClipPlane = farplane;
  461. //mainCamera.nearClipPlane = 0.1f;
  462. //mainCamera.farClipPlane = 500.0f;
  463. scale(canvas.gameObject, GetFOVYFromProjectionMatrix(cam.projectionMatrix));
  464. cam.fieldOfView = zedCamera.VerticalFieldOfView * Mathf.Rad2Deg;
  465. }
  466. else //Just scale the screen.
  467. {
  468. scale(canvas.gameObject, cam.fieldOfView);
  469. }
  470. }
  471. /// <summary>
  472. /// Hides the canvas. Called when the ZED is disconnected via the ZEDManager.OnZEDDisconnected event.
  473. /// </summary>
  474. void ZEDDisconnected()
  475. {
  476. canvas.SetActive(false);
  477. }
  478. /// <summary>
  479. /// Fixes GI, enables the canvas and subscribes to events from the ZED.
  480. /// </summary>
  481. private void OnEnable()
  482. {
  483. SetUpGI();
  484. meshCanvas = gameObject.transform.GetChild(0).GetComponent<MeshFilter>();
  485. canvas.SetActive(false);
  486. //iterate until we found the ZED Manager parent...
  487. Transform ObjParent = gameObject.transform;
  488. int tries = 0;
  489. while (zedManager == null && tries < 5)
  490. {
  491. if (ObjParent != null)
  492. zedManager = ObjParent.GetComponent<ZEDManager>();
  493. if (zedManager == null && ObjParent != null)
  494. ObjParent = ObjParent.parent;
  495. tries++;
  496. }
  497. if (zedManager != null)
  498. {
  499. zedManager.OnZEDReady += ZEDReady;
  500. zedManager.OnZEDDisconnected += ZEDDisconnected;
  501. }
  502. #if ZED_HDRP
  503. //Check which material the ZEDManager's SRP Lighting Type wants us to use, then apply it.
  504. Renderer rend = canvas.GetComponent<Renderer>();
  505. Material basemattoapply;
  506. bool changemat = zedManager.GetChosenSRPMaterial(out basemattoapply);
  507. if (changemat) //A specific material has been specified. Apply that one.
  508. {
  509. matRGB = new Material(basemattoapply); //We make a new instance so we can apply different textures to the left/right eye, and different cameras.
  510. }
  511. else //We'll leave whatever material is already on the canvas.
  512. {
  513. matRGB = new Material(rend.material);
  514. }
  515. rend.material = matRGB;
  516. #endif
  517. }
  518. /// <summary>
  519. /// Disables the canvas and unsubscribes from events from the ZED.
  520. /// </summary>
  521. private void OnDisable()
  522. {
  523. if (zedManager != null)
  524. {
  525. zedManager.OnZEDReady -= ZEDReady;
  526. zedManager.OnZEDDisconnected -= ZEDDisconnected;
  527. }
  528. canvas.SetActive(false);
  529. }
  530. /// <summary>
  531. /// Invisible object used to force Unity to render a shadow map.
  532. /// </summary>
  533. GameObject forceShadowObject = null;
  534. /// <summary>
  535. /// Configure the canvas to get and light and shadow.
  536. /// </summary>
  537. /// <param name="renderingPath">The current rendering path used</param>
  538. private void ConfigureLightAndShadow(RenderingPath renderingPath)
  539. {
  540. RenderingPath current = actualRenderingPath;
  541. actualRenderingPath = renderingPath;
  542. if (renderingPath == RenderingPath.Forward)
  543. {
  544. canvas.SetActive(true);
  545. SetForward();
  546. }
  547. else if (renderingPath == RenderingPath.DeferredShading)
  548. {
  549. SetDeferred();
  550. }
  551. else //We're using an unknown rendering path. Log an error.
  552. {
  553. actualRenderingPath = current;
  554. Debug.LogError(" [ ZED Plugin ] : The rendering path " + cam.actualRenderingPath.ToString() + " is not compatible with the ZED");
  555. }
  556. }
  557. #if !ZED_HDRP && !ZED_URP
  558. /// <summary>
  559. /// Clear the depth buffer used.
  560. /// Called when configuring this script for the given rendering path (forward or deferred).
  561. /// </summary>
  562. private void ClearDepthBuffers()
  563. {
  564. if (buffer[(int)ZED_RENDERING_MODE.FORWARD] != null)
  565. {
  566. buffer[(int)ZED_RENDERING_MODE.FORWARD].Dispose();
  567. buffer[(int)ZED_RENDERING_MODE.FORWARD] = null;
  568. }
  569. if (buffer[(int)ZED_RENDERING_MODE.DEFERRED] != null)
  570. {
  571. buffer[(int)ZED_RENDERING_MODE.DEFERRED].Dispose();
  572. buffer[(int)ZED_RENDERING_MODE.DEFERRED] = null;
  573. }
  574. }
  575. #endif
  576. /// <summary>
  577. /// Configure the materials and buffer for the forward rendering path.
  578. /// </summary>
  579. private void SetForward()
  580. {
  581. ghasShadows = false;
  582. blitMaterial = new Material(Resources.Load("Materials/PostProcessing/Mat_ZED_Blit") as Material);
  583. Shader.SetGlobalInt("_HasShadows", 0);
  584. gameObject.transform.GetChild(0).GetComponent<MeshRenderer>().enabled = true;
  585. //Set the canvas's material to the material for forward rendering.
  586. matRGB = canvas.GetComponent<Renderer>().material;
  587. matRGB.SetInt("_isLinear", System.Convert.ToInt32(QualitySettings.activeColorSpace));
  588. forwardMat = new Material(Resources.Load("Materials/Lighting/Mat_ZED_Forward") as Material);
  589. // Configure the invisible object that forces Unity to calculate shadows.
  590. if (forceShadowObject == null)
  591. {
  592. ConfigureForceShadowObject();
  593. }
  594. //Set the textures in the materials to the proper ones.
  595. matRGB.SetTexture("_MainTex", textureEye);
  596. matRGB.SetTexture("_CameraTex", textureEye);
  597. matRGB.SetTexture("_DepthXYZTex", depth);
  598. matRGB.SetTexture("_NormalsTex", normals);
  599. #if ZED_HDRP && !ZED_URP//Need FoV to calculate world space positions accurately.
  600. matRGB.SetFloat("_ZEDHFoVRad", zedCamera.GetCalibrationParameters().leftCam.hFOV * Mathf.Deg2Rad);
  601. matRGB.SetFloat("_ZEDVFoVRad", zedCamera.GetCalibrationParameters().leftCam.vFOV * Mathf.Deg2Rad);
  602. #endif
  603. forwardMat.SetTexture("_MainTex", textureEye);
  604. forwardMat.SetTexture("_DepthXYZTex", depth);
  605. #if !ZED_HDRP && !ZED_URP
  606. //Clear the buffers.
  607. if (buffer[(int)ZED_RENDERING_MODE.FORWARD] != null)
  608. cam.RemoveCommandBuffer(CameraEvent.BeforeDepthTexture, buffer[(int)ZED_RENDERING_MODE.FORWARD]);
  609. if (buffer[(int)ZED_RENDERING_MODE.DEFERRED] != null)
  610. cam.RemoveCommandBuffer(CameraEvent.AfterGBuffer, buffer[(int)ZED_RENDERING_MODE.DEFERRED]);
  611. ClearDepthBuffers();
  612. if (postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED] != null)
  613. cam.RemoveCommandBuffer(CameraEvent.AfterFinalPass, postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED]);
  614. if (postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED] != null)
  615. {
  616. postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED].Dispose();
  617. postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED] = null;
  618. }
  619. //Set the depth buffer.
  620. buffer[(int)ZED_RENDERING_MODE.FORWARD] = new CommandBuffer();
  621. buffer[(int)ZED_RENDERING_MODE.FORWARD].name = "ZED_DEPTH";
  622. buffer[(int)ZED_RENDERING_MODE.FORWARD].SetRenderTarget(BuiltinRenderTextureType.CurrentActive);
  623. buffer[(int)ZED_RENDERING_MODE.FORWARD].DrawMesh(meshCanvas.mesh, gameObject.transform.GetChild(0).transform.localToWorldMatrix, forwardMat);
  624. #endif
  625. if (mask == null || !mask.IsCreated())
  626. {
  627. mask = new RenderTexture(Screen.width, Screen.height, 0, RenderTextureFormat.R8);
  628. }
  629. //Set up the post-processing material.
  630. postprocessMaterial.SetTexture("ZEDMaskPostProcess", mask);
  631. postprocessMaterial.SetTexture("ZEDTex", textureEye);
  632. #if !ZED_HDRP && !ZED_URP
  633. postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD] = new CommandBuffer();
  634. postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD].name = "ZED_FORWARD_POSTPROCESS";
  635. postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD].Blit(BuiltinRenderTextureType.CameraTarget, mask, blitMaterial, 0);
  636. postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD].SetGlobalTexture("_ZEDMaskVirtual", mask);
  637. cam.RemoveCommandBuffer(CameraEvent.AfterForwardAlpha, postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD]);
  638. cam.AddCommandBuffer(CameraEvent.AfterForwardAlpha, postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD]);
  639. #endif
  640. //Configure the light containers.
  641. if (computeBufferPointLight == null)
  642. {
  643. computeBufferPointLight = new ComputeBuffer(NUMBER_POINT_LIGHT_MAX, SIZE_POINT_LIGHT_BYTES);
  644. computeBufferPointLight.SetData(pointLights);
  645. matRGB.SetBuffer("pointLights", computeBufferPointLight);
  646. }
  647. if (computeBufferSpotLight == null)
  648. {
  649. computeBufferSpotLight = new ComputeBuffer(NUMBER_SPOT_LIGHT_MAX, SIZE_SPOT_LIGHT_BYTES);
  650. computeBufferSpotLight.SetData(spotLights);
  651. matRGB.SetBuffer("spotLights", computeBufferSpotLight);
  652. }
  653. //Register the property IDs to improve performance. (Setting properties by string is slower)
  654. numberPointLightsID = Shader.PropertyToID("numberPointLights");
  655. numberSpotLightsID = Shader.PropertyToID("numberSpotLights");
  656. }
  657. /// <summary>
  658. /// Configure the materials and buffer for the deferred rendering path.
  659. /// </summary>
  660. private void SetDeferred()
  661. {
  662. //Disable MSSA as it's not supported with deferred.
  663. #if UNITY_5_6_OR_NEWER
  664. cam.allowMSAA = false;
  665. #endif
  666. ghasShadows = false;
  667. deferredMat = new Material(Resources.Load("Materials/Lighting/Mat_ZED_Deferred") as Material);
  668. blitMaterial = new Material(Resources.Load("Materials/PostProcessing/Mat_ZED_Blit") as Material);
  669. //Sets the custom shader for the deferred pipeline.
  670. GraphicsSettings.SetCustomShader(BuiltinShaderType.DeferredShading, (Resources.Load("Materials/Lighting/Mat_ZED_Deferred_Lighting") as Material).shader);
  671. deferredMat.SetMatrix("_Model", canvas.transform.localToWorldMatrix.transpose);
  672. deferredMat.SetMatrix("_Projection", cam.projectionMatrix);
  673. deferredMat.SetTexture("_MainTex", textureEye);
  674. deferredMat.SetTexture("_DepthXYZTex", depth);
  675. deferredMat.SetTexture("_NormalsTex", normals);
  676. //Clear the buffers.
  677. #if !ZED_HDRP && !ZED_URP
  678. if (buffer[(int)ZED_RENDERING_MODE.FORWARD] != null)
  679. cam.RemoveCommandBuffer(CameraEvent.BeforeDepthTexture, buffer[(int)ZED_RENDERING_MODE.FORWARD]);
  680. if (buffer[(int)ZED_RENDERING_MODE.DEFERRED] != null)
  681. cam.RemoveCommandBuffer(CameraEvent.AfterGBuffer, buffer[(int)ZED_RENDERING_MODE.DEFERRED]);
  682. if (postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD] != null)
  683. cam.RemoveCommandBuffer(CameraEvent.AfterForwardAlpha, postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD]);
  684. if (postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD] != null)
  685. {
  686. postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD].Dispose();
  687. postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD] = null;
  688. }
  689. ClearDepthBuffers();
  690. //Set the depths buffer. This buffer will be changed if the camera is set to allow HDR.
  691. buffer[(int)ZED_RENDERING_MODE.DEFERRED] = new CommandBuffer();
  692. buffer[(int)ZED_RENDERING_MODE.DEFERRED].name = "ZED_DEPTH";
  693. if (cam.allowHDR)
  694. {
  695. RenderTargetIdentifier[] mrt = { BuiltinRenderTextureType.GBuffer0, BuiltinRenderTextureType.GBuffer1, BuiltinRenderTextureType.GBuffer2, BuiltinRenderTextureType.CameraTarget };
  696. buffer[(int)ZED_RENDERING_MODE.DEFERRED].SetRenderTarget(mrt, BuiltinRenderTextureType.CameraTarget);
  697. }
  698. else
  699. {
  700. RenderTargetIdentifier[] mrt = { BuiltinRenderTextureType.GBuffer0, BuiltinRenderTextureType.GBuffer1, BuiltinRenderTextureType.GBuffer2, BuiltinRenderTextureType.GBuffer3 };
  701. buffer[(int)ZED_RENDERING_MODE.DEFERRED].SetRenderTarget(mrt, BuiltinRenderTextureType.CameraTarget);
  702. }
  703. buffer[(int)ZED_RENDERING_MODE.DEFERRED].DrawMesh(meshCanvas.mesh, gameObject.transform.GetChild(0).transform.localToWorldMatrix, deferredMat);
  704. if (mask == null || !mask.IsCreated())
  705. {
  706. mask = new RenderTexture(Screen.width, Screen.height, 0, RenderTextureFormat.R8);
  707. }
  708. //Set the post process buffer
  709. postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED] = new CommandBuffer();
  710. postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED].name = "ZED_FORWARD_POSTPROCESS";
  711. postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED].Blit(BuiltinRenderTextureType.GBuffer0, mask, blitMaterial, 0);
  712. postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED].SetGlobalTexture("_ZEDMaskVirtual", mask);
  713. postprocessMaterial.SetTexture("ZEDMaskPostProcess", mask);
  714. postprocessMaterial.SetTexture("ZEDTex", textureEye);
  715. cam.AddCommandBuffer(CameraEvent.AfterGBuffer, buffer[(int)ZED_RENDERING_MODE.DEFERRED]);
  716. cam.AddCommandBuffer(CameraEvent.AfterFinalPass, postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED]);
  717. #endif
  718. //Congigure the invisible object
  719. if (forceShadowObject == null)
  720. {
  721. ConfigureForceShadowObject();
  722. }
  723. transform.GetChild(0).GetComponent<MeshRenderer>().enabled = false;
  724. }
  725. /// <summary>
  726. /// Sets up the invisible shadow GameObject that forces Unity to draw shadows.
  727. /// </summary>
  728. private void ConfigureForceShadowObject()
  729. {
  730. forceShadowObject = GameObject.CreatePrimitive(PrimitiveType.Quad);
  731. forceShadowObject.name = "ZED_FORCE_SHADOW";
  732. forceShadowObject.transform.parent = transform;
  733. forceShadowObject.transform.localPosition = new Vector3(0, 0, cam.nearClipPlane);
  734. forceShadowObject.GetComponent<MeshRenderer>().sharedMaterial = Resources.Load("Materials/Lighting/Mat_ZED_Hide") as Material;
  735. Destroy(forceShadowObject.GetComponent<MeshCollider>());
  736. forceShadowObject.hideFlags = HideFlags.HideInHierarchy;
  737. }
  738. /// <summary>
  739. /// The bounds around the camera that filter out point/spotlights that are too far away to be rendered.
  740. /// </summary>
  741. private Bounds bounds;
  742. /// <summary>
  743. /// Sets the camera's local pos/rot to origin/identity and sets up the RenderTexture if in stereo mode.
  744. /// This RenderTexture is then displayed in hidden planes handled by ZEDMixedRealityPlugin where the final
  745. /// output to the HMD is rendered.
  746. /// </summary>
  747. private void CreateRenderTexture()
  748. {
  749. transform.localRotation = Quaternion.identity;
  750. transform.localPosition = new Vector3(0, 0, 0);
  751. if (cam.stereoTargetEye != StereoTargetEyeMask.None && zedManager.IsStereoRig == true)
  752. {
  753. if (zedCamera != null && zedCamera.IsCameraReady)
  754. {
  755. renderTextureTarget = new RenderTexture(zedCamera.ImageWidth, zedCamera.ImageHeight, 24, RenderTextureFormat.ARGB32);
  756. cam.targetTexture = renderTextureTarget;
  757. }
  758. else if (sl.ZEDCamera.CheckPlugin())
  759. {
  760. renderTextureTarget = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32);
  761. cam.targetTexture = renderTextureTarget;
  762. }
  763. }
  764. }
  765. /// <summary>
  766. /// Creates and sets the textures from the ZED, including image, depth and normals as needed.
  767. /// Once created, the ZED SDK updates the textures automatically when the ZED sends new frames, so they don't need to be updated here.
  768. /// </summary>
  769. /// <param name="zedCamera"></param>
  770. private void SetTextures(sl.ZEDCamera zedCamera, sl.VIEW_MODE view_mode)
  771. {
  772. float baseline = zedCamera.Baseline;
  773. canvas.transform.localRotation = Quaternion.identity;
  774. canvas.transform.localPosition = new Vector3(0, 0, 0);
  775. if (zedManager.IsStereoRig == true && cam.stereoTargetEye != StereoTargetEyeMask.None)
  776. {
  777. if (zedCamera != null && zedCamera.IsCameraReady)
  778. {
  779. renderTextureTarget = new RenderTexture(zedCamera.ImageWidth, zedCamera.ImageHeight, 24, RenderTextureFormat.ARGB32);
  780. cam.targetTexture = renderTextureTarget;
  781. }
  782. //Set the camera to match the target stereo eye, unless force otherwise.
  783. switch (cam.stereoTargetEye)
  784. {
  785. case StereoTargetEyeMask.Left:
  786. if (viewSide == ZED_CAMERA_SIDE.RIGHT) viewSide = ZED_CAMERA_SIDE.LEFT;
  787. break;
  788. case StereoTargetEyeMask.Right:
  789. if (viewSide == ZED_CAMERA_SIDE.LEFT) viewSide = ZED_CAMERA_SIDE.RIGHT;
  790. break;
  791. default:
  792. break;
  793. }
  794. }
  795. switch (viewSide) //Set up textures from the left camera or right camera, depending.
  796. {
  797. case ZED_CAMERA_SIDE.LEFT:
  798. case ZED_CAMERA_SIDE.LEFT_FORCE:
  799. default:
  800. switch (view_mode) //Which kind of texture we view.
  801. {
  802. case sl.VIEW_MODE.VIEW_IMAGE:
  803. textureEye = zedCamera.CreateTextureImageType(sl.VIEW.LEFT);
  804. break;
  805. case sl.VIEW_MODE.VIEW_DEPTH:
  806. textureEye = zedCamera.CreateTextureImageType(sl.VIEW.DEPTH);
  807. break;
  808. case sl.VIEW_MODE.VIEW_NORMALS:
  809. textureEye = zedCamera.CreateTextureImageType(sl.VIEW.NORMALS);
  810. break;
  811. }
  812. normals = zedCamera.CreateTextureMeasureType(sl.MEASURE.NORMALS, resolution);
  813. depth = zedCamera.CreateTextureMeasureType(sl.MEASURE.DEPTH, resolution);
  814. break;
  815. case ZED_CAMERA_SIDE.RIGHT:
  816. case ZED_CAMERA_SIDE.RIGHT_FORCE:
  817. switch (view_mode)//Which kind of texture we view.
  818. {
  819. case sl.VIEW_MODE.VIEW_IMAGE:
  820. textureEye = zedCamera.CreateTextureImageType(sl.VIEW.RIGHT);
  821. break;
  822. case sl.VIEW_MODE.VIEW_DEPTH:
  823. textureEye = zedCamera.CreateTextureImageType(sl.VIEW.DEPTH_RIGHT);
  824. break;
  825. case sl.VIEW_MODE.VIEW_NORMALS:
  826. textureEye = zedCamera.CreateTextureImageType(sl.VIEW.NORMALS_RIGHT);
  827. break;
  828. }
  829. normals = zedCamera.CreateTextureMeasureType(sl.MEASURE.NORMALS_RIGHT, resolution);
  830. depth = zedCamera.CreateTextureMeasureType(sl.MEASURE.DEPTH_RIGHT, resolution);
  831. break;
  832. }
  833. }
  834. /// <summary>
  835. /// Enables/disables keywords for the material used in the first pass, when in forward rendering.
  836. /// </summary>
  837. /// <param name="enable">New state of the keyword.</param>
  838. /// <param name="name">Keyword's name.</param>
  839. /// <returns></returns>
  840. public bool ManageKeywordForwardMat(bool enable, string name)
  841. {
  842. if (forwardMat)
  843. {
  844. if (enable)
  845. {
  846. forwardMat.EnableKeyword(name);
  847. }
  848. else
  849. {
  850. forwardMat.DisableKeyword(name);
  851. }
  852. return true;
  853. }
  854. return false;
  855. }
  856. /// <summary>
  857. /// Enables/disables keywords for the material used in the first pass, when in deferred rendering.
  858. /// </summary>
  859. /// <param name="enable">New state of the keyword.</param>
  860. /// <param name="name">Keyword's name.</param>
  861. /// <returns></returns>
  862. public bool ManageKeywordDeferredMat(bool enable, string name)
  863. {
  864. if (deferredMat)
  865. {
  866. if (enable)
  867. {
  868. deferredMat.EnableKeyword(name);
  869. }
  870. else
  871. {
  872. deferredMat.DisableKeyword(name);
  873. }
  874. return true;
  875. }
  876. return false;
  877. }
  878. /// <summary>
  879. /// Enables/disables keywords for the final display material.
  880. /// </summary>
  881. /// <param name="enable">New state of the keyword.</param>
  882. /// <param name="name">Keyword's name.</param>
  883. /// <returns></returns>
  884. public bool ManageKeywordPipe(bool enable, string name)
  885. {
  886. if (matRGB)
  887. {
  888. if (enable)
  889. {
  890. matRGB.EnableKeyword(name);
  891. }
  892. else
  893. {
  894. matRGB.DisableKeyword(name);
  895. }
  896. return true;
  897. }
  898. return false;
  899. }
  900. //Variables to get information about the lights.
  901. /// <summary>
  902. /// How many point lights are currently being rendered on the real world by this camera. Excludes ones filtered out by distance.
  903. /// </summary>
  904. [HideInInspector]
  905. public int numberPointLights;
  906. /// <summary>
  907. /// How many spotlights are currently being rendered on the real world by this camera. Excludes ones filtered out by distance.
  908. /// </summary>
  909. [HideInInspector]
  910. public int numberSpotLights;
  911. bool ghasShadows = false;
  912. /// <summary>
  913. /// Updates lighting information, packages them into ComputeBuffers and sends them to the shader.
  914. /// </summary>
  915. void UpdateLights()
  916. {
  917. bool hasShadows = false;
  918. int pointLightIndex = 0;
  919. int spotLightIndex = 0;
  920. bounds.center = transform.position;
  921. foreach (ZEDLight zed_light in ZEDLight.s_lights)
  922. {
  923. Light light = zed_light.cachedLight;
  924. if (light.type == LightType.Directional || Vector3.Distance(bounds.center, light.transform.position) < (light.range + bounds.extents.x))
  925. {
  926. //Deactivate all shadows from point light and spotlights as they are not currently supported.
  927. if (light.type != LightType.Directional)
  928. {
  929. light.shadows = LightShadows.None;
  930. }
  931. if (zed_light.IsEnabled() && ((pointLightIndex + spotLightIndex) < NUMBER_LIGHTS_MAX || light.type == LightType.Directional))
  932. {
  933. if (light.type == LightType.Point)
  934. {
  935. if (pointLightIndex < NUMBER_POINT_LIGHT_MAX)
  936. {
  937. pointLights[pointLightIndex].color = light.color * light.intensity;
  938. pointLights[pointLightIndex].position = light.gameObject.transform.position;
  939. pointLights[pointLightIndex].range = light.range;
  940. pointLightIndex++;
  941. }
  942. }
  943. else if (light.type == LightType.Spot)
  944. {
  945. if (spotLightIndex < NUMBER_SPOT_LIGHT_MAX)
  946. {
  947. spotLights[spotLightIndex].color = light.color * light.intensity;
  948. spotLights[spotLightIndex].position = light.gameObject.transform.position;
  949. spotLights[spotLightIndex].direction = new Vector4(light.gameObject.transform.forward.normalized.x, light.gameObject.transform.forward.normalized.y, light.gameObject.transform.forward.normalized.z, Mathf.Cos((light.spotAngle / 2.0f) * Mathf.Deg2Rad));
  950. spotLights[spotLightIndex].parameters = new Vector4(light.spotAngle, light.intensity, 1.0f / light.range, zed_light.interiorCone);
  951. spotLightIndex++;
  952. }
  953. }
  954. else if (light.type == LightType.Directional)
  955. {
  956. hasShadows = light.shadows != LightShadows.None && QualitySettings.shadows != ShadowQuality.Disable;
  957. directionalLightData[0] = new Vector4(light.gameObject.transform.forward.normalized.x, light.gameObject.transform.forward.normalized.y, light.gameObject.transform.forward.normalized.z, 0);
  958. directionalLightData[1] = light.color * light.intensity;
  959. // Copy the shadows from the directional light. If not, no shadows in transparent mode.
  960. if (light.commandBufferCount == 0)
  961. {
  962. forwardMat.SetInt("_HasShadows", System.Convert.ToInt32(light.shadows != LightShadows.None));
  963. // Copy the shadows from the directional light. If not, no shadows in transparent mode.
  964. if (light.commandBufferCount == 0)
  965. {
  966. CommandBuffer lightBuffer = new CommandBuffer();
  967. lightBuffer.name = "ZED_Copy_ShadowMap";
  968. lightBuffer.SetGlobalTexture("_DirectionalShadowMap", BuiltinRenderTextureType.CurrentActive);
  969. light.AddCommandBuffer(LightEvent.AfterScreenspaceMask, lightBuffer);
  970. }
  971. }
  972. }
  973. }
  974. }
  975. }
  976. //Send the new light data to the final display material.
  977. if (computeBufferPointLight != null)
  978. {
  979. computeBufferPointLight.SetData(pointLights);
  980. }
  981. if (computeBufferSpotLight != null)
  982. {
  983. computeBufferSpotLight.SetData(spotLights);
  984. }
  985. numberPointLights = pointLightIndex;
  986. numberSpotLights = spotLightIndex;
  987. if (matRGB != null)
  988. {
  989. //Send the number of point lights/spotlights to the shader.
  990. matRGB.SetInt(numberPointLightsID, pointLightIndex);
  991. matRGB.SetInt(numberSpotLightsID, spotLightIndex);
  992. #if !ZED_HDRP && !ZED_URP
  993. //Add the command buffer to get shadows only if a directional light creates shadows.
  994. if (hasShadows != ghasShadows)
  995. {
  996. ghasShadows = hasShadows;
  997. Shader.SetGlobalInt("_HasShadows", System.Convert.ToInt32(ghasShadows));
  998. cam.RemoveCommandBuffer(CameraEvent.BeforeDepthTexture, buffer[(int)ZED_RENDERING_MODE.FORWARD]);
  999. if (hasShadows)
  1000. {
  1001. cam.AddCommandBuffer(CameraEvent.BeforeDepthTexture, buffer[(int)ZED_RENDERING_MODE.FORWARD]);
  1002. }
  1003. }
  1004. matRGB.SetVectorArray("ZED_directionalLight", directionalLightData);
  1005. #endif
  1006. }
  1007. }
  1008. /// <summary>
  1009. /// Gets the vertical field of view from the given projection matrix, to bypass a round number.
  1010. /// </summary>
  1011. /// <param name="projection">Projection matrix from a camera.</param>
  1012. /// <returns></returns>
  1013. float GetFOVYFromProjectionMatrix(Matrix4x4 projection)
  1014. {
  1015. return Mathf.Atan(1 / projection[1, 1]) * 2.0f;
  1016. }
  1017. /// <summary>
  1018. /// Gets the horizontal field of view from the given projection matrix.
  1019. /// </summary>
  1020. /// <param name="projection">Projection matrix from a camera.</param>
  1021. /// <returns></returns>
  1022. float GetFOVXFromProjectionMatrix(Matrix4x4 projection)
  1023. {
  1024. return Mathf.Atan(1 / projection[0, 0]) * 2.0f;
  1025. }
  1026. /// <summary>
  1027. /// Scales the canvas in front of the camera so that it fills the whole screen exactly.
  1028. /// </summary>
  1029. /// <param name="screen">Canvas object.</param>
  1030. /// <param name="fov">Camera's vertical field of view. </param>
  1031. private void scale(GameObject screen, float fov)
  1032. {
  1033. float height = Mathf.Tan(0.5f * fov) * Vector3.Distance(screen.transform.localPosition, Vector3.zero) * 2;
  1034. screen.transform.localScale = new Vector3((height * aspect), height, 1);
  1035. }
  1036. private void scaleXY(GameObject screen, float fovH, float fovV)
  1037. {
  1038. float height = Mathf.Tan(0.5f * fovV) * Vector3.Distance(screen.transform.localPosition, Vector3.zero) * 2;
  1039. float width = Mathf.Tan(0.5f * fovH) * Vector3.Distance(screen.transform.localPosition, Vector3.zero) * 2;
  1040. screen.transform.localScale = new Vector3(width, height, 1);
  1041. }
  1042. #if !ZED_HDRP && !ZED_URP
  1043. /// <summary>
  1044. /// Clears all command buffers on the camera.
  1045. /// </summary>
  1046. public void Clear()
  1047. {
  1048. if (buffer[(int)ZED_RENDERING_MODE.FORWARD] != null)
  1049. cam.RemoveCommandBuffer(CameraEvent.BeforeDepthTexture, buffer[(int)ZED_RENDERING_MODE.FORWARD]);
  1050. if (buffer[(int)ZED_RENDERING_MODE.DEFERRED] != null)
  1051. cam.RemoveCommandBuffer(CameraEvent.AfterGBuffer, buffer[(int)ZED_RENDERING_MODE.DEFERRED]);
  1052. if (postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD] != null)
  1053. cam.RemoveCommandBuffer(CameraEvent.AfterForwardAlpha, postProcessBuffer[(int)ZED_RENDERING_MODE.FORWARD]);
  1054. if (postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED] != null)
  1055. cam.RemoveCommandBuffer(CameraEvent.AfterFinalPass, postProcessBuffer[(int)ZED_RENDERING_MODE.DEFERRED]);
  1056. ClearDepthBuffers();
  1057. }
  1058. #endif
  1059. void OnApplicationQuit()
  1060. {
  1061. if (computeBufferPointLight != null)
  1062. {
  1063. computeBufferPointLight.Release();
  1064. }
  1065. if (computeBufferSpotLight != null)
  1066. {
  1067. computeBufferSpotLight.Release();
  1068. }
  1069. if (mask != null)
  1070. {
  1071. mask.Release();
  1072. }
  1073. #if ZED_HDRP || ZED_URP
  1074. RenderPipelineManager.beginFrameRendering -= SRPStartFrame;
  1075. #endif
  1076. }
  1077. /// <summary>
  1078. /// Updates the output size to fit the window at 16:9 and the bounds for light filtering, and calculates the lighting.
  1079. /// </summary>
  1080. void Update()
  1081. {
  1082. if (zedManager == null)
  1083. return;
  1084. if (aspectRatio != null)
  1085. {
  1086. aspectRatio.Update();
  1087. }
  1088. if (actualRenderingPath == RenderingPath.Forward)
  1089. {
  1090. bounds.center = transform.position;
  1091. UpdateLights();
  1092. }
  1093. if (zedManager.IsZEDReady && (cam.nearClipPlane != nearplane || cam.farClipPlane != farplane))
  1094. {
  1095. SetProjection(nearplane, farplane); //If the camera's near/far planes changed, update the matrix.
  1096. }
  1097. #if UNITY_EDITOR
  1098. if (actualRenderingPath != RenderingPath.VertexLit && cam.actualRenderingPath != actualRenderingPath)
  1099. {
  1100. ConfigureLightAndShadow(cam.actualRenderingPath);
  1101. }
  1102. #endif
  1103. }
  1104. /// <summary>
  1105. /// Used by the ZEDMeshRenderer/ZEDPlaneRenderer to draw chunks/planes onto the final images.
  1106. /// </summary>
  1107. private RenderTexture textureMapping;
  1108. /// <summary>
  1109. /// Sets the RenderTexture that gets blended into the final result, if using Plane Detection or Spatial Mapping.
  1110. /// ZEDPlaneRenderer and ZEDMeshRenderer call this with the RenderTextures to which they render each frame.
  1111. /// </summary>
  1112. /// <param name="texture"></param>
  1113. public void SetTextureOverlayMapping(RenderTexture texture)
  1114. {
  1115. textureMapping = texture;
  1116. blender.SetTexture("_ZEDMeshTex", textureMapping);
  1117. }
  1118. public void SetMeshRenderAvailable(bool r)
  1119. {
  1120. int d = -1;
  1121. if (r) d = 0;
  1122. blender.SetInt("_IsTextured", d);
  1123. blender.SetInt(isTexturedID, d);
  1124. }
  1125. #if ZED_HDRP || ZED_URP
  1126. /// <summary>
  1127. /// Blend the wireframe into the image. Used in SRP because there is no OnRenderImage automatic function.
  1128. /// </summary>
  1129. private void SRPStartFrame(ScriptableRenderContext context, Camera[] rendcam)
  1130. {
  1131. foreach(Camera camera in rendcam)
  1132. {
  1133. if (camera == renderingCam && zedManager.GetSpatialMapping.display)
  1134. {
  1135. DrawSpatialMappingMeshes(camera);
  1136. }
  1137. }
  1138. }
  1139. /// <summary>
  1140. /// Draw every chunk of the wiremesh
  1141. /// </summary>
  1142. /// <param name="drawcam"></param>
  1143. private void DrawSpatialMappingMeshes(Camera drawcam)
  1144. {
  1145. ZEDSpatialMapping spatialMapping = zedManager.GetSpatialMapping;
  1146. if (spatialMapping == null) return;
  1147. if(spatialMapping.IsRunning()) // Draw all chunks/submeshes used while spatial mapping is running, before merging.
  1148. {
  1149. foreach (ZEDSpatialMapping.Chunk chunk in spatialMapping.Chunks.Values)
  1150. {
  1151. Matrix4x4 canvastrs = Matrix4x4.TRS(chunk.o.transform.position, chunk.o.transform.rotation, chunk.o.transform.localScale);
  1152. Graphics.DrawMesh(chunk.mesh, canvastrs, chunk.o.GetComponent<MeshRenderer>().material, gameObject.layer, drawcam, 0, null, false, false);
  1153. }
  1154. }
  1155. else if (!spatialMapping.IsRunning()) // Draw final chunks, after merging.
  1156. foreach (ZEDSpatialMapping.Chunk chunk in spatialMapping.ChunkList)
  1157. {
  1158. Matrix4x4 canvastrs = Matrix4x4.TRS(chunk.o.transform.position, chunk.o.transform.rotation, chunk.o.transform.localScale);
  1159. Graphics.DrawMesh(chunk.mesh, canvastrs, chunk.o.GetComponent<MeshRenderer>().material, gameObject.layer, drawcam, 0, null, false, false);
  1160. }
  1161. }
  1162. #else
  1163. /// <summary>
  1164. /// Where the post-processing occurs.
  1165. /// Called by Unity whenever the attached Camera renders an image.
  1166. /// </summary>
  1167. /// <param name="source"></param>
  1168. /// <param name="destination"></param>
  1169. private void OnRenderImage(RenderTexture source, RenderTexture destination)
  1170. {
  1171. if (zedManager.GetSpatialMapping.display) //If displaying a mesh from spatial mapping, blend the wireframe into the image.
  1172. {
  1173. RenderTexture tmpSource = RenderTexture.GetTemporary(source.width, source.height, source.depth, source.format, RenderTextureReadWrite.sRGB);
  1174. Graphics.Blit(source, tmpSource);
  1175. Graphics.Blit(tmpSource, destination, blender);
  1176. RenderTexture.ReleaseTemporary(tmpSource);
  1177. }
  1178. else
  1179. {
  1180. if (ARpostProcessing && mask != null && zedCamera.IsCameraReady) //Apply post-processing, if enabled.
  1181. {
  1182. if (actualRenderingPath == RenderingPath.DeferredShading)
  1183. {
  1184. RenderTexture bluredMask = RenderTexture.GetTemporary(mask.width, mask.height, mask.depth, mask.format);
  1185. RenderTexture buffer = RenderTexture.GetTemporary(source.width, source.height, 24);
  1186. Graphics.SetRenderTarget(buffer);
  1187. GL.Clear(false, true, new Color(0, 0, 0, 0)); // clear the full RT
  1188. //To keep the stencil in post-processing, since Graphics.Blit normally clears it.
  1189. Graphics.SetRenderTarget(buffer.colorBuffer, source.depthBuffer);
  1190. Graphics.Blit(source, matStencilToMask);
  1191. //Compose the second mask retrieved in the forward pass. The shader should set the stencil to 148.
  1192. Graphics.Blit(mask, bluredMask);
  1193. //matComposeMask.SetTexture("_Mask", bluredMask);
  1194. matComposeMask.SetTexture(maskPropID, bluredMask);
  1195. Graphics.Blit(buffer, mask, matComposeMask);
  1196. ApplyPostProcess(source, destination, bluredMask);
  1197. RenderTexture.ReleaseTemporary(buffer);
  1198. RenderTexture.ReleaseTemporary(bluredMask);
  1199. }
  1200. else //Forward path.
  1201. {
  1202. RenderTexture bluredMask = RenderTexture.GetTemporary(mask.width, mask.height, mask.depth, mask.format);
  1203. ApplyPostProcess(source, destination, bluredMask);
  1204. RenderTexture.ReleaseTemporary(bluredMask);
  1205. }
  1206. }
  1207. else //Not using post-processing.
  1208. {
  1209. Graphics.Blit(source, destination);
  1210. }
  1211. }
  1212. }
  1213. #endif
  1214. /// <summary>
  1215. /// Apply post-processing effects to the given RenderTexture.
  1216. /// </summary>
  1217. /// <param name="source">Source RenderTexture.</param>
  1218. /// <param name="destination">Destination RenderTexture.</param>
  1219. /// <param name="bluredMask">Mask used to apply blurring effects.</param>
  1220. private void ApplyPostProcess(RenderTexture source, RenderTexture destination, RenderTexture bluredMask)
  1221. {
  1222. RenderTexture tempDestination = RenderTexture.GetTemporary(source.width, source.height, source.depth, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
  1223. Graphics.Blit(source, tempDestination, postprocessMaterial);
  1224. ZEDPostProcessingTools.Blur(mask, bluredMask, blurMaterial, 3, 1, 1);
  1225. //blurMaterial.SetTexture("_Mask", bluredMask);
  1226. blurMaterial.SetTexture(maskPropID, bluredMask);
  1227. ZEDPostProcessingTools.Blur(tempDestination, destination, blurMaterial, 2, 1, 1);
  1228. mask.SetGlobalShaderProperty("_ZEDMaskVirtual");
  1229. RenderTexture.ReleaseTemporary(tempDestination);
  1230. }
  1231. /// <summary>
  1232. /// Assigns the projection matrix from the ZED to this camera with the specified near/far planes.
  1233. /// </summary><remarks>
  1234. /// Adjusts the matrix values from a copy rather than reassigning them in ZEDCamera to avoid getting applied
  1235. /// to all copies of the camera.
  1236. ///</remarks>
  1237. ///<param name="near">Desired near plane distance.</param>
  1238. ///<param name="far">Desired far plane distance.</param>
  1239. private void SetProjection(float near = 0.1f, float far = 500f)
  1240. {
  1241. //float near = mainCamera.nearClipPlane;
  1242. //float far = mainCamera.farClipPlane;
  1243. Matrix4x4 newmat = zedCamera.Projection;
  1244. newmat[2, 2] = -(far + near) / (far - near);
  1245. newmat[2, 3] = -(2.0f * far * near) / (far - near);
  1246. cam.projectionMatrix = newmat;
  1247. nearplane = near;
  1248. farplane = far;
  1249. }
  1250. /// Forces the ZED's image to be displayed at a 16:9 ratio, regardless of the window's aspect ratio.
  1251. /// This is why the image doesn't stretch when the Game window in the editor is set to Free Aspet.
  1252. /// </summary>
  1253. public class WindowAspectRatio
  1254. {
  1255. /// <summary>
  1256. /// Current screen width.
  1257. /// </summary>
  1258. private int ScreenSizeX = 0;
  1259. /// <summary>
  1260. /// Current screen height.
  1261. /// </summary>
  1262. private int ScreenSizeY = 0;
  1263. /// <summary>
  1264. /// Camera to set to 16:9.
  1265. /// </summary>
  1266. private Camera cam;
  1267. /// <summary>
  1268. /// Aspect ratio targeted.
  1269. /// </summary>
  1270. private const float TARGET_ASPECT = 16.0f / 9.0f;
  1271. public WindowAspectRatio(Camera camera)
  1272. {
  1273. cam = camera;
  1274. RescaleCamera();
  1275. CreateCamera();
  1276. }
  1277. /// <summary>
  1278. /// Create a custom hidden camera to render black bars in the background.
  1279. /// </summary>
  1280. /// <returns></returns>
  1281. private GameObject CreateCamera()
  1282. {
  1283. GameObject o = new GameObject("CameraBlackBackground");
  1284. Camera cam = o.AddComponent<Camera>();
  1285. cam.backgroundColor = Color.black;
  1286. cam.cullingMask = 0;
  1287. cam.clearFlags = CameraClearFlags.SolidColor;
  1288. cam.depth = -int.MaxValue;
  1289. cam.useOcclusionCulling = false;
  1290. #if UNITY_5_6_OR_NEWER
  1291. cam.allowHDR = false;
  1292. cam.allowMSAA = false;
  1293. #endif
  1294. cam.stereoTargetEye = StereoTargetEyeMask.None;
  1295. cam.renderingPath = RenderingPath.Forward;
  1296. o.hideFlags = HideFlags.HideInHierarchy;
  1297. return o;
  1298. }
  1299. /// <summary>
  1300. /// Rescale the view port of the current camera to keep the 16:9 aspect ratio.
  1301. /// This is called on start and updated each frame.
  1302. /// </summary>
  1303. private void RescaleCamera()
  1304. {
  1305. //If no change, then return
  1306. if (Screen.width == ScreenSizeX && Screen.height == ScreenSizeY) return;
  1307. float windowaspect = (float)Screen.width / (float)Screen.height;
  1308. float scaleheight = windowaspect / TARGET_ASPECT;
  1309. if (scaleheight < 1.0f) //Height is too large. Shrink it, adding letterboxes to the top and bottom.
  1310. {
  1311. Rect rect = cam.rect;
  1312. rect.width = 1.0f;
  1313. rect.height = scaleheight;
  1314. rect.x = 0;
  1315. rect.y = (1.0f - scaleheight) / 2.0f;
  1316. //cam.rect = rect;
  1317. }
  1318. else //Height is too small. Reduce width, adding pillarboxes to the sides.
  1319. {
  1320. float scalewidth = 1.0f / scaleheight;
  1321. Rect rect = cam.rect;
  1322. rect.width = scalewidth;
  1323. rect.height = 1.0f;
  1324. rect.x = (1.0f - scalewidth) / 2.0f;
  1325. rect.y = 0;
  1326. cam.rect = rect;
  1327. }
  1328. ScreenSizeX = Screen.width;
  1329. ScreenSizeY = Screen.height;
  1330. }
  1331. /// <summary>
  1332. /// Calls RescaleCamera(). Called in ZEDRenderingPlane's Update() function.
  1333. /// </summary>
  1334. public void Update()
  1335. {
  1336. RescaleCamera();
  1337. }
  1338. }
  1339. }