Ssao.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // Copyright (C) 2009-2020, 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/core/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("shaders/SsaoCompute.ankiprog", m_main.m_prog));
  25. }
  26. else
  27. {
  28. ANKI_CHECK(getResourceManager().loadResource("shaders/Ssao.ankiprog", m_main.m_prog));
  29. }
  30. ShaderProgramResourceVariantInitInfo variantInitInfo(m_main.m_prog);
  31. variantInitInfo.addMutation("USE_NORMAL", (m_useNormal) ? 1u : 0u);
  32. variantInitInfo.addMutation("SOFT_BLUR", (m_useSoftBlur) ? 1u : 0u);
  33. variantInitInfo.addConstant("NOISE_MAP_SIZE", U32(m_main.m_noiseTex->getWidth()));
  34. variantInitInfo.addConstant("FB_SIZE", UVec2(m_width, m_height));
  35. variantInitInfo.addConstant("RADIUS", 2.5f);
  36. variantInitInfo.addConstant("BIAS", 0.0f);
  37. variantInitInfo.addConstant("STRENGTH", 2.5f);
  38. variantInitInfo.addConstant("SAMPLE_COUNT", 8u);
  39. const ShaderProgramResourceVariant* variant;
  40. m_main.m_prog->getOrCreateVariant(variantInitInfo, variant);
  41. m_main.m_workgroupSize[0] = variant->getWorkgroupSizes()[0];
  42. m_main.m_workgroupSize[1] = variant->getWorkgroupSizes()[1];
  43. m_main.m_grProg = variant->getProgram();
  44. return Error::NONE;
  45. }
  46. Error Ssao::initBlur(const ConfigSet& config)
  47. {
  48. // shader
  49. if(m_blurUseCompute)
  50. {
  51. ANKI_CHECK(m_r->getResourceManager().loadResource("shaders/GaussianBlurCompute.ankiprog", m_blur.m_prog));
  52. ShaderProgramResourceVariantInitInfo variantInitInfo(m_blur.m_prog);
  53. variantInitInfo.addMutation("ORIENTATION", 2);
  54. variantInitInfo.addMutation("KERNEL_SIZE", 3);
  55. variantInitInfo.addMutation("COLOR_COMPONENTS", 1);
  56. variantInitInfo.addConstant("TEXTURE_SIZE", UVec2(m_width, m_height));
  57. const ShaderProgramResourceVariant* variant;
  58. m_blur.m_prog->getOrCreateVariant(variantInitInfo, variant);
  59. m_blur.m_workgroupSize[0] = variant->getWorkgroupSizes()[0];
  60. m_blur.m_workgroupSize[1] = variant->getWorkgroupSizes()[1];
  61. m_blur.m_grProg = variant->getProgram();
  62. }
  63. else
  64. {
  65. ANKI_CHECK(m_r->getResourceManager().loadResource("shaders/GaussianBlur.ankiprog", m_blur.m_prog));
  66. ShaderProgramResourceVariantInitInfo variantInitInfo(m_blur.m_prog);
  67. variantInitInfo.addMutation("ORIENTATION", 2);
  68. variantInitInfo.addMutation("KERNEL_SIZE", 3);
  69. variantInitInfo.addMutation("COLOR_COMPONENTS", 1);
  70. variantInitInfo.addConstant("TEXTURE_SIZE", UVec2(m_width, m_height));
  71. const ShaderProgramResourceVariant* variant;
  72. m_blur.m_prog->getOrCreateVariant(variantInitInfo, variant);
  73. m_blur.m_grProg = variant->getProgram();
  74. }
  75. return Error::NONE;
  76. }
  77. Error Ssao::init(const ConfigSet& config)
  78. {
  79. m_width = m_r->getWidth() / SSAO_FRACTION;
  80. m_height = m_r->getHeight() / SSAO_FRACTION;
  81. ANKI_R_LOGI("Initializing SSAO. Size %ux%u", m_width, m_height);
  82. // RT
  83. m_rtDescrs[0] = m_r->create2DRenderTargetDescription(m_width, m_height, RT_PIXEL_FORMAT, "SSAOMain");
  84. m_rtDescrs[0].bake();
  85. m_rtDescrs[1] = m_r->create2DRenderTargetDescription(m_width, m_height, RT_PIXEL_FORMAT, "SSAOBlur");
  86. m_rtDescrs[1].bake();
  87. // FB descr
  88. m_fbDescr.m_colorAttachmentCount = 1;
  89. m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
  90. m_fbDescr.bake();
  91. Error err = initMain(config);
  92. if(!err)
  93. {
  94. err = initBlur(config);
  95. }
  96. if(err)
  97. {
  98. ANKI_R_LOGE("Failed to init PPS SSAO");
  99. }
  100. return err;
  101. }
  102. void Ssao::runMain(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
  103. {
  104. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  105. cmdb->bindShaderProgram(m_main.m_grProg);
  106. // Bind resources
  107. cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
  108. cmdb->bindSampler(0, 1, m_r->getSamplers().m_trilinearRepeat);
  109. rgraphCtx.bindTexture(0, 2, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
  110. cmdb->bindTexture(0, 3, m_main.m_noiseTex->getGrTextureView(), TextureUsageBit::SAMPLED_FRAGMENT);
  111. if(m_useNormal)
  112. {
  113. rgraphCtx.bindColorTexture(0, 4, m_r->getGBuffer().getColorRt(2));
  114. }
  115. struct Unis
  116. {
  117. Vec4 m_unprojectionParams;
  118. Vec4 m_projectionMat;
  119. Mat3x4 m_viewRotMat;
  120. } unis;
  121. const Mat4& pmat = ctx.m_renderQueue->m_projectionMatrix;
  122. unis.m_unprojectionParams = ctx.m_unprojParams;
  123. unis.m_projectionMat = Vec4(pmat(0, 0), pmat(1, 1), pmat(2, 2), pmat(2, 3));
  124. unis.m_viewRotMat = Mat3x4(Vec3(0.0f), ctx.m_renderQueue->m_viewMatrix.getRotationPart());
  125. cmdb->setPushConstants(&unis, sizeof(unis));
  126. if(m_useCompute)
  127. {
  128. rgraphCtx.bindImage(0, 5, m_runCtx.m_rts[0], TextureSubresourceInfo());
  129. dispatchPPCompute(cmdb, m_main.m_workgroupSize[0], m_main.m_workgroupSize[1], m_width, m_height);
  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. cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
  142. rgraphCtx.bindColorTexture(0, 1, m_runCtx.m_rts[0]);
  143. if(m_blurUseCompute)
  144. {
  145. rgraphCtx.bindImage(0, 2, m_runCtx.m_rts[1], TextureSubresourceInfo());
  146. dispatchPPCompute(cmdb, m_blur.m_workgroupSize[0], m_blur.m_workgroupSize[1], m_width, m_height);
  147. }
  148. else
  149. {
  150. cmdb->setViewport(0, 0, m_width, m_height);
  151. drawQuad(cmdb);
  152. }
  153. }
  154. void Ssao::populateRenderGraph(RenderingContext& ctx)
  155. {
  156. m_runCtx.m_ctx = &ctx;
  157. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  158. // Create RTs
  159. m_runCtx.m_rts[0] = rgraph.newRenderTarget(m_rtDescrs[0]);
  160. m_runCtx.m_rts[1] = rgraph.newRenderTarget(m_rtDescrs[1]);
  161. // Create main render pass
  162. {
  163. if(m_useCompute)
  164. {
  165. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SSAO main");
  166. if(m_useNormal)
  167. {
  168. pass.newDependency({m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE});
  169. }
  170. pass.newDependency({m_r->getDepthDownscale().getHiZRt(), TextureUsageBit::SAMPLED_COMPUTE, HIZ_HALF_DEPTH});
  171. pass.newDependency({m_runCtx.m_rts[0], TextureUsageBit::IMAGE_COMPUTE_WRITE});
  172. pass.setWork(
  173. [](RenderPassWorkContext& rgraphCtx) {
  174. Ssao* const self = static_cast<Ssao*>(rgraphCtx.m_userData);
  175. self->runMain(*self->m_runCtx.m_ctx, rgraphCtx);
  176. },
  177. this, 0);
  178. }
  179. else
  180. {
  181. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SSAO main");
  182. pass.setFramebufferInfo(m_fbDescr, {{m_runCtx.m_rts[0]}}, {});
  183. if(m_useNormal)
  184. {
  185. pass.newDependency({m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_FRAGMENT});
  186. }
  187. pass.newDependency(
  188. {m_r->getDepthDownscale().getHiZRt(), TextureUsageBit::SAMPLED_FRAGMENT, HIZ_HALF_DEPTH});
  189. pass.newDependency({m_runCtx.m_rts[0], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  190. pass.setWork(
  191. [](RenderPassWorkContext& rgraphCtx) {
  192. Ssao* const self = static_cast<Ssao*>(rgraphCtx.m_userData);
  193. self->runMain(*self->m_runCtx.m_ctx, rgraphCtx);
  194. },
  195. this, 0);
  196. }
  197. }
  198. // Create Blur pass
  199. {
  200. if(m_blurUseCompute)
  201. {
  202. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SSAO blur");
  203. pass.setWork(
  204. [](RenderPassWorkContext& rgraphCtx) {
  205. Ssao* const self = static_cast<Ssao*>(rgraphCtx.m_userData);
  206. self->runBlur(rgraphCtx);
  207. },
  208. this, 0);
  209. pass.newDependency({m_runCtx.m_rts[1], TextureUsageBit::IMAGE_COMPUTE_WRITE});
  210. pass.newDependency({m_runCtx.m_rts[0], TextureUsageBit::SAMPLED_COMPUTE});
  211. }
  212. else
  213. {
  214. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SSAO blur");
  215. pass.setWork(
  216. [](RenderPassWorkContext& rgraphCtx) {
  217. Ssao* const self = static_cast<Ssao*>(rgraphCtx.m_userData);
  218. self->runBlur(rgraphCtx);
  219. },
  220. this, 0);
  221. pass.setFramebufferInfo(m_fbDescr, {{m_runCtx.m_rts[1]}}, {});
  222. pass.newDependency({m_runCtx.m_rts[1], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  223. pass.newDependency({m_runCtx.m_rts[0], TextureUsageBit::SAMPLED_FRAGMENT});
  224. }
  225. }
  226. }
  227. } // end namespace anki