VolumetricFogRTManager.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. //-----------------------------------------------------------------------------
  23. // Volumetric Fog Rendertarget Manager
  24. //
  25. // Creates and maintains one set of rendertargets to be used by every
  26. // VolumetricFog object in the scene.
  27. //
  28. // Will be loaded at startup end removed when ending game.
  29. //
  30. //-----------------------------------------------------------------------------
  31. #include "VolumetricFogRTManager.h"
  32. #include "core/module.h"
  33. #include "scene/sceneManager.h"
  34. #include "windowManager/platformWindowMgr.h"
  35. #include "console/engineAPI.h"
  36. #include "gui/core/guiCanvas.h"
  37. #include "gfx/gfxDevice.h"
  38. MODULE_BEGIN(VolumetricFogRTManager)
  39. MODULE_INIT_AFTER(Scene)
  40. MODULE_SHUTDOWN_BEFORE(Scene)
  41. MODULE_INIT
  42. {
  43. gVolumetricFogRTManager = new VolumetricFogRTManager;
  44. gClientSceneGraph->addObjectToScene(gVolumetricFogRTManager);
  45. }
  46. MODULE_SHUTDOWN
  47. {
  48. gClientSceneGraph->removeObjectFromScene(gVolumetricFogRTManager);
  49. SAFE_DELETE(gVolumetricFogRTManager);
  50. }
  51. MODULE_END;
  52. ConsoleDocClass( VolumetricFogRTManager,
  53. "@brief Creates and maintains one set of rendertargets to be used by every\n"
  54. "VolumetricFog object in the scene.\n\n"
  55. "Will be loaded at startup end removed when ending game.\n\n"
  56. "Methods:\n"
  57. " get() returns the currently loaded VolumetricFogRTManager, also accessible\n"
  58. " through VFRTM define.\n"
  59. " Init() Initializes the rendertargets, called when a VolumetricFog object is\n"
  60. " added to the scene.\n"
  61. " isInitialed() returns true if Rendertargets are present, false if not, then\n"
  62. " Init() should be called to create the rendertargets.\n"
  63. " setQuality(U32 Quality) Normally a rendertarget has the same size as the view,\n"
  64. " with this method you can scale down the size of it.\n"
  65. " Be aware that scaling down will introduce renderartefacts.\n"
  66. "@ingroup Atmosphere"
  67. );
  68. VolumetricFogRTMResizeSignal VolumetricFogRTManager::smVolumetricFogRTMResizeSignal;
  69. VolumetricFogRTManager *gVolumetricFogRTManager = NULL;
  70. S32 VolumetricFogRTManager::mTargetScale = 1;
  71. IMPLEMENT_CONOBJECT(VolumetricFogRTManager);
  72. VolumetricFogRTManager::VolumetricFogRTManager()
  73. {
  74. setGlobalBounds();
  75. mTypeMask |= EnvironmentObjectType;
  76. mNetFlags.set(IsGhost);
  77. mPlatformWindow = NULL;
  78. mIsInitialized = false;
  79. mNumFogObjects = 0;
  80. mWidth = 0;
  81. mHeight = 0;
  82. }
  83. VolumetricFogRTManager::~VolumetricFogRTManager()
  84. {
  85. if (mFrontTarget.isRegistered())
  86. mFrontTarget.unregister();
  87. if (mDepthTarget.isRegistered())
  88. mDepthTarget.unregister();
  89. if (mDepthBuffer.isValid())
  90. mDepthBuffer->kill();
  91. if (mFrontBuffer.isValid())
  92. mFrontBuffer->kill();
  93. }
  94. void VolumetricFogRTManager::onSceneRemove()
  95. {
  96. if (mIsInitialized)
  97. mPlatformWindow->resizeEvent.remove(this, &VolumetricFogRTManager::ResizeRT);
  98. }
  99. void VolumetricFogRTManager::onRemove()
  100. {
  101. removeFromScene();
  102. Parent::onRemove();
  103. }
  104. void VolumetricFogRTManager::consoleInit()
  105. {
  106. Con::addVariable("$pref::VolumetricFog::Quality", TypeS32, &mTargetScale,
  107. "The scale of the rendertargets.\n"
  108. "@ingroup Rendering\n");
  109. }
  110. bool VolumetricFogRTManager::Init()
  111. {
  112. if (mIsInitialized)
  113. {
  114. Con::errorf("VolumetricFogRTManager allready initialized!!");
  115. return true;
  116. }
  117. if (GFX->getAdapterType() == NullDevice)
  118. {
  119. mIsInitialized = true;
  120. Con::errorf("VolumetricFogRTManager - Dedicated server");
  121. return true;
  122. }
  123. GuiCanvas* cv = dynamic_cast<GuiCanvas*>(Sim::findObject("Canvas"));
  124. if (cv == NULL)
  125. {
  126. Con::errorf("VolumetricFogRTManager::Init() - Canvas not found!!");
  127. return false;
  128. }
  129. mPlatformWindow = cv->getPlatformWindow();
  130. mPlatformWindow->resizeEvent.notify(this,&VolumetricFogRTManager::ResizeRT);
  131. if (mTargetScale < 1 || GFX->getAdapterType() == Direct3D11)
  132. mTargetScale = 1;
  133. mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale);
  134. mHeight = mFloor(mPlatformWindow->getClientExtent().y / mTargetScale);
  135. mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
  136. &GFXRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__));
  137. if (!mDepthBuffer.isValid())
  138. {
  139. Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create Depthbuffer");
  140. return false;
  141. }
  142. if (!mDepthTarget.registerWithName("volfogdepth"))
  143. {
  144. Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Depthbuffer");
  145. return false;
  146. }
  147. mDepthTarget.setTexture(mDepthBuffer);
  148. mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
  149. &GFXRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__));
  150. if (!mFrontBuffer.isValid())
  151. {
  152. Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create front buffer");
  153. return false;
  154. }
  155. if (!mFrontTarget.registerWithName("volfogfront"))
  156. {
  157. Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Frontbuffer");
  158. return false;
  159. }
  160. mFrontTarget.setTexture(mFrontBuffer);
  161. Con::setVariable("$VolumetricFog::density", "0.0");
  162. mIsInitialized = true;
  163. return true;
  164. }
  165. U32 VolumetricFogRTManager::IncFogObjects()
  166. {
  167. mNumFogObjects++;
  168. return mNumFogObjects;
  169. }
  170. U32 VolumetricFogRTManager::DecFogObjects()
  171. {
  172. if (mNumFogObjects > 0)
  173. mNumFogObjects--;
  174. return mNumFogObjects;
  175. }
  176. void VolumetricFogRTManager::ResizeRT( WindowId did, S32 width, S32 height )
  177. {
  178. smVolumetricFogRTMResizeSignal.trigger(this, true);
  179. }
  180. void VolumetricFogRTManager::FogAnswered()
  181. {
  182. if (Resize())
  183. smVolumetricFogRTMResizeSignal.trigger(this, false);
  184. else
  185. Con::errorf("VolumetricFogRTManager::FogAnswered - Error resizing rendertargets!");
  186. }
  187. bool VolumetricFogRTManager::Resize()
  188. {
  189. if (mTargetScale < 1 || GFX->getAdapterType() == Direct3D11)
  190. mTargetScale = 1;
  191. mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale);
  192. mHeight = mFloor(mPlatformWindow->getClientExtent().y / mTargetScale);
  193. if (mWidth < 16 || mHeight < 16)
  194. return false;
  195. if (mFrontTarget.isRegistered())
  196. mFrontTarget.setTexture(NULL);
  197. if (mDepthTarget.isRegistered())
  198. mDepthTarget.setTexture(NULL);
  199. if (mDepthBuffer.isValid())
  200. mDepthBuffer->kill();
  201. if (mFrontBuffer.isValid())
  202. mFrontBuffer->kill();
  203. mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
  204. &GFXRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__));
  205. if (!mFrontBuffer.isValid())
  206. {
  207. Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create front buffer");
  208. return false;
  209. }
  210. mFrontTarget.setTexture(mFrontBuffer);
  211. mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
  212. &GFXRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__));
  213. if (!mDepthBuffer.isValid())
  214. {
  215. Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create Depthbuffer");
  216. return false;
  217. }
  218. mDepthTarget.setTexture(mDepthBuffer);
  219. return true;
  220. }
  221. S32 VolumetricFogRTManager::setQuality(U32 Quality)
  222. {
  223. if (!mIsInitialized)
  224. return (mTargetScale = Quality);
  225. if (Quality < 1)
  226. Quality = 1;
  227. if (Quality == mTargetScale)
  228. return mTargetScale;
  229. mTargetScale = Quality;
  230. smVolumetricFogRTMResizeSignal.trigger(this, true);
  231. return mTargetScale;
  232. }
  233. VolumetricFogRTManager* VolumetricFogRTManager::get()
  234. {
  235. return gVolumetricFogRTManager;
  236. }
  237. DefineEngineFunction(SetFogVolumeQuality, S32, (U32 new_quality), ,
  238. "@brief Resizes the rendertargets of the Volumetric Fog object.\n"
  239. "@params new_quality new quality for the rendertargets 1 = full size, 2 = halfsize, 3 = 1/3, 4 = 1/4 ...")
  240. {
  241. if (VFRTM == NULL)
  242. return -1;
  243. return VFRTM->setQuality(new_quality);
  244. }