LensFlare.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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/LensFlare.h>
  6. #include <AnKi/Renderer/DepthDownscale.h>
  7. #include <AnKi/Renderer/Renderer.h>
  8. #include <AnKi/Util/CVarSet.h>
  9. #include <AnKi/GpuMemory/GpuVisibleTransientMemoryPool.h>
  10. #include <AnKi/Util/Functions.h>
  11. #include <AnKi/Scene/Components/LensFlareComponent.h>
  12. #include <AnKi/Util/Tracer.h>
  13. namespace anki {
  14. Error LensFlare::init()
  15. {
  16. const Error err = initInternal();
  17. if(err)
  18. {
  19. ANKI_R_LOGE("Failed to initialize lens flare pass");
  20. }
  21. return err;
  22. }
  23. Error LensFlare::initInternal()
  24. {
  25. m_maxSpritesPerFlare = g_lensFlareMaxSpritesPerFlareCVar;
  26. ANKI_CHECK(loadShaderProgram("ShaderBinaries/LensFlareSprite.ankiprogbin", m_realProg, m_realGrProg));
  27. ANKI_CHECK(loadShaderProgram("ShaderBinaries/LensFlareUpdateIndirectInfo.ankiprogbin", m_updateIndirectBuffProg, m_updateIndirectBuffGrProg));
  28. return Error::kNone;
  29. }
  30. void LensFlare::populateRenderGraph(RenderingContext& ctx)
  31. {
  32. ANKI_TRACE_SCOPED_EVENT(LensFlare);
  33. const U32 flareCount = SceneGraph::getSingleton().getComponentArrays().getLensFlares().getSize();
  34. if(flareCount == 0)
  35. {
  36. m_runCtx = {};
  37. return;
  38. }
  39. RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
  40. // Create indirect buffer
  41. m_runCtx.m_indirectBuff = GpuVisibleTransientMemoryPool::getSingleton().allocateStructuredBuffer<DrawIndirectArgs>(flareCount);
  42. m_runCtx.m_indirectBuffHandle = rgraph.importBuffer(m_runCtx.m_indirectBuff, BufferUsageBit::kNone);
  43. // Create the pass
  44. NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("Lens flare indirect");
  45. rpass.newBufferDependency(m_runCtx.m_indirectBuffHandle, BufferUsageBit::kUavCompute);
  46. rpass.newTextureDependency(getRenderer().getDepthDownscale().getRt(), TextureUsageBit::kSrvCompute, DepthDownscale::kEighthInternalResolution);
  47. rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
  48. ANKI_TRACE_SCOPED_EVENT(LensFlare);
  49. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  50. const U32 flareCount = SceneGraph::getSingleton().getComponentArrays().getLensFlares().getSize();
  51. ANKI_ASSERT(flareCount > 0);
  52. cmdb.bindShaderProgram(m_updateIndirectBuffGrProg.get());
  53. cmdb.setFastConstants(&ctx.m_matrices.m_viewProjectionJitter, sizeof(ctx.m_matrices.m_viewProjectionJitter));
  54. // Write flare info
  55. WeakArray<Vec4> flarePositions = allocateAndBindSrvStructuredBuffer<Vec4>(cmdb, 0, 0, flareCount);
  56. U32 count = 0;
  57. for(const LensFlareComponent& comp : SceneGraph::getSingleton().getComponentArrays().getLensFlares())
  58. {
  59. flarePositions[count++] = Vec4(comp.getWorldPosition(), 1.0f);
  60. }
  61. rgraphCtx.bindUav(0, 0, m_runCtx.m_indirectBuffHandle);
  62. // Bind neareset because you don't need high quality
  63. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
  64. rgraphCtx.bindSrv(1, 0, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kEighthInternalResolution);
  65. cmdb.dispatchCompute(flareCount, 1, 1);
  66. });
  67. }
  68. void LensFlare::runDrawFlares(const RenderingContext& ctx, CommandBuffer& cmdb)
  69. {
  70. const U32 flareCount = SceneGraph::getSingleton().getComponentArrays().getLensFlares().getSize();
  71. if(flareCount == 0)
  72. {
  73. return;
  74. }
  75. cmdb.bindShaderProgram(m_realGrProg.get());
  76. cmdb.setBlendFactors(0, BlendFactor::kSrcAlpha, BlendFactor::kOneMinusSrcAlpha);
  77. cmdb.setDepthWrite(false);
  78. U32 count = 0;
  79. for(const LensFlareComponent& comp : SceneGraph::getSingleton().getComponentArrays().getLensFlares())
  80. {
  81. // Compute position
  82. Vec4 lfPos = Vec4(comp.getWorldPosition(), 1.0f);
  83. Vec4 posClip = ctx.m_matrices.m_viewProjectionJitter * lfPos;
  84. /*if(posClip.x() > posClip.w() || posClip.x() < -posClip.w() || posClip.y() > posClip.w()
  85. || posClip.y() < -posClip.w())
  86. {
  87. // Outside clip
  88. ANKI_ASSERT(0 && "Check that before");
  89. }*/
  90. U32 c = 0;
  91. U32 spritesCount = max<U32>(1, m_maxSpritesPerFlare);
  92. // Get uniform memory
  93. WeakArray<LensFlareSprite> sprites = allocateAndBindSrvStructuredBuffer<LensFlareSprite>(cmdb, 0, 0, spritesCount);
  94. // misc
  95. Vec2 posNdc = posClip.xy() / posClip.w();
  96. // First flare
  97. sprites[c].m_posScale = Vec4(posNdc, comp.getFirstFlareSize() * Vec2(1.0f, getRenderer().getAspectRatio()));
  98. sprites[c].m_depthPad3 = Vec4(0.0f);
  99. const F32 alpha = comp.getColorMultiplier().w() * (1.0f - pow(absolute(posNdc.x()), 6.0f))
  100. * (1.0f - pow(absolute(posNdc.y()), 6.0f)); // Fade the flare on the edges
  101. sprites[c].m_color = Vec4(comp.getColorMultiplier().xyz(), alpha);
  102. ++c;
  103. // Render
  104. cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
  105. cmdb.bindSrv(1, 0, TextureView(&comp.getImage().getTexture(), TextureSubresourceDesc::all()));
  106. cmdb.drawIndirect(PrimitiveTopology::kTriangleStrip, BufferView(m_runCtx.m_indirectBuff).incrementOffset(count * sizeof(DrawIndirectArgs)));
  107. ++count;
  108. }
  109. // Restore state
  110. cmdb.setBlendFactors(0, BlendFactor::kOne, BlendFactor::kZero);
  111. cmdb.setDepthWrite(true);
  112. }
  113. } // end namespace anki