Sky.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Renderer/Sky.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Util/Tracer.h>
  8. #include <AnKi/Scene/Components/SkyboxComponent.h>
  9. #include <AnKi/Scene/Components/LightComponent.h>
  10. namespace anki {
  11. Error GeneratedSky::init()
  12. {
  13. ANKI_CHECK(loadShaderProgram("ShaderBinaries/Sky.ankiprogbin", {}, m_prog, m_transmittanceLutGrProg, "SkyTransmittanceLut"));
  14. ANKI_CHECK(loadShaderProgram("ShaderBinaries/Sky.ankiprogbin", {}, m_prog, m_multipleScatteringLutGrProg, "SkyMultipleScatteringLut"));
  15. ANKI_CHECK(loadShaderProgram("ShaderBinaries/Sky.ankiprogbin", {}, m_prog, m_skyLutGrProg, "SkyLut"));
  16. ANKI_CHECK(loadShaderProgram("ShaderBinaries/Sky.ankiprogbin", {}, m_prog, m_computeSunColorGrProg, "ComputeSunColor"));
  17. ANKI_CHECK(loadShaderProgram("ShaderBinaries/Sky.ankiprogbin", {}, m_prog, m_computeEnvMapGrProg, "ComputeEnvMap"));
  18. const TextureUsageBit usage = TextureUsageBit::kAllCompute;
  19. const TextureUsageBit initialUsage = TextureUsageBit::kSrvCompute;
  20. const Format formatB = getRenderer().getHdrFormat();
  21. m_transmittanceLut = getRenderer().createAndClearRenderTarget(
  22. getRenderer().create2DRenderTargetInitInfo(kTransmittanceLutSize.x, kTransmittanceLutSize.y, formatB, usage, "SkyTransmittanceLut"),
  23. initialUsage);
  24. m_multipleScatteringLut = getRenderer().createAndClearRenderTarget(
  25. getRenderer().create2DRenderTargetInitInfo(kMultipleScatteringLutSize.x, kMultipleScatteringLutSize.y, formatB, usage,
  26. "SkyMultipleScatteringLut"),
  27. initialUsage);
  28. m_skyLut = getRenderer().createAndClearRenderTarget(
  29. getRenderer().create2DRenderTargetInitInfo(kSkyLutSize.x, kSkyLutSize.y, formatB, usage | TextureUsageBit::kSrvPixel, "SkyLut"),
  30. initialUsage);
  31. m_envMap = getRenderer().createAndClearRenderTarget(getRenderer().create2DRenderTargetInitInfo(kEnvMapSize.x, kEnvMapSize.y,
  32. getRenderer().getHdrFormat(),
  33. usage | TextureUsageBit::kAllSrv, "SkyEnvMap"),
  34. initialUsage);
  35. return Error::kNone;
  36. }
  37. void GeneratedSky::populateRenderGraph(RenderingContext& ctx)
  38. {
  39. ANKI_TRACE_SCOPED_EVENT(Sky);
  40. if(!isEnabled())
  41. {
  42. m_runCtx = {};
  43. return;
  44. }
  45. RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
  46. const LightComponent* dirLightc = SceneGraph::getSingleton().getDirectionalLight();
  47. ANKI_ASSERT(dirLightc);
  48. const F32 sunPower = dirLightc->getLightPower();
  49. const Bool renderSkyLut = dirLightc->getDirection() != m_sunDir || m_sunPower != sunPower;
  50. const Bool renderTransAndMultiScatLuts = !m_transmittanceAndMultiScatterLutsGenerated;
  51. m_sunDir = dirLightc->getDirection();
  52. m_sunPower = sunPower;
  53. // Create render targets
  54. RenderTargetHandle transmittanceLutRt;
  55. RenderTargetHandle multipleScatteringLutRt;
  56. if(renderTransAndMultiScatLuts)
  57. {
  58. transmittanceLutRt = rgraph.importRenderTarget(m_transmittanceLut.get(), TextureUsageBit::kSrvCompute);
  59. multipleScatteringLutRt = rgraph.importRenderTarget(m_multipleScatteringLut.get(), TextureUsageBit::kSrvCompute);
  60. m_transmittanceAndMultiScatterLutsGenerated = true;
  61. }
  62. else
  63. {
  64. transmittanceLutRt = rgraph.importRenderTarget(m_transmittanceLut.get(), TextureUsageBit::kSrvCompute);
  65. multipleScatteringLutRt = rgraph.importRenderTarget(m_multipleScatteringLut.get(), TextureUsageBit::kSrvCompute);
  66. }
  67. if(m_skyLutImportedOnce) [[likely]]
  68. {
  69. m_runCtx.m_skyLutRt = rgraph.importRenderTarget(m_skyLut.get());
  70. m_runCtx.m_envMapRt = rgraph.importRenderTarget(m_envMap.get());
  71. }
  72. else
  73. {
  74. m_runCtx.m_skyLutRt = rgraph.importRenderTarget(m_skyLut.get(), TextureUsageBit::kSrvCompute);
  75. m_runCtx.m_envMapRt = rgraph.importRenderTarget(m_envMap.get(), TextureUsageBit::kSrvCompute);
  76. m_skyLutImportedOnce = true;
  77. }
  78. // Transmittance LUT
  79. if(renderTransAndMultiScatLuts)
  80. {
  81. NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("SkyTransmittanceLut");
  82. rpass.newTextureDependency(transmittanceLutRt, TextureUsageBit::kUavCompute);
  83. rpass.setWork([this, transmittanceLutRt](RenderPassWorkContext& rgraphCtx) {
  84. ANKI_TRACE_SCOPED_EVENT(SkyTransmittanceLut);
  85. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  86. cmdb.bindShaderProgram(m_transmittanceLutGrProg.get());
  87. rgraphCtx.bindUav(0, 0, transmittanceLutRt);
  88. dispatchPPCompute(cmdb, 8, 8, kTransmittanceLutSize.x, kTransmittanceLutSize.y);
  89. });
  90. }
  91. // Multiple scattering LUT
  92. if(renderTransAndMultiScatLuts)
  93. {
  94. NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("SkyMultipleScatteringLut");
  95. rpass.newTextureDependency(transmittanceLutRt, TextureUsageBit::kSrvCompute);
  96. rpass.newTextureDependency(multipleScatteringLutRt, TextureUsageBit::kUavCompute);
  97. rpass.setWork([this, transmittanceLutRt, multipleScatteringLutRt](RenderPassWorkContext& rgraphCtx) {
  98. ANKI_TRACE_SCOPED_EVENT(SkyMultipleScatteringLut);
  99. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  100. cmdb.bindShaderProgram(m_multipleScatteringLutGrProg.get());
  101. rgraphCtx.bindSrv(0, 0, transmittanceLutRt);
  102. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
  103. rgraphCtx.bindUav(0, 0, multipleScatteringLutRt);
  104. dispatchPPCompute(cmdb, 8, 8, kMultipleScatteringLutSize.x, kMultipleScatteringLutSize.y);
  105. });
  106. }
  107. // Sky LUT
  108. if(renderSkyLut)
  109. {
  110. NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("SkyLut");
  111. rpass.newTextureDependency(transmittanceLutRt, TextureUsageBit::kSrvCompute);
  112. rpass.newTextureDependency(multipleScatteringLutRt, TextureUsageBit::kSrvCompute);
  113. rpass.newTextureDependency(m_runCtx.m_skyLutRt, TextureUsageBit::kUavCompute);
  114. rpass.setWork([this, transmittanceLutRt, multipleScatteringLutRt, &ctx](RenderPassWorkContext& rgraphCtx) {
  115. ANKI_TRACE_SCOPED_EVENT(SkyLut);
  116. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  117. cmdb.bindShaderProgram(m_skyLutGrProg.get());
  118. rgraphCtx.bindSrv(0, 0, transmittanceLutRt);
  119. rgraphCtx.bindSrv(1, 0, multipleScatteringLutRt);
  120. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
  121. rgraphCtx.bindUav(0, 0, m_runCtx.m_skyLutRt);
  122. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  123. dispatchPPCompute(cmdb, 8, 8, kSkyLutSize.x, kSkyLutSize.y);
  124. });
  125. }
  126. // Sky env map
  127. if(renderSkyLut)
  128. {
  129. NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("SkyLutEnvMap");
  130. rpass.newTextureDependency(m_runCtx.m_skyLutRt, TextureUsageBit::kSrvCompute);
  131. rpass.newTextureDependency(m_runCtx.m_envMapRt, TextureUsageBit::kUavCompute);
  132. rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
  133. ANKI_TRACE_SCOPED_EVENT(SkyLut);
  134. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  135. cmdb.bindShaderProgram(m_computeEnvMapGrProg.get());
  136. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
  137. rgraphCtx.bindSrv(0, 0, m_runCtx.m_skyLutRt);
  138. rgraphCtx.bindUav(0, 0, m_runCtx.m_envMapRt);
  139. cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
  140. dispatchPPCompute(cmdb, 8, 8, kEnvMapSize.x, kEnvMapSize.y);
  141. });
  142. }
  143. // Compute sun color always
  144. {
  145. NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("ComputeSunColor");
  146. rpass.newTextureDependency(transmittanceLutRt, TextureUsageBit::kSrvCompute);
  147. rpass.setWork([this, transmittanceLutRt, &ctx](RenderPassWorkContext& rgraphCtx) {
  148. ANKI_TRACE_SCOPED_EVENT(ComputeSunColor);
  149. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  150. cmdb.bindShaderProgram(m_computeSunColorGrProg.get());
  151. rgraphCtx.bindSrv(0, 0, transmittanceLutRt);
  152. cmdb.bindUav(0, 0, ctx.m_globalRenderingConstantsBuffer);
  153. const UVec4 consts(offsetof(GlobalRendererConstants, m_directionalLight));
  154. cmdb.setFastConstants(&consts, sizeof(consts));
  155. cmdb.dispatchCompute(1, 1, 1);
  156. });
  157. }
  158. }
  159. Bool GeneratedSky::isEnabled() const
  160. {
  161. const SkyboxComponent* skyc = SceneGraph::getSingleton().getSkybox();
  162. const LightComponent* dirLightc = SceneGraph::getSingleton().getDirectionalLight();
  163. return skyc && skyc->getSkyboxType() == SkyboxType::kGenerated && dirLightc;
  164. }
  165. } // end namespace anki