RendererFrontend.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. #include "AtmScatteringPass.h"
  2. #include "BloomCompositePass.h"
  3. #include "BloomPass.h"
  4. #include "BlurPass.h"
  5. #include "EntityViewDefinitions.h"
  6. #include "GeometryPass.h"
  7. #include "GUIPass.h"
  8. #include "LenseFlareCompositePass.h"
  9. #include "LenseFlarePass.h"
  10. #include "LightingPass.h"
  11. #include "LuminancePass.h"
  12. #include "FinalPass.h"
  13. #include "HdrMappingPass.h"
  14. #include "PostProcessPass.h"
  15. #include "ReflectionPass.h"
  16. #include "RendererFrontend.h"
  17. #include "SkyPass.h"
  18. RendererFrontend::RendererFrontend() : m_renderPassData(nullptr)
  19. {
  20. // Disable GUI rendering until GUI render pass is set (as calling GUI functions from GUI components will crash without GUI rendering pass)
  21. m_guiRenderWasEnabled = Config::GUIVar().gui_render;
  22. Config::m_GUIVar.gui_render = false;
  23. m_renderingPassesSet = false;
  24. for(unsigned int i = 0; i < RenderPassType::RenderPassType_NumOfTypes; i++)
  25. m_allRenderPasses[i] = nullptr;
  26. m_zFar = Config::graphicsVar().z_far;
  27. m_zNear = Config::graphicsVar().z_near;
  28. /*/ Set up the order of the rendering passes
  29. m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Geometry);
  30. m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_AtmScattering);
  31. m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Lighting);
  32. m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_AtmScattering);
  33. //m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_HdrMapping);
  34. m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Bloom);
  35. m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Luminance);
  36. //m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Blur);
  37. //m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_BloomComposite);
  38. //m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_LenseFlare);
  39. //m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Blur);
  40. //m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_LenseFlareComposite);
  41. m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Final);
  42. m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_GUI);
  43. // Make sure the entries of the rendering passes are set to nullptr
  44. for(unsigned int i = 0; i < RenderPassType::RenderPassType_NumOfTypes; i++)
  45. m_initializedRenderingPasses[i] = nullptr;
  46. // Create rendering passes
  47. for(decltype(m_renderingPassesTypes.size()) i = 0, size = m_renderingPassesTypes.size(); i < size; i++)
  48. {
  49. switch(m_renderingPassesTypes[i])
  50. {
  51. case RenderPassType_Geometry:
  52. if(m_initializedRenderingPasses[RenderPassType_Geometry] == nullptr)
  53. m_initializedRenderingPasses[RenderPassType_Geometry] = new GeometryPass(*this);
  54. break;
  55. case RenderPassType_Lighting:
  56. if(m_initializedRenderingPasses[RenderPassType_Lighting] == nullptr)
  57. m_initializedRenderingPasses[RenderPassType_Lighting] = new LightingPass(*this);
  58. break;
  59. case RenderPassType_AtmScattering:
  60. if(m_initializedRenderingPasses[RenderPassType_AtmScattering] == nullptr)
  61. m_initializedRenderingPasses[RenderPassType_AtmScattering] = new AtmScatteringPass(*this);
  62. break;
  63. case RenderPassType_HdrMapping:
  64. if(m_initializedRenderingPasses[RenderPassType_HdrMapping] == nullptr)
  65. m_initializedRenderingPasses[RenderPassType_HdrMapping] = new HdrMappingPass(*this);
  66. break;
  67. case RenderPassType_Blur:
  68. if(m_initializedRenderingPasses[RenderPassType_Blur] == nullptr)
  69. m_initializedRenderingPasses[RenderPassType_Blur] = new BlurPass(*this);
  70. break;
  71. case RenderPassType_Bloom:
  72. if(m_initializedRenderingPasses[RenderPassType_Bloom] == nullptr)
  73. m_initializedRenderingPasses[RenderPassType_Bloom] = new BloomPass(*this);
  74. break;
  75. case RenderPassType_BloomComposite:
  76. if(m_initializedRenderingPasses[RenderPassType_BloomComposite] == nullptr)
  77. m_initializedRenderingPasses[RenderPassType_BloomComposite] = new BloomCompositePass(*this);
  78. break;
  79. case RenderPassType_LenseFlare:
  80. if(m_initializedRenderingPasses[RenderPassType_LenseFlare] == nullptr)
  81. m_initializedRenderingPasses[RenderPassType_LenseFlare] = new LenseFlarePass(*this);
  82. break;
  83. case RenderPassType_LenseFlareComposite:
  84. if(m_initializedRenderingPasses[RenderPassType_LenseFlareComposite] == nullptr)
  85. m_initializedRenderingPasses[RenderPassType_LenseFlareComposite] = new LenseFlareCompositePass(*this);
  86. break;
  87. case RenderPassType_Luminance:
  88. if(m_initializedRenderingPasses[RenderPassType_Luminance] == nullptr)
  89. m_initializedRenderingPasses[RenderPassType_Luminance] = new LuminancePass(*this);
  90. break;
  91. case RenderPassType_Final:
  92. if(m_initializedRenderingPasses[RenderPassType_Final] == nullptr)
  93. m_initializedRenderingPasses[RenderPassType_Final] = new FinalPass(*this);
  94. break;
  95. case RenderPassType_GUI:
  96. if(m_initializedRenderingPasses[RenderPassType_GUI] == nullptr)
  97. m_initializedRenderingPasses[RenderPassType_GUI] = new GUIPass(*this);
  98. break;
  99. }
  100. }*/
  101. }
  102. RendererFrontend::~RendererFrontend()
  103. {
  104. // Delete rendering passes
  105. for(unsigned int i = 0; i < RenderPassType::RenderPassType_NumOfTypes; i++)
  106. {
  107. // Check if has been created
  108. if(m_allRenderPasses[i] != nullptr)
  109. delete m_allRenderPasses[i];
  110. }
  111. delete m_renderPassData;
  112. }
  113. ErrorCode RendererFrontend::init()
  114. {
  115. ErrorCode returnCode = ErrorCode::Success;
  116. // Load all default textures from the texture loader, before a scene has started to load
  117. auto texturesToLoad = Loaders::texture2D().getDefaultTextures();
  118. for(decltype(texturesToLoad.size()) size = texturesToLoad.size(), i = 0; i < size; i++)
  119. queueForLoading(texturesToLoad[i]);
  120. // If eye adaption is disabled, eye adaption rate should be set to 0
  121. if(!Config::graphicsVar().eye_adaption)
  122. {
  123. Config::m_graphicsVar.eye_adaption_rate = 0.0f;
  124. }
  125. // Get the current screen size
  126. m_frameData.m_screenSize.x = Config::graphicsVar().current_resolution_x;
  127. m_frameData.m_screenSize.y = Config::graphicsVar().current_resolution_y;
  128. // Initialize renderer backend and check if it was successful
  129. if(!ErrHandlerLoc::get().ifSuccessful(m_backend.init(m_frameData), returnCode))
  130. return returnCode;
  131. // Create the render pass data struct
  132. m_renderPassData = new RenderPassData();
  133. updateProjectionMatrix();
  134. passLoadCommandsToBackend();
  135. glViewport(0, 0, m_frameData.m_screenSize.x, m_frameData.m_screenSize.y);
  136. return returnCode;
  137. }
  138. const bool RendererFrontend::getRenderFinalToTexture() const { return (m_renderPassData != nullptr) ? m_renderPassData->getRenderFinalToTexture() : false; }
  139. void RendererFrontend::setGUIPassFunctorSequence(FunctorSequence *p_GUIPassFunctorSequence)
  140. {
  141. m_renderPassData->setGUIPassFunctorSequence(p_GUIPassFunctorSequence);
  142. }
  143. void RendererFrontend::setRenderFinalToTexture(const bool p_renderToTexture)
  144. {
  145. if(m_renderPassData != nullptr)
  146. m_renderPassData->setRenderFinalToTexture(p_renderToTexture);
  147. }
  148. void RendererFrontend::setRenderToTextureResolution(const glm::ivec2 p_renderToTextureResolution)
  149. {
  150. Config::m_graphicsVar.render_to_texture_resolution_x = p_renderToTextureResolution.x;
  151. Config::m_graphicsVar.render_to_texture_resolution_y = p_renderToTextureResolution.y;
  152. }
  153. void RendererFrontend::setRenderingPasses(const RenderingPasses &p_renderingPasses)
  154. {
  155. m_renderingPassesSet = true;
  156. m_activeRenderPasses.clear();
  157. bool guiRenderPassSet = false;
  158. for(decltype(p_renderingPasses.size()) i = 0, size = p_renderingPasses.size(); i < size; i++)
  159. {
  160. switch(p_renderingPasses[i])
  161. {
  162. case RenderPassType_Geometry:
  163. if(m_allRenderPasses[RenderPassType_Geometry] == nullptr)
  164. m_allRenderPasses[RenderPassType_Geometry] = new GeometryPass(*this);
  165. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_Geometry]);
  166. break;
  167. case RenderPassType_Lighting:
  168. if(m_allRenderPasses[RenderPassType_Lighting] == nullptr)
  169. m_allRenderPasses[RenderPassType_Lighting] = new LightingPass(*this);
  170. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_Lighting]);
  171. break;
  172. case RenderPassType_AtmScattering:
  173. if(m_allRenderPasses[RenderPassType_AtmScattering] == nullptr)
  174. m_allRenderPasses[RenderPassType_AtmScattering] = new AtmScatteringPass(*this);
  175. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_AtmScattering]);
  176. break;
  177. case RenderPassType_HdrMapping:
  178. if(m_allRenderPasses[RenderPassType_HdrMapping] == nullptr)
  179. m_allRenderPasses[RenderPassType_HdrMapping] = new HdrMappingPass(*this);
  180. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_HdrMapping]);
  181. break;
  182. case RenderPassType_Blur:
  183. if(m_allRenderPasses[RenderPassType_Blur] == nullptr)
  184. m_allRenderPasses[RenderPassType_Blur] = new BlurPass(*this);
  185. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_Blur]);
  186. break;
  187. case RenderPassType_Bloom:
  188. if(m_allRenderPasses[RenderPassType_Bloom] == nullptr)
  189. m_allRenderPasses[RenderPassType_Bloom] = new BloomPass(*this);
  190. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_Bloom]);
  191. break;
  192. case RenderPassType_BloomComposite:
  193. if(m_allRenderPasses[RenderPassType_BloomComposite] == nullptr)
  194. m_allRenderPasses[RenderPassType_BloomComposite] = new BloomCompositePass(*this);
  195. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_BloomComposite]);
  196. break;
  197. case RenderPassType_LenseFlare:
  198. if(m_allRenderPasses[RenderPassType_LenseFlare] == nullptr)
  199. m_allRenderPasses[RenderPassType_LenseFlare] = new LenseFlarePass(*this);
  200. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_LenseFlare]);
  201. break;
  202. case RenderPassType_LenseFlareComposite:
  203. if(m_allRenderPasses[RenderPassType_LenseFlareComposite] == nullptr)
  204. m_allRenderPasses[RenderPassType_LenseFlareComposite] = new LenseFlareCompositePass(*this);
  205. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_LenseFlareComposite]);
  206. break;
  207. case RenderPassType_Luminance:
  208. if(m_allRenderPasses[RenderPassType_Luminance] == nullptr)
  209. m_allRenderPasses[RenderPassType_Luminance] = new LuminancePass(*this);
  210. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_Luminance]);
  211. break;
  212. case RenderPassType_Final:
  213. if(m_allRenderPasses[RenderPassType_Final] == nullptr)
  214. m_allRenderPasses[RenderPassType_Final] = new FinalPass(*this);
  215. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_Final]);
  216. break;
  217. case RenderPassType_GUI:
  218. if(m_allRenderPasses[RenderPassType_GUI] == nullptr)
  219. m_allRenderPasses[RenderPassType_GUI] = new GUIPass(*this);
  220. m_activeRenderPasses.push_back(m_allRenderPasses[RenderPassType_GUI]);
  221. guiRenderPassSet = true;
  222. break;
  223. }
  224. }
  225. // Disable GUI rendering if the GUI render pass wasn't set; re-enable GUI rendering if GUI pass was set and if it GUI rendering was enabled before
  226. if(!guiRenderPassSet)
  227. Config::m_GUIVar.gui_render = false;
  228. else
  229. if(m_guiRenderWasEnabled)
  230. Config::m_GUIVar.gui_render = true;
  231. for(decltype(m_activeRenderPasses.size()) size = m_activeRenderPasses.size(), i = 0; i < size; i++)
  232. {
  233. if(!m_activeRenderPasses[i]->isInitialized())
  234. {
  235. // Initialize the rendering pass and check if it was successful
  236. if(m_activeRenderPasses[i]->init() != ErrorCode::Success)
  237. {
  238. // Log an error and delete the rendering pass
  239. ErrHandlerLoc::get().log(ErrorType::Error, ErrorSource::Source_Renderer, m_activeRenderPasses[i]->getName() + " failed to load.");
  240. m_activeRenderPasses.erase(m_activeRenderPasses.begin() + i);
  241. i--;
  242. }
  243. }
  244. }
  245. //passLoadCommandsToBackend();
  246. glViewport(0, 0, m_frameData.m_screenSize.x, m_frameData.m_screenSize.y);
  247. }
  248. const RenderingPasses RendererFrontend::getRenderingPasses()
  249. {
  250. RenderingPasses renderPasses;
  251. for(const auto renderPass : m_activeRenderPasses)
  252. {
  253. if(renderPass != nullptr)
  254. {
  255. renderPasses.push_back(renderPass->getRenderPassType());
  256. }
  257. }
  258. return renderPasses;
  259. }
  260. void RendererFrontend::renderFrame(SceneObjects &p_sceneObjects, const float p_deltaTime)
  261. {
  262. bool projectionMatrixNeedsUpdating = false;
  263. // Adjust rendering resolution if the screen size has changed
  264. if(m_renderPassData->m_renderFinalToTexture)
  265. {
  266. if(m_frameData.m_screenSize.x != Config::graphicsVar().render_to_texture_resolution_x ||
  267. m_frameData.m_screenSize.y != Config::graphicsVar().render_to_texture_resolution_y)
  268. {
  269. // Set the new resolution
  270. m_frameData.m_screenSize.x = Config::graphicsVar().render_to_texture_resolution_x;
  271. m_frameData.m_screenSize.y = Config::graphicsVar().render_to_texture_resolution_y;
  272. // Update the projection matrix because it is dependent on the screen size
  273. projectionMatrixNeedsUpdating = true;
  274. // Set screen size in the backend
  275. m_backend.setScreenSize(m_frameData);
  276. }
  277. }
  278. else
  279. {
  280. if(m_frameData.m_screenSize.x != Config::graphicsVar().current_resolution_x ||
  281. m_frameData.m_screenSize.y != Config::graphicsVar().current_resolution_y)
  282. {
  283. // Set the new resolution
  284. m_frameData.m_screenSize.x = Config::graphicsVar().current_resolution_x;
  285. m_frameData.m_screenSize.y = Config::graphicsVar().current_resolution_y;
  286. // Update the projection matrix because it is dependent on the screen size
  287. projectionMatrixNeedsUpdating = true;
  288. // Set screen size in the backend
  289. m_backend.setScreenSize(m_frameData);
  290. }
  291. }
  292. // If Z-buffer near or far values have changed, flag projection matrix for updating
  293. if(m_zFar != p_sceneObjects.m_zFar || m_zNear != p_sceneObjects.m_zNear)
  294. {
  295. m_zFar = p_sceneObjects.m_zFar;
  296. m_zNear = p_sceneObjects.m_zNear;
  297. projectionMatrixNeedsUpdating = true;
  298. }
  299. // Update the projection matrix if it was flagged
  300. if(projectionMatrixNeedsUpdating)
  301. updateProjectionMatrix();
  302. // Clear draw commands at the beginning of each frame
  303. m_drawCommands.clear();
  304. // Load all the objects in the load-to-GPU queue. This needs to be done before any rendering, as objects in this
  305. // array might have been also added to objects-to-render arrays, so they need to be loaded first
  306. for(decltype(p_sceneObjects.m_loadToVideoMemory.size()) i = 0, size = p_sceneObjects.m_loadToVideoMemory.size(); i < size; i++)
  307. {
  308. switch(p_sceneObjects.m_loadToVideoMemory[i].getType())
  309. {
  310. case LoadableObjectsContainer::LoadableObjectType_Model:
  311. queueForLoading(p_sceneObjects.m_loadToVideoMemory[i].getModelHandle());
  312. break;
  313. case LoadableObjectsContainer::LoadableObjectType_Shader:
  314. queueForLoading(*p_sceneObjects.m_loadToVideoMemory[i].getShaderProgram());
  315. break;
  316. case LoadableObjectsContainer::LoadableObjectType_Texture:
  317. queueForLoading(p_sceneObjects.m_loadToVideoMemory[i].getTextureHandle());
  318. break;
  319. }
  320. }
  321. // Release all objects from video memory that are in the unload-from-GPU queue
  322. for(decltype(p_sceneObjects.m_unloadFromVideoMemory.size()) i = 0, size = p_sceneObjects.m_unloadFromVideoMemory.size(); i < size; i++)
  323. {
  324. switch(p_sceneObjects.m_unloadFromVideoMemory[i].getType())
  325. {
  326. case LoadableObjectsContainer::LoadableObjectType_Model:
  327. queueForUnloading(p_sceneObjects.m_unloadFromVideoMemory[i].getModelHandle());
  328. break;
  329. case LoadableObjectsContainer::LoadableObjectType_Shader:
  330. queueForUnloading(*p_sceneObjects.m_unloadFromVideoMemory[i].getShaderProgram());
  331. break;
  332. case LoadableObjectsContainer::LoadableObjectType_Texture:
  333. queueForUnloading(p_sceneObjects.m_unloadFromVideoMemory[i].getTextureHandle());
  334. break;
  335. }
  336. }
  337. unsigned int numLoadedObjectsThisFrame = 0;
  338. const unsigned int maxLoadedObjectsThisFrame = Config::rendererVar().objects_loaded_per_frame;
  339. // Iterate over all objects that require to be loaded to video memory
  340. for(auto entity : p_sceneObjects.m_objectsToLoadToVideoMemory)
  341. {
  342. GraphicsLoadToVideoMemoryComponent &component = p_sceneObjects.m_objectsToLoadToVideoMemory.get<GraphicsLoadToVideoMemoryComponent>(entity);
  343. while(!component.m_objectsToLoad.empty())
  344. {
  345. if(numLoadedObjectsThisFrame++ >= maxLoadedObjectsThisFrame)
  346. goto jumpAfterLoading;
  347. LoadableObjectsContainer &loadableObject = component.m_objectsToLoad.front();
  348. switch(loadableObject.getType())
  349. {
  350. case LoadableObjectsContainer::LoadableObjectType_Model:
  351. queueForLoading(loadableObject.getModelHandle());
  352. loadableObject.getModelHandle().setLoadedToVideoMemory(true);
  353. break;
  354. case LoadableObjectsContainer::LoadableObjectType_Shader:
  355. queueForLoading(*loadableObject.getShaderProgram());
  356. loadableObject.getShaderProgram()->setLoadedToVideoMemory(true);
  357. break;
  358. case LoadableObjectsContainer::LoadableObjectType_Texture:
  359. queueForLoading(loadableObject.getTextureHandle());
  360. loadableObject.getTextureHandle().setLoadedToVideoMemory(true);
  361. break;
  362. }
  363. component.m_objectsToLoad.pop();
  364. }
  365. component.m_loaded = true;
  366. }
  367. jumpAfterLoading:
  368. // Handle loading before any rendering takes place
  369. passLoadCommandsToBackend();
  370. // Clear the load-to-GPU queue, since everything in it has been processed
  371. p_sceneObjects.m_loadToVideoMemory.clear();
  372. // Handle object unloading
  373. passUnloadCommandsToBackend();
  374. // Clear the unload-from-GPU queue
  375. p_sceneObjects.m_unloadFromVideoMemory.clear();
  376. // Calculate the view rotation matrix
  377. const glm::quat orientation = glm::normalize(glm::toQuat(p_sceneObjects.m_cameraViewMatrix));
  378. const glm::mat4 rotate = glm::mat4_cast(orientation);
  379. // Calculate the view translation matrix
  380. const glm::mat4 translate = glm::translate(glm::mat4(1.0f), -glm::vec3(p_sceneObjects.m_cameraViewMatrix[3]));
  381. // Set the full view matrix
  382. m_frameData.m_viewMatrix = rotate * translate;
  383. // Calculate the view-projection matrix here, so it is only done once, since it only changes between frames
  384. m_frameData.m_viewProjMatrix = m_frameData.m_projMatrix * m_frameData.m_viewMatrix;
  385. // Convert the view matrix to row major for the atmospheric scattering shaders
  386. m_frameData.m_transposeViewMatrix = glm::transpose(m_frameData.m_viewMatrix);
  387. // Set the camera position
  388. m_frameData.m_cameraPosition = p_sceneObjects.m_cameraViewMatrix[3];
  389. // Set the camera target vector
  390. m_frameData.m_cameraTarget = normalize(glm::vec3(0.0f, 0.0f, -1.0f) * glm::mat3(p_sceneObjects.m_cameraViewMatrix));
  391. // Set ambient intensity multiplier
  392. m_frameData.m_ambientIntensity = p_sceneObjects.m_ambientIntensity;
  393. // Prepare the geometry buffer for a new frame and a geometry pass
  394. m_backend.getGeometryBuffer()->initFrame();
  395. glDepthMask(GL_TRUE);
  396. glEnable(GL_DEPTH_TEST); // Enable depth testing, as this is much like a regular forward render pass
  397. glClear(GL_DEPTH_BUFFER_BIT); // Make sure to clear the depth buffer for the new frame
  398. // Set depth test function
  399. glDepthFunc(Config::rendererVar().depth_test_func);
  400. //glDisable(GL_CULL_FACE);
  401. for(decltype(m_activeRenderPasses.size()) i = 0, size = m_activeRenderPasses.size(); i < size; i++)
  402. {
  403. m_activeRenderPasses[i]->update(*m_renderPassData, p_sceneObjects, p_deltaTime);
  404. }
  405. }
  406. unsigned int RendererFrontend::getFramebufferTextureHandle(GBufferTextureType p_bufferType) const
  407. {
  408. return m_backend.getFramebufferTextureHandle(p_bufferType);
  409. }