LensFlare.cpp 5.4 KB

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