BsRenderTargets.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #include "BsRenderTargets.h"
  2. #include "BsRenderTexturePool.h"
  3. #include "BsViewport.h"
  4. #include "BsRenderAPI.h"
  5. #include "BsTextureManager.h"
  6. #include "BsRendererUtility.h"
  7. namespace BansheeEngine
  8. {
  9. RenderTargets::RenderTargets(const SPtr<ViewportCore>& viewport, bool hdr, UINT32 numSamples)
  10. :mNumSamples(numSamples), mHDR(hdr), mViewport(viewport)
  11. {
  12. if (hdr)
  13. mDiffuseFormat = PF_FLOAT_R11G11B10;
  14. else
  15. mDiffuseFormat = PF_B8G8R8X8;
  16. mNormalFormat = PF_UNORM_R10G10B10A2;
  17. }
  18. SPtr<RenderTargets> RenderTargets::create(const SPtr<ViewportCore>& viewport, bool hdr, UINT32 numSamples)
  19. {
  20. return bs_shared_ptr<RenderTargets>(new (bs_alloc<RenderTargets>()) RenderTargets(viewport, hdr, numSamples));
  21. }
  22. void RenderTargets::allocate()
  23. {
  24. RenderTexturePool& texPool = RenderTexturePool::instance();
  25. UINT32 width = getWidth();
  26. UINT32 height = getHeight();
  27. SPtr<PooledRenderTexture> newAlbedoRT = texPool.get(mDiffuseFormat, width, height, false, mNumSamples);
  28. SPtr<PooledRenderTexture> newNormalRT = texPool.get(mNormalFormat, width, height, false, mNumSamples);
  29. SPtr<PooledRenderTexture> newDepthRT = texPool.get(PF_D24S8, width, height, false, mNumSamples);
  30. SPtr<PooledRenderTexture> newColorRT = nullptr;
  31. // See if I can use the final output color target for gbuffer rendering, this saves a little memory
  32. SPtr<RenderTargetCore> resolvedRT = mViewport->getTarget();
  33. const RenderTargetProperties& resolvedRTProps = resolvedRT->getProperties();
  34. bool useResolvedColor = !resolvedRTProps.isWindow() &&
  35. mViewport->getWidth() == getWidth() &&
  36. mViewport->getHeight() == getHeight() &&
  37. ((resolvedRTProps.getMultisampleCount() <= 1) == (mNumSamples <= 1) ||
  38. resolvedRTProps.getMultisampleCount() == mNumSamples);
  39. if (!useResolvedColor)
  40. newColorRT = texPool.get(PF_B8G8R8X8, width, height, false, mNumSamples);
  41. bool rebuildTargets = newColorRT != mSceneColorTex || newAlbedoRT != mAlbedoTex || newNormalRT != mNormalTex || newDepthRT != mDepthTex;
  42. mSceneColorTex = newColorRT;
  43. mAlbedoTex = newAlbedoRT;
  44. mNormalTex = newNormalRT;
  45. mDepthTex = newDepthRT;
  46. if (mGBufferRT == nullptr || mSceneColorRT == nullptr || rebuildTargets)
  47. {
  48. MULTI_RENDER_TEXTURE_CORE_DESC gbufferDesc;
  49. gbufferDesc.colorSurfaces.resize(3);
  50. SPtr<TextureCore> sceneColorTex = nullptr;
  51. if (newColorRT != nullptr)
  52. sceneColorTex = newColorRT->texture;
  53. else // Re-using output scene color texture
  54. {
  55. SPtr<RenderTextureCore> resolvedRTex = std::static_pointer_cast<RenderTextureCore>(resolvedRT);
  56. sceneColorTex = resolvedRTex->getBindableColorTexture();
  57. }
  58. gbufferDesc.colorSurfaces[0].texture = sceneColorTex;
  59. gbufferDesc.colorSurfaces[0].face = 0;
  60. gbufferDesc.colorSurfaces[0].mipLevel = 0;
  61. gbufferDesc.colorSurfaces[1].texture = mAlbedoTex->texture;
  62. gbufferDesc.colorSurfaces[1].face = 0;
  63. gbufferDesc.colorSurfaces[1].mipLevel = 0;
  64. gbufferDesc.colorSurfaces[2].texture = mNormalTex->texture;
  65. gbufferDesc.colorSurfaces[2].face = 0;
  66. gbufferDesc.colorSurfaces[2].mipLevel = 0;
  67. gbufferDesc.depthStencilSurface.texture = mDepthTex->texture;
  68. gbufferDesc.depthStencilSurface.face = 0;
  69. gbufferDesc.depthStencilSurface.mipLevel = 0;
  70. mGBufferRT = TextureCoreManager::instance().createMultiRenderTexture(gbufferDesc);
  71. RENDER_TEXTURE_CORE_DESC sceneColorDesc;
  72. sceneColorDesc.colorSurface.texture = sceneColorTex;
  73. sceneColorDesc.colorSurface.face = 0;
  74. sceneColorDesc.colorSurface.mipLevel = 0;
  75. sceneColorDesc.depthStencilSurface.texture = mDepthTex->texture;
  76. sceneColorDesc.depthStencilSurface.face = 0;
  77. sceneColorDesc.depthStencilSurface.mipLevel = 0;
  78. mSceneColorRT = TextureCoreManager::instance().createRenderTexture(sceneColorDesc);
  79. }
  80. }
  81. void RenderTargets::release()
  82. {
  83. RenderAPICore& rapi = RenderAPICore::instance();
  84. rapi.setRenderTarget(nullptr);
  85. RenderTexturePool& texPool = RenderTexturePool::instance();
  86. if (mSceneColorTex != nullptr)
  87. texPool.release(mSceneColorTex);
  88. texPool.release(mAlbedoTex);
  89. texPool.release(mNormalTex);
  90. texPool.release(mDepthTex);
  91. }
  92. void RenderTargets::bindGBuffer()
  93. {
  94. RenderAPICore& rapi = RenderAPICore::instance();
  95. rapi.setRenderTarget(mGBufferRT);
  96. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  97. rapi.setViewport(area);
  98. UINT32 clearBuffers = 0;
  99. if (mViewport->getRequiresColorClear())
  100. clearBuffers |= FBT_COLOR;
  101. if (mViewport->getRequiresDepthClear())
  102. clearBuffers |= FBT_DEPTH;
  103. if (mViewport->getRequiresStencilClear())
  104. clearBuffers |= FBT_STENCIL;
  105. // Clear scene color, depth, stencil according to user defined values
  106. if (clearBuffers != 0)
  107. {
  108. RenderAPICore::instance().clearViewport(clearBuffers, mViewport->getClearColor(),
  109. mViewport->getClearDepthValue(), mViewport->getClearStencilValue(), 0x01);
  110. }
  111. // Clear all others
  112. RenderAPICore::instance().clearViewport(FBT_COLOR, Color::ZERO, 1.0f, 0, 0xFF & ~0x01);
  113. }
  114. void RenderTargets::bindSceneColor(bool readOnlyDepthStencil)
  115. {
  116. RenderAPICore& rapi = RenderAPICore::instance();
  117. rapi.setRenderTarget(mSceneColorRT, readOnlyDepthStencil);
  118. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  119. rapi.setViewport(area);
  120. }
  121. void RenderTargets::resolve()
  122. {
  123. // Prepare final render target
  124. SPtr<RenderTargetCore> target = mViewport->getTarget();
  125. RenderAPICore::instance().setRenderTarget(target);
  126. RenderAPICore::instance().setViewport(mViewport->getNormArea());
  127. // If using a separate scene color texture clear the final render target
  128. if (mSceneColorTex == nullptr)
  129. {
  130. // Do nothing as final render target is already our scene color target
  131. }
  132. else
  133. {
  134. UINT32 clearBuffers = 0;
  135. if (mViewport->getRequiresColorClear())
  136. clearBuffers |= FBT_COLOR;
  137. if (mViewport->getRequiresDepthClear())
  138. clearBuffers |= FBT_DEPTH;
  139. if (mViewport->getRequiresStencilClear())
  140. clearBuffers |= FBT_STENCIL;
  141. if (clearBuffers != 0)
  142. {
  143. RenderAPICore::instance().clearViewport(clearBuffers, mViewport->getClearColor(),
  144. mViewport->getClearDepthValue(), mViewport->getClearStencilValue());
  145. }
  146. // TODO - Merge this blit into some post-processing shader, no reason for it to be on its own
  147. gRendererUtility().blit(mSceneColorTex->texture);
  148. }
  149. }
  150. SPtr<TextureCore> RenderTargets::getTextureA() const
  151. {
  152. return mAlbedoTex->texture;
  153. }
  154. SPtr<TextureCore> RenderTargets::getTextureB() const
  155. {
  156. return mNormalTex->texture;
  157. }
  158. SPtr<TextureCore> RenderTargets::getTextureDepth() const
  159. {
  160. return mDepthTex->texture;
  161. }
  162. UINT32 RenderTargets::getWidth() const
  163. {
  164. return (UINT32)mViewport->getWidth();
  165. }
  166. UINT32 RenderTargets::getHeight() const
  167. {
  168. return (UINT32)mViewport->getHeight();
  169. }
  170. }