BsRenderCompositor.cpp 51 KB

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