BsRenderCompositor.cpp 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsRenderCompositor.h"
  4. #include "BsGpuResourcePool.h"
  5. #include "BsRendererView.h"
  6. #include "Renderer/BsRendererUtility.h"
  7. #include "Mesh/BsMesh.h"
  8. #include "RenderAPI/BsGpuBuffer.h"
  9. #include "BsStandardDeferredLighting.h"
  10. #include "BsRenderBeastOptions.h"
  11. #include "Renderer/BsCamera.h"
  12. #include "BsRendererScene.h"
  13. #include "BsRenderBeast.h"
  14. #include "Utility/BsBitwise.h"
  15. #include "BsRendererTextures.h"
  16. #include "BsObjectRendering.h"
  17. #include "Material/BsGpuParamsSet.h"
  18. #include "Renderer/BsRendererExtension.h"
  19. #include "Renderer/BsSkybox.h"
  20. #include "BsLightProbes.h"
  21. namespace bs { namespace ct
  22. {
  23. UnorderedMap<StringID, RenderCompositor::NodeType*> RenderCompositor::mNodeTypes;
  24. RenderCompositor::~RenderCompositor()
  25. {
  26. clear();
  27. }
  28. void RenderCompositor::build(const RendererView& view, const StringID& finalNode)
  29. {
  30. clear();
  31. bs_frame_mark();
  32. {
  33. FrameUnorderedMap<StringID, UINT32> processedNodes;
  34. mIsValid = true;
  35. std::function<bool(const StringID&)> registerNode = [&](const StringID& nodeId)
  36. {
  37. // Find node type
  38. auto iterFind = mNodeTypes.find(nodeId);
  39. if (iterFind == mNodeTypes.end())
  40. {
  41. LOGERR("Cannot find render compositor node of type \"" + String(nodeId.cstr()) + "\".");
  42. return false;
  43. }
  44. NodeType* nodeType = iterFind->second;
  45. // Register current node
  46. auto iterFind2 = processedNodes.find(nodeId);
  47. // New node
  48. if (iterFind2 == processedNodes.end())
  49. {
  50. // Mark it as invalid for now
  51. processedNodes[nodeId] = -1;
  52. }
  53. // Register node dependencies
  54. SmallVector<StringID, 4> depIds = nodeType->getDependencies(view);
  55. for (auto& dep : depIds)
  56. {
  57. if (!registerNode(dep))
  58. return false;
  59. }
  60. // Register current node
  61. UINT32 curIdx;
  62. // New node, properly populate its index
  63. if (iterFind2 == processedNodes.end())
  64. {
  65. iterFind2 = processedNodes.find(nodeId);
  66. curIdx = (UINT32)mNodeInfos.size();
  67. mNodeInfos.push_back(NodeInfo());
  68. processedNodes[nodeId] = curIdx;
  69. NodeInfo& nodeInfo = mNodeInfos.back();
  70. nodeInfo.node = nodeType->create();
  71. nodeInfo.lastUseIdx = -1;
  72. for (auto& depId : depIds)
  73. {
  74. iterFind2 = processedNodes.find(depId);
  75. NodeInfo& depNodeInfo = mNodeInfos[iterFind2->second];
  76. nodeInfo.inputs.push_back(depNodeInfo.node);
  77. }
  78. }
  79. else // Existing node
  80. {
  81. curIdx = iterFind2->second;
  82. // Check if invalid
  83. if (curIdx == -1)
  84. {
  85. LOGERR("Render compositor nodes recursion detected. Node \"" + String(nodeId.cstr()) + "\" " +
  86. "depends on node \"" + String(iterFind->first.cstr()) + "\" which is not available at " +
  87. "this stage.");
  88. return false;
  89. }
  90. }
  91. // Update dependency last use counters
  92. for (auto& dep : depIds)
  93. {
  94. iterFind2 = processedNodes.find(dep);
  95. NodeInfo& depNodeInfo = mNodeInfos[iterFind2->second];
  96. if (depNodeInfo.lastUseIdx == -1)
  97. depNodeInfo.lastUseIdx = curIdx;
  98. else
  99. depNodeInfo.lastUseIdx = std::max(depNodeInfo.lastUseIdx, curIdx);
  100. }
  101. return true;
  102. };
  103. mIsValid = registerNode(finalNode);
  104. if (!mIsValid)
  105. clear();
  106. }
  107. bs_frame_clear();
  108. }
  109. void RenderCompositor::execute(RenderCompositorNodeInputs& inputs) const
  110. {
  111. if (!mIsValid)
  112. return;
  113. bs_frame_mark();
  114. {
  115. FrameVector<const NodeInfo*> activeNodes;
  116. UINT32 idx = 0;
  117. for (auto& entry : mNodeInfos)
  118. {
  119. inputs.inputNodes = entry.inputs;
  120. entry.node->render(inputs);
  121. activeNodes.push_back(&entry);
  122. for (UINT32 i = 0; i < (UINT32)activeNodes.size(); ++i)
  123. {
  124. if (activeNodes[i] == nullptr)
  125. continue;
  126. if (activeNodes[i]->lastUseIdx <= idx)
  127. {
  128. activeNodes[i]->node->clear();
  129. activeNodes[i] = nullptr;
  130. }
  131. }
  132. idx++;
  133. }
  134. }
  135. bs_frame_clear();
  136. if (!mNodeInfos.empty())
  137. mNodeInfos.back().node->clear();
  138. }
  139. void RenderCompositor::clear()
  140. {
  141. for (auto& entry : mNodeInfos)
  142. bs_delete(entry.node);
  143. mNodeInfos.clear();
  144. mIsValid = false;
  145. }
  146. void RCNodeSceneDepth::render(const RenderCompositorNodeInputs& inputs)
  147. {
  148. GpuResourcePool& resPool = GpuResourcePool::instance();
  149. const RendererViewProperties& viewProps = inputs.view.getProperties();
  150. UINT32 width = viewProps.viewRect.width;
  151. UINT32 height = viewProps.viewRect.height;
  152. UINT32 numSamples = viewProps.numSamples;
  153. depthTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_D32_S8X24, width, height, TU_DEPTHSTENCIL,
  154. numSamples, false));
  155. }
  156. void RCNodeSceneDepth::clear()
  157. {
  158. GpuResourcePool& resPool = GpuResourcePool::instance();
  159. resPool.release(depthTex);
  160. }
  161. SmallVector<StringID, 4> RCNodeSceneDepth::getDependencies(const RendererView& view)
  162. {
  163. return {};
  164. }
  165. void RCNodeGBuffer::render(const RenderCompositorNodeInputs& inputs)
  166. {
  167. // Allocate necessary textures & targets
  168. GpuResourcePool& resPool = GpuResourcePool::instance();
  169. const RendererViewProperties& viewProps = inputs.view.getProperties();
  170. UINT32 width = viewProps.viewRect.width;
  171. UINT32 height = viewProps.viewRect.height;
  172. UINT32 numSamples = viewProps.numSamples;
  173. // Note: Consider customizable formats. e.g. for testing if quality can be improved with higher precision normals.
  174. albedoTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA8, width, height, TU_RENDERTARGET,
  175. numSamples, true));
  176. normalTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGB10A2, width, height, TU_RENDERTARGET,
  177. numSamples, false));
  178. roughMetalTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RG16F, width, height, TU_RENDERTARGET,
  179. numSamples, false)); // Note: Metal doesn't need 16-bit float
  180. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[0]);
  181. SPtr<PooledRenderTexture> sceneDepthTex = sceneDepthNode->depthTex;
  182. bool rebuildRT = false;
  183. if (renderTarget != nullptr)
  184. {
  185. rebuildRT |= renderTarget->getColorTexture(0) != albedoTex->texture;
  186. rebuildRT |= renderTarget->getColorTexture(1) != normalTex->texture;
  187. rebuildRT |= renderTarget->getColorTexture(2) != roughMetalTex->texture;
  188. rebuildRT |= renderTarget->getDepthStencilTexture() != sceneDepthTex->texture;
  189. }
  190. else
  191. rebuildRT = true;
  192. if (renderTarget == nullptr || rebuildRT)
  193. {
  194. RENDER_TEXTURE_DESC gbufferDesc;
  195. gbufferDesc.colorSurfaces[0].texture = albedoTex->texture;
  196. gbufferDesc.colorSurfaces[0].face = 0;
  197. gbufferDesc.colorSurfaces[0].numFaces = 1;
  198. gbufferDesc.colorSurfaces[0].mipLevel = 0;
  199. gbufferDesc.colorSurfaces[1].texture = normalTex->texture;
  200. gbufferDesc.colorSurfaces[1].face = 0;
  201. gbufferDesc.colorSurfaces[1].numFaces = 1;
  202. gbufferDesc.colorSurfaces[1].mipLevel = 0;
  203. gbufferDesc.colorSurfaces[2].texture = roughMetalTex->texture;
  204. gbufferDesc.colorSurfaces[2].face = 0;
  205. gbufferDesc.colorSurfaces[2].numFaces = 1;
  206. gbufferDesc.colorSurfaces[2].mipLevel = 0;
  207. gbufferDesc.depthStencilSurface.texture = sceneDepthTex->texture;
  208. gbufferDesc.depthStencilSurface.face = 0;
  209. gbufferDesc.depthStencilSurface.mipLevel = 0;
  210. renderTarget = RenderTexture::create(gbufferDesc);
  211. }
  212. // Prepare all visible objects. Note that this also prepares non-opaque objects.
  213. const VisibilityInfo& visibility = inputs.view.getVisibilityMasks();
  214. UINT32 numRenderables = (UINT32)inputs.scene.renderables.size();
  215. for (UINT32 i = 0; i < numRenderables; i++)
  216. {
  217. if (!visibility.renderables[i])
  218. continue;
  219. RendererObject* rendererObject = inputs.scene.renderables[i];
  220. rendererObject->updatePerCallBuffer(viewProps.viewProjTransform);
  221. for (auto& element : inputs.scene.renderables[i]->elements)
  222. {
  223. if (element.perCameraBindingIdx != -1)
  224. element.params->setParamBlockBuffer(element.perCameraBindingIdx, inputs.view.getPerViewBuffer(), true);
  225. }
  226. }
  227. Camera* sceneCamera = inputs.view.getSceneCamera();
  228. // Trigger pre-base-pass callbacks
  229. if (sceneCamera != nullptr)
  230. {
  231. for(auto& extension : inputs.extPreBasePass)
  232. {
  233. if (extension->check(*sceneCamera))
  234. extension->render(*sceneCamera);
  235. }
  236. }
  237. // Render base pass
  238. RenderAPI& rapi = RenderAPI::instance();
  239. rapi.setRenderTarget(renderTarget);
  240. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  241. rapi.setViewport(area);
  242. // Clear all targets
  243. rapi.clearViewport(FBT_COLOR | FBT_DEPTH | FBT_STENCIL, Color::ZERO, 1.0f, 0);
  244. // Render all visible opaque elements
  245. const Vector<RenderQueueElement>& opaqueElements = inputs.view.getOpaqueQueue()->getSortedElements();
  246. for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
  247. {
  248. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  249. SPtr<Material> material = renderElem->material;
  250. if (iter->applyPass)
  251. gRendererUtility().setPass(material, iter->passIdx, renderElem->techniqueIdx);
  252. gRendererUtility().setPassParams(renderElem->params, iter->passIdx);
  253. if(renderElem->morphVertexDeclaration == nullptr)
  254. gRendererUtility().draw(renderElem->mesh, renderElem->subMesh);
  255. else
  256. gRendererUtility().drawMorph(renderElem->mesh, renderElem->subMesh, renderElem->morphShapeBuffer,
  257. renderElem->morphVertexDeclaration);
  258. }
  259. // Trigger post-base-pass callbacks
  260. if (sceneCamera != nullptr)
  261. {
  262. for(auto& extension : inputs.extPostBasePass)
  263. {
  264. if (extension->check(*sceneCamera))
  265. extension->render(*sceneCamera);
  266. }
  267. }
  268. }
  269. void RCNodeGBuffer::clear()
  270. {
  271. GpuResourcePool& resPool = GpuResourcePool::instance();
  272. resPool.release(albedoTex);
  273. resPool.release(normalTex);
  274. resPool.release(roughMetalTex);
  275. }
  276. SmallVector<StringID, 4> RCNodeGBuffer::getDependencies(const RendererView& view)
  277. {
  278. return { RCNodeSceneDepth::getNodeId() };
  279. }
  280. void RCNodeSceneColor::render(const RenderCompositorNodeInputs& inputs)
  281. {
  282. GpuResourcePool& resPool = GpuResourcePool::instance();
  283. const RendererViewProperties& viewProps = inputs.view.getProperties();
  284. UINT32 width = viewProps.viewRect.width;
  285. UINT32 height = viewProps.viewRect.height;
  286. UINT32 numSamples = viewProps.numSamples;
  287. // Note: Consider customizable HDR format via options? e.g. smaller PF_FLOAT_R11G11B10 or larger 32-bit format
  288. sceneColorTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, width, height, TU_RENDERTARGET |
  289. TU_LOADSTORE, numSamples, false));
  290. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[0]);
  291. SPtr<PooledRenderTexture> sceneDepthTex = sceneDepthNode->depthTex;
  292. if (viewProps.numSamples > 1)
  293. {
  294. UINT32 bufferNumElements = width * height * viewProps.numSamples;
  295. flattenedSceneColorBuffer = resPool.get(POOLED_STORAGE_BUFFER_DESC::createStandard(BF_16X4F, bufferNumElements));
  296. }
  297. else
  298. flattenedSceneColorBuffer = nullptr;
  299. bool rebuildRT = false;
  300. if (renderTarget != nullptr)
  301. {
  302. rebuildRT |= renderTarget->getColorTexture(0) != sceneColorTex->texture;
  303. rebuildRT |= renderTarget->getDepthStencilTexture() != sceneDepthTex->texture;
  304. }
  305. else
  306. rebuildRT = true;
  307. if (rebuildRT)
  308. {
  309. RENDER_TEXTURE_DESC sceneColorDesc;
  310. sceneColorDesc.colorSurfaces[0].texture = sceneColorTex->texture;
  311. sceneColorDesc.colorSurfaces[0].face = 0;
  312. sceneColorDesc.colorSurfaces[0].numFaces = 1;
  313. sceneColorDesc.colorSurfaces[0].mipLevel = 0;
  314. sceneColorDesc.depthStencilSurface.texture = sceneDepthTex->texture;
  315. sceneColorDesc.depthStencilSurface.face = 0;
  316. sceneColorDesc.depthStencilSurface.numFaces = 1;
  317. sceneColorDesc.depthStencilSurface.mipLevel = 0;
  318. renderTarget = RenderTexture::create(sceneColorDesc);
  319. }
  320. }
  321. void RCNodeSceneColor::clear()
  322. {
  323. GpuResourcePool& resPool = GpuResourcePool::instance();
  324. resPool.release(sceneColorTex);
  325. if (flattenedSceneColorBuffer != nullptr)
  326. resPool.release(flattenedSceneColorBuffer);
  327. }
  328. SmallVector<StringID, 4> RCNodeSceneColor::getDependencies(const RendererView& view)
  329. {
  330. return { RCNodeSceneDepth::getNodeId() };
  331. }
  332. void RCNodeLightAccumulation::render(const RenderCompositorNodeInputs& inputs)
  333. {
  334. GpuResourcePool& resPool = GpuResourcePool::instance();
  335. const RendererViewProperties& viewProps = inputs.view.getProperties();
  336. UINT32 width = viewProps.viewRect.width;
  337. UINT32 height = viewProps.viewRect.height;
  338. UINT32 numSamples = viewProps.numSamples;
  339. if (numSamples > 1)
  340. {
  341. UINT32 bufferNumElements = width * height * numSamples;
  342. flattenedLightAccumBuffer =
  343. resPool.get(POOLED_STORAGE_BUFFER_DESC::createStandard(BF_16X4F, bufferNumElements));
  344. SPtr<GpuBuffer> buffer = flattenedLightAccumBuffer->buffer;
  345. auto& bufferProps = buffer->getProperties();
  346. UINT32 bufferSize = bufferProps.getElementSize() * bufferProps.getElementCount();
  347. UINT16* data = (UINT16*)buffer->lock(0, bufferSize, GBL_WRITE_ONLY_DISCARD);
  348. {
  349. memset(data, 0, bufferSize);
  350. }
  351. buffer->unlock();
  352. }
  353. else
  354. flattenedLightAccumBuffer = nullptr;
  355. lightAccumulationTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, width,
  356. height, TU_LOADSTORE | TU_RENDERTARGET, numSamples, false));
  357. bool rebuildRT;
  358. if (renderTarget != nullptr)
  359. rebuildRT = renderTarget->getColorTexture(0) != lightAccumulationTex->texture;
  360. else
  361. rebuildRT = true;
  362. if (rebuildRT)
  363. {
  364. RENDER_TEXTURE_DESC lightAccumulationRTDesc;
  365. lightAccumulationRTDesc.colorSurfaces[0].texture = lightAccumulationTex->texture;
  366. lightAccumulationRTDesc.colorSurfaces[0].face = 0;
  367. lightAccumulationRTDesc.colorSurfaces[0].numFaces = 1;
  368. lightAccumulationRTDesc.colorSurfaces[0].mipLevel = 0;
  369. renderTarget = RenderTexture::create(lightAccumulationRTDesc);
  370. }
  371. }
  372. void RCNodeLightAccumulation::clear()
  373. {
  374. GpuResourcePool& resPool = GpuResourcePool::instance();
  375. resPool.release(lightAccumulationTex);
  376. if (flattenedLightAccumBuffer)
  377. resPool.release(flattenedLightAccumBuffer);
  378. }
  379. SmallVector<StringID, 4> RCNodeLightAccumulation::getDependencies(const RendererView& view)
  380. {
  381. return {};
  382. }
  383. void RCNodeTiledDeferredLighting::render(const RenderCompositorNodeInputs& inputs)
  384. {
  385. output = static_cast<RCNodeLightAccumulation*>(inputs.inputNodes[0]);
  386. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[1]);
  387. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[2]);
  388. const RendererViewProperties& viewProps = inputs.view.getProperties();
  389. TiledDeferredLightingMat* tiledDeferredMat = TiledDeferredLightingMat::getVariation(viewProps.numSamples);
  390. GBufferTextures gbuffer;
  391. gbuffer.albedo = gbufferNode->albedoTex->texture;
  392. gbuffer.normals = gbufferNode->normalTex->texture;
  393. gbuffer.roughMetal = gbufferNode->roughMetalTex->texture;
  394. gbuffer.depth = sceneDepthNode->depthTex->texture;
  395. RenderAPI& rapi = RenderAPI::instance();
  396. rapi.setRenderTarget(output->renderTarget, FBT_DEPTH | FBT_STENCIL, RT_COLOR0 | RT_DEPTH_STENCIL);
  397. const VisibleLightData& lightData = inputs.viewGroup.getVisibleLightData();
  398. SPtr<GpuBuffer> flattenedLightAccumBuffer;
  399. if (output->flattenedLightAccumBuffer)
  400. flattenedLightAccumBuffer = output->flattenedLightAccumBuffer->buffer;
  401. tiledDeferredMat->execute(inputs.view, lightData, gbuffer, output->lightAccumulationTex->texture,
  402. flattenedLightAccumBuffer);
  403. }
  404. void RCNodeTiledDeferredLighting::clear()
  405. {
  406. output = nullptr;
  407. }
  408. SmallVector<StringID, 4> RCNodeTiledDeferredLighting::getDependencies(const RendererView& view)
  409. {
  410. return { RCNodeLightAccumulation::getNodeId(), RCNodeGBuffer::getNodeId(), RCNodeSceneDepth::getNodeId() };
  411. }
  412. void RCNodeStandardDeferredLighting::render(const RenderCompositorNodeInputs& inputs)
  413. {
  414. RCNodeTiledDeferredLighting* tileDeferredNode = static_cast<RCNodeTiledDeferredLighting*>(inputs.inputNodes[0]);
  415. output = tileDeferredNode->output;
  416. // If shadows are disabled we handle all lights through tiled deferred
  417. if (!inputs.view.getRenderSettings().enableShadows)
  418. return;
  419. GpuResourcePool& resPool = GpuResourcePool::instance();
  420. const RendererViewProperties& viewProps = inputs.view.getProperties();
  421. UINT32 width = viewProps.viewRect.width;
  422. UINT32 height = viewProps.viewRect.height;
  423. UINT32 numSamples = viewProps.numSamples;
  424. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[1]);
  425. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[2]);
  426. // Allocate light occlusion
  427. SPtr<PooledRenderTexture> lightOcclusionTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, width,
  428. height, TU_RENDERTARGET, numSamples, false));
  429. bool rebuildRT = false;
  430. if (mRenderTarget != nullptr)
  431. {
  432. rebuildRT |= mRenderTarget->getColorTexture(0) != lightOcclusionTex->texture;
  433. rebuildRT |= mRenderTarget->getDepthStencilTexture() != sceneDepthNode->depthTex->texture;
  434. }
  435. else
  436. rebuildRT = true;
  437. if (rebuildRT)
  438. {
  439. RENDER_TEXTURE_DESC lightOcclusionRTDesc;
  440. lightOcclusionRTDesc.colorSurfaces[0].texture = lightOcclusionTex->texture;
  441. lightOcclusionRTDesc.colorSurfaces[0].face = 0;
  442. lightOcclusionRTDesc.colorSurfaces[0].numFaces = 1;
  443. lightOcclusionRTDesc.colorSurfaces[0].mipLevel = 0;
  444. lightOcclusionRTDesc.depthStencilSurface.texture = sceneDepthNode->depthTex->texture;
  445. lightOcclusionRTDesc.depthStencilSurface.face = 0;
  446. lightOcclusionRTDesc.depthStencilSurface.numFaces = 1;
  447. lightOcclusionRTDesc.depthStencilSurface.mipLevel = 0;
  448. mRenderTarget = RenderTexture::create(lightOcclusionRTDesc);
  449. }
  450. GBufferTextures gbuffer;
  451. gbuffer.albedo = gbufferNode->albedoTex->texture;
  452. gbuffer.normals = gbufferNode->normalTex->texture;
  453. gbuffer.roughMetal = gbufferNode->roughMetalTex->texture;
  454. gbuffer.depth = sceneDepthNode->depthTex->texture;
  455. const VisibleLightData& lightData = inputs.viewGroup.getVisibleLightData();
  456. const ShadowRendering& shadowRenderer = inputs.viewGroup.getShadowRenderer();
  457. RenderAPI& rapi = RenderAPI::instance();
  458. for (UINT32 i = 0; i < (UINT32)LightType::Count; i++)
  459. {
  460. LightType lightType = (LightType)i;
  461. auto& lights = lightData.getLights(lightType);
  462. UINT32 count = lightData.getNumShadowedLights(lightType);
  463. UINT32 offset = lightData.getNumUnshadowedLights(lightType);
  464. for (UINT32 j = 0; j < count; j++)
  465. {
  466. rapi.setRenderTarget(mRenderTarget, FBT_DEPTH, RT_DEPTH_STENCIL);
  467. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  468. rapi.setViewport(area);
  469. rapi.clearViewport(FBT_COLOR, Color::ZERO);
  470. UINT32 lightIdx = offset + j;
  471. const RendererLight& light = *lights[lightIdx];
  472. shadowRenderer.renderShadowOcclusion(inputs.view, inputs.options.shadowFilteringQuality, light, gbuffer);
  473. rapi.setRenderTarget(output->renderTarget, FBT_DEPTH | FBT_STENCIL, RT_COLOR0 | RT_DEPTH_STENCIL);
  474. StandardDeferred::instance().renderLight(lightType, light, inputs.view, gbuffer,
  475. lightOcclusionTex->texture);
  476. }
  477. }
  478. // Makes sure light accumulation can be read by following passes
  479. rapi.setRenderTarget(nullptr);
  480. resPool.release(lightOcclusionTex);
  481. }
  482. void RCNodeStandardDeferredLighting::clear()
  483. {
  484. output = nullptr;
  485. }
  486. SmallVector<StringID, 4> RCNodeStandardDeferredLighting::getDependencies(const RendererView& view)
  487. {
  488. SmallVector<StringID, 4> deps;
  489. deps.push_back(RCNodeTiledDeferredLighting::getNodeId());
  490. deps.push_back(RCNodeGBuffer::getNodeId());
  491. deps.push_back(RCNodeSceneDepth::getNodeId());
  492. if (view.getProperties().numSamples > 1)
  493. deps.push_back(RCNodeUnflattenLightAccum::getNodeId());
  494. return deps;
  495. }
  496. void RCNodeUnflattenLightAccum::render(const RenderCompositorNodeInputs& inputs)
  497. {
  498. RCNodeLightAccumulation* lightAccumNode = static_cast<RCNodeLightAccumulation*>(inputs.inputNodes[0]);
  499. FlatFramebufferToTextureMat* material = FlatFramebufferToTextureMat::get();
  500. RenderAPI& rapi = RenderAPI::instance();
  501. rapi.setRenderTarget(lightAccumNode->renderTarget, FBT_DEPTH | FBT_STENCIL, RT_COLOR0 | RT_DEPTH_STENCIL);
  502. material->execute(lightAccumNode->flattenedLightAccumBuffer->buffer, lightAccumNode->lightAccumulationTex->texture);
  503. }
  504. void RCNodeUnflattenLightAccum::clear()
  505. {
  506. output = nullptr;
  507. }
  508. SmallVector<StringID, 4> RCNodeUnflattenLightAccum::getDependencies(const RendererView& view)
  509. {
  510. return { RCNodeLightAccumulation::getNodeId() };
  511. }
  512. void RCNodeIndirectLighting::render(const RenderCompositorNodeInputs& inputs)
  513. {
  514. if (!inputs.view.getRenderSettings().enableIndirectLighting)
  515. return;
  516. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[0]);
  517. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[1]);
  518. RCNodeLightAccumulation* lightAccumNode = static_cast <RCNodeLightAccumulation*>(inputs.inputNodes[2]);
  519. SPtr<Texture> ssao;
  520. if (inputs.view.getRenderSettings().ambientOcclusion.enabled)
  521. {
  522. RCNodeSSAO* ssaoNode = static_cast<RCNodeSSAO*>(inputs.inputNodes[4]);
  523. ssao = ssaoNode->output->texture;
  524. }
  525. else
  526. ssao = Texture::WHITE;
  527. GpuResourcePool& resPool = GpuResourcePool::instance();
  528. const RendererViewProperties& viewProps = inputs.view.getProperties();
  529. const LightProbes& lightProbes = inputs.scene.lightProbes;
  530. LightProbesInfo lpInfo = lightProbes.getInfo();
  531. IrradianceEvaluateMat* evaluateMat;
  532. SPtr<PooledRenderTexture> volumeIndices;
  533. if(lightProbes.hasAnyProbes())
  534. {
  535. POOLED_RENDER_TEXTURE_DESC volumeIndicesDesc;
  536. POOLED_RENDER_TEXTURE_DESC depthDesc;
  537. TetrahedraRenderMat::getOutputDesc(inputs.view, volumeIndicesDesc, depthDesc);
  538. volumeIndices = resPool.get(volumeIndicesDesc);
  539. SPtr<PooledRenderTexture> depthTex = resPool.get(depthDesc);
  540. RENDER_TEXTURE_DESC rtDesc;
  541. rtDesc.colorSurfaces[0].texture = volumeIndices->texture;
  542. rtDesc.depthStencilSurface.texture = depthTex->texture;
  543. SPtr<RenderTexture> rt = RenderTexture::create(rtDesc);
  544. RenderAPI& rapi = RenderAPI::instance();
  545. rapi.setRenderTarget(rt);
  546. rapi.clearRenderTarget(FBT_DEPTH);
  547. gRendererUtility().clear(-1);
  548. TetrahedraRenderMat* renderTetrahedra = TetrahedraRenderMat::getVariation(viewProps.numSamples > 1);
  549. renderTetrahedra->execute(inputs.view, sceneDepthNode->depthTex->texture, lpInfo.tetrahedraVolume, rt);
  550. rt = nullptr;
  551. resPool.release(depthTex);
  552. evaluateMat = IrradianceEvaluateMat::getVariation(viewProps.numSamples, false);
  553. }
  554. else // Sky only
  555. {
  556. evaluateMat = IrradianceEvaluateMat::getVariation(viewProps.numSamples, true);
  557. }
  558. GBufferTextures gbuffer;
  559. gbuffer.albedo = gbufferNode->albedoTex->texture;
  560. gbuffer.normals = gbufferNode->normalTex->texture;
  561. gbuffer.roughMetal = gbufferNode->roughMetalTex->texture;
  562. gbuffer.depth = sceneDepthNode->depthTex->texture;
  563. SPtr<Texture> volumeIndicesTex;
  564. if (volumeIndices)
  565. volumeIndicesTex = volumeIndices->texture;
  566. evaluateMat->execute(inputs.view, gbuffer, volumeIndicesTex, lpInfo, inputs.scene.skybox, ssao,
  567. lightAccumNode->renderTarget);
  568. if(volumeIndices)
  569. resPool.release(volumeIndices);
  570. }
  571. void RCNodeIndirectLighting::clear()
  572. {
  573. // Do nothing
  574. }
  575. SmallVector<StringID, 4> RCNodeIndirectLighting::getDependencies(const RendererView& view)
  576. {
  577. SmallVector<StringID, 4> deps;
  578. deps.push_back(RCNodeGBuffer::getNodeId());
  579. deps.push_back(RCNodeSceneDepth::getNodeId());
  580. deps.push_back(RCNodeLightAccumulation::getNodeId());
  581. deps.push_back(RCNodeStandardDeferredLighting::getNodeId());
  582. if(view.getRenderSettings().ambientOcclusion.enabled)
  583. deps.push_back(RCNodeSSAO::getNodeId());
  584. if (view.getProperties().numSamples > 1)
  585. deps.push_back(RCNodeUnflattenLightAccum::getNodeId());
  586. return deps;
  587. }
  588. void RCNodeTiledDeferredIBL::render(const RenderCompositorNodeInputs& inputs)
  589. {
  590. const RenderSettings& rs = inputs.view.getRenderSettings();
  591. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[0]);
  592. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[1]);
  593. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[2]);
  594. RCNodeLightAccumulation* lightAccumNode = static_cast <RCNodeLightAccumulation*>(inputs.inputNodes[3]);
  595. SPtr<Texture> ssr;
  596. if (rs.screenSpaceReflections.enabled)
  597. {
  598. RCNodeSSR* ssrNode = static_cast<RCNodeSSR*>(inputs.inputNodes[5]);
  599. ssr = ssrNode->output->texture;
  600. }
  601. else
  602. ssr = Texture::BLACK;
  603. SPtr<Texture> ssao;
  604. if (rs.ambientOcclusion.enabled)
  605. {
  606. RCNodeSSAO* ssaoNode = static_cast<RCNodeSSAO*>(inputs.inputNodes[6]);
  607. ssao = ssaoNode->output->texture;
  608. }
  609. else
  610. ssao = Texture::WHITE;
  611. const RendererViewProperties& viewProps = inputs.view.getProperties();
  612. TiledDeferredImageBasedLightingMat* material = TiledDeferredImageBasedLightingMat::getVariation(viewProps.numSamples);
  613. TiledDeferredImageBasedLightingMat::Inputs iblInputs;
  614. iblInputs.gbuffer.albedo = gbufferNode->albedoTex->texture;
  615. iblInputs.gbuffer.normals = gbufferNode->normalTex->texture;
  616. iblInputs.gbuffer.roughMetal = gbufferNode->roughMetalTex->texture;
  617. iblInputs.gbuffer.depth = sceneDepthNode->depthTex->texture;
  618. iblInputs.sceneColorTex = sceneColorNode->sceneColorTex->texture;
  619. iblInputs.lightAccumulation = lightAccumNode->lightAccumulationTex->texture;
  620. iblInputs.preIntegratedGF = RendererTextures::preintegratedEnvGF;
  621. iblInputs.ambientOcclusion = ssao;
  622. iblInputs.ssr = ssr;
  623. if(sceneColorNode->flattenedSceneColorBuffer)
  624. iblInputs.sceneColorBuffer = sceneColorNode->flattenedSceneColorBuffer->buffer;
  625. material->execute(inputs.view, inputs.scene, inputs.viewGroup.getVisibleReflProbeData(), iblInputs);
  626. }
  627. void RCNodeTiledDeferredIBL::clear()
  628. {
  629. output = nullptr;
  630. }
  631. SmallVector<StringID, 4> RCNodeTiledDeferredIBL::getDependencies(const RendererView& view)
  632. {
  633. SmallVector<StringID, 4> deps;
  634. deps.push_back(RCNodeSceneColor::getNodeId());
  635. deps.push_back(RCNodeGBuffer::getNodeId());
  636. deps.push_back(RCNodeSceneDepth::getNodeId());
  637. deps.push_back(RCNodeLightAccumulation::getNodeId());
  638. deps.push_back(RCNodeIndirectLighting::getNodeId());
  639. deps.push_back(RCNodeSSR::getNodeId());
  640. if(view.getRenderSettings().ambientOcclusion.enabled)
  641. deps.push_back(RCNodeSSAO::getNodeId());
  642. return deps;
  643. }
  644. void RCNodeUnflattenSceneColor::render(const RenderCompositorNodeInputs& inputs)
  645. {
  646. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[0]);
  647. FlatFramebufferToTextureMat* material = FlatFramebufferToTextureMat::get();
  648. int readOnlyFlags = FBT_DEPTH | FBT_STENCIL;
  649. RenderAPI& rapi = RenderAPI::instance();
  650. rapi.setRenderTarget(sceneColorNode->renderTarget, readOnlyFlags, RT_COLOR0 | RT_DEPTH_STENCIL);
  651. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  652. rapi.setViewport(area);
  653. material->execute(sceneColorNode->flattenedSceneColorBuffer->buffer, sceneColorNode->sceneColorTex->texture);
  654. }
  655. void RCNodeUnflattenSceneColor::clear()
  656. {
  657. output = nullptr;
  658. }
  659. SmallVector<StringID, 4> RCNodeUnflattenSceneColor::getDependencies(const RendererView& view)
  660. {
  661. return { RCNodeSceneColor::getNodeId() };
  662. }
  663. void RCNodeClusteredForward::render(const RenderCompositorNodeInputs& inputs)
  664. {
  665. const SceneInfo& sceneInfo = inputs.scene;
  666. const RendererViewProperties& viewProps = inputs.view.getProperties();
  667. const VisibleLightData& visibleLightData = inputs.viewGroup.getVisibleLightData();
  668. const VisibleReflProbeData& visibleReflProbeData = inputs.viewGroup.getVisibleReflProbeData();
  669. const LightGrid& lightGrid = inputs.view.getLightGrid();
  670. SPtr<GpuParamBlockBuffer> gridParams;
  671. SPtr<GpuBuffer> gridLightOffsetsAndSize, gridLightIndices;
  672. SPtr<GpuBuffer> gridProbeOffsetsAndSize, gridProbeIndices;
  673. lightGrid.getOutputs(gridLightOffsetsAndSize, gridLightIndices, gridProbeOffsetsAndSize, gridProbeIndices,
  674. gridParams);
  675. // Prepare refl. probe param buffer
  676. ReflProbeParamBuffer reflProbeParamBuffer;
  677. reflProbeParamBuffer.populate(sceneInfo.skybox, visibleReflProbeData, sceneInfo.reflProbeCubemapsTex,
  678. viewProps.renderingReflections);
  679. SPtr<Texture> skyFilteredRadiance;
  680. if(sceneInfo.skybox)
  681. skyFilteredRadiance = sceneInfo.skybox->getFilteredRadiance();
  682. // Prepare objects for rendering
  683. const VisibilityInfo& visibility = inputs.view.getVisibilityMasks();
  684. UINT32 numRenderables = (UINT32)sceneInfo.renderables.size();
  685. for (UINT32 i = 0; i < numRenderables; i++)
  686. {
  687. if (!visibility.renderables[i])
  688. continue;
  689. for (auto& element : sceneInfo.renderables[i]->elements)
  690. {
  691. bool isTransparent = (element.material->getShader()->getFlags() & (UINT32)ShaderFlags::Transparent) != 0;
  692. if (!isTransparent)
  693. continue;
  694. // Note: It would be nice to be able to set this once and keep it, only updating if the buffers actually
  695. // change (e.g. when growing). Although technically the internal systems should be smart enough to
  696. // avoid updates unless objects actually changed.
  697. if (element.gridParamsBindingIdx != -1)
  698. element.params->setParamBlockBuffer(element.gridParamsBindingIdx, gridParams, true);
  699. element.gridLightOffsetsAndSizeParam.set(gridLightOffsetsAndSize);
  700. element.gridLightIndicesParam.set(gridLightIndices);
  701. element.lightsBufferParam.set(visibleLightData.getLightBuffer());
  702. // Image based lighting params
  703. ImageBasedLightingParams& iblParams = element.imageBasedParams;
  704. if (iblParams.reflProbeParamsBindingIdx != -1)
  705. element.params->setParamBlockBuffer(iblParams.reflProbeParamsBindingIdx, reflProbeParamBuffer.buffer);
  706. element.gridProbeOffsetsAndSizeParam.set(gridProbeOffsetsAndSize);
  707. iblParams.reflectionProbeIndicesParam.set(gridProbeIndices);
  708. iblParams.reflectionProbesParam.set(visibleReflProbeData.getProbeBuffer());
  709. iblParams.skyReflectionsTexParam.set(skyFilteredRadiance);
  710. iblParams.ambientOcclusionTexParam.set(Texture::WHITE); // Note: Add SSAO here?
  711. iblParams.ssrTexParam.set(Texture::BLACK); // Note: Add SSR here?
  712. iblParams.reflectionProbeCubemapsTexParam.set(sceneInfo.reflProbeCubemapsTex);
  713. iblParams.preintegratedEnvBRDFParam.set(RendererTextures::preintegratedEnvGF);
  714. }
  715. }
  716. // TODO: Transparent objects cannot receive shadows. In order to support this I'd have to render the light occlusion
  717. // for all lights affecting this object into a single (or a few) textures. I can likely use texture arrays for this,
  718. // or to avoid sampling many textures, perhaps just jam it all in one or few texture channels.
  719. const Vector<RenderQueueElement>& transparentElements = inputs.view.getTransparentQueue()->getSortedElements();
  720. for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
  721. {
  722. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  723. SPtr<Material> material = renderElem->material;
  724. if (iter->applyPass)
  725. gRendererUtility().setPass(material, iter->passIdx, renderElem->techniqueIdx);
  726. gRendererUtility().setPassParams(renderElem->params, iter->passIdx);
  727. if(renderElem->morphVertexDeclaration == nullptr)
  728. gRendererUtility().draw(renderElem->mesh, renderElem->subMesh);
  729. else
  730. gRendererUtility().drawMorph(renderElem->mesh, renderElem->subMesh, renderElem->morphShapeBuffer,
  731. renderElem->morphVertexDeclaration);
  732. }
  733. // Trigger post-lighting callbacks
  734. Camera* sceneCamera = inputs.view.getSceneCamera();
  735. if (sceneCamera != nullptr)
  736. {
  737. for(auto& extension : inputs.extPostLighting)
  738. {
  739. if (extension->check(*sceneCamera))
  740. extension->render(*sceneCamera);
  741. }
  742. }
  743. }
  744. void RCNodeClusteredForward::clear()
  745. {
  746. // Do nothing
  747. }
  748. SmallVector<StringID, 4> RCNodeClusteredForward::getDependencies(const RendererView& view)
  749. {
  750. return { RCNodeSceneColor::getNodeId(), RCNodeSkybox::getNodeId() };
  751. }
  752. void RCNodeSkybox::render(const RenderCompositorNodeInputs& inputs)
  753. {
  754. Skybox* skybox = inputs.scene.skybox;
  755. SPtr<Texture> radiance = skybox ? skybox->getTexture() : nullptr;
  756. if (radiance != nullptr)
  757. {
  758. SkyboxMat* material = SkyboxMat::getVariation(false);
  759. material->bind(inputs.view.getPerViewBuffer());
  760. material->setParams(radiance, Color::White);
  761. }
  762. else
  763. {
  764. Color clearColor = inputs.view.getProperties().clearColor;
  765. SkyboxMat* material = SkyboxMat::getVariation(true);
  766. material->bind(inputs.view.getPerViewBuffer());
  767. material->setParams(nullptr, clearColor);
  768. }
  769. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[1]);
  770. int readOnlyFlags = FBT_DEPTH | FBT_STENCIL;
  771. RenderAPI& rapi = RenderAPI::instance();
  772. rapi.setRenderTarget(sceneColorNode->renderTarget, readOnlyFlags, RT_COLOR0 | RT_DEPTH_STENCIL);
  773. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  774. rapi.setViewport(area);
  775. SPtr<Mesh> mesh = gRendererUtility().getSkyBoxMesh();
  776. gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
  777. }
  778. void RCNodeSkybox::clear()
  779. { }
  780. SmallVector<StringID, 4> RCNodeSkybox::getDependencies(const RendererView& view)
  781. {
  782. SmallVector<StringID, 4> deps;
  783. deps.push_back(RCNodeTiledDeferredIBL::getNodeId());
  784. deps.push_back(RCNodeSceneColor::getNodeId());
  785. if (view.getProperties().numSamples > 1)
  786. deps.push_back(RCNodeUnflattenSceneColor::getNodeId());
  787. return deps;
  788. }
  789. void RCNodeFinalResolve::render(const RenderCompositorNodeInputs& inputs)
  790. {
  791. const RendererViewProperties& viewProps = inputs.view.getProperties();
  792. SPtr<Texture> input;
  793. if(viewProps.runPostProcessing)
  794. {
  795. RCNodePostProcess* postProcessNode = static_cast<RCNodePostProcess*>(inputs.inputNodes[0]);
  796. // Note: Ideally the last PP effect could write directly to the final target and we could avoid this copy
  797. input = postProcessNode->getLastOutput();
  798. }
  799. else
  800. {
  801. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[0]);
  802. input = sceneColorNode->sceneColorTex->texture;
  803. }
  804. SPtr<RenderTarget> target = viewProps.target;
  805. RenderAPI& rapi = RenderAPI::instance();
  806. rapi.setRenderTarget(target);
  807. rapi.setViewport(viewProps.nrmViewRect);
  808. gRendererUtility().blit(input, Rect2I::EMPTY, viewProps.flipView);
  809. if(viewProps.encodeDepth)
  810. {
  811. RCNodeResolvedSceneDepth* resolvedSceneDepthNode = static_cast<RCNodeResolvedSceneDepth*>(inputs.inputNodes[0]);
  812. EncodeDepthMat* encodeDepthMat = EncodeDepthMat::get();
  813. encodeDepthMat->execute(resolvedSceneDepthNode->output->texture, viewProps.depthEncodeNear,
  814. viewProps.depthEncodeFar, target);
  815. }
  816. // Trigger overlay callbacks
  817. Camera* sceneCamera = inputs.view.getSceneCamera();
  818. if (sceneCamera != nullptr)
  819. {
  820. for(auto& extension : inputs.extOverlay)
  821. {
  822. if (extension->check(*sceneCamera))
  823. extension->render(*sceneCamera);
  824. }
  825. }
  826. }
  827. void RCNodeFinalResolve::clear()
  828. { }
  829. SmallVector<StringID, 4> RCNodeFinalResolve::getDependencies(const RendererView& view)
  830. {
  831. const RendererViewProperties& viewProps = view.getProperties();
  832. SmallVector<StringID, 4> deps;
  833. if(viewProps.runPostProcessing)
  834. {
  835. deps.push_back(RCNodePostProcess::getNodeId());
  836. deps.push_back(RCNodeFXAA::getNodeId());
  837. }
  838. else
  839. {
  840. deps.push_back(RCNodeSceneColor::getNodeId());
  841. deps.push_back(RCNodeClusteredForward::getNodeId());
  842. }
  843. if(viewProps.encodeDepth)
  844. deps.push_back(RCNodeResolvedSceneDepth::getNodeId());
  845. return deps;
  846. }
  847. RCNodePostProcess::RCNodePostProcess()
  848. :mOutput(), mAllocated()
  849. { }
  850. void RCNodePostProcess::getAndSwitch(const RendererView& view, SPtr<RenderTexture>& output, SPtr<Texture>& lastFrame) const
  851. {
  852. GpuResourcePool& resPool = GpuResourcePool::instance();
  853. const RendererViewProperties& viewProps = view.getProperties();
  854. UINT32 width = viewProps.viewRect.width;
  855. UINT32 height = viewProps.viewRect.height;
  856. if(!mAllocated[mCurrentIdx])
  857. {
  858. mOutput[mCurrentIdx] = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA8, width, height,
  859. TU_RENDERTARGET, 1, false));
  860. mAllocated[mCurrentIdx] = true;
  861. }
  862. output = mOutput[mCurrentIdx]->renderTexture;
  863. UINT32 otherIdx = (mCurrentIdx + 1) % 2;
  864. if (mAllocated[otherIdx])
  865. lastFrame = mOutput[otherIdx]->texture;
  866. mCurrentIdx = otherIdx;
  867. }
  868. SPtr<Texture> RCNodePostProcess::getLastOutput() const
  869. {
  870. UINT32 otherIdx = (mCurrentIdx + 1) % 2;
  871. if (mAllocated[otherIdx])
  872. return mOutput[otherIdx]->texture;
  873. return nullptr;
  874. }
  875. void RCNodePostProcess::render(const RenderCompositorNodeInputs& inputs)
  876. {
  877. // Do nothing, this is just a helper node
  878. }
  879. void RCNodePostProcess::clear()
  880. {
  881. GpuResourcePool& resPool = GpuResourcePool::instance();
  882. if (mAllocated[0])
  883. resPool.release(mOutput[0]);
  884. if (mAllocated[1])
  885. resPool.release(mOutput[1]);
  886. mAllocated[0] = false;
  887. mAllocated[1] = false;
  888. mCurrentIdx = 0;
  889. }
  890. SmallVector<StringID, 4> RCNodePostProcess::getDependencies(const RendererView& view)
  891. {
  892. return {};
  893. }
  894. RCNodeTonemapping::~RCNodeTonemapping()
  895. {
  896. GpuResourcePool& resPool = GpuResourcePool::instance();
  897. if (mTonemapLUT)
  898. resPool.release(mTonemapLUT);
  899. if (prevEyeAdaptation)
  900. resPool.release(prevEyeAdaptation);
  901. }
  902. void RCNodeTonemapping::render(const RenderCompositorNodeInputs& inputs)
  903. {
  904. GpuResourcePool& resPool = GpuResourcePool::instance();
  905. const RendererViewProperties& viewProps = inputs.view.getProperties();
  906. const RenderSettings& settings = inputs.view.getRenderSettings();
  907. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[0]);
  908. RCNodePostProcess* postProcessNode = static_cast<RCNodePostProcess*>(inputs.inputNodes[2]);
  909. SPtr<Texture> sceneColor = sceneColorNode->sceneColorTex->texture;
  910. bool hdr = settings.enableHDR;
  911. bool msaa = viewProps.numSamples > 1;
  912. if(hdr && settings.enableAutoExposure)
  913. {
  914. // Downsample scene
  915. DownsampleMat* downsampleMat = DownsampleMat::getVariation(1, msaa);
  916. SPtr<PooledRenderTexture> downsampledScene = resPool.get(DownsampleMat::getOutputDesc(sceneColor));
  917. downsampleMat->execute(sceneColor, downsampledScene->renderTexture);
  918. // Generate histogram
  919. SPtr<PooledRenderTexture> eyeAdaptHistogram = resPool.get(
  920. EyeAdaptHistogramMat::getOutputDesc(downsampledScene->texture));
  921. EyeAdaptHistogramMat* eyeAdaptHistogramMat = EyeAdaptHistogramMat::get();
  922. eyeAdaptHistogramMat->execute(downsampledScene->texture, eyeAdaptHistogram->texture, settings.autoExposure);
  923. // Reduce histogram
  924. SPtr<PooledRenderTexture> reducedHistogram = resPool.get(EyeAdaptHistogramReduceMat::getOutputDesc());
  925. SPtr<Texture> prevFrameEyeAdaptation;
  926. if (prevEyeAdaptation != nullptr)
  927. prevFrameEyeAdaptation = prevEyeAdaptation->texture;
  928. EyeAdaptHistogramReduceMat* eyeAdaptHistogramReduce = EyeAdaptHistogramReduceMat::get();
  929. eyeAdaptHistogramReduce->execute(downsampledScene->texture, eyeAdaptHistogram->texture,
  930. prevFrameEyeAdaptation, reducedHistogram->renderTexture);
  931. resPool.release(downsampledScene);
  932. downsampledScene = nullptr;
  933. resPool.release(eyeAdaptHistogram);
  934. eyeAdaptHistogram = nullptr;
  935. // Generate eye adaptation value
  936. eyeAdaptation = resPool.get(EyeAdaptationMat::getOutputDesc());
  937. EyeAdaptationMat* eyeAdaptationMat = EyeAdaptationMat::get();
  938. eyeAdaptationMat->execute(reducedHistogram->texture, eyeAdaptation->renderTexture, inputs.frameInfo.timeDelta,
  939. settings.autoExposure, settings.exposureScale);
  940. resPool.release(reducedHistogram);
  941. reducedHistogram = nullptr;
  942. }
  943. else
  944. {
  945. if(prevEyeAdaptation)
  946. resPool.release(prevEyeAdaptation);
  947. prevEyeAdaptation = nullptr;
  948. eyeAdaptation = nullptr;
  949. }
  950. bool gammaOnly;
  951. bool autoExposure;
  952. if (hdr)
  953. {
  954. if (settings.enableTonemapping)
  955. {
  956. UINT64 latestHash = inputs.view.getRenderSettingsHash();
  957. bool tonemapLUTDirty = mTonemapLastUpdateHash != latestHash;
  958. if (tonemapLUTDirty) // Rebuild LUT if PP settings changed
  959. {
  960. if(mTonemapLUT == nullptr)
  961. mTonemapLUT = resPool.get(CreateTonemapLUTMat::getOutputDesc());
  962. CreateTonemapLUTMat* createLUT = CreateTonemapLUTMat::get();
  963. createLUT->execute(mTonemapLUT->texture, settings);
  964. mTonemapLastUpdateHash = latestHash;
  965. }
  966. gammaOnly = false;
  967. }
  968. else
  969. gammaOnly = true;
  970. autoExposure = settings.enableAutoExposure;
  971. }
  972. else
  973. {
  974. gammaOnly = true;
  975. autoExposure = false;
  976. }
  977. if(gammaOnly)
  978. {
  979. if(mTonemapLUT)
  980. {
  981. resPool.release(mTonemapLUT);
  982. mTonemapLUT = nullptr;
  983. }
  984. }
  985. TonemappingMat* tonemapping = TonemappingMat::getVariation(gammaOnly, autoExposure, msaa);
  986. SPtr<RenderTexture> ppOutput;
  987. SPtr<Texture> ppLastFrame;
  988. postProcessNode->getAndSwitch(inputs.view, ppOutput, ppLastFrame);
  989. SPtr<Texture> eyeAdaptationTex;
  990. if (eyeAdaptation)
  991. eyeAdaptationTex = eyeAdaptation->texture;
  992. SPtr<Texture> tonemapLUTTex;
  993. if (mTonemapLUT)
  994. tonemapLUTTex = mTonemapLUT->texture;
  995. tonemapping->execute(sceneColor, eyeAdaptationTex, tonemapLUTTex, ppOutput, settings);
  996. }
  997. void RCNodeTonemapping::clear()
  998. {
  999. GpuResourcePool& resPool = GpuResourcePool::instance();
  1000. // Save eye adaptation for next frame
  1001. if(prevEyeAdaptation)
  1002. resPool.release(prevEyeAdaptation);
  1003. std::swap(eyeAdaptation, prevEyeAdaptation);
  1004. }
  1005. SmallVector<StringID, 4> RCNodeTonemapping::getDependencies(const RendererView& view)
  1006. {
  1007. return{ RCNodeSceneColor::getNodeId(), RCNodeClusteredForward::getNodeId(), RCNodePostProcess::getNodeId() };
  1008. }
  1009. void RCNodeGaussianDOF::render(const RenderCompositorNodeInputs& inputs)
  1010. {
  1011. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[1]);
  1012. RCNodePostProcess* postProcessNode = static_cast<RCNodePostProcess*>(inputs.inputNodes[2]);
  1013. const DepthOfFieldSettings& settings = inputs.view.getRenderSettings().depthOfField;
  1014. bool near = settings.nearBlurAmount > 0.0f;
  1015. bool far = settings.farBlurAmount > 0.0f;
  1016. bool enabled = settings.enabled && (near || far);
  1017. if(!enabled)
  1018. return;
  1019. GaussianDOFSeparateMat* separateMat = GaussianDOFSeparateMat::getVariation(near, far);
  1020. GaussianDOFCombineMat* combineMat = GaussianDOFCombineMat::getVariation(near, far);
  1021. GaussianBlurMat* blurMat = GaussianBlurMat::get();
  1022. SPtr<RenderTexture> ppOutput;
  1023. SPtr<Texture> ppLastFrame;
  1024. postProcessNode->getAndSwitch(inputs.view, ppOutput, ppLastFrame);
  1025. separateMat->execute(ppLastFrame, sceneDepthNode->depthTex->texture, inputs.view, settings);
  1026. SPtr<PooledRenderTexture> nearTex, farTex;
  1027. if(near && far)
  1028. {
  1029. nearTex = separateMat->getOutput(0);
  1030. farTex = separateMat->getOutput(1);
  1031. }
  1032. else
  1033. {
  1034. if (near)
  1035. nearTex = separateMat->getOutput(0);
  1036. else
  1037. farTex = separateMat->getOutput(0);
  1038. }
  1039. // Blur the out of focus pixels
  1040. // Note: Perhaps set up stencil so I can avoid performing blur on unused parts of the textures?
  1041. const TextureProperties& texProps = nearTex ? nearTex->texture->getProperties() : farTex->texture->getProperties();
  1042. POOLED_RENDER_TEXTURE_DESC tempTexDesc = POOLED_RENDER_TEXTURE_DESC::create2D(texProps.getFormat(),
  1043. texProps.getWidth(), texProps.getHeight(), TU_RENDERTARGET);
  1044. SPtr<PooledRenderTexture> tempTexture = GpuResourcePool::instance().get(tempTexDesc);
  1045. SPtr<Texture> blurredNearTex;
  1046. if(nearTex)
  1047. {
  1048. blurMat->execute(nearTex->texture, settings.nearBlurAmount, tempTexture->renderTexture);
  1049. blurredNearTex = tempTexture->texture;
  1050. }
  1051. SPtr<Texture> blurredFarTex;
  1052. if(farTex)
  1053. {
  1054. // If temporary texture is used up, re-use the original near texture for the blurred result
  1055. if(blurredNearTex)
  1056. {
  1057. blurMat->execute(farTex->texture, settings.farBlurAmount, nearTex->renderTexture);
  1058. blurredFarTex = nearTex->texture;
  1059. }
  1060. else // Otherwise just use the temporary
  1061. {
  1062. blurMat->execute(farTex->texture, settings.farBlurAmount, tempTexture->renderTexture);
  1063. blurredFarTex = tempTexture->texture;
  1064. }
  1065. }
  1066. combineMat->execute(ppLastFrame, blurredNearTex, blurredFarTex,
  1067. sceneDepthNode->depthTex->texture, ppOutput, inputs.view, settings);
  1068. separateMat->release();
  1069. GpuResourcePool::instance().release(tempTexture);
  1070. }
  1071. void RCNodeGaussianDOF::clear()
  1072. {
  1073. // Do nothing
  1074. }
  1075. SmallVector<StringID, 4> RCNodeGaussianDOF::getDependencies(const RendererView& view)
  1076. {
  1077. return { RCNodeTonemapping::getNodeId(), RCNodeSceneDepth::getNodeId(), RCNodePostProcess::getNodeId() };
  1078. }
  1079. void RCNodeFXAA::render(const RenderCompositorNodeInputs& inputs)
  1080. {
  1081. const RenderSettings& settings = inputs.view.getRenderSettings();
  1082. if (!settings.enableFXAA)
  1083. return;
  1084. RCNodePostProcess* postProcessNode = static_cast<RCNodePostProcess*>(inputs.inputNodes[1]);
  1085. SPtr<RenderTexture> ppOutput;
  1086. SPtr<Texture> ppLastFrame;
  1087. postProcessNode->getAndSwitch(inputs.view, ppOutput, ppLastFrame);
  1088. // Note: I could skip executing FXAA over DOF and motion blurred pixels
  1089. FXAAMat* fxaa = FXAAMat::get();
  1090. fxaa->execute(ppLastFrame, ppOutput);
  1091. }
  1092. void RCNodeFXAA::clear()
  1093. {
  1094. // Do nothing
  1095. }
  1096. SmallVector<StringID, 4> RCNodeFXAA::getDependencies(const RendererView& view)
  1097. {
  1098. return { RCNodeGaussianDOF::getNodeId(), RCNodePostProcess::getNodeId() };
  1099. }
  1100. void RCNodeResolvedSceneDepth::render(const RenderCompositorNodeInputs& inputs)
  1101. {
  1102. GpuResourcePool& resPool = GpuResourcePool::instance();
  1103. const RendererViewProperties& viewProps = inputs.view.getProperties();
  1104. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[0]);
  1105. if (viewProps.numSamples > 1)
  1106. {
  1107. UINT32 width = viewProps.viewRect.width;
  1108. UINT32 height = viewProps.viewRect.height;
  1109. output = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_D32_S8X24, width, height, TU_RENDERTARGET, 1, false));
  1110. RenderAPI& rapi = RenderAPI::instance();
  1111. rapi.setRenderTarget(output->renderTexture);
  1112. rapi.clearRenderTarget(FBT_STENCIL);
  1113. gRendererUtility().blit(sceneDepthNode->depthTex->texture, Rect2I::EMPTY, false, true);
  1114. mPassThrough = false;
  1115. }
  1116. else
  1117. {
  1118. output = sceneDepthNode->depthTex;
  1119. mPassThrough = true;
  1120. }
  1121. }
  1122. void RCNodeResolvedSceneDepth::clear()
  1123. {
  1124. GpuResourcePool& resPool = GpuResourcePool::instance();
  1125. if (!mPassThrough)
  1126. resPool.release(output);
  1127. else
  1128. output = nullptr;
  1129. mPassThrough = false;
  1130. }
  1131. SmallVector<StringID, 4> RCNodeResolvedSceneDepth::getDependencies(const RendererView& view)
  1132. {
  1133. // GBuffer require because it renders the base pass (populates the depth buffer)
  1134. return { RCNodeSceneDepth::getNodeId(), RCNodeGBuffer::getNodeId() };
  1135. }
  1136. void RCNodeHiZ::render(const RenderCompositorNodeInputs& inputs)
  1137. {
  1138. GpuResourcePool& resPool = GpuResourcePool::instance();
  1139. const RendererViewProperties& viewProps = inputs.view.getProperties();
  1140. RCNodeResolvedSceneDepth* resolvedSceneDepth = static_cast<RCNodeResolvedSceneDepth*>(inputs.inputNodes[0]);
  1141. UINT32 width = viewProps.viewRect.width;
  1142. UINT32 height = viewProps.viewRect.height;
  1143. UINT32 size = Bitwise::nextPow2(std::max(width, height));
  1144. UINT32 numMips = PixelUtil::getMaxMipmaps(size, size, 1, PF_R32F);
  1145. size = 1 << numMips;
  1146. // Note: Use the 32-bit buffer here as 16-bit causes too much banding (most of the scene gets assigned 4-5 different
  1147. // depth values).
  1148. // - When I add UNORM 16-bit format I should be able to switch to that
  1149. output = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_R32F, size, size, TU_RENDERTARGET, 1, false, 1,
  1150. numMips));
  1151. Rect2 srcRect = viewProps.nrmViewRect;
  1152. // If viewport size is odd, adjust UV
  1153. srcRect.width += (viewProps.viewRect.width % 2) * (1.0f / viewProps.viewRect.width);
  1154. srcRect.height += (viewProps.viewRect.height % 2) * (1.0f / viewProps.viewRect.height);
  1155. // Generate first mip
  1156. RENDER_TEXTURE_DESC rtDesc;
  1157. rtDesc.colorSurfaces[0].texture = output->texture;
  1158. rtDesc.colorSurfaces[0].mipLevel = 0;
  1159. SPtr<RenderTexture> rt = RenderTexture::create(rtDesc);
  1160. Rect2 destRect;
  1161. bool downsampledFirstMip = false; // Not used currently
  1162. if (downsampledFirstMip)
  1163. {
  1164. // Make sure that 1 pixel in HiZ maps to a 2x2 block in source
  1165. destRect = Rect2(0, 0,
  1166. Math::ceilToInt(viewProps.viewRect.width / 2.0f) / (float)size,
  1167. Math::ceilToInt(viewProps.viewRect.height / 2.0f) / (float)size);
  1168. BuildHiZMat* material = BuildHiZMat::get();
  1169. material->execute(resolvedSceneDepth->output->texture, 0, srcRect, destRect, rt);
  1170. }
  1171. else // First level is just a copy of the depth buffer
  1172. {
  1173. destRect = Rect2(0, 0,
  1174. viewProps.viewRect.width / (float)size,
  1175. viewProps.viewRect.height / (float)size);
  1176. RenderAPI& rapi = RenderAPI::instance();
  1177. rapi.setRenderTarget(rt);
  1178. rapi.setViewport(destRect);
  1179. Rect2I srcAreaInt;
  1180. srcAreaInt.x = (INT32)(srcRect.x * viewProps.viewRect.width);
  1181. srcAreaInt.y = (INT32)(srcRect.y * viewProps.viewRect.height);
  1182. srcAreaInt.width = (UINT32)(srcRect.width * viewProps.viewRect.width);
  1183. srcAreaInt.height = (UINT32)(srcRect.height * viewProps.viewRect.height);
  1184. gRendererUtility().blit(resolvedSceneDepth->output->texture, srcAreaInt);
  1185. rapi.setViewport(Rect2(0, 0, 1, 1));
  1186. }
  1187. // Generate remaining mip levels
  1188. for(UINT32 i = 1; i <= numMips; i++)
  1189. {
  1190. rtDesc.colorSurfaces[0].mipLevel = i;
  1191. rt = RenderTexture::create(rtDesc);
  1192. BuildHiZMat* material = BuildHiZMat::get();
  1193. material->execute(output->texture, i - 1, destRect, destRect, rt);
  1194. }
  1195. }
  1196. void RCNodeHiZ::clear()
  1197. {
  1198. GpuResourcePool& resPool = GpuResourcePool::instance();
  1199. resPool.release(output);
  1200. }
  1201. SmallVector<StringID, 4> RCNodeHiZ::getDependencies(const RendererView& view)
  1202. {
  1203. // Note: This doesn't actually use any gbuffer textures, but node is a dependency because it renders to the depth
  1204. // buffer. In order to avoid keeping gbuffer textures alive I could separate out the base pass into its own node
  1205. // perhaps. But at the moment it doesn't matter, as anything using HiZ also needs gbuffer.
  1206. return { RCNodeResolvedSceneDepth::getNodeId(), RCNodeGBuffer::getNodeId() };
  1207. }
  1208. void RCNodeSSAO::render(const RenderCompositorNodeInputs& inputs)
  1209. {
  1210. /** Maximum valid depth range within samples in a sample set. In meters. */
  1211. static const float DEPTH_RANGE = 1.0f;
  1212. GpuResourcePool& resPool = GpuResourcePool::instance();
  1213. const RendererViewProperties& viewProps = inputs.view.getProperties();
  1214. const AmbientOcclusionSettings& settings = inputs.view.getRenderSettings().ambientOcclusion;
  1215. RCNodeResolvedSceneDepth* resolvedDepthNode = static_cast<RCNodeResolvedSceneDepth*>(inputs.inputNodes[0]);
  1216. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[1]);
  1217. SPtr<Texture> sceneDepth = resolvedDepthNode->output->texture;
  1218. SPtr<Texture> sceneNormals = gbufferNode->normalTex->texture;
  1219. const TextureProperties& normalsProps = sceneNormals->getProperties();
  1220. SPtr<PooledRenderTexture> resolvedNormals;
  1221. RenderAPI& rapi = RenderAPI::instance();
  1222. if(sceneNormals->getProperties().getNumSamples() > 1)
  1223. {
  1224. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(normalsProps.getFormat(),
  1225. normalsProps.getWidth(), normalsProps.getHeight(), TU_RENDERTARGET);
  1226. resolvedNormals = resPool.get(desc);
  1227. rapi.setRenderTarget(resolvedNormals->renderTexture);
  1228. gRendererUtility().blit(sceneNormals);
  1229. sceneNormals = resolvedNormals->texture;
  1230. }
  1231. // Multiple downsampled AO levels are used to minimize cache trashing. Downsampled AO targets use larger radius,
  1232. // whose contents are then blended with the higher level.
  1233. UINT32 quality = settings.quality;
  1234. UINT32 numDownsampleLevels = 0;
  1235. if (quality > 1)
  1236. numDownsampleLevels = 1;
  1237. else if (quality > 2)
  1238. numDownsampleLevels = 2;
  1239. SSAODownsampleMat* downsample = SSAODownsampleMat::get();
  1240. SPtr<PooledRenderTexture> setupTex0;
  1241. if(numDownsampleLevels > 0)
  1242. {
  1243. Vector2I downsampledSize(
  1244. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.width, 2)),
  1245. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.height, 2))
  1246. );
  1247. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, downsampledSize.x,
  1248. downsampledSize.y, TU_RENDERTARGET);
  1249. setupTex0 = GpuResourcePool::instance().get(desc);
  1250. downsample->execute(inputs.view, sceneDepth, sceneNormals, setupTex0->renderTexture, DEPTH_RANGE);
  1251. }
  1252. SPtr<PooledRenderTexture> setupTex1;
  1253. if(numDownsampleLevels > 1)
  1254. {
  1255. Vector2I downsampledSize(
  1256. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.width, 4)),
  1257. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.height, 4))
  1258. );
  1259. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, downsampledSize.x,
  1260. downsampledSize.y, TU_RENDERTARGET);
  1261. setupTex1 = GpuResourcePool::instance().get(desc);
  1262. downsample->execute(inputs.view, sceneDepth, sceneNormals, setupTex1->renderTexture, DEPTH_RANGE);
  1263. }
  1264. SSAOTextureInputs textures;
  1265. textures.sceneDepth = sceneDepth;
  1266. textures.sceneNormals = sceneNormals;
  1267. textures.randomRotations = RendererTextures::ssaoRandomization4x4;
  1268. SPtr<PooledRenderTexture> downAOTex1;
  1269. if(numDownsampleLevels > 1)
  1270. {
  1271. textures.aoSetup = setupTex1->texture;
  1272. Vector2I downsampledSize(
  1273. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.width, 4)),
  1274. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.height, 4))
  1275. );
  1276. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, downsampledSize.x,
  1277. downsampledSize.y, TU_RENDERTARGET);
  1278. downAOTex1 = GpuResourcePool::instance().get(desc);
  1279. SSAOMat* ssaoMat = SSAOMat::getVariation(false, false, quality);
  1280. ssaoMat->execute(inputs.view, textures, downAOTex1->renderTexture, settings);
  1281. GpuResourcePool::instance().release(setupTex1);
  1282. setupTex1 = nullptr;
  1283. }
  1284. SPtr<PooledRenderTexture> downAOTex0;
  1285. if(numDownsampleLevels > 0)
  1286. {
  1287. textures.aoSetup = setupTex0->texture;
  1288. if(downAOTex1)
  1289. textures.aoDownsampled = downAOTex1->texture;
  1290. Vector2I downsampledSize(
  1291. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.width, 2)),
  1292. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.height, 2))
  1293. );
  1294. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, downsampledSize.x,
  1295. downsampledSize.y, TU_RENDERTARGET);
  1296. downAOTex0 = GpuResourcePool::instance().get(desc);
  1297. bool upsample = numDownsampleLevels > 1;
  1298. SSAOMat* ssaoMat = SSAOMat::getVariation(upsample, false, quality);
  1299. ssaoMat->execute(inputs.view, textures, downAOTex0->renderTexture, settings);
  1300. if(upsample)
  1301. {
  1302. GpuResourcePool::instance().release(downAOTex1);
  1303. downAOTex1 = nullptr;
  1304. }
  1305. }
  1306. UINT32 width = viewProps.viewRect.width;
  1307. UINT32 height = viewProps.viewRect.height;
  1308. output = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, width, height, TU_RENDERTARGET));
  1309. {
  1310. if(setupTex0)
  1311. textures.aoSetup = setupTex0->texture;
  1312. if(downAOTex0)
  1313. textures.aoDownsampled = downAOTex0->texture;
  1314. bool upsample = numDownsampleLevels > 0;
  1315. SSAOMat* ssaoMat = SSAOMat::getVariation(upsample, true, quality);
  1316. ssaoMat->execute(inputs.view, textures, output->renderTexture, settings);
  1317. }
  1318. if(resolvedNormals)
  1319. {
  1320. GpuResourcePool::instance().release(resolvedNormals);
  1321. resolvedNormals = nullptr;
  1322. }
  1323. if(numDownsampleLevels > 0)
  1324. {
  1325. GpuResourcePool::instance().release(setupTex0);
  1326. GpuResourcePool::instance().release(downAOTex0);
  1327. }
  1328. // Blur the output
  1329. // Note: If I implement temporal AA then this can probably be avoided. I can instead jitter the sample offsets
  1330. // each frame, and averaging them out should yield blurred AO.
  1331. if(quality > 1) // On level 0 we don't blur at all, on level 1 we use the ad-hoc blur in shader
  1332. {
  1333. const RenderTargetProperties& rtProps = output->renderTexture->getProperties();
  1334. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, rtProps.getWidth(),
  1335. rtProps.getHeight(), TU_RENDERTARGET);
  1336. SPtr<PooledRenderTexture> blurIntermediateTex = GpuResourcePool::instance().get(desc);
  1337. SSAOBlurMat* blurHorz = SSAOBlurMat::getVariation(true);
  1338. SSAOBlurMat* blurVert = SSAOBlurMat::getVariation(false);
  1339. blurHorz->execute(inputs.view, output->texture, sceneDepth, blurIntermediateTex->renderTexture, DEPTH_RANGE);
  1340. blurVert->execute(inputs.view, blurIntermediateTex->texture, sceneDepth, output->renderTexture, DEPTH_RANGE);
  1341. GpuResourcePool::instance().release(blurIntermediateTex);
  1342. }
  1343. }
  1344. void RCNodeSSAO::clear()
  1345. {
  1346. GpuResourcePool& resPool = GpuResourcePool::instance();
  1347. resPool.release(output);
  1348. }
  1349. SmallVector<StringID, 4> RCNodeSSAO::getDependencies(const RendererView& view)
  1350. {
  1351. return { RCNodeResolvedSceneDepth::getNodeId(), RCNodeGBuffer::getNodeId() };
  1352. }
  1353. RCNodeSSR::~RCNodeSSR()
  1354. {
  1355. deallocOutputs();
  1356. }
  1357. void RCNodeSSR::render(const RenderCompositorNodeInputs& inputs)
  1358. {
  1359. const ScreenSpaceReflectionsSettings& settings = inputs.view.getRenderSettings().screenSpaceReflections;
  1360. if (settings.enabled)
  1361. {
  1362. RenderAPI& rapi = RenderAPI::instance();
  1363. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[0]);
  1364. RCNodeLightAccumulation* lightAccumNode = static_cast<RCNodeLightAccumulation*>(inputs.inputNodes[1]);
  1365. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[2]);
  1366. RCNodeHiZ* hiZNode = static_cast<RCNodeHiZ*>(inputs.inputNodes[3]);
  1367. RCNodeResolvedSceneDepth* resolvedSceneDepthNode = static_cast<RCNodeResolvedSceneDepth*>(inputs.inputNodes[4]);
  1368. GpuResourcePool& resPool = GpuResourcePool::instance();
  1369. const RendererViewProperties& viewProps = inputs.view.getProperties();
  1370. UINT32 width = viewProps.viewRect.width;
  1371. UINT32 height = viewProps.viewRect.height;
  1372. SPtr<Texture> hiZ = hiZNode->output->texture;
  1373. // This will be executing before scene color is resolved, so get the light accum buffer instead
  1374. SPtr<Texture> sceneColor = lightAccumNode->lightAccumulationTex->texture;
  1375. // Resolve multiple samples if MSAA is used
  1376. SPtr<PooledRenderTexture> resolvedSceneColor;
  1377. if(viewProps.numSamples > 1)
  1378. {
  1379. resolvedSceneColor = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, width, height,
  1380. TU_RENDERTARGET));
  1381. rapi.setRenderTarget(resolvedSceneColor->renderTexture);
  1382. gRendererUtility().blit(sceneColor);
  1383. sceneColor = resolvedSceneColor->texture;
  1384. }
  1385. GBufferTextures gbuffer;
  1386. gbuffer.albedo = gbufferNode->albedoTex->texture;
  1387. gbuffer.normals = gbufferNode->normalTex->texture;
  1388. gbuffer.roughMetal = gbufferNode->roughMetalTex->texture;
  1389. gbuffer.depth = sceneDepthNode->depthTex->texture;
  1390. SSRStencilMat* stencilMat = SSRStencilMat::getVariation(viewProps.numSamples > 1);
  1391. // Note: Making the assumption that the stencil buffer is clear at this point
  1392. rapi.setRenderTarget(resolvedSceneDepthNode->output->renderTexture);
  1393. stencilMat->execute(inputs.view, gbuffer, settings);
  1394. SPtr<PooledRenderTexture> traceOutput = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, width,
  1395. height, TU_RENDERTARGET));
  1396. RENDER_TEXTURE_DESC traceRtDesc;
  1397. traceRtDesc.colorSurfaces[0].texture = traceOutput->texture;
  1398. traceRtDesc.depthStencilSurface.texture = resolvedSceneDepthNode->output->texture;
  1399. SPtr<RenderTexture> traceRt = RenderTexture::create(traceRtDesc);
  1400. rapi.setRenderTarget(traceRt);
  1401. rapi.clearRenderTarget(FBT_COLOR);
  1402. SSRTraceMat* traceMat = SSRTraceMat::getVariation(settings.quality, viewProps.numSamples > 1);
  1403. traceMat->execute(inputs.view, gbuffer, sceneColor, hiZ, settings, traceRt);
  1404. if (resolvedSceneColor)
  1405. {
  1406. resPool.release(resolvedSceneColor);
  1407. resolvedSceneColor = nullptr;
  1408. }
  1409. if (mPrevFrame)
  1410. {
  1411. output = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, width, height, TU_RENDERTARGET));
  1412. rapi.setRenderTarget(output->renderTexture);
  1413. rapi.clearRenderTarget(FBT_COLOR);
  1414. SSRResolveMat* resolveMat = SSRResolveMat::getVariation(viewProps.numSamples > 1);
  1415. resolveMat->execute(inputs.view, mPrevFrame->texture, traceOutput->texture, sceneDepthNode->depthTex->texture,
  1416. output->renderTexture);
  1417. resPool.release(traceOutput);
  1418. }
  1419. else
  1420. output = traceOutput;
  1421. RenderAPI::instance().setRenderTarget(nullptr);
  1422. }
  1423. else
  1424. deallocOutputs();
  1425. }
  1426. void RCNodeSSR::clear()
  1427. {
  1428. GpuResourcePool& resPool = GpuResourcePool::instance();
  1429. if(mPrevFrame)
  1430. resPool.release(mPrevFrame);
  1431. mPrevFrame = output;
  1432. output = nullptr;
  1433. }
  1434. void RCNodeSSR::deallocOutputs()
  1435. {
  1436. GpuResourcePool& resPool = GpuResourcePool::instance();
  1437. if(mPrevFrame)
  1438. {
  1439. resPool.release(mPrevFrame);
  1440. mPrevFrame = nullptr;
  1441. }
  1442. }
  1443. SmallVector<StringID, 4> RCNodeSSR::getDependencies(const RendererView& view)
  1444. {
  1445. SmallVector<StringID, 4> deps;
  1446. if (view.getRenderSettings().screenSpaceReflections.enabled)
  1447. {
  1448. deps.push_back(RCNodeSceneDepth::getNodeId());
  1449. deps.push_back(RCNodeLightAccumulation::getNodeId());
  1450. deps.push_back(RCNodeGBuffer::getNodeId());
  1451. deps.push_back(RCNodeHiZ::getNodeId());
  1452. deps.push_back(RCNodeResolvedSceneDepth::getNodeId());
  1453. if (view.getProperties().numSamples > 1)
  1454. deps.push_back(RCNodeUnflattenLightAccum::getNodeId());
  1455. }
  1456. return deps;
  1457. }
  1458. }}