BsRenderBeast.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsRenderBeast.h"
  4. #include "BsCCamera.h"
  5. #include "BsCRenderable.h"
  6. #include "BsMaterial.h"
  7. #include "BsMesh.h"
  8. #include "BsPass.h"
  9. #include "BsSamplerState.h"
  10. #include "BsCoreApplication.h"
  11. #include "BsViewport.h"
  12. #include "BsRenderTarget.h"
  13. #include "BsRenderQueue.h"
  14. #include "BsCoreThread.h"
  15. #include "BsProfilerCPU.h"
  16. #include "BsProfilerGPU.h"
  17. #include "BsShader.h"
  18. #include "BsGpuParamBlockBuffer.h"
  19. #include "BsTime.h"
  20. #include "BsRenderableElement.h"
  21. #include "BsCoreObjectManager.h"
  22. #include "BsRenderBeastOptions.h"
  23. #include "BsLight.h"
  24. #include "BsGpuResourcePool.h"
  25. #include "BsRenderTargets.h"
  26. #include "BsRendererUtility.h"
  27. #include "BsAnimationManager.h"
  28. #include "BsSkeleton.h"
  29. #include "BsGpuBuffer.h"
  30. #include "BsGpuParamsSet.h"
  31. #include "BsRendererExtension.h"
  32. #include "BsLightProbeCache.h"
  33. #include "BsReflectionProbe.h"
  34. #include "BsIBLUtility.h"
  35. #include "BsLightGrid.h"
  36. #include "BsSkybox.h"
  37. #include "BsShadowRendering.h"
  38. #include "BsStandardDeferredLighting.h"
  39. using namespace std::placeholders;
  40. namespace bs { namespace ct
  41. {
  42. // Limited by max number of array elements in texture for DX11 hardware
  43. constexpr UINT32 MaxReflectionCubemaps = 2048 / 6;
  44. RenderBeast::RenderBeast()
  45. {
  46. mOptions = bs_shared_ptr_new<RenderBeastOptions>();
  47. }
  48. const StringID& RenderBeast::getName() const
  49. {
  50. static StringID name = "RenderBeast";
  51. return name;
  52. }
  53. void RenderBeast::initialize()
  54. {
  55. Renderer::initialize();
  56. gCoreThread().queueCommand(std::bind(&RenderBeast::initializeCore, this), CTQF_InternalQueue);
  57. }
  58. void RenderBeast::destroy()
  59. {
  60. Renderer::destroy();
  61. gCoreThread().queueCommand(std::bind(&RenderBeast::destroyCore, this));
  62. gCoreThread().submit(true);
  63. }
  64. void RenderBeast::initializeCore()
  65. {
  66. RendererUtility::startUp();
  67. mCoreOptions = bs_shared_ptr_new<RenderBeastOptions>();
  68. mScene = bs_shared_ptr_new<RendererScene>(mCoreOptions);
  69. mObjectRenderer = bs_new<ObjectRenderer>();
  70. mSkyboxMat = bs_new<SkyboxMat<false>>();
  71. mSkyboxSolidColorMat = bs_new<SkyboxMat<true>>();
  72. mFlatFramebufferToTextureMat = bs_new<FlatFramebufferToTextureMat>();
  73. mTiledDeferredLightingMats = bs_new<TiledDeferredLightingMaterials>();
  74. mTileDeferredImageBasedLightingMats = bs_new<TiledDeferredImageBasedLightingMaterials>();
  75. mPreintegratedEnvBRDF = TiledDeferredImageBasedLighting::generatePreintegratedEnvBRDF();
  76. mVisibleLightInfo = bs_new<VisibleLightData>();
  77. mVisibleReflProbeInfo = bs_new<VisibleReflProbeData>();
  78. mLightGrid = bs_new<LightGrid>();
  79. GpuResourcePool::startUp();
  80. PostProcessing::startUp();
  81. ShadowRendering::startUp(mCoreOptions->shadowMapSize);
  82. StandardDeferred::startUp();
  83. }
  84. void RenderBeast::destroyCore()
  85. {
  86. if (mObjectRenderer != nullptr)
  87. bs_delete(mObjectRenderer);
  88. mScene = nullptr;
  89. mReflCubemapArrayTex = nullptr;
  90. mSkyboxTexture = nullptr;
  91. mSkyboxFilteredReflections = nullptr;
  92. mSkyboxIrradiance = nullptr;
  93. StandardDeferred::shutDown();
  94. ShadowRendering::shutDown();
  95. PostProcessing::shutDown();
  96. GpuResourcePool::shutDown();
  97. bs_delete(mSkyboxMat);
  98. bs_delete(mSkyboxSolidColorMat);
  99. bs_delete(mVisibleLightInfo);
  100. bs_delete(mVisibleReflProbeInfo);
  101. bs_delete(mLightGrid);
  102. bs_delete(mFlatFramebufferToTextureMat);
  103. bs_delete(mTiledDeferredLightingMats);
  104. bs_delete(mTileDeferredImageBasedLightingMats);
  105. mPreintegratedEnvBRDF = nullptr;
  106. RendererUtility::shutDown();
  107. }
  108. void RenderBeast::notifyRenderableAdded(Renderable* renderable)
  109. {
  110. mScene->registerRenderable(renderable);
  111. const SceneInfo& sceneInfo = mScene->getSceneInfo();
  112. RendererObject* rendererObject = sceneInfo.renderables[renderable->getRendererId()];
  113. for(auto& entry : rendererObject->elements)
  114. mObjectRenderer->initElement(*rendererObject, entry);
  115. }
  116. void RenderBeast::notifyRenderableRemoved(Renderable* renderable)
  117. {
  118. mScene->unregisterRenderable(renderable);
  119. }
  120. void RenderBeast::notifyRenderableUpdated(Renderable* renderable)
  121. {
  122. mScene->updateRenderable(renderable);
  123. }
  124. void RenderBeast::notifyLightAdded(Light* light)
  125. {
  126. mScene->registerLight(light);
  127. }
  128. void RenderBeast::notifyLightUpdated(Light* light)
  129. {
  130. mScene->updateLight(light);
  131. }
  132. void RenderBeast::notifyLightRemoved(Light* light)
  133. {
  134. mScene->unregisterLight(light);
  135. }
  136. void RenderBeast::notifyCameraAdded(Camera* camera)
  137. {
  138. mScene->registerCamera(camera);
  139. }
  140. void RenderBeast::notifyCameraUpdated(Camera* camera, UINT32 updateFlag)
  141. {
  142. mScene->updateCamera(camera, updateFlag);
  143. }
  144. void RenderBeast::notifyCameraRemoved(Camera* camera)
  145. {
  146. mScene->unregisterCamera(camera);
  147. }
  148. void RenderBeast::notifyReflectionProbeAdded(ReflectionProbe* probe)
  149. {
  150. mScene->registerReflectionProbe(probe);
  151. // Find a spot in cubemap array
  152. const SceneInfo& sceneInfo = mScene->getSceneInfo();
  153. UINT32 probeId = probe->getRendererId();
  154. const RendererReflectionProbe* probeInfo = &sceneInfo.reflProbes[probeId];
  155. UINT32 numArrayEntries = (UINT32)mCubemapArrayUsedSlots.size();
  156. for(UINT32 i = 0; i < numArrayEntries; i++)
  157. {
  158. if(!mCubemapArrayUsedSlots[i])
  159. {
  160. mScene->setReflectionProbeArrayIndex(probeId, i, false);
  161. mCubemapArrayUsedSlots[i] = true;
  162. break;
  163. }
  164. }
  165. // No empty slot was found
  166. if (probeInfo->arrayIdx == -1)
  167. {
  168. mScene->setReflectionProbeArrayIndex(probeId, numArrayEntries, false);
  169. mCubemapArrayUsedSlots.push_back(true);
  170. }
  171. if(probeInfo->arrayIdx > MaxReflectionCubemaps)
  172. {
  173. LOGERR("Reached the maximum number of allowed reflection probe cubemaps at once. "
  174. "Ignoring reflection probe data.");
  175. }
  176. }
  177. void RenderBeast::notifyReflectionProbeUpdated(ReflectionProbe* probe)
  178. {
  179. mScene->updateReflectionProbe(probe);
  180. }
  181. void RenderBeast::notifyReflectionProbeRemoved(ReflectionProbe* probe)
  182. {
  183. const SceneInfo& sceneInfo = mScene->getSceneInfo();
  184. UINT32 probeId = probe->getRendererId();
  185. UINT32 arrayIdx = sceneInfo.reflProbes[probeId].arrayIdx;
  186. if (arrayIdx != -1)
  187. mCubemapArrayUsedSlots[arrayIdx] = false;
  188. mScene->unregisterReflectionProbe(probe);
  189. }
  190. void RenderBeast::notifyLightProbeVolumeAdded(LightProbeVolume* volume)
  191. {
  192. assert(false); // TODO
  193. }
  194. void RenderBeast::notifyLightProbeVolumeUpdated(LightProbeVolume* volume)
  195. {
  196. assert(false); // TODO
  197. }
  198. void RenderBeast::notifyLightProbeVolumeRemoved(LightProbeVolume* volume)
  199. {
  200. assert(false); // TODO
  201. }
  202. void RenderBeast::notifySkyboxAdded(Skybox* skybox)
  203. {
  204. mSkybox = skybox;
  205. SPtr<Texture> skyTex = skybox->getTexture();
  206. if (skyTex != nullptr && skyTex->getProperties().getTextureType() == TEX_TYPE_CUBE_MAP)
  207. mSkyboxTexture = skyTex;
  208. mSkyboxFilteredReflections = nullptr;
  209. mSkyboxIrradiance = nullptr;
  210. }
  211. void RenderBeast::notifySkyboxTextureChanged(Skybox* skybox)
  212. {
  213. LightProbeCache::instance().notifyDirty(skybox->getUUID());
  214. if (mSkybox == skybox)
  215. {
  216. mSkyboxTexture = skybox->getTexture();
  217. mSkyboxFilteredReflections = nullptr;
  218. mSkyboxIrradiance = nullptr;
  219. }
  220. }
  221. void RenderBeast::notifySkyboxRemoved(Skybox* skybox)
  222. {
  223. LightProbeCache::instance().unloadCachedTexture(skybox->getUUID());
  224. if (mSkybox == skybox)
  225. mSkyboxTexture = nullptr;
  226. }
  227. SPtr<PostProcessSettings> RenderBeast::createPostProcessSettings() const
  228. {
  229. return bs_shared_ptr_new<StandardPostProcessSettings>();
  230. }
  231. void RenderBeast::setOptions(const SPtr<RendererOptions>& options)
  232. {
  233. mOptions = std::static_pointer_cast<RenderBeastOptions>(options);
  234. mOptionsDirty = true;
  235. }
  236. SPtr<RendererOptions> RenderBeast::getOptions() const
  237. {
  238. return mOptions;
  239. }
  240. void RenderBeast::syncOptions(const RenderBeastOptions& options)
  241. {
  242. bool filteringChanged = mCoreOptions->filtering != options.filtering;
  243. if (options.filtering == RenderBeastFiltering::Anisotropic)
  244. filteringChanged |= mCoreOptions->anisotropyMax != options.anisotropyMax;
  245. if (filteringChanged)
  246. mScene->refreshSamplerOverrides(true);
  247. *mCoreOptions = options;
  248. mScene->setOptions(mCoreOptions);
  249. ShadowRendering::instance().setShadowMapSize(mCoreOptions->shadowMapSize);
  250. }
  251. void RenderBeast::renderAll()
  252. {
  253. // Sync all dirty sim thread CoreObject data to core thread
  254. CoreObjectManager::instance().syncToCore();
  255. if (mOptionsDirty)
  256. {
  257. gCoreThread().queueCommand(std::bind(&RenderBeast::syncOptions, this, *mOptions));
  258. mOptionsDirty = false;
  259. }
  260. gCoreThread().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime(), gTime().getFrameDelta()));
  261. }
  262. void RenderBeast::renderAllCore(float time, float delta)
  263. {
  264. THROW_IF_NOT_CORE_THREAD;
  265. gProfilerGPU().beginFrame();
  266. gProfilerCPU().beginSample("renderAllCore");
  267. const SceneInfo& sceneInfo = mScene->getSceneInfo();
  268. // Note: I'm iterating over all sampler states every frame. If this ends up being a performance
  269. // issue consider handling this internally in ct::Material which can only do it when sampler states
  270. // are actually modified after sync
  271. mScene->refreshSamplerOverrides();
  272. // Update global per-frame hardware buffers
  273. mObjectRenderer->setParamFrameParams(time);
  274. // Retrieve animation data
  275. AnimationManager::instance().waitUntilComplete();
  276. const RendererAnimationData& animData = AnimationManager::instance().getRendererData();
  277. sceneInfo.renderableReady.resize(sceneInfo.renderables.size(), false);
  278. sceneInfo.renderableReady.assign(sceneInfo.renderables.size(), false);
  279. FrameInfo frameInfo(delta, animData);
  280. // Gather all views
  281. Vector<RendererView*> views;
  282. for (auto& rtInfo : sceneInfo.renderTargets)
  283. {
  284. SPtr<RenderTarget> target = rtInfo.target;
  285. const Vector<Camera*>& cameras = rtInfo.cameras;
  286. UINT32 numCameras = (UINT32)cameras.size();
  287. for (UINT32 i = 0; i < numCameras; i++)
  288. {
  289. UINT32 viewIdx = sceneInfo.cameraToView.at(cameras[i]);
  290. RendererView* viewInfo = sceneInfo.views[viewIdx];
  291. views.push_back(viewInfo);
  292. }
  293. }
  294. mMainViewGroup.setViews(views.data(), (UINT32)views.size());
  295. mMainViewGroup.determineVisibility(sceneInfo);
  296. // Render shadow maps
  297. ShadowRendering::instance().renderShadowMaps(*mScene, mMainViewGroup, frameInfo);
  298. // Update reflection probes
  299. updateLightProbes(frameInfo);
  300. // Render everything
  301. renderViews(mMainViewGroup, frameInfo);
  302. gProfilerGPU().endFrame();
  303. // Present render targets with back buffers
  304. for (auto& rtInfo : sceneInfo.renderTargets)
  305. {
  306. if(rtInfo.target->getProperties().isWindow())
  307. RenderAPI::instance().swapBuffers(rtInfo.target);
  308. }
  309. gProfilerCPU().endSample("renderAllCore");
  310. }
  311. void RenderBeast::renderViews(const RendererViewGroup& viewGroup, const FrameInfo& frameInfo)
  312. {
  313. const SceneInfo& sceneInfo = mScene->getSceneInfo();
  314. const VisibilityInfo& visibility = viewGroup.getVisibilityInfo();
  315. // Note: I'm determining light and refl. probe visibility for the entire group. It might be more performance
  316. // efficient to do it per view. Additionally I'm using a single GPU buffer to hold their information, which is
  317. // then updated when each view group is rendered. It might be better to keep one buffer reserved per-view.
  318. // Update GPU light data
  319. mVisibleLightInfo->update(sceneInfo, viewGroup);
  320. // Update reflection probe data
  321. mVisibleReflProbeInfo->update(sceneInfo, viewGroup);
  322. // Update various buffers required by each renderable
  323. UINT32 numRenderables = (UINT32)sceneInfo.renderables.size();
  324. for (UINT32 i = 0; i < numRenderables; i++)
  325. {
  326. if (!visibility.renderables[i])
  327. continue;
  328. mScene->prepareRenderable(i, frameInfo);
  329. }
  330. UINT32 numViews = viewGroup.getNumViews();
  331. for (UINT32 i = 0; i < numViews; i++)
  332. {
  333. RendererView* view = viewGroup.getView(i);
  334. if (view->getProperties().isOverlay)
  335. renderOverlay(view);
  336. else
  337. renderView(view, frameInfo.timeDelta);
  338. }
  339. }
  340. void RenderBeast::renderView(RendererView* viewInfo, float frameDelta)
  341. {
  342. gProfilerCPU().beginSample("Render");
  343. const SceneInfo& sceneInfo = mScene->getSceneInfo();
  344. auto& viewProps = viewInfo->getProperties();
  345. const Camera* sceneCamera = viewInfo->getSceneCamera();
  346. SPtr<GpuParamBlockBuffer> perCameraBuffer = viewInfo->getPerViewBuffer();
  347. perCameraBuffer->flushToGPU();
  348. Matrix4 viewProj = viewProps.viewProjTransform;
  349. UINT32 numSamples = viewProps.numSamples;
  350. bool allowShadows = !viewProps.noShadows;
  351. if(allowShadows)
  352. {
  353. if(sceneCamera == nullptr)
  354. {
  355. // Note: In order to support shadows on non-scene views I'd need to be aware of what those views are before
  356. // rendering, in order to properly generate shadow maps.
  357. LOGWRN("Shadows are currently not supported on non-scene views. Disabling shadow rendering.");
  358. allowShadows = false;
  359. }
  360. }
  361. viewInfo->beginRendering(true);
  362. // Prepare light grid required for transparent object rendering
  363. mLightGrid->updateGrid(*viewInfo, *mVisibleLightInfo, *mVisibleReflProbeInfo, viewProps.noLighting);
  364. SPtr<GpuParamBlockBuffer> gridParams;
  365. SPtr<GpuBuffer> gridLightOffsetsAndSize, gridLightIndices;
  366. SPtr<GpuBuffer> gridProbeOffsetsAndSize, gridProbeIndices;
  367. mLightGrid->getOutputs(gridLightOffsetsAndSize, gridLightIndices, gridProbeOffsetsAndSize, gridProbeIndices,
  368. gridParams);
  369. // Prepare image based material and its param buffer
  370. ITiledDeferredImageBasedLightingMat* imageBasedLightingMat =
  371. mTileDeferredImageBasedLightingMats->get(numSamples);
  372. imageBasedLightingMat->setReflectionProbes(*mVisibleReflProbeInfo, mReflCubemapArrayTex, viewProps.renderingReflections);
  373. float skyBrightness = 1.0f;
  374. if (mSkybox != nullptr)
  375. skyBrightness = mSkybox->getBrightness();
  376. imageBasedLightingMat->setSky(mSkyboxFilteredReflections, mSkyboxIrradiance, skyBrightness);
  377. // Assign camera and per-call data to all relevant renderables
  378. const VisibilityInfo& visibility = viewInfo->getVisibilityMasks();
  379. UINT32 numRenderables = (UINT32)sceneInfo.renderables.size();
  380. SPtr<GpuParamBlockBuffer> reflParamBuffer = imageBasedLightingMat->getReflectionsParamBuffer();
  381. SPtr<SamplerState> reflSamplerState = imageBasedLightingMat->getReflectionsSamplerState();
  382. for (UINT32 i = 0; i < numRenderables; i++)
  383. {
  384. if (!visibility.renderables[i])
  385. continue;
  386. RendererObject* rendererObject = sceneInfo.renderables[i];
  387. rendererObject->updatePerCallBuffer(viewProj);
  388. for (auto& element : sceneInfo.renderables[i]->elements)
  389. {
  390. if (element.perCameraBindingIdx != -1)
  391. element.params->setParamBlockBuffer(element.perCameraBindingIdx, perCameraBuffer, true);
  392. // Everything below is required only for forward rendering (ATM only used for transparent objects)
  393. // Note: It would be nice to be able to set this once and keep it, only updating if the buffers actually
  394. // change (e.g. when growing). Although technically the internal systems should be smart enough to
  395. // avoid updates unless objects actually changed.
  396. if (element.gridParamsBindingIdx != -1)
  397. element.params->setParamBlockBuffer(element.gridParamsBindingIdx, gridParams, true);
  398. element.gridLightOffsetsAndSizeParam.set(gridLightOffsetsAndSize);
  399. element.gridLightIndicesParam.set(gridLightIndices);
  400. element.lightsBufferParam.set(mVisibleLightInfo->getLightBuffer());
  401. // Image based lighting params
  402. ImageBasedLightingParams& iblParams = element.imageBasedParams;
  403. if (iblParams.reflProbeParamsBindingIdx != -1)
  404. element.params->setParamBlockBuffer(iblParams.reflProbeParamsBindingIdx, reflParamBuffer);
  405. element.gridProbeOffsetsAndSizeParam.set(gridProbeOffsetsAndSize);
  406. iblParams.reflectionProbeIndicesParam.set(gridProbeIndices);
  407. iblParams.reflectionProbesParam.set(mVisibleReflProbeInfo->getProbeBuffer());
  408. iblParams.skyReflectionsTexParam.set(mSkyboxFilteredReflections);
  409. iblParams.skyIrradianceTexParam.set(mSkyboxIrradiance);
  410. iblParams.reflectionProbeCubemapsTexParam.set(mReflCubemapArrayTex);
  411. iblParams.preintegratedEnvBRDFParam.set(mPreintegratedEnvBRDF);
  412. iblParams.reflectionProbeCubemapsSampParam.set(reflSamplerState);
  413. iblParams.skyReflectionsSampParam.set(reflSamplerState);
  414. }
  415. }
  416. SPtr<RenderTargets> renderTargets = viewInfo->getRenderTargets();
  417. renderTargets->allocate(RTT_GBuffer);
  418. renderTargets->bind(RTT_GBuffer);
  419. // Trigger pre-base-pass callbacks
  420. auto iterRenderCallback = mCallbacks.begin();
  421. if (viewProps.triggerCallbacks)
  422. {
  423. while (iterRenderCallback != mCallbacks.end())
  424. {
  425. RendererExtension* extension = *iterRenderCallback;
  426. if (extension->getLocation() != RenderLocation::PreBasePass)
  427. break;
  428. if (extension->check(*sceneCamera))
  429. extension->render(*sceneCamera);
  430. ++iterRenderCallback;
  431. }
  432. }
  433. // Render base pass
  434. const Vector<RenderQueueElement>& opaqueElements = viewInfo->getOpaqueQueue()->getSortedElements();
  435. for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
  436. {
  437. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  438. renderElement(*renderElem, iter->passIdx, iter->applyPass, viewProj);
  439. }
  440. // Build HiZ buffer
  441. bool isMSAA = numSamples > 1;
  442. // TODO - Avoid generating it unless it actually gets used in some system
  443. if (isMSAA)
  444. {
  445. renderTargets->allocate(RTT_ResolvedDepth);
  446. renderTargets->generate(RTT_ResolvedDepth);
  447. }
  448. // Trigger post-base-pass callbacks
  449. if (viewProps.triggerCallbacks)
  450. {
  451. while (iterRenderCallback != mCallbacks.end())
  452. {
  453. RendererExtension* extension = *iterRenderCallback;
  454. if (extension->getLocation() != RenderLocation::PostBasePass)
  455. break;
  456. if (extension->check(*sceneCamera))
  457. extension->render(*sceneCamera);
  458. ++iterRenderCallback;
  459. }
  460. }
  461. renderTargets->allocate(RTT_HiZ);
  462. renderTargets->generate(RTT_HiZ);
  463. // Build AO if required
  464. bool useSSAO = viewInfo->getPPInfo().settings->ambientOcclusion.enabled;
  465. if(useSSAO)
  466. {
  467. renderTargets->allocate(RTT_AmbientOcclusion);
  468. // Note: This could be done as async compute (and started earlier, right after base pass)
  469. PostProcessing::instance().buildSSAO(*viewInfo);
  470. }
  471. RenderAPI& rapi = RenderAPI::instance();
  472. rapi.setRenderTarget(nullptr);
  473. // Accumulate all direct lighting into the light accumulation texture
  474. renderTargets->allocate(RTT_LightAccumulation);
  475. // Render non-shadowed lights into light accumulation texture (or buffer if MSAA)
  476. ITiledDeferredLightingMat* lightingMat = mTiledDeferredLightingMats->get(numSamples);
  477. lightingMat->setLights(*mVisibleLightInfo);
  478. lightingMat->execute(renderTargets, perCameraBuffer, viewProps.noLighting, !allowShadows);
  479. // If we're using flattened accumulation buffer for MSAA we need to copy its contents to the MSAA texture before
  480. // continuing
  481. if(isMSAA)
  482. {
  483. renderTargets->bind(RTT_LightAccumulation);
  484. mFlatFramebufferToTextureMat->execute(renderTargets->getLightAccumulationBuffer(),
  485. renderTargets->get(RTT_LightAccumulation));
  486. }
  487. // Render shadowed lights into light accumulation texture, using standard deferred
  488. if (allowShadows)
  489. {
  490. renderTargets->allocate(RTT_LightOcclusion);
  491. UINT32 viewIdx = sceneCamera->getRendererId();
  492. for(UINT32 i = 0; i < (UINT32)LightType::Count; i++)
  493. {
  494. LightType lightType = (LightType)i;
  495. auto& lights = mVisibleLightInfo->getLights(lightType);
  496. UINT32 count = mVisibleLightInfo->getNumShadowedLights(lightType);
  497. UINT32 offset = mVisibleLightInfo->getNumUnshadowedLights(lightType);
  498. for (UINT32 j = 0; j < count; j++)
  499. {
  500. renderTargets->bind(RTT_LightOcclusion);
  501. UINT32 lightIdx = offset + j;
  502. const RendererLight& light = *lights[lightIdx];
  503. ShadowRendering::instance().renderShadowOcclusion(*mScene, mCoreOptions->shadowFilteringQuality,
  504. light, viewIdx);
  505. renderTargets->bind(RTT_LightAccumulation);
  506. StandardDeferred::instance().renderLight(lightType, light, *viewInfo, *renderTargets);
  507. }
  508. }
  509. renderTargets->release(RTT_LightOcclusion);
  510. }
  511. // Make sure light accumulation buffer isn't bound and can be read from
  512. rapi.setRenderTarget(nullptr);
  513. // Render image based lighting, add it to light accumulation and output scene color
  514. renderTargets->allocate(RTT_SceneColor);
  515. imageBasedLightingMat->execute(renderTargets, perCameraBuffer, mPreintegratedEnvBRDF);
  516. if (useSSAO)
  517. renderTargets->release(RTT_AmbientOcclusion);
  518. renderTargets->release(RTT_LightAccumulation);
  519. renderTargets->release(RTT_GBuffer);
  520. renderTargets->bind(RTT_SceneColor, true);
  521. // If we're using flattened framebuffer for MSAA we need to copy its contents to the MSAA scene texture before
  522. // continuing
  523. if(isMSAA)
  524. mFlatFramebufferToTextureMat->execute(renderTargets->getSceneColorBuffer(), renderTargets->get(RTT_SceneColor));
  525. // Render skybox (if any)
  526. if (mSkyboxTexture != nullptr)
  527. {
  528. mSkyboxMat->bind(perCameraBuffer);
  529. mSkyboxMat->setParams(mSkyboxTexture, Color::White);
  530. }
  531. else
  532. {
  533. Color clearColor = viewProps.clearColor;
  534. mSkyboxSolidColorMat->bind(perCameraBuffer);
  535. mSkyboxSolidColorMat->setParams(nullptr, clearColor);
  536. }
  537. SPtr<Mesh> mesh = gRendererUtility().getSkyBoxMesh();
  538. gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
  539. renderTargets->bind(RTT_SceneColor, false);
  540. // Render transparent objects
  541. // TODO: Transparent objects cannot receive shadows. In order to support this I'd have to render the light occlusion
  542. // for all lights affecting this object into a single (or a few) textures. I can likely use texture arrays for this,
  543. // or to avoid sampling many textures, perhaps just jam it all in one or few texture channels.
  544. const Vector<RenderQueueElement>& transparentElements = viewInfo->getTransparentQueue()->getSortedElements();
  545. for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
  546. {
  547. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  548. renderElement(*renderElem, iter->passIdx, iter->applyPass, viewProj);
  549. }
  550. // Trigger post-light-pass callbacks
  551. if (viewProps.triggerCallbacks)
  552. {
  553. while (iterRenderCallback != mCallbacks.end())
  554. {
  555. RendererExtension* extension = *iterRenderCallback;
  556. if (extension->getLocation() != RenderLocation::PostLightPass)
  557. break;
  558. if (extension->check(*sceneCamera))
  559. extension->render(*sceneCamera);
  560. ++iterRenderCallback;
  561. }
  562. }
  563. // Post-processing and final resolve
  564. Rect2 viewportArea = viewProps.nrmViewRect;
  565. if (viewProps.runPostProcessing)
  566. {
  567. // Post-processing code also takes care of writting to the final output target
  568. PostProcessing::instance().postProcess(viewInfo, renderTargets, frameDelta);
  569. }
  570. else
  571. {
  572. // Just copy from scene color to output if no post-processing
  573. SPtr<RenderTarget> target = viewProps.target;
  574. rapi.setRenderTarget(target);
  575. rapi.setViewport(viewportArea);
  576. SPtr<Texture> sceneColor = renderTargets->get(RTT_SceneColor);
  577. gRendererUtility().blit(sceneColor, Rect2I::EMPTY, viewProps.flipView);
  578. }
  579. renderTargets->release(RTT_HiZ);
  580. renderTargets->release(RTT_SceneColor);
  581. if (isMSAA)
  582. renderTargets->release(RTT_ResolvedDepth);
  583. // Trigger overlay callbacks
  584. if (viewProps.triggerCallbacks)
  585. {
  586. while (iterRenderCallback != mCallbacks.end())
  587. {
  588. RendererExtension* extension = *iterRenderCallback;
  589. if (extension->getLocation() != RenderLocation::Overlay)
  590. break;
  591. if (extension->check(*sceneCamera))
  592. extension->render(*sceneCamera);
  593. ++iterRenderCallback;
  594. }
  595. }
  596. viewInfo->endRendering();
  597. gProfilerCPU().endSample("Render");
  598. }
  599. void RenderBeast::renderOverlay(RendererView* viewInfo)
  600. {
  601. gProfilerCPU().beginSample("RenderOverlay");
  602. viewInfo->getPerViewBuffer()->flushToGPU();
  603. viewInfo->beginRendering(false);
  604. auto& viewProps = viewInfo->getProperties();
  605. const Camera* camera = viewInfo->getSceneCamera();
  606. SPtr<RenderTarget> target = viewProps.target;
  607. SPtr<Viewport> viewport = camera->getViewport();
  608. UINT32 clearBuffers = 0;
  609. if (viewport->getRequiresColorClear())
  610. clearBuffers |= FBT_COLOR;
  611. if (viewport->getRequiresDepthClear())
  612. clearBuffers |= FBT_DEPTH;
  613. if (viewport->getRequiresStencilClear())
  614. clearBuffers |= FBT_STENCIL;
  615. if (clearBuffers != 0)
  616. {
  617. RenderAPI::instance().setRenderTarget(target);
  618. RenderAPI::instance().clearViewport(clearBuffers, viewport->getClearColor(),
  619. viewport->getClearDepthValue(), viewport->getClearStencilValue());
  620. }
  621. else
  622. RenderAPI::instance().setRenderTarget(target, 0, RT_COLOR0);
  623. RenderAPI::instance().setViewport(viewport->getNormArea());
  624. // Trigger overlay callbacks
  625. auto iterRenderCallback = mCallbacks.begin();
  626. while (iterRenderCallback != mCallbacks.end())
  627. {
  628. RendererExtension* extension = *iterRenderCallback;
  629. if (extension->getLocation() != RenderLocation::Overlay)
  630. {
  631. ++iterRenderCallback;
  632. continue;
  633. }
  634. if (extension->check(*camera))
  635. extension->render(*camera);
  636. ++iterRenderCallback;
  637. }
  638. viewInfo->endRendering();
  639. gProfilerCPU().endSample("RenderOverlay");
  640. }
  641. void RenderBeast::renderElement(const BeastRenderableElement& element, UINT32 passIdx, bool bindPass,
  642. const Matrix4& viewProj)
  643. {
  644. SPtr<Material> material = element.material;
  645. if (bindPass)
  646. gRendererUtility().setPass(material, passIdx, element.techniqueIdx);
  647. gRendererUtility().setPassParams(element.params, passIdx);
  648. if(element.morphVertexDeclaration == nullptr)
  649. gRendererUtility().draw(element.mesh, element.subMesh);
  650. else
  651. gRendererUtility().drawMorph(element.mesh, element.subMesh, element.morphShapeBuffer,
  652. element.morphVertexDeclaration);
  653. }
  654. void RenderBeast::updateLightProbes(const FrameInfo& frameInfo)
  655. {
  656. const SceneInfo& sceneInfo = mScene->getSceneInfo();
  657. UINT32 numProbes = (UINT32)sceneInfo.reflProbes.size();
  658. bs_frame_mark();
  659. {
  660. UINT32 currentCubeArraySize = 0;
  661. if(mReflCubemapArrayTex != nullptr)
  662. mReflCubemapArrayTex->getProperties().getNumArraySlices();
  663. bool forceArrayUpdate = false;
  664. if(mReflCubemapArrayTex == nullptr || (currentCubeArraySize < numProbes && currentCubeArraySize != MaxReflectionCubemaps))
  665. {
  666. TEXTURE_DESC cubeMapDesc;
  667. cubeMapDesc.type = TEX_TYPE_CUBE_MAP;
  668. cubeMapDesc.format = PF_FLOAT_R11G11B10;
  669. cubeMapDesc.width = IBLUtility::REFLECTION_CUBEMAP_SIZE;
  670. cubeMapDesc.height = IBLUtility::REFLECTION_CUBEMAP_SIZE;
  671. cubeMapDesc.numMips = PixelUtil::getMaxMipmaps(cubeMapDesc.width, cubeMapDesc.height, 1, cubeMapDesc.format);
  672. cubeMapDesc.numArraySlices = std::min(MaxReflectionCubemaps, numProbes + 4); // Keep a few empty entries
  673. mReflCubemapArrayTex = Texture::create(cubeMapDesc);
  674. forceArrayUpdate = true;
  675. }
  676. auto& cubemapArrayProps = mReflCubemapArrayTex->getProperties();
  677. TEXTURE_DESC cubemapDesc;
  678. cubemapDesc.type = TEX_TYPE_CUBE_MAP;
  679. cubemapDesc.format = PF_FLOAT_R11G11B10;
  680. cubemapDesc.width = IBLUtility::REFLECTION_CUBEMAP_SIZE;
  681. cubemapDesc.height = IBLUtility::REFLECTION_CUBEMAP_SIZE;
  682. cubemapDesc.numMips = PixelUtil::getMaxMipmaps(cubemapDesc.width, cubemapDesc.height, 1, cubemapDesc.format);
  683. cubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
  684. SPtr<Texture> scratchCubemap;
  685. if (numProbes > 0)
  686. scratchCubemap = Texture::create(cubemapDesc);
  687. FrameQueue<UINT32> emptySlots;
  688. for (UINT32 i = 0; i < numProbes; i++)
  689. {
  690. const RendererReflectionProbe& probeInfo = sceneInfo.reflProbes[i];
  691. if (probeInfo.arrayIdx > MaxReflectionCubemaps)
  692. continue;
  693. SPtr<Texture> texture = probeInfo.texture;
  694. if (texture == nullptr)
  695. texture = LightProbeCache::instance().getCachedRadianceTexture(probeInfo.probe->getUUID());
  696. if (texture == nullptr || probeInfo.textureDirty)
  697. {
  698. texture = Texture::create(cubemapDesc);
  699. if (!probeInfo.customTexture)
  700. captureSceneCubeMap(texture, probeInfo.probe->getPosition(), true, frameInfo);
  701. else
  702. {
  703. SPtr<Texture> customTexture = probeInfo.probe->getCustomTexture();
  704. IBLUtility::scaleCubemap(customTexture, 0, texture, 0);
  705. }
  706. IBLUtility::filterCubemapForSpecular(texture, scratchCubemap);
  707. LightProbeCache::instance().setCachedRadianceTexture(probeInfo.probe->getUUID(), texture);
  708. }
  709. mScene->setReflectionProbeTexture(i, texture);
  710. if(probeInfo.arrayDirty || forceArrayUpdate)
  711. {
  712. auto& srcProps = probeInfo.texture->getProperties();
  713. bool isValid = srcProps.getWidth() == IBLUtility::REFLECTION_CUBEMAP_SIZE &&
  714. srcProps.getHeight() == IBLUtility::REFLECTION_CUBEMAP_SIZE &&
  715. srcProps.getNumMipmaps() == cubemapArrayProps.getNumMipmaps() &&
  716. srcProps.getTextureType() == TEX_TYPE_CUBE_MAP;
  717. if(!isValid)
  718. {
  719. if (!probeInfo.errorFlagged)
  720. {
  721. String errMsg = StringUtil::format("Cubemap texture invalid to use as a reflection cubemap. "
  722. "Check texture size (must be {0}x{0}) and mip-map count",
  723. IBLUtility::REFLECTION_CUBEMAP_SIZE);
  724. LOGERR(errMsg);
  725. probeInfo.errorFlagged = true;
  726. }
  727. }
  728. else
  729. {
  730. for(UINT32 face = 0; face < 6; face++)
  731. for(UINT32 mip = 0; mip <= srcProps.getNumMipmaps(); mip++)
  732. probeInfo.texture->copy(mReflCubemapArrayTex, face, mip, probeInfo.arrayIdx * 6 + face, mip);
  733. }
  734. mScene->setReflectionProbeArrayIndex(i, probeInfo.arrayIdx, true);
  735. }
  736. // Note: Consider pruning the reflection cubemap array if empty slot count becomes too high
  737. }
  738. // Get skybox image-based lighting textures if needed/available
  739. if (mSkybox != nullptr && mSkyboxTexture != nullptr)
  740. {
  741. // If haven't assigned them already, do it now
  742. if (mSkyboxFilteredReflections == nullptr)
  743. {
  744. if (!LightProbeCache::instance().isRadianceDirty(mSkybox->getUUID()))
  745. mSkyboxFilteredReflections = LightProbeCache::instance().getCachedRadianceTexture(mSkybox->getUUID());
  746. else
  747. {
  748. mSkyboxFilteredReflections = Texture::create(cubemapDesc);
  749. IBLUtility::scaleCubemap(mSkyboxTexture, 0, mSkyboxFilteredReflections, 0);
  750. IBLUtility::filterCubemapForSpecular(mSkyboxFilteredReflections, scratchCubemap);
  751. LightProbeCache::instance().setCachedRadianceTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
  752. }
  753. }
  754. if(mSkyboxIrradiance == nullptr)
  755. {
  756. if (!LightProbeCache::instance().isIrradianceDirty(mSkybox->getUUID()))
  757. mSkyboxIrradiance = LightProbeCache::instance().getCachedIrradianceTexture(mSkybox->getUUID());
  758. else
  759. {
  760. TEXTURE_DESC irradianceCubemapDesc;
  761. irradianceCubemapDesc.type = TEX_TYPE_CUBE_MAP;
  762. irradianceCubemapDesc.format = PF_FLOAT_R11G11B10;
  763. irradianceCubemapDesc.width = IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
  764. irradianceCubemapDesc.height = IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
  765. irradianceCubemapDesc.numMips = 0;
  766. irradianceCubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
  767. mSkyboxIrradiance = Texture::create(irradianceCubemapDesc);
  768. IBLUtility::filterCubemapForIrradiance(mSkyboxFilteredReflections, mSkyboxIrradiance);
  769. LightProbeCache::instance().setCachedIrradianceTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
  770. }
  771. }
  772. }
  773. else
  774. {
  775. mSkyboxFilteredReflections = nullptr;
  776. mSkyboxIrradiance = nullptr;
  777. }
  778. }
  779. bs_frame_clear();
  780. }
  781. void RenderBeast::captureSceneCubeMap(const SPtr<Texture>& cubemap, const Vector3& position, bool hdr, const FrameInfo& frameInfo)
  782. {
  783. const SceneInfo& sceneInfo = mScene->getSceneInfo();
  784. auto& texProps = cubemap->getProperties();
  785. Matrix4 projTransform = Matrix4::projectionPerspective(Degree(90.0f), 1.0f, 0.05f, 1000.0f);
  786. ConvexVolume localFrustum(projTransform);
  787. RenderAPI::instance().convertProjectionMatrix(projTransform, projTransform);
  788. RENDERER_VIEW_DESC viewDesc;
  789. viewDesc.target.clearFlags = FBT_COLOR | FBT_DEPTH;
  790. viewDesc.target.clearColor = Color::Black;
  791. viewDesc.target.clearDepthValue = 1.0f;
  792. viewDesc.target.clearStencilValue = 0;
  793. viewDesc.target.nrmViewRect = Rect2(0, 0, 1.0f, 1.0f);
  794. viewDesc.target.viewRect = Rect2I(0, 0, texProps.getWidth(), texProps.getHeight());
  795. viewDesc.target.targetWidth = texProps.getWidth();
  796. viewDesc.target.targetHeight = texProps.getHeight();
  797. viewDesc.target.numSamples = 1;
  798. viewDesc.isOverlay = false;
  799. viewDesc.isHDR = hdr;
  800. viewDesc.noLighting = false;
  801. viewDesc.noShadows = true; // Note: If I ever change this I need to make sure that shadow map rendering is aware of this view (currently it is only aware of main camera views)
  802. viewDesc.triggerCallbacks = false;
  803. viewDesc.runPostProcessing = false;
  804. viewDesc.renderingReflections = true;
  805. viewDesc.visibleLayers = 0xFFFFFFFFFFFFFFFF;
  806. viewDesc.nearPlane = 0.5f;
  807. viewDesc.farPlane = 1000.0f;
  808. viewDesc.flipView = RenderAPI::instance().getAPIInfo().isFlagSet(RenderAPIFeatureFlag::UVYAxisUp);
  809. viewDesc.viewOrigin = position;
  810. viewDesc.projTransform = projTransform;
  811. viewDesc.projType = PT_PERSPECTIVE;
  812. viewDesc.stateReduction = mCoreOptions->stateReductionMode;
  813. viewDesc.sceneCamera = nullptr;
  814. Matrix4 viewOffsetMat = Matrix4::translation(-position);
  815. RendererView views[6];
  816. for(UINT32 i = 0; i < 6; i++)
  817. {
  818. // Calculate view matrix
  819. Matrix3 viewRotationMat;
  820. Vector3 forward;
  821. Vector3 up = Vector3::UNIT_Y;
  822. switch (i)
  823. {
  824. case CF_PositiveX:
  825. forward = Vector3::UNIT_X;
  826. break;
  827. case CF_NegativeX:
  828. forward = -Vector3::UNIT_X;
  829. break;
  830. case CF_PositiveY:
  831. forward = Vector3::UNIT_Y;
  832. up = -Vector3::UNIT_Z;
  833. break;
  834. case CF_NegativeY:
  835. forward = Vector3::UNIT_X; // TODO: Why X here?
  836. up = Vector3::UNIT_Z;
  837. break;
  838. case CF_PositiveZ:
  839. forward = Vector3::UNIT_Z;
  840. break;
  841. case CF_NegativeZ:
  842. forward = -Vector3::UNIT_Z;
  843. break;
  844. }
  845. Vector3 right = Vector3::cross(up, forward);
  846. viewRotationMat = Matrix3(right, up, forward); // TODO - Use -forward here? (Works for shadows)
  847. viewDesc.viewDirection = forward;
  848. viewDesc.viewTransform = Matrix4(viewRotationMat) * viewOffsetMat;
  849. // Calculate world frustum for culling
  850. const Vector<Plane>& frustumPlanes = localFrustum.getPlanes();
  851. Matrix4 worldMatrix = viewDesc.viewTransform.transpose();
  852. Vector<Plane> worldPlanes(frustumPlanes.size());
  853. UINT32 j = 0;
  854. for (auto& plane : frustumPlanes)
  855. {
  856. worldPlanes[j] = worldMatrix.multiplyAffine(plane);
  857. j++;
  858. }
  859. viewDesc.cullFrustum = ConvexVolume(worldPlanes);
  860. // Set up face render target
  861. RENDER_TEXTURE_DESC cubeFaceRTDesc;
  862. cubeFaceRTDesc.colorSurfaces[0].texture = cubemap;
  863. cubeFaceRTDesc.colorSurfaces[0].face = i;
  864. cubeFaceRTDesc.colorSurfaces[0].numFaces = 1;
  865. viewDesc.target.target = RenderTexture::create(cubeFaceRTDesc);
  866. views[i].setView(viewDesc);
  867. views[i].updatePerViewBuffer();
  868. views[i].determineVisible(sceneInfo.renderables, sceneInfo.renderableCullInfos);
  869. }
  870. RendererView* viewPtrs[] = { &views[0], &views[1], &views[2], &views[3], &views[4], &views[5] };
  871. RendererViewGroup viewGroup(viewPtrs, 6);
  872. viewGroup.determineVisibility(sceneInfo);
  873. renderViews(viewGroup, frameInfo);
  874. }
  875. }}