BsRenderTargets.cpp 7.0 KB

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