Ssao.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. // Copyright (C) 2009-2018, 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/Ssao.h>
  6. #include <anki/renderer/Renderer.h>
  7. #include <anki/renderer/GBuffer.h>
  8. #include <anki/renderer/RenderQueue.h>
  9. #include <anki/renderer/DepthDownscale.h>
  10. #include <anki/util/Functions.h>
  11. #include <anki/misc/ConfigSet.h>
  12. namespace anki
  13. {
  14. Ssao::~Ssao()
  15. {
  16. }
  17. Error Ssao::initMain(const ConfigSet& config)
  18. {
  19. // Noise
  20. ANKI_CHECK(getResourceManager().loadResource("engine_data/BlueNoiseLdrRgb64x64.ankitex", m_main.m_noiseTex));
  21. // Shader
  22. if(m_useCompute)
  23. {
  24. ANKI_CHECK(getResourceManager().loadResource("programs/SsaoCompute.ankiprog", m_main.m_prog));
  25. }
  26. else
  27. {
  28. ANKI_CHECK(getResourceManager().loadResource("programs/Ssao.ankiprog", m_main.m_prog));
  29. }
  30. ShaderProgramResourceMutationInitList<2> mutators(m_main.m_prog);
  31. mutators.add("USE_NORMAL", (m_useNormal) ? 1u : 0u).add("SOFT_BLUR", (m_useSoftBlur) ? 1u : 0u);
  32. ShaderProgramResourceConstantValueInitList<7> consts(m_main.m_prog);
  33. consts.add("NOISE_MAP_SIZE", U32(m_main.m_noiseTex->getWidth()))
  34. .add("FB_SIZE", UVec2(m_width, m_height))
  35. .add("RADIUS", 2.5f)
  36. .add("BIAS", 0.0f)
  37. .add("STRENGTH", 2.5f)
  38. .add("SAMPLE_COUNT", 8u)
  39. .add("WORKGROUP_SIZE", UVec2(m_workgroupSize[0], m_workgroupSize[1]));
  40. const ShaderProgramResourceVariant* variant;
  41. m_main.m_prog->getOrCreateVariant(mutators.get(), consts.get(), variant);
  42. m_main.m_grProg = variant->getProgram();
  43. return Error::NONE;
  44. }
  45. Error Ssao::initBlur(const ConfigSet& config)
  46. {
  47. // shader
  48. if(m_blurUseCompute)
  49. {
  50. ANKI_CHECK(m_r->getResourceManager().loadResource("programs/GaussianBlurCompute.ankiprog", m_blur.m_prog));
  51. ShaderProgramResourceMutationInitList<3> mutators(m_blur.m_prog);
  52. mutators.add("ORIENTATION", 2).add("KERNEL_SIZE", 3).add("COLOR_COMPONENTS", 1);
  53. ShaderProgramResourceConstantValueInitList<2> consts(m_blur.m_prog);
  54. consts.add("TEXTURE_SIZE", UVec2(m_width, m_height))
  55. .add("WORKGROUP_SIZE", UVec2(m_workgroupSize[0], m_workgroupSize[1]));
  56. const ShaderProgramResourceVariant* variant;
  57. m_blur.m_prog->getOrCreateVariant(mutators.get(), consts.get(), variant);
  58. m_blur.m_grProg = variant->getProgram();
  59. }
  60. else
  61. {
  62. ANKI_CHECK(m_r->getResourceManager().loadResource("programs/GaussianBlur.ankiprog", m_blur.m_prog));
  63. ShaderProgramResourceMutationInitList<3> mutators(m_blur.m_prog);
  64. mutators.add("ORIENTATION", 2).add("KERNEL_SIZE", 3).add("COLOR_COMPONENTS", 1);
  65. ShaderProgramResourceConstantValueInitList<1> consts(m_blur.m_prog);
  66. consts.add("TEXTURE_SIZE", UVec2(m_width, m_height));
  67. const ShaderProgramResourceVariant* variant;
  68. m_blur.m_prog->getOrCreateVariant(mutators.get(), consts.get(), variant);
  69. m_blur.m_grProg = variant->getProgram();
  70. }
  71. return Error::NONE;
  72. }
  73. Error Ssao::init(const ConfigSet& config)
  74. {
  75. m_width = m_r->getWidth() / SSAO_FRACTION;
  76. m_height = m_r->getHeight() / SSAO_FRACTION;
  77. ANKI_R_LOGI("Initializing SSAO. Size %ux%u", m_width, m_height);
  78. // RT
  79. m_rtDescrs[0] = m_r->create2DRenderTargetDescription(m_width, m_height, Ssao::RT_PIXEL_FORMAT, "SSAOMain");
  80. m_rtDescrs[0].bake();
  81. m_rtDescrs[1] = m_r->create2DRenderTargetDescription(m_width, m_height, Ssao::RT_PIXEL_FORMAT, "SSAOBlur");
  82. m_rtDescrs[1].bake();
  83. // FB descr
  84. m_fbDescr.m_colorAttachmentCount = 1;
  85. m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
  86. m_fbDescr.bake();
  87. Error err = initMain(config);
  88. if(!err)
  89. {
  90. err = initBlur(config);
  91. }
  92. if(err)
  93. {
  94. ANKI_R_LOGE("Failed to init PPS SSAO");
  95. }
  96. return err;
  97. }
  98. void Ssao::runMain(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
  99. {
  100. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  101. cmdb->bindShaderProgram(m_main.m_grProg);
  102. rgraphCtx.bindTextureAndSampler(
  103. 0, 0, m_r->getDepthDownscale().getHiZRt(), HIZ_QUARTER_DEPTH, m_r->getLinearSampler());
  104. cmdb->bindTextureAndSampler(0,
  105. 1,
  106. m_main.m_noiseTex->getGrTextureView(),
  107. m_r->getTrilinearRepeatSampler(),
  108. TextureUsageBit::SAMPLED_FRAGMENT);
  109. if(m_useNormal)
  110. {
  111. rgraphCtx.bindColorTextureAndSampler(0, 2, m_r->getGBuffer().getColorRt(2), m_r->getLinearSampler());
  112. }
  113. struct Unis
  114. {
  115. Vec4 m_unprojectionParams;
  116. Vec4 m_projectionMat;
  117. Mat3x4 m_viewRotMat;
  118. };
  119. Unis* unis = allocateAndBindUniforms<Unis*>(sizeof(Unis), cmdb, 0, 0);
  120. const Mat4& pmat = ctx.m_renderQueue->m_projectionMatrix;
  121. unis->m_unprojectionParams = ctx.m_unprojParams;
  122. unis->m_projectionMat = Vec4(pmat(0, 0), pmat(1, 1), pmat(2, 2), pmat(2, 3));
  123. unis->m_viewRotMat = Mat3x4(ctx.m_renderQueue->m_viewMatrix.getRotationPart());
  124. if(m_useCompute)
  125. {
  126. rgraphCtx.bindImage(0, 0, m_runCtx.m_rts[0], TextureSubresourceInfo());
  127. const U sizeX = (m_width + m_workgroupSize[0] - 1) / m_workgroupSize[0];
  128. const U sizeY = (m_height + m_workgroupSize[1] - 1) / m_workgroupSize[1];
  129. cmdb->dispatchCompute(sizeX, sizeY, 1);
  130. }
  131. else
  132. {
  133. cmdb->setViewport(0, 0, m_width, m_height);
  134. drawQuad(cmdb);
  135. }
  136. }
  137. void Ssao::runBlur(RenderPassWorkContext& rgraphCtx)
  138. {
  139. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  140. cmdb->bindShaderProgram(m_blur.m_grProg);
  141. rgraphCtx.bindColorTextureAndSampler(0, 0, m_runCtx.m_rts[0], m_r->getLinearSampler());
  142. if(m_blurUseCompute)
  143. {
  144. rgraphCtx.bindImage(0, 0, m_runCtx.m_rts[1], TextureSubresourceInfo());
  145. dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], m_width, m_height);
  146. }
  147. else
  148. {
  149. cmdb->setViewport(0, 0, m_width, m_height);
  150. drawQuad(cmdb);
  151. }
  152. }
  153. void Ssao::populateRenderGraph(RenderingContext& ctx)
  154. {
  155. m_runCtx.m_ctx = &ctx;
  156. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  157. // Create RTs
  158. m_runCtx.m_rts[0] = rgraph.newRenderTarget(m_rtDescrs[0]);
  159. m_runCtx.m_rts[1] = rgraph.newRenderTarget(m_rtDescrs[1]);
  160. // Create main render pass
  161. {
  162. if(m_useCompute)
  163. {
  164. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SSAO main");
  165. if(m_useNormal)
  166. {
  167. pass.newConsumer({m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE});
  168. }
  169. pass.newConsumer(
  170. {m_r->getDepthDownscale().getHiZRt(), TextureUsageBit::SAMPLED_COMPUTE, HIZ_QUARTER_DEPTH});
  171. pass.newConsumer({m_runCtx.m_rts[0], TextureUsageBit::IMAGE_COMPUTE_WRITE});
  172. pass.newProducer({m_runCtx.m_rts[0], TextureUsageBit::IMAGE_COMPUTE_WRITE});
  173. pass.setWork(runMainCallback, this, 0);
  174. }
  175. else
  176. {
  177. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SSAO main");
  178. pass.setFramebufferInfo(m_fbDescr, {{m_runCtx.m_rts[0]}}, {});
  179. if(m_useNormal)
  180. {
  181. pass.newConsumer({m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_FRAGMENT});
  182. }
  183. pass.newConsumer(
  184. {m_r->getDepthDownscale().getHiZRt(), TextureUsageBit::SAMPLED_FRAGMENT, HIZ_QUARTER_DEPTH});
  185. pass.newConsumer({m_runCtx.m_rts[0], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  186. pass.newProducer({m_runCtx.m_rts[0], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  187. pass.setWork(runMainCallback, this, 0);
  188. }
  189. }
  190. // Create Blur pass
  191. {
  192. if(m_blurUseCompute)
  193. {
  194. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SSAO blur");
  195. pass.setWork(runBlurCallback, this, 0);
  196. pass.newConsumer({m_runCtx.m_rts[1], TextureUsageBit::IMAGE_COMPUTE_WRITE});
  197. pass.newConsumer({m_runCtx.m_rts[0], TextureUsageBit::SAMPLED_COMPUTE});
  198. pass.newProducer({m_runCtx.m_rts[1], TextureUsageBit::IMAGE_COMPUTE_WRITE});
  199. }
  200. else
  201. {
  202. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SSAO blur");
  203. pass.setWork(runBlurCallback, this, 0);
  204. pass.setFramebufferInfo(m_fbDescr, {{m_runCtx.m_rts[1]}}, {});
  205. pass.newConsumer({m_runCtx.m_rts[1], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  206. pass.newConsumer({m_runCtx.m_rts[0], TextureUsageBit::SAMPLED_FRAGMENT});
  207. pass.newProducer({m_runCtx.m_rts[1], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  208. }
  209. }
  210. }
  211. } // end namespace anki