VolumetricFog.cpp 3.6 KB

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