VolumetricFog.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright (C) 2009-2021, 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/VolumetricFog.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Renderer/DepthDownscale.h>
  8. #include <AnKi/Renderer/ShadowMapping.h>
  9. #include <AnKi/Renderer/LightShading.h>
  10. #include <AnKi/Renderer/RenderQueue.h>
  11. #include <AnKi/Renderer/VolumetricLightingAccumulation.h>
  12. #include <AnKi/Core/ConfigSet.h>
  13. namespace anki
  14. {
  15. Error VolumetricFog::init(const ConfigSet& config)
  16. {
  17. // Misc
  18. const F32 qualityXY = config.getNumberF32("r_volumetricLightingAccumulationQualityXY");
  19. const F32 qualityZ = config.getNumberF32("r_volumetricLightingAccumulationQualityZ");
  20. m_finalZSplit = min(m_r->getZSplitCount(), config.getNumberU32("r_volumetricLightingAccumulationFinalZSplit"));
  21. m_volumeSize[0] = U32(F32(m_r->getTileCounts().x()) * qualityXY);
  22. m_volumeSize[1] = U32(F32(m_r->getTileCounts().y()) * qualityXY);
  23. m_volumeSize[2] = U32(F32(m_finalZSplit + 1) * qualityZ);
  24. ANKI_R_LOGI("Initializing volumetric fog. Size %ux%ux%u", m_volumeSize[0], m_volumeSize[1], m_volumeSize[2]);
  25. // Shaders
  26. ANKI_CHECK(getResourceManager().loadResource("Shaders/VolumetricFogAccumulation.ankiprog", m_prog));
  27. ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
  28. variantInitInfo.addConstant("VOLUME_SIZE", UVec3(m_volumeSize[0], m_volumeSize[1], m_volumeSize[2]));
  29. variantInitInfo.addConstant("Z_SPLIT_COUNT", m_r->getZSplitCount());
  30. variantInitInfo.addConstant("FINAL_Z_SPLIT", m_finalZSplit);
  31. const ShaderProgramResourceVariant* variant;
  32. m_prog->getOrCreateVariant(variantInitInfo, variant);
  33. m_grProg = variant->getProgram();
  34. m_workgroupSize[0] = variant->getWorkgroupSizes()[0];
  35. m_workgroupSize[1] = variant->getWorkgroupSizes()[1];
  36. // RT descr
  37. m_rtDescr =
  38. m_r->create2DRenderTargetDescription(m_volumeSize[0], m_volumeSize[1], Format::R16G16B16A16_SFLOAT, "Fog");
  39. m_rtDescr.m_depth = m_volumeSize[2];
  40. m_rtDescr.m_type = TextureType::_3D;
  41. m_rtDescr.bake();
  42. return Error::NONE;
  43. }
  44. void VolumetricFog::run(RenderPassWorkContext& rgraphCtx)
  45. {
  46. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  47. const RenderingContext& ctx = *m_runCtx.m_ctx;
  48. cmdb->bindShaderProgram(m_grProg);
  49. cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
  50. rgraphCtx.bindColorTexture(0, 1, m_r->getVolumetricLightingAccumulation().getRt());
  51. rgraphCtx.bindImage(0, 2, m_runCtx.m_rt, TextureSubresourceInfo());
  52. struct PushConsts
  53. {
  54. F32 m_fogScatteringCoeff;
  55. F32 m_fogAbsorptionCoeff;
  56. F32 m_density;
  57. F32 m_near;
  58. Vec3 m_fogDiffuse;
  59. F32 m_far;
  60. } regs;
  61. regs.m_fogScatteringCoeff = m_fogScatteringCoeff;
  62. regs.m_fogAbsorptionCoeff = m_fogAbsorptionCoeff;
  63. regs.m_density = m_fogDensity;
  64. regs.m_fogDiffuse = m_fogDiffuseColor;
  65. regs.m_near = ctx.m_renderQueue->m_cameraNear;
  66. regs.m_far = ctx.m_renderQueue->m_cameraFar;
  67. cmdb->setPushConstants(&regs, sizeof(regs));
  68. dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_volumeSize[0], m_volumeSize[1]);
  69. }
  70. void VolumetricFog::populateRenderGraph(RenderingContext& ctx)
  71. {
  72. m_runCtx.m_ctx = &ctx;
  73. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  74. m_runCtx.m_rt = rgraph.newRenderTarget(m_rtDescr);
  75. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Vol fog");
  76. auto callback = [](RenderPassWorkContext& rgraphCtx) -> void {
  77. static_cast<VolumetricFog*>(rgraphCtx.m_userData)->run(rgraphCtx);
  78. };
  79. pass.setWork(callback, this, 0);
  80. pass.newDependency({m_runCtx.m_rt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
  81. pass.newDependency({m_r->getVolumetricLightingAccumulation().getRt(), TextureUsageBit::SAMPLED_COMPUTE});
  82. }
  83. } // end namespace anki