LensFlare.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Copyright (C) 2009-2023, 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. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  44. // Create indirect buffer
  45. m_runCtx.m_indirectBuff = GpuVisibleTransientMemoryPool::getSingleton().allocate(sizeof(DrawIndirectArgs) * flareCount);
  46. m_runCtx.m_indirectBuffHandle = rgraph.importBuffer(m_runCtx.m_indirectBuff, BufferUsageBit::kNone);
  47. // Create the pass
  48. ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("Lens flare indirect");
  49. rpass.newBufferDependency(m_runCtx.m_indirectBuffHandle, BufferUsageBit::kStorageComputeWrite);
  50. rpass.newTextureDependency(getRenderer().getDepthDownscale().getRt(), TextureUsageBit::kSampledCompute,
  51. DepthDownscale::kEighthInternalResolution);
  52. rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
  53. ANKI_TRACE_SCOPED_EVENT(LensFlare);
  54. CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
  55. const U32 flareCount = SceneGraph::getSingleton().getComponentArrays().getLensFlares().getSize();
  56. ANKI_ASSERT(flareCount > 0);
  57. cmdb.bindShaderProgram(m_updateIndirectBuffGrProg.get());
  58. cmdb.setPushConstants(&ctx.m_matrices.m_viewProjectionJitter, sizeof(ctx.m_matrices.m_viewProjectionJitter));
  59. // Write flare info
  60. Vec4* flarePositions = allocateAndBindStorageBuffer<Vec4>(cmdb, 0, 0, flareCount);
  61. for(const LensFlareComponent& comp : SceneGraph::getSingleton().getComponentArrays().getLensFlares())
  62. {
  63. *flarePositions = Vec4(comp.getWorldPosition(), 1.0f);
  64. ++flarePositions;
  65. }
  66. rgraphCtx.bindStorageBuffer(0, 1, m_runCtx.m_indirectBuffHandle);
  67. // Bind neareset because you don't need high quality
  68. cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_nearestNearestClamp.get());
  69. rgraphCtx.bindTexture(0, 3, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kEighthInternalResolution);
  70. cmdb.dispatchCompute(flareCount, 1, 1);
  71. });
  72. }
  73. void LensFlare::runDrawFlares(const RenderingContext& ctx, CommandBuffer& cmdb)
  74. {
  75. const U32 flareCount = SceneGraph::getSingleton().getComponentArrays().getLensFlares().getSize();
  76. if(flareCount == 0)
  77. {
  78. return;
  79. }
  80. cmdb.bindShaderProgram(m_realGrProg.get());
  81. cmdb.setBlendFactors(0, BlendFactor::kSrcAlpha, BlendFactor::kOneMinusSrcAlpha);
  82. cmdb.setDepthWrite(false);
  83. U32 count = 0;
  84. for(const LensFlareComponent& comp : SceneGraph::getSingleton().getComponentArrays().getLensFlares())
  85. {
  86. // Compute position
  87. Vec4 lfPos = Vec4(comp.getWorldPosition(), 1.0f);
  88. Vec4 posClip = ctx.m_matrices.m_viewProjectionJitter * lfPos;
  89. /*if(posClip.x() > posClip.w() || posClip.x() < -posClip.w() || posClip.y() > posClip.w()
  90. || posClip.y() < -posClip.w())
  91. {
  92. // Outside clip
  93. ANKI_ASSERT(0 && "Check that before");
  94. }*/
  95. U32 c = 0;
  96. U32 spritesCount = max<U32>(1, m_maxSpritesPerFlare);
  97. // Get uniform memory
  98. LensFlareSprite* tmpSprites = allocateAndBindStorageBuffer<LensFlareSprite>(cmdb, 0, 0, spritesCount);
  99. WeakArray<LensFlareSprite> sprites(tmpSprites, spritesCount);
  100. // misc
  101. Vec2 posNdc = posClip.xy() / posClip.w();
  102. // First flare
  103. sprites[c].m_posScale = Vec4(posNdc, comp.getFirstFlareSize() * Vec2(1.0f, getRenderer().getAspectRatio()));
  104. sprites[c].m_depthPad3 = Vec4(0.0f);
  105. const F32 alpha = comp.getColorMultiplier().w() * (1.0f - pow(absolute(posNdc.x()), 6.0f))
  106. * (1.0f - pow(absolute(posNdc.y()), 6.0f)); // Fade the flare on the edges
  107. sprites[c].m_color = Vec4(comp.getColorMultiplier().xyz(), alpha);
  108. ++c;
  109. // Render
  110. cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearRepeat.get());
  111. cmdb.bindTexture(0, 2, &comp.getImage().getTextureView());
  112. cmdb.drawIndirect(PrimitiveTopology::kTriangleStrip, BufferView(m_runCtx.m_indirectBuff).incrementOffset(count * sizeof(DrawIndirectArgs)));
  113. ++count;
  114. }
  115. // Restore state
  116. cmdb.setBlendFactors(0, BlendFactor::kOne, BlendFactor::kZero);
  117. cmdb.setDepthWrite(true);
  118. }
  119. } // end namespace anki