Ssao.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #include "anki/renderer/Ssao.h"
  2. #include "anki/renderer/Renderer.h"
  3. #include "anki/scene/Camera.h"
  4. #include "anki/scene/SceneGraph.h"
  5. namespace anki {
  6. //==============================================================================
  7. struct ShaderCommonUniforms
  8. {
  9. Vec4 nearPlanes;
  10. Vec4 limitsOfNearPlane;
  11. };
  12. //==============================================================================
  13. void Ssao::createFbo(Fbo& fbo, Texture& fai, F32 width, F32 height)
  14. {
  15. Renderer::createFai(width, height, GL_RED, GL_RED, GL_UNSIGNED_BYTE, fai);
  16. fai.setFiltering(Texture::TFT_LINEAR);
  17. fbo.create();
  18. fbo.setColorAttachments({&fai});
  19. if(!fbo.isComplete())
  20. {
  21. throw ANKI_EXCEPTION("Fbo not complete");
  22. }
  23. }
  24. //==============================================================================
  25. void Ssao::initInternal(const RendererInitializer& initializer)
  26. {
  27. enabled = initializer.pps.ssao.enabled;
  28. if(!enabled)
  29. {
  30. return;
  31. }
  32. blurringIterationsCount = initializer.pps.ssao.blurringIterationsNum;
  33. //
  34. // Init the widths/heights
  35. //
  36. const F32 bQuality = initializer.pps.ssao.blurringRenderingQuality;
  37. const F32 mpQuality = initializer.pps.ssao.mainPassRenderingQuality;
  38. if(mpQuality > bQuality)
  39. {
  40. throw ANKI_EXCEPTION("SSAO blur quality shouldn't be less than "
  41. "main pass SSAO quality");
  42. }
  43. bWidth = bQuality * (F32)r->getWidth();
  44. bHeight = bQuality * (F32)r->getHeight();
  45. mpWidth = mpQuality * (F32)r->getWidth();
  46. mpHeight = mpQuality * (F32)r->getHeight();
  47. //
  48. // create FBOs
  49. //
  50. createFbo(hblurFbo, hblurFai, bWidth, bHeight);
  51. createFbo(vblurFbo, vblurFai, bWidth, bHeight);
  52. if(blit())
  53. {
  54. createFbo(mpFbo, mpFai, mpWidth, mpHeight);
  55. }
  56. //
  57. // noise map
  58. //
  59. noiseMap.load("engine-rsrc/noise.png");
  60. noiseMap->setFiltering(Texture::TFT_NEAREST);
  61. if(noiseMap->getWidth() != noiseMap->getHeight())
  62. {
  63. throw ANKI_EXCEPTION("Incorrect noisemap size");
  64. }
  65. //
  66. // Shaders
  67. //
  68. commonUbo.create(sizeof(ShaderCommonUniforms), nullptr);
  69. std::string pps;
  70. // main pass prog
  71. pps = "#define NOISE_MAP_SIZE " + std::to_string(noiseMap->getWidth())
  72. + "\n#define WIDTH " + std::to_string(mpWidth)
  73. + "\n#define HEIGHT " + std::to_string(mpHeight) + "\n";
  74. ssaoSProg.load(ShaderProgramResource::createSrcCodeToCache(
  75. "shaders/PpsSsao.glsl", pps.c_str()).c_str());
  76. ssaoSProg->findUniformBlock("commonBlock").setBinding(0);
  77. // blurring progs
  78. const char* SHADER_FILENAME = "shaders/VariableSamplingBlurGeneric.glsl";
  79. pps = "#define HPASS\n"
  80. "#define COL_R\n"
  81. "#define IMG_DIMENSION " + std::to_string(bHeight) + "\n"
  82. "#define SAMPLES 8\n";
  83. hblurSProg.load(ShaderProgramResource::createSrcCodeToCache(
  84. SHADER_FILENAME, pps.c_str()).c_str());
  85. pps = "#define VPASS\n"
  86. "#define COL_R\n"
  87. "#define IMG_DIMENSION " + std::to_string(bWidth) + "\n"
  88. "#define SAMPLES 8\n";
  89. vblurSProg.load(ShaderProgramResource::createSrcCodeToCache(
  90. SHADER_FILENAME, pps.c_str()).c_str());
  91. }
  92. //==============================================================================
  93. void Ssao::init(const RendererInitializer& initializer)
  94. {
  95. try
  96. {
  97. initInternal(initializer);
  98. }
  99. catch(const std::exception& e)
  100. {
  101. throw ANKI_EXCEPTION("Failed to init PPS SSAO") << e;
  102. }
  103. }
  104. //==============================================================================
  105. void Ssao::run()
  106. {
  107. ANKI_ASSERT(enabled);
  108. const Camera& cam = r->getSceneGraph().getActiveCamera();
  109. GlStateSingleton::get().disable(GL_BLEND);
  110. GlStateSingleton::get().disable(GL_DEPTH_TEST);
  111. // 1st pass
  112. //
  113. if(blit())
  114. {
  115. mpFbo.bind();
  116. GlStateSingleton::get().setViewport(0, 0, mpWidth, mpHeight);
  117. }
  118. else
  119. {
  120. vblurFbo.bind();
  121. GlStateSingleton::get().setViewport(0, 0, bWidth, bHeight);
  122. }
  123. r->clearAfterBindingFbo(GL_COLOR_BUFFER_BIT);
  124. ssaoSProg->bind();
  125. commonUbo.setBinding(0);
  126. // Write common block
  127. if(commonUboUpdateTimestamp < r->getPlanesUpdateTimestamp()
  128. || commonUboUpdateTimestamp == 1)
  129. {
  130. ShaderCommonUniforms blk;
  131. blk.nearPlanes = Vec4(cam.getNear(), 0.0, r->getPlanes().x(),
  132. r->getPlanes().y());
  133. blk.limitsOfNearPlane = Vec4(r->getLimitsOfNearPlane(),
  134. r->getLimitsOfNearPlane2());
  135. commonUbo.write(&blk);
  136. commonUboUpdateTimestamp = getGlobTimestamp();
  137. }
  138. // msDepthFai
  139. ssaoSProg->findUniformVariable("msDepthFai").set(
  140. r->getMs().getDepthFai());
  141. // noiseMap
  142. ssaoSProg->findUniformVariable("noiseMap").set(*noiseMap);
  143. // msGFai
  144. ssaoSProg->findUniformVariable("msGFai").set(r->getMs().getFai0());
  145. // Draw
  146. r->drawQuad();
  147. // Blit from main pass FBO to vertical pass FBO
  148. if(blit())
  149. {
  150. vblurFbo.blit(mpFbo,
  151. 0, 0, mpWidth, mpHeight,
  152. 0, 0, bWidth, bHeight,
  153. GL_COLOR_BUFFER_BIT, GL_LINEAR);
  154. // Set the correct viewport
  155. GlStateSingleton::get().setViewport(0, 0, bWidth, bHeight);
  156. }
  157. // Blurring passes
  158. //
  159. for(U32 i = 0; i < blurringIterationsCount; i++)
  160. {
  161. // hpass
  162. hblurFbo.bind();
  163. r->clearAfterBindingFbo(GL_COLOR_BUFFER_BIT);
  164. hblurSProg->bind();
  165. if(i == 0)
  166. {
  167. hblurSProg->findUniformVariable("img").set(vblurFai);
  168. }
  169. r->drawQuad();
  170. // vpass
  171. vblurFbo.bind();
  172. r->clearAfterBindingFbo(GL_COLOR_BUFFER_BIT);
  173. vblurSProg->bind();
  174. if(i == 0)
  175. {
  176. vblurSProg->findUniformVariable("img").set(hblurFai);
  177. }
  178. r->drawQuad();
  179. }
  180. }
  181. } // end namespace anki