Renderer.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. #include "anki/renderer/Renderer.h"
  2. #include "anki/util/Exception.h"
  3. #include "anki/scene/Camera.h"
  4. #include "anki/scene/SceneGraph.h"
  5. #include "anki/core/Counters.h"
  6. #include <sstream>
  7. namespace anki {
  8. //==============================================================================
  9. // RendererInitializer =
  10. //==============================================================================
  11. //==============================================================================
  12. RendererInitializer::RendererInitializer()
  13. {
  14. // Ms
  15. newOption("ms.ez.enabled", false);
  16. newOption("ms.ez.maxObjectsToDraw", 10);
  17. // Is
  18. newOption("is.sm.enabled", true);
  19. newOption("is.sm.poissonEnabled", true);
  20. newOption("is.sm.bilinearEnabled", true);
  21. newOption("is.sm.resolution", 512);
  22. newOption("is.sm.maxLights", 4);
  23. newOption("is.groundLightEnabled", true);
  24. newOption("is.maxPointLights", 512 - 16);
  25. newOption("is.maxSpotLights", 8);
  26. newOption("is.maxSpotTexLights", 4);
  27. newOption("is.maxPointLightsPerTile", 48);
  28. newOption("is.maxSpotLightsPerTile", 4);
  29. newOption("is.maxSpotTexLightsPerTile", 4);
  30. // Pps
  31. newOption("pps.hdr.enabled", true);
  32. newOption("pps.hdr.renderingQuality", 0.5);
  33. newOption("pps.hdr.blurringDist", 1.0);
  34. newOption("pps.hdr.samples", 5);
  35. newOption("pps.hdr.blurringIterationsCount", 1);
  36. newOption("pps.hdr.exposure", 4.0);
  37. newOption("pps.ssao.enabled", true);
  38. newOption("pps.ssao.renderingQuality", 0.3);
  39. newOption("pps.ssao.blurringIterationsCount", 1);
  40. newOption("pps.sslr.enabled", true);
  41. newOption("pps.sslr.renderingQuality", 0.2);
  42. newOption("pps.sslr.blurringIterationsCount", 1);
  43. newOption("pps.bl.enabled", true);
  44. newOption("pps.bl.blurringIterationsCount", 1);
  45. newOption("pps.bl.sideBlurFactor", 1.0);
  46. newOption("pps.lf.enabled", true);
  47. newOption("pps.lf.maxFlaresPerLight", 8);
  48. newOption("pps.lf.maxLightsWithFlares", 4);
  49. newOption("pps.enabled", true);
  50. newOption("pps.sharpen", true);
  51. newOption("pps.gammaCorrection", true);
  52. // Dbg
  53. newOption("dbg.enabled", false);
  54. // Globals
  55. newOption("width", 0);
  56. newOption("height", 0);
  57. newOption("renderingQuality", 1.0); // Applies only to MainRenderer
  58. newOption("lodDistance", 10.0); // Distance that used to calculate the LOD
  59. newOption("samples", 1);
  60. newOption("tilesXCount", 16);
  61. newOption("tilesYCount", 16);
  62. newOption("tessellation", true);
  63. newOption("maxTextureSize", 1048576); // Cap to limit quality in resources
  64. newOption("offscreen", false);
  65. }
  66. //==============================================================================
  67. // Renderer =
  68. //==============================================================================
  69. //==============================================================================
  70. Renderer::Renderer()
  71. : m_ms(this),
  72. m_is(this),
  73. m_pps(this),
  74. m_bs(this),
  75. m_dbg(this),
  76. m_sceneDrawer(this)
  77. {}
  78. //==============================================================================
  79. Renderer::~Renderer()
  80. {}
  81. //==============================================================================
  82. void Renderer::init(const RendererInitializer& initializer)
  83. {
  84. // Set from the initializer
  85. m_width = initializer.get("width");
  86. alignRoundUp(16, m_width);
  87. m_height = initializer.get("height");
  88. alignRoundUp(16, m_height);
  89. m_lodDistance = initializer.get("lodDistance");
  90. m_framesNum = 0;
  91. m_samples = initializer.get("samples");
  92. m_isOffscreen = initializer.get("offscreen");
  93. m_renderingQuality = initializer.get("renderingQuality");
  94. m_maxTextureSize = initializer.get("maxTextureSize");
  95. m_tilesCount.x() = initializer.get("tilesXCount");
  96. m_tilesCount.y() = initializer.get("tilesYCount");
  97. m_tessellation = initializer.get("tessellation");
  98. // A few sanity checks
  99. if(m_samples != 1 && m_samples != 4 && m_samples != 8 && m_samples != 16
  100. && m_samples != 32)
  101. {
  102. throw ANKI_EXCEPTION("Incorrect samples");
  103. }
  104. if(m_width < 10 || m_height < 10)
  105. {
  106. throw ANKI_EXCEPTION("Incorrect sizes");
  107. }
  108. // quad setup
  109. static const F32 quadVertCoords[][2] = {{1.0, 1.0}, {-1.0, 1.0},
  110. {1.0, -1.0}, {-1.0, -1.0}};
  111. GlManager& gl = GlManagerSingleton::get();
  112. GlJobChainHandle jobs(&gl);
  113. GlClientBufferHandle tmpBuff = GlClientBufferHandle(jobs,
  114. sizeof(quadVertCoords), (void*)&quadVertCoords[0][0]);
  115. m_quadPositionsBuff = GlBufferHandle(jobs, GL_ARRAY_BUFFER,
  116. tmpBuff, 0);
  117. m_drawQuadVert.load("shaders/Quad.vert.glsl");
  118. // Init the stages. Careful with the order!!!!!!!!!!
  119. m_tiler.init(this);
  120. m_ms.init(initializer);;
  121. m_is.init(initializer);
  122. m_bs.init(initializer);
  123. m_pps.init(initializer);
  124. m_dbg.init(initializer);
  125. // Init the shaderPostProcessorString
  126. std::stringstream ss;
  127. ss << "#define RENDERING_WIDTH " << m_width << "\n"
  128. << "#define RENDERING_HEIGHT " << m_height << "\n";
  129. m_shaderPostProcessorString = ss.str();
  130. // Default FB
  131. m_defaultFb = GlFramebufferHandle(jobs, {});
  132. jobs.finish();
  133. }
  134. //==============================================================================
  135. void Renderer::render(SceneGraph& scene,
  136. Array<GlJobChainHandle, JOB_CHAINS_COUNT>& jobs)
  137. {
  138. m_scene = &scene;
  139. Camera& cam = m_scene->getActiveCamera();
  140. // Calc a few vars
  141. //
  142. Timestamp camUpdateTimestamp = cam.FrustumComponent::getTimestamp();
  143. if(m_projectionParamsUpdateTimestamp
  144. < m_scene->getActiveCameraChangeTimestamp()
  145. || m_projectionParamsUpdateTimestamp < camUpdateTimestamp
  146. || m_projectionParamsUpdateTimestamp == 1)
  147. {
  148. ANKI_ASSERT(cam.getCameraType() == Camera::Type::PERSPECTIVE);
  149. computeProjectionParams(cam.getProjectionMatrix());
  150. m_projectionParamsUpdateTimestamp = getGlobTimestamp();
  151. }
  152. ANKI_COUNTER_START_TIMER(RENDERER_MS_TIME);
  153. m_ms.run(jobs[0]);
  154. ANKI_ASSERT(jobs[0].getReferenceCount() == 1);
  155. jobs[0].flush();
  156. ANKI_COUNTER_STOP_TIMER_INC(RENDERER_MS_TIME);
  157. m_tiler.runMinMax(m_ms._getDepthRt());
  158. ANKI_COUNTER_START_TIMER(RENDERER_IS_TIME);
  159. m_is.run(jobs[1]);
  160. ANKI_COUNTER_STOP_TIMER_INC(RENDERER_IS_TIME);
  161. m_bs.run(jobs[1]);
  162. ANKI_COUNTER_START_TIMER(RENDERER_PPS_TIME);
  163. if(m_pps.getEnabled())
  164. {
  165. m_pps.run(jobs[1]);
  166. }
  167. ANKI_COUNTER_STOP_TIMER_INC(RENDERER_PPS_TIME);
  168. if(m_dbg.getEnabled())
  169. {
  170. m_dbg.run(jobs[1]);
  171. }
  172. ++m_framesNum;
  173. }
  174. //==============================================================================
  175. void Renderer::drawQuad(GlJobChainHandle& jobs)
  176. {
  177. drawQuadInstanced(jobs, 1);
  178. }
  179. //==============================================================================
  180. void Renderer::drawQuadInstanced(GlJobChainHandle& jobs, U32 primitiveCount)
  181. {
  182. m_quadPositionsBuff.bindVertexBuffer(jobs, 2, GL_FLOAT, false, 0, 0, 0);
  183. GlDrawcallArrays dc(GL_TRIANGLE_STRIP, 4, primitiveCount);
  184. dc.draw(jobs);
  185. }
  186. //==============================================================================
  187. Vec3 Renderer::unproject(const Vec3& windowCoords, const Mat4& modelViewMat,
  188. const Mat4& projectionMat, const int view[4])
  189. {
  190. Mat4 invPm = projectionMat * modelViewMat;
  191. invPm.invert();
  192. // the vec is in NDC space meaning: -1<=vec.x<=1 -1<=vec.y<=1 -1<=vec.z<=1
  193. Vec4 vec;
  194. vec.x() = (2.0 * (windowCoords.x() - view[0])) / view[2] - 1.0;
  195. vec.y() = (2.0 * (windowCoords.y() - view[1])) / view[3] - 1.0;
  196. vec.z() = 2.0 * windowCoords.z() - 1.0;
  197. vec.w() = 1.0;
  198. Vec4 out = invPm * vec;
  199. out /= out.w();
  200. return out.xyz();
  201. }
  202. //==============================================================================
  203. void Renderer::computeProjectionParams(const Mat4& m)
  204. {
  205. // First, z' = (m * Pv) / 2 + 0.5 where Pv is the view space position.
  206. // Solving that for Pv.z we get
  207. // Pv.z = A / (z' + B)
  208. // where A = (-m23 / 2) and B = (m22/2 - 0.5)
  209. // so we save the A and B in the projection params vector
  210. m_projectionParams.z() = -m(2, 3) * 0.5;
  211. m_projectionParams.w() = m(2, 2) * 0.5 - 0.5;
  212. // Using the same logic the Pv.x = x' * w / m00
  213. // so Pv.x = x' * Pv.z * (-1 / m00)
  214. m_projectionParams.x() = -1.0 / m(0, 0);
  215. // Same for y
  216. m_projectionParams.y() = -1.0 / m(1, 1);
  217. }
  218. //==============================================================================
  219. void Renderer::createRenderTarget(U32 w, U32 h, GLenum internalFormat,
  220. GLenum format, GLenum type, U32 samples, GlTextureHandle& rt)
  221. {
  222. // Not very important but keep the resulution of render targets aligned to
  223. // 16
  224. ANKI_ASSERT(isAligned(16, w));
  225. ANKI_ASSERT(isAligned(16, h));
  226. GlTextureHandle::Initializer init;
  227. init.m_width = w;
  228. init.m_height = h;
  229. init.m_depth = 0;
  230. #if ANKI_GL == ANKI_GL_DESKTOP
  231. init.m_target = (samples == 1) ? GL_TEXTURE_2D : GL_TEXTURE_2D_MULTISAMPLE;
  232. #else
  233. ANKI_ASSERT(samples == 1);
  234. init.m_target = GL_TEXTURE_2D;
  235. #endif
  236. init.m_internalFormat = internalFormat;
  237. init.m_format = format;
  238. init.m_type = type;
  239. init.m_mipmapsCount = 1;
  240. init.m_filterType = GlTextureHandle::Filter::NEAREST;
  241. init.m_repeat = false;
  242. init.m_anisotropyLevel = 0;
  243. init.m_genMipmaps = false;
  244. init.m_samples = samples;
  245. GlManager& gl = GlManagerSingleton::get();
  246. GlJobChainHandle jobs(&gl);
  247. rt = GlTextureHandle(jobs, init);
  248. jobs.finish();
  249. }
  250. //==============================================================================
  251. GlProgramPipelineHandle Renderer::createDrawQuadProgramPipeline(
  252. GlProgramHandle frag)
  253. {
  254. GlManager& gl = GlManagerSingleton::get();
  255. GlJobChainHandle jobs(&gl);
  256. Array<GlProgramHandle, 2> progs = {{m_drawQuadVert->getGlProgram(), frag}};
  257. GlProgramPipelineHandle ppline(jobs, &progs[0], &progs[0] + 2);
  258. jobs.finish();
  259. return ppline;
  260. }
  261. } // end namespace anki