BsRenderTargets.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. :mViewport(viewport), mNumSamples(numSamples), mHDR(hdr)
  13. {
  14. // Note: Consider customizable HDR format via options? e.g. smaller PF_FLOAT_R11G11B10 or larger 32-bit format
  15. mSceneColorFormat = hdr ? PF_FLOAT16_RGBA : PF_B8G8R8A8;
  16. mAlbedoFormat = PF_B8G8R8X8; // Note: Also consider customizable format (e.g. 16-bit float?)
  17. mNormalFormat = PF_UNORM_R10G10B10A2; // Note: Also consider customizable format (e.g. 16-bit float?)
  18. }
  19. SPtr<RenderTargets> RenderTargets::create(const SPtr<ViewportCore>& viewport, bool hdr, UINT32 numSamples)
  20. {
  21. return bs_shared_ptr<RenderTargets>(new (bs_alloc<RenderTargets>()) RenderTargets(viewport, hdr, numSamples));
  22. }
  23. void RenderTargets::allocate()
  24. {
  25. RenderTexturePool& texPool = RenderTexturePool::instance();
  26. UINT32 width = getWidth();
  27. UINT32 height = getHeight();
  28. // Note: Albedo is allocated as SRGB, meaning when reading from textures during depth pass we decode from sRGB into linear,
  29. // then back into sRGB when writing to albedo, and back to linear when reading from albedo during light pass. This /might/ have
  30. // a performance impact. In which case we could just use a higher precision albedo buffer, which can then store linear color
  31. // directly (storing linear in 8bit buffer causes too much detail to be lost in the blacks).
  32. SPtr<PooledRenderTexture> newColorRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mSceneColorFormat, width, height, TU_RENDERTARGET,
  33. mNumSamples, false));
  34. SPtr<PooledRenderTexture> newAlbedoRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mAlbedoFormat, width,
  35. height, TU_RENDERTARGET, mNumSamples, true));
  36. SPtr<PooledRenderTexture> newNormalRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mNormalFormat, width,
  37. height, TU_RENDERTARGET, mNumSamples, false));
  38. SPtr<PooledRenderTexture> newDepthRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_D24S8, width, height,
  39. TU_DEPTHSTENCIL, mNumSamples, false));
  40. bool rebuildTargets = newColorRT != mSceneColorTex || newAlbedoRT != mAlbedoTex || newNormalRT != mNormalTex || newDepthRT != mDepthTex;
  41. mSceneColorTex = newColorRT;
  42. mAlbedoTex = newAlbedoRT;
  43. mNormalTex = newNormalRT;
  44. mDepthTex = newDepthRT;
  45. if (mGBufferRT == nullptr || mSceneColorRT == nullptr || rebuildTargets)
  46. {
  47. MULTI_RENDER_TEXTURE_CORE_DESC gbufferDesc;
  48. gbufferDesc.colorSurfaces.resize(3);
  49. gbufferDesc.colorSurfaces[0].texture = mSceneColorTex->texture;
  50. gbufferDesc.colorSurfaces[0].face = 0;
  51. gbufferDesc.colorSurfaces[0].numFaces = 1;
  52. gbufferDesc.colorSurfaces[0].mipLevel = 0;
  53. gbufferDesc.colorSurfaces[1].texture = mAlbedoTex->texture;
  54. gbufferDesc.colorSurfaces[1].face = 0;
  55. gbufferDesc.colorSurfaces[1].numFaces = 1;
  56. gbufferDesc.colorSurfaces[1].mipLevel = 0;
  57. gbufferDesc.colorSurfaces[2].texture = mNormalTex->texture;
  58. gbufferDesc.colorSurfaces[2].face = 0;
  59. gbufferDesc.colorSurfaces[2].numFaces = 1;
  60. gbufferDesc.colorSurfaces[2].mipLevel = 0;
  61. gbufferDesc.depthStencilSurface.texture = mDepthTex->texture;
  62. gbufferDesc.depthStencilSurface.face = 0;
  63. gbufferDesc.depthStencilSurface.mipLevel = 0;
  64. mGBufferRT = TextureCoreManager::instance().createMultiRenderTexture(gbufferDesc);
  65. RENDER_TEXTURE_CORE_DESC sceneColorDesc;
  66. sceneColorDesc.colorSurface.texture = mSceneColorTex->texture;
  67. sceneColorDesc.colorSurface.face = 0;
  68. sceneColorDesc.colorSurface.numFaces = 1;
  69. sceneColorDesc.colorSurface.mipLevel = 0;
  70. sceneColorDesc.depthStencilSurface.texture = mDepthTex->texture;
  71. sceneColorDesc.depthStencilSurface.face = 0;
  72. sceneColorDesc.depthStencilSurface.numFaces = 1;
  73. sceneColorDesc.depthStencilSurface.mipLevel = 0;
  74. mSceneColorRT = TextureCoreManager::instance().createRenderTexture(sceneColorDesc);
  75. }
  76. }
  77. void RenderTargets::release()
  78. {
  79. RenderAPICore& rapi = RenderAPICore::instance();
  80. rapi.setRenderTarget(nullptr);
  81. RenderTexturePool& texPool = RenderTexturePool::instance();
  82. texPool.release(mSceneColorTex);
  83. texPool.release(mAlbedoTex);
  84. texPool.release(mNormalTex);
  85. texPool.release(mDepthTex);
  86. }
  87. void RenderTargets::bindGBuffer()
  88. {
  89. RenderAPICore& rapi = RenderAPICore::instance();
  90. rapi.setRenderTarget(mGBufferRT);
  91. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  92. rapi.setViewport(area);
  93. UINT32 clearBuffers = 0;
  94. if (mViewport->getRequiresColorClear())
  95. clearBuffers |= FBT_COLOR;
  96. if (mViewport->getRequiresDepthClear())
  97. clearBuffers |= FBT_DEPTH;
  98. if (mViewport->getRequiresStencilClear())
  99. clearBuffers |= FBT_STENCIL;
  100. // Clear scene color, depth, stencil according to user defined values
  101. if (clearBuffers != 0)
  102. {
  103. RenderAPICore::instance().clearViewport(clearBuffers, mViewport->getClearColor(),
  104. mViewport->getClearDepthValue(), mViewport->getClearStencilValue(), 0x01);
  105. }
  106. // Clear all others
  107. RenderAPICore::instance().clearViewport(FBT_COLOR, Color::ZERO, 1.0f, 0, 0xFF & ~0x01);
  108. }
  109. void RenderTargets::bindSceneColor(bool readOnlyDepthStencil)
  110. {
  111. RenderAPICore& rapi = RenderAPICore::instance();
  112. rapi.setRenderTarget(mSceneColorRT, readOnlyDepthStencil);
  113. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  114. rapi.setViewport(area);
  115. }
  116. SPtr<TextureCore> RenderTargets::getTextureA() const
  117. {
  118. return mAlbedoTex->texture;
  119. }
  120. SPtr<TextureCore> RenderTargets::getTextureB() const
  121. {
  122. return mNormalTex->texture;
  123. }
  124. SPtr<TextureCore> RenderTargets::getTextureDepth() const
  125. {
  126. return mDepthTex->texture;
  127. }
  128. UINT32 RenderTargets::getWidth() const
  129. {
  130. return (UINT32)mViewport->getWidth();
  131. }
  132. UINT32 RenderTargets::getHeight() const
  133. {
  134. return (UINT32)mViewport->getHeight();
  135. }
  136. }