renderProbeMgr.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  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. #include "renderProbeMgr.h"
  23. #include "math/util/sphereMesh.h"
  24. #include "math/util/matrixSet.h"
  25. #include "renderInstance/renderDeferredMgr.h"
  26. #include "math/mPolyhedron.impl.h"
  27. #include "gfx/gfxTransformSaver.h"
  28. #include "lighting/advanced/advancedLightBinManager.h" //for ssao
  29. #include "gfx/gfxDebugEvent.h"
  30. #include "shaderGen/shaderGenVars.h"
  31. #include "materials/shaderData.h"
  32. #include "scene/reflectionManager.h"
  33. #include "postFx/postEffect.h"
  34. #include "T3D/lighting/reflectionProbe.h"
  35. #include "T3D/lighting/IBLUtilities.h"
  36. #include "T3D/Scene.h"
  37. //For our cameraQuery setup
  38. #include "T3D/gameTSCtrl.h"
  39. #define TORQUE_GFX_VISUAL_DEBUG //renderdoc debugging
  40. IMPLEMENT_CONOBJECT(RenderProbeMgr);
  41. ConsoleDocClass( RenderProbeMgr,
  42. "@brief This render bin handles the rendering of reflection probes to provide IBL\n"
  43. "lighting for PBR\n\n"
  44. "Probes when added to the scene, are registered to the Manager, and then during the steps\n"
  45. "leading up to the frame being rendered, the probes submit to the Manager that they are ready to be rendered\n"
  46. "resulting in them being added to the active list.\n"
  47. "When the manager is invoked to render, it processes the active probe list and finds the best probes based on\n"
  48. "settings like max probes per frame, probe score, etc to get the final list of probes to be submitted to the shader.\n\n"
  49. "@ingroup RenderBin\n" );
  50. RenderProbeMgr *RenderProbeMgr::smProbeManager = NULL;
  51. // This variable is a global toggle on if reflection probes should be rendered or not
  52. bool RenderProbeMgr::smRenderReflectionProbes = true;
  53. bool RenderProbeMgr::smBakeReflectionProbes = false;
  54. // This variable defines the maximum draw distance of a probe.
  55. F32 RenderProbeMgr::smMaxProbeDrawDistance = 100;
  56. // This variable defines the maximum number of probes that can be rendered in a single frame in deferred
  57. S32 RenderProbeMgr::smMaxProbesPerFrame = 8;
  58. S32 RenderProbeMgr::smProbeBakeResolution = 64;
  59. //
  60. //
  61. ProbeRenderInst::ProbeRenderInst() :
  62. mCubemapIndex(0),
  63. mProbeInfo(nullptr)
  64. {
  65. }
  66. ProbeRenderInst::~ProbeRenderInst()
  67. {
  68. }
  69. void ProbeRenderInst::set(const ProbeRenderInst *probe)
  70. {
  71. mCubemapIndex = probe->mCubemapIndex;
  72. mProbeInfo = probe->mProbeInfo;
  73. }
  74. //
  75. //
  76. ProbeShaderConstants::ProbeShaderConstants()
  77. : mInit(false),
  78. mShader(NULL),
  79. mProbePositionArraySC(NULL),
  80. mProbeRefPosArraySC(NULL),
  81. mRefScaleArraySC(NULL),
  82. mProbeConfigDataArraySC(NULL),
  83. mProbeSpecularCubemapArraySC(NULL),
  84. mProbeIrradianceCubemapArraySC(NULL),
  85. mProbeCountSC(NULL),
  86. mBRDFTextureMap(NULL),
  87. mWetnessTextureMap(NULL),
  88. mSkylightCubemapIdxSC(NULL),
  89. mSkylightDampSC(NULL),
  90. mWorldToObjArraySC(NULL),
  91. mMaxProbeDrawDistanceSC(NULL)
  92. {
  93. }
  94. ProbeShaderConstants::~ProbeShaderConstants()
  95. {
  96. if (mShader.isValid())
  97. {
  98. mShader->getReloadSignal().remove(this, &ProbeShaderConstants::_onShaderReload);
  99. mShader = NULL;
  100. }
  101. }
  102. void ProbeShaderConstants::init(GFXShader* shader)
  103. {
  104. if (mShader.getPointer() != shader)
  105. {
  106. if (mShader.isValid())
  107. mShader->getReloadSignal().remove(this, &ProbeShaderConstants::_onShaderReload);
  108. mShader = shader;
  109. mShader->getReloadSignal().notify(this, &ProbeShaderConstants::_onShaderReload);
  110. }
  111. //Reflection Probes
  112. mProbePositionArraySC = shader->getShaderConstHandle(ShaderGenVars::probePositionArray);
  113. mProbeRefPosArraySC = shader->getShaderConstHandle(ShaderGenVars::probeRefPosArray);
  114. mRefScaleArraySC = shader->getShaderConstHandle(ShaderGenVars::refScaleArray);
  115. mWorldToObjArraySC = shader->getShaderConstHandle(ShaderGenVars::worldToObjArray);
  116. mProbeConfigDataArraySC = shader->getShaderConstHandle(ShaderGenVars::probeConfigDataArray);
  117. mProbeSpecularCubemapArraySC = shader->getShaderConstHandle(ShaderGenVars::specularCubemapAR);
  118. mProbeIrradianceCubemapArraySC = shader->getShaderConstHandle(ShaderGenVars::irradianceCubemapAR);
  119. mProbeCountSC = shader->getShaderConstHandle(ShaderGenVars::probeCount);
  120. mBRDFTextureMap = shader->getShaderConstHandle(ShaderGenVars::BRDFTextureMap);
  121. mWetnessTextureMap = shader->getShaderConstHandle(ShaderGenVars::WetnessTextureMap);
  122. mSkylightCubemapIdxSC = shader->getShaderConstHandle(ShaderGenVars::skylightCubemapIdx);
  123. mSkylightDampSC = shader->getShaderConstHandle(ShaderGenVars::skylightDamp);
  124. mMaxProbeDrawDistanceSC = shader->getShaderConstHandle(ShaderGenVars::maxProbeDrawDistance);
  125. mInit = true;
  126. }
  127. bool ProbeShaderConstants::isValid()
  128. {
  129. if (mProbePositionArraySC->isValid() &&
  130. mProbeConfigDataArraySC->isValid() &&
  131. mRefScaleArraySC->isValid() &&
  132. mProbeSpecularCubemapArraySC->isValid() &&
  133. mProbeIrradianceCubemapArraySC->isValid())
  134. return true;
  135. return false;
  136. }
  137. void ProbeShaderConstants::_onShaderReload()
  138. {
  139. if (mShader.isValid())
  140. init(mShader);
  141. }
  142. //
  143. //
  144. RenderProbeMgr::RenderProbeMgr()
  145. : RenderBinManager(RenderPassManager::RIT_Probes, 1.0f, 1.0f),
  146. mLastShader(nullptr),
  147. mLastConstants(nullptr),
  148. mHasSkylight(false),
  149. mSkylightCubemapIdx(-1),
  150. mSkylightDamp(true),
  151. mCubeMapCount(0),
  152. mUseHDRCaptures(true)
  153. {
  154. mEffectiveProbeCount = 0;
  155. mMipCount = 0;
  156. mProbeArrayEffect = nullptr;
  157. smProbeManager = this;
  158. mCubeMapCount = 0;
  159. mCubeSlotCount = PROBE_ARRAY_SLOT_BUFFER_SIZE;
  160. for (U32 i = 0; i < PROBE_MAX_COUNT; i++)
  161. {
  162. mCubeMapSlots[i] = false;
  163. }
  164. }
  165. RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder)
  166. : RenderBinManager(riType, renderOrder, processAddOrder)
  167. {
  168. mCubeMapCount = 0;
  169. dMemset(mCubeMapSlots, false, sizeof(mCubeMapSlots));
  170. mCubeSlotCount = PROBE_ARRAY_SLOT_BUFFER_SIZE;
  171. mEffectiveProbeCount = 0;
  172. mHasSkylight = false;
  173. mSkylightCubemapIdx = -1;
  174. mSkylightDamp = true;
  175. mLastConstants = nullptr;
  176. mMipCount = 0;
  177. mUseHDRCaptures = true;
  178. }
  179. RenderProbeMgr::~RenderProbeMgr()
  180. {
  181. mLastShader = NULL;
  182. mLastConstants = NULL;
  183. for (ProbeConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++)
  184. {
  185. if (i->value)
  186. SAFE_DELETE(i->value);
  187. }
  188. mConstantLookup.clear();
  189. }
  190. bool RenderProbeMgr::onAdd()
  191. {
  192. if (!Parent::onAdd())
  193. return false;
  194. mIrradianceArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
  195. mPrefilterArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
  196. U32 scaledSize = getProbeTexSize();
  197. //pre-allocate a few slots
  198. mIrradianceArray->init(PROBE_ARRAY_SLOT_BUFFER_SIZE, scaledSize, PROBE_FORMAT);
  199. mPrefilterArray->init(PROBE_ARRAY_SLOT_BUFFER_SIZE, scaledSize, PROBE_FORMAT);
  200. mCubeSlotCount = PROBE_ARRAY_SLOT_BUFFER_SIZE;
  201. String brdfTexturePath = GFXTextureManager::getBRDFTexturePath();
  202. if (!mBRDFTexture.set(brdfTexturePath, &GFXTexturePersistentSRGBProfile, "BRDFTexture"))
  203. {
  204. Con::errorf("RenderProbeMgr::onAdd: Failed to load BRDF Texture");
  205. return false;
  206. }
  207. String wetnessTexturePath = GFXTextureManager::getWetnessTexturePath();
  208. if (!mWetnessTexture.set(wetnessTexturePath, &GFXTexturePersistentProfile, "WetnessTexture"))
  209. {
  210. Con::errorf("RenderProbeMgr::onAdd: Failed to load Wetness Texture");
  211. return false;
  212. }
  213. return true;
  214. }
  215. void RenderProbeMgr::onRemove()
  216. {
  217. Parent::onRemove();
  218. }
  219. void RenderProbeMgr::initPersistFields()
  220. {
  221. docsURL;
  222. Parent::initPersistFields();
  223. }
  224. void RenderProbeMgr::consoleInit()
  225. {
  226. Parent::consoleInit();
  227. // Vars for debug rendering while the RoadEditor is open, only used if smEditorOpen is true.
  228. Con::addVariable("$pref::maxProbeDrawDistance", TypeF32, &RenderProbeMgr::smMaxProbeDrawDistance, "Max distance for reflection probes to render.\n");
  229. Con::addVariable("$pref::MaxProbesPerFrame", TypeS32, &RenderProbeMgr::smMaxProbesPerFrame, "Max number of Environment Probes that can be rendered per-frame.\n");
  230. Con::addVariable("$pref::ReflectionProbes::BakeResolution", TypeS32, &RenderProbeMgr::smProbeBakeResolution, "");
  231. }
  232. //=============================================================================
  233. // Utility functions for processing and setting up the probes for rendering
  234. //=============================================================================
  235. S32 QSORT_CALLBACK RenderProbeMgr::_probeScoreCmp(const ProbeRenderInst* a, const ProbeRenderInst* b)
  236. {
  237. F32 diff = a->mProbeInfo->mScore - b->mProbeInfo->mScore;
  238. return diff > 0 ? 1 : diff < 0 ? -1 : 0;
  239. }
  240. void RenderProbeMgr::getBestProbes(const Point3F& objPosition, ProbeDataSet* probeDataSet)
  241. {
  242. PROFILE_SCOPE(ProbeManager_getBestProbes);
  243. //Array rendering
  244. U32 probeCount = mActiveProbes.size();
  245. Vector<S8> bestPickProbes;
  246. bestPickProbes.setSize(probeDataSet->maxProbeCount);
  247. bestPickProbes.fill(-1);
  248. mHasSkylight = false;
  249. probeDataSet->skyLightIdx = -1;
  250. probeDataSet->effectiveProbeCount = 0;
  251. for (U32 i = 0; i < probeCount; i++)
  252. {
  253. //Check if we've already got a skylight. If we do and we've otherwise filled to our max amounto of probes alloewed, then bail
  254. if (mHasSkylight && probeDataSet->effectiveProbeCount >= probeDataSet->maxProbeCount)
  255. break;
  256. const ProbeRenderInst& curEntry = mActiveProbes[i];
  257. //Obviously, if the probe is marked as not enabled, we skip
  258. if (!curEntry.mProbeInfo->mIsEnabled)
  259. continue;
  260. if (curEntry.mProbeInfo->mProbeShapeType != ReflectionProbe::ProbeInfo::Skylight)
  261. {
  262. if (probeDataSet->effectiveProbeCount < probeDataSet->maxProbeCount)
  263. {
  264. bestPickProbes[probeDataSet->effectiveProbeCount] = i;
  265. probeDataSet->effectiveProbeCount++;
  266. }
  267. }
  268. else
  269. {
  270. probeDataSet->skyLightIdx = curEntry.mCubemapIndex;
  271. probeDataSet->skyLightDamp = curEntry.mProbeInfo->mCanDamp;
  272. mHasSkylight = true;
  273. }
  274. }
  275. //If we, for whatever reason, have nothing, bail now
  276. if (mHasSkylight == false && probeDataSet->effectiveProbeCount == 0)
  277. return;
  278. //Grab our best probe picks
  279. for (U32 i = 0; i < bestPickProbes.size(); i++)
  280. {
  281. if (bestPickProbes[i] == -1)
  282. continue;
  283. const ProbeRenderInst& curEntry = mActiveProbes[bestPickProbes[i]];
  284. probeDataSet->probeConfigArray[i] = Point4F(curEntry.mProbeInfo->mProbeShapeType,
  285. curEntry.mProbeInfo->mRadius,
  286. curEntry.mProbeInfo->mAtten,
  287. curEntry.mCubemapIndex);
  288. MatrixF p2A = curEntry.mProbeInfo->mTransform;
  289. probeDataSet->probeWorldToObjArray[i] = p2A;
  290. p2A.inverse();
  291. probeDataSet->refScaleArray[i] = curEntry.mProbeInfo->mProbeRefScale / (p2A.getScale()*2);
  292. probeDataSet->refScaleArray[i].w = curEntry.mProbeInfo->mCanDamp? 1.0 : 0.0;
  293. Point3F probePos = curEntry.mProbeInfo->mObject->getPosition();
  294. Point3F refPos = curEntry.mProbeInfo->mProbeRefOffset;
  295. probeDataSet->probePositionArray[i] = Point4F(probePos.x, probePos.y, probePos.z, 0);
  296. probeDataSet->probeRefPositionArray[i] = Point4F(refPos.x, refPos.y, refPos.z, 0);
  297. }
  298. }
  299. void RenderProbeMgr::registerProbe(ReflectionProbe::ProbeInfo* newProbe)
  300. {
  301. //Can't have over the probe limit
  302. if (mRegisteredProbes.size() + 1 >= PROBE_MAX_COUNT)
  303. return;
  304. ProbeRenderInst newProbeRenderInst;
  305. newProbeRenderInst.mProbeInfo = newProbe;
  306. const U32 cubeIndex = _findNextEmptyCubeSlot();
  307. if (cubeIndex == INVALID_CUBE_SLOT)
  308. {
  309. Con::warnf("RenderProbeMgr::registerProbe() - Invalid cubemap slot.");
  310. return;
  311. }
  312. //check if we need to resize the cubemap array
  313. if (cubeIndex >= mCubeSlotCount)
  314. {
  315. //alloc temp array handles
  316. GFXCubemapArrayHandle irr = GFXCubemapArrayHandle(GFX->createCubemapArray());
  317. GFXCubemapArrayHandle prefilter = GFXCubemapArrayHandle(GFX->createCubemapArray());
  318. U32 scaledSize = getProbeTexSize();
  319. irr->init(mCubeSlotCount + PROBE_ARRAY_SLOT_BUFFER_SIZE, scaledSize, PROBE_FORMAT);
  320. prefilter->init(mCubeSlotCount + PROBE_ARRAY_SLOT_BUFFER_SIZE, scaledSize, PROBE_FORMAT);
  321. mIrradianceArray->copyTo(irr);
  322. mPrefilterArray->copyTo(prefilter);
  323. //assign the temp handles to the new ones, this will destroy the old ones as well
  324. mIrradianceArray = irr;
  325. mPrefilterArray = prefilter;
  326. mCubeSlotCount += PROBE_ARRAY_SLOT_BUFFER_SIZE;
  327. }
  328. newProbeRenderInst.mCubemapIndex = cubeIndex;
  329. //mark cubemap slot as taken
  330. mCubeMapSlots[cubeIndex] = true;
  331. mCubeMapCount++;
  332. mRegisteredProbes.push_back(newProbeRenderInst);
  333. #ifdef TORQUE_DEBUG
  334. Con::warnf("RenderProbeMgr::registerProbe() - Registered probe %u to cubeIndex %u", newProbe->mObject->getId(), cubeIndex);
  335. #endif
  336. }
  337. void RenderProbeMgr::unregisterProbe(ReflectionProbe::ProbeInfo* probeInfo)
  338. {
  339. ProbeRenderInst* probe = findProbeInst(probeInfo);
  340. if (probe == nullptr)
  341. return;
  342. if (probe->mCubemapIndex == INVALID_CUBE_SLOT)
  343. return;
  344. //mark cubemap slot as available now
  345. mCubeMapSlots[probe->mCubemapIndex] = false;
  346. mCubeMapCount--;
  347. mRegisteredProbes.erase(probe);
  348. }
  349. void RenderProbeMgr::submitProbe(ReflectionProbe::ProbeInfo* probe)
  350. {
  351. ProbeRenderInst* probeInst = findProbeInst(probe);
  352. mActiveProbes.push_back(*probeInst);
  353. }
  354. PostEffect* RenderProbeMgr::getProbeArrayEffect()
  355. {
  356. if (!mProbeArrayEffect)
  357. {
  358. mProbeArrayEffect = dynamic_cast<PostEffect*>(Sim::findObject("reflectionProbeArrayPostFX"));
  359. if (!mProbeArrayEffect)
  360. return nullptr;
  361. mProbeArrayEffect->setShaderConst("$numProbes", (S32)0);
  362. mProbeArrayEffect->setShaderConst("$skylightCubemapIdx", (S32)-1);
  363. mProbeArrayEffect->setShaderConst(ShaderGenVars::skylightDamp, (S32)true);
  364. mProbeArrayEffect->setShaderConst("$cubeMips", (float)0);
  365. mProbeArrayEffect->setShaderConst("$maxProbeDrawDistance", smMaxProbeDrawDistance);
  366. }
  367. return mProbeArrayEffect;
  368. }
  369. U32 RenderProbeMgr::getProbeTexSize()
  370. {
  371. U32 scaledSize = RenderProbeMgr::smProbeBakeResolution;
  372. U32 downscalePower = 0;// GFXTextureManager::smTextureReductionLevel;
  373. if (downscalePower != 0)
  374. {
  375. // Otherwise apply the appropriate scale...
  376. scaledSize >>= downscalePower;
  377. }
  378. return scaledSize;
  379. }
  380. void RenderProbeMgr::updateProbeTexture(ReflectionProbe::ProbeInfo* probeInfo)
  381. {
  382. //If we don't have a registered probe, there's no point in updating the cubemap array for it
  383. ProbeRenderInst* probe = findProbeInst(probeInfo);
  384. if (probe == nullptr)
  385. return;
  386. U32 scaledSize = getProbeTexSize();
  387. //Some basic sanity checking that we have valid cubemaps to work with
  388. if (probeInfo->mIrradianceCubemap.isNull() || !probeInfo->mIrradianceCubemap->isInitialized() ||
  389. probeInfo->mIrradianceCubemap->getSize() != scaledSize)
  390. {
  391. Con::errorf("RenderProbeMgr::updateProbeTexture() - tried to update a probe's texture with an invalid or uninitialized irradiance map!");
  392. return;
  393. }
  394. if (probeInfo->mPrefilterCubemap.isNull() || !probeInfo->mPrefilterCubemap->isInitialized() ||
  395. probeInfo->mPrefilterCubemap->getSize() != scaledSize)
  396. {
  397. Con::errorf("RenderProbeMgr::updateProbeTexture() - tried to update a probe's texture with an invalid or uninitialized specular map!");
  398. return;
  399. }
  400. //Run the update on the array pair with the probe's cubemaps and index
  401. const U32 cubeIndex = probe->mCubemapIndex;
  402. mIrradianceArray->updateTexture(probeInfo->mIrradianceCubemap, cubeIndex);
  403. mPrefilterArray->updateTexture(probeInfo->mPrefilterCubemap, cubeIndex);
  404. #ifdef TORQUE_DEBUG
  405. Con::warnf("UpdatedProbeTexture - probe id: %u on cubeIndex %u, Irrad validity: %d, Prefilter validity: %d", probeInfo->mObject->getId(), cubeIndex,
  406. probeInfo->mIrradianceCubemap->isInitialized(), probeInfo->mPrefilterCubemap->isInitialized());
  407. #endif
  408. }
  409. void RenderProbeMgr::reloadTextures()
  410. {
  411. U32 probeCount = mRegisteredProbes.size();
  412. for (U32 i = 0; i < probeCount; i++)
  413. {
  414. updateProbeTexture(mRegisteredProbes[i].mProbeInfo);
  415. }
  416. }
  417. void RenderProbeMgr::preBake()
  418. {
  419. RenderProbeMgr::smBakeReflectionProbes = true;
  420. Con::setBoolVariable("$ReflectionProbes::Capturing", RenderProbeMgr::smBakeReflectionProbes);
  421. }
  422. void RenderProbeMgr::postBake()
  423. {
  424. RenderProbeMgr::smBakeReflectionProbes = false;
  425. Con::setBoolVariable("$ReflectionProbes::Capturing", RenderProbeMgr::smBakeReflectionProbes);
  426. }
  427. void RenderProbeMgr::bakeProbe(ReflectionProbe* probe)
  428. {
  429. GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
  430. Con::warnf("RenderProbeMgr::bakeProbe() - Beginning bake!");
  431. U32 startMSTime = Platform::getRealMilliseconds();
  432. String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
  433. U32 resolution = Con::getIntVariable("$pref::ReflectionProbes::BakeResolution", 64);
  434. U32 prefilterMipLevels = mLog2(F32(resolution)) + 1;
  435. bool renderWithProbes = Con::getIntVariable("$pref::ReflectionProbes::RenderWithProbes", false);
  436. ReflectionProbe* clientProbe = nullptr;
  437. if (probe->isServerObject())
  438. clientProbe = static_cast<ReflectionProbe*>(probe->getClientObject());
  439. else
  440. return;
  441. if (clientProbe == nullptr)
  442. return;
  443. String probePrefilterPath = clientProbe->getPrefilterMapPath();
  444. String probeIrradPath = clientProbe->getIrradianceMapPath();
  445. if (clientProbe->mReflectionModeType != ReflectionProbe::DynamicCubemap)
  446. {
  447. //Prep our bake path
  448. if (probePrefilterPath.isEmpty() || probeIrradPath.isEmpty())
  449. {
  450. Con::errorf("RenderProbeMgr::bake() - Unable to bake our captures because probe doesn't have a path set");
  451. return;
  452. }
  453. }
  454. // Save the current transforms so we can restore
  455. // it for child control rendering below.
  456. GFXTransformSaver saver;
  457. bool probeRenderState = RenderProbeMgr::smRenderReflectionProbes;
  458. F32 farPlane = 1000.0f;
  459. ReflectorDesc reflDesc;
  460. reflDesc.texSize = resolution;
  461. reflDesc.farDist = farPlane;
  462. reflDesc.detailAdjust = (F32)resolution;
  463. reflDesc.objectTypeMask = probe->mCaptureMask;
  464. CubeReflector cubeRefl;
  465. cubeRefl.registerReflector(probe, &reflDesc);
  466. ReflectParams reflParams;
  467. MatrixF camTrans = clientProbe->getTransform();
  468. camTrans.setPosition(clientProbe->getTransform().getPosition() + clientProbe->mProbeRefOffset);
  469. //need to get the query somehow. Likely do some sort of get function to fetch from the guiTSControl that's active
  470. CameraQuery query; //need to get the last cameraQuery
  471. query.fov = 90; //90 degree slices for each of the 6 sides
  472. query.nearPlane = 0.0001f;
  473. query.farPlane = farPlane;
  474. query.headMatrix = MatrixF();
  475. query.cameraMatrix = camTrans;
  476. Frustum culler;
  477. culler.set(false,
  478. query.fov,
  479. 1.0f,
  480. query.nearPlane,
  481. query.farPlane,
  482. query.cameraMatrix);
  483. S32 stereoTarget = GFX->getCurrentStereoTarget();
  484. Point2I maxRes(2048, 2048); //basically a boundary so we don't go over this and break stuff
  485. reflParams.culler = culler;
  486. reflParams.eyeId = stereoTarget;
  487. reflParams.query = &query;
  488. reflParams.startOfUpdateMs = startMSTime;
  489. reflParams.viewportExtent = maxRes;
  490. if (!renderWithProbes)
  491. RenderProbeMgr::smRenderReflectionProbes = false;
  492. GFXFormat reflectFormat;
  493. if (mUseHDRCaptures)
  494. reflectFormat = GFXFormatR16G16B16A16F;
  495. else
  496. reflectFormat = GFXFormatR8G8B8A8;
  497. const GFXFormat oldRefFmt = REFLECTMGR->getReflectFormat();
  498. REFLECTMGR->setReflectFormat(reflectFormat);
  499. cubeRefl.updateReflection(reflParams, clientProbe->getTransform().getPosition() + clientProbe->mProbeRefOffset);
  500. //Now, save out the maps
  501. //create irridiance cubemap
  502. if (cubeRefl.getCubemap())
  503. {
  504. //Just to ensure we're prepped for the generation
  505. clientProbe->createClientResources();
  506. //Prep it with whatever resolution we've dictated for our bake
  507. clientProbe->mIrridianceMap->mCubemap->initDynamic(resolution, reflectFormat);
  508. clientProbe->mPrefilterMap->mCubemap->initDynamic(resolution, reflectFormat);
  509. GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
  510. clientProbe->mPrefilterMap->mCubemap = cubeRefl.getCubemap();
  511. IBLUtilities::GenerateIrradianceMap(renderTarget, cubeRefl.getCubemap(), clientProbe->mIrridianceMap->mCubemap);
  512. //IBLUtilities::GeneratePrefilterMap(renderTarget, cubeRefl.getCubemap(), prefilterMipLevels, clientProbe->mPrefilterMap->mCubemap);
  513. U32 endMSTime = Platform::getRealMilliseconds();
  514. F32 diffTime = F32(endMSTime - startMSTime);
  515. Con::warnf("RenderProbeMgr::bake() - Finished Capture! Took %g milliseconds", diffTime);
  516. Con::warnf("RenderProbeMgr::bake() - Beginning save now!");
  517. IBLUtilities::SaveCubeMap(clientProbe->getIrradianceMapPath(), clientProbe->mIrridianceMap->mCubemap);
  518. IBLUtilities::SaveCubeMap(clientProbe->getPrefilterMapPath(), clientProbe->mPrefilterMap->mCubemap);
  519. }
  520. else
  521. {
  522. Con::errorf("RenderProbeMgr::bake() - Didn't generate a valid scene capture cubemap, unable to generate prefilter and irradiance maps!");
  523. }
  524. if (!renderWithProbes)
  525. RenderProbeMgr::smRenderReflectionProbes = probeRenderState;
  526. cubeRefl.unregisterReflector();
  527. U32 endMSTime = Platform::getRealMilliseconds();
  528. F32 diffTime = F32(endMSTime - startMSTime);
  529. probe->setMaskBits(-1);
  530. Con::warnf("RenderProbeMgr::bake() - Finished bake! Took %g milliseconds", diffTime);
  531. REFLECTMGR->setReflectFormat(oldRefFmt);
  532. }
  533. void RenderProbeMgr::bakeProbes()
  534. {
  535. Vector<ReflectionProbe*> probes;
  536. Scene::getRootScene()->findObjectByType<ReflectionProbe>(probes);
  537. for (U32 i = 0; i < probes.size(); i++)
  538. {
  539. if (probes[i]->isClientObject())
  540. continue;
  541. bakeProbe(probes[i]);
  542. }
  543. }
  544. //=============================================================================
  545. // Forward Rendering functions
  546. //=============================================================================
  547. ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuffer* buffer)
  548. {
  549. if (!buffer)
  550. return NULL;
  551. PROFILE_SCOPE(ProbeManager_GetProbeShaderConstants);
  552. GFXShader* shader = buffer->getShader();
  553. // Check to see if this is the same shader, we'll get hit repeatedly by
  554. // the same one due to the render bin loops.
  555. if (mLastShader.getPointer() != shader)
  556. {
  557. ProbeConstantMap::Iterator iter = mConstantLookup.find(shader);
  558. if (iter != mConstantLookup.end())
  559. {
  560. mLastConstants = iter->value;
  561. }
  562. else
  563. {
  564. ProbeShaderConstants* psc = new ProbeShaderConstants();
  565. mConstantLookup[shader] = psc;
  566. mLastConstants = psc;
  567. }
  568. // Set our new shader
  569. mLastShader = shader;
  570. }
  571. /*if (mLastConstants == nullptr)
  572. {
  573. ProbeShaderConstants* psc = new ProbeShaderConstants();
  574. mConstantLookup[shader] = psc;
  575. mLastConstants = psc;
  576. }*/
  577. // Make sure that our current lighting constants are initialized
  578. if (mLastConstants && !mLastConstants->mInit)
  579. mLastConstants->init(shader);
  580. return mLastConstants;
  581. }
  582. void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,
  583. const Material *mat,
  584. const SceneData &sgData,
  585. const SceneRenderState *state,
  586. U32 pass,
  587. GFXShaderConstBuffer *shaderConsts)
  588. {
  589. // Skip this if we're rendering from the deferred bin.
  590. if (sgData.binType == SceneData::DeferredBin)
  591. return;
  592. PROFILE_SCOPE(ProbeManager_setProbeInfo);
  593. ProbeShaderConstants *psc = getProbeShaderConstants(shaderConsts);
  594. // NOTE: If you encounter a crash from this point forward
  595. // while setting a shader constant its probably because the
  596. // mConstantLookup has bad shaders/constants in it.
  597. //
  598. // This is a known crash bug that can occur if materials/shaders
  599. // are reloaded and the light manager is not reset.
  600. //
  601. // We should look to fix this by clearing the table.
  602. MatrixSet matSet = state->getRenderPass()->getMatrixSet();
  603. // Update the forward shading light constants.
  604. _update4ProbeConsts(sgData, matSet, psc, shaderConsts);
  605. }
  606. void RenderProbeMgr::setupSGData(SceneData& data, const SceneRenderState* state, LightInfo* light)
  607. {
  608. //ensure they're sorted for forward rendering
  609. mActiveProbes.sort(_probeScoreCmp);
  610. }
  611. void RenderProbeMgr::_update4ProbeConsts(const SceneData& sgData,
  612. MatrixSet& matSet,
  613. ProbeShaderConstants* probeShaderConsts,
  614. GFXShaderConstBuffer* shaderConsts)
  615. {
  616. PROFILE_SCOPE(ProbeManager_Update4ProbeConsts);
  617. // Skip over gathering lights if we don't have to!
  618. if (probeShaderConsts->isValid())
  619. {
  620. PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
  621. const U32 MAX_FORWARD_PROBES = 4;
  622. ProbeDataSet probeSet(MAX_FORWARD_PROBES);
  623. matSet.restoreSceneViewProjection();
  624. getBestProbes(sgData.objTrans->getPosition(), &probeSet);
  625. static AlignedArray<Point4F> probePositionAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
  626. static AlignedArray<Point4F> refScaleAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
  627. static AlignedArray<Point4F> probeRefPositionAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
  628. static AlignedArray<Point4F> probeConfigAlignedArray(probeSet.maxProbeCount, sizeof(Point4F));
  629. for (U32 i = 0; i < probeSet.maxProbeCount; i++)
  630. {
  631. probePositionAlignedArray[i] = probeSet.probePositionArray[i];
  632. probeRefPositionAlignedArray[i] = probeSet.probeRefPositionArray[i];
  633. refScaleAlignedArray[i] = probeSet.refScaleArray[i];
  634. probeConfigAlignedArray[i] = probeSet.probeConfigArray[i];
  635. }
  636. if (probeSet.effectiveProbeCount != 0)
  637. {
  638. shaderConsts->setSafe(probeShaderConsts->mProbeCountSC, (S32)probeSet.effectiveProbeCount);
  639. shaderConsts->setSafe(probeShaderConsts->mProbePositionArraySC, probePositionAlignedArray);
  640. shaderConsts->setSafe(probeShaderConsts->mProbeRefPosArraySC, probeRefPositionAlignedArray);
  641. if (probeShaderConsts->isValid())
  642. shaderConsts->set(probeShaderConsts->mWorldToObjArraySC, probeSet.probeWorldToObjArray.address(), probeSet.probeWorldToObjArray.size(), GFXSCT_Float4x4);
  643. shaderConsts->setSafe(probeShaderConsts->mRefScaleArraySC, refScaleAlignedArray);
  644. shaderConsts->setSafe(probeShaderConsts->mProbeConfigDataArraySC, probeConfigAlignedArray);
  645. }
  646. if (mBRDFTexture.isValid() && probeShaderConsts->mBRDFTextureMap->getSamplerRegister() != -1)
  647. GFX->setTexture(probeShaderConsts->mBRDFTextureMap->getSamplerRegister(), mBRDFTexture);
  648. if (mWetnessTexture.isValid() && probeShaderConsts->mWetnessTextureMap->getSamplerRegister() != -1)
  649. GFX->setTexture(probeShaderConsts->mWetnessTextureMap->getSamplerRegister(), mWetnessTexture);
  650. shaderConsts->setSafe(probeShaderConsts->mSkylightCubemapIdxSC, (float)probeSet.skyLightIdx);
  651. shaderConsts->setSafe(probeShaderConsts->mSkylightDampSC, (int)probeSet.skyLightDamp);
  652. if (probeShaderConsts->mProbeSpecularCubemapArraySC->getSamplerRegister() != -1)
  653. GFX->setCubeArrayTexture(probeShaderConsts->mProbeSpecularCubemapArraySC->getSamplerRegister(), mPrefilterArray);
  654. if (probeShaderConsts->mProbeIrradianceCubemapArraySC->getSamplerRegister() != -1)
  655. GFX->setCubeArrayTexture(probeShaderConsts->mProbeIrradianceCubemapArraySC->getSamplerRegister(), mIrradianceArray);
  656. shaderConsts->setSafe(probeShaderConsts->mMaxProbeDrawDistanceSC, smMaxProbeDrawDistance);
  657. }
  658. }
  659. //=============================================================================
  660. // Deferred Rendering Functions
  661. //=============================================================================
  662. void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState* state)
  663. {
  664. PROFILE_SCOPE(RenderProbeMgr_SetupPerFrameParameters);
  665. mProbeData = ProbeDataSet(smMaxProbesPerFrame);
  666. getBestProbes(state->getCameraPosition(), &mProbeData);
  667. }
  668. void RenderProbeMgr::render( SceneRenderState *state )
  669. {
  670. if (getProbeArrayEffect() == nullptr)
  671. {
  672. mActiveProbes.clear();
  673. return;
  674. }
  675. GFXDEBUGEVENT_SCOPE(RenderProbeMgr_render, ColorI::WHITE);
  676. //Sort the active probes
  677. mActiveProbes.sort(_probeScoreCmp);
  678. // Initialize and set the per-frame data
  679. _setupPerFrameParameters(state);
  680. // Early out if nothing to draw.
  681. if (!RenderProbeMgr::smRenderReflectionProbes || (!mHasSkylight && mProbeData.effectiveProbeCount == 0))
  682. {
  683. getProbeArrayEffect()->setSkip(true);
  684. mActiveProbes.clear();
  685. return;
  686. }
  687. GFXTransformSaver saver;
  688. //Visualization
  689. String useDebugAtten = Con::getVariable("$Probes::showAttenuation", "0");
  690. mProbeArrayEffect->setShaderMacro("DEBUGVIZ_ATTENUATION", useDebugAtten);
  691. String useDebugSpecCubemap = Con::getVariable("$Probes::showSpecularCubemaps", "0");
  692. mProbeArrayEffect->setShaderMacro("DEBUGVIZ_SPECCUBEMAP", useDebugSpecCubemap);
  693. String useDebugDiffuseCubemap = Con::getVariable("$Probes::showDiffuseCubemaps", "0");
  694. mProbeArrayEffect->setShaderMacro("DEBUGVIZ_DIFFCUBEMAP", useDebugDiffuseCubemap);
  695. String useDebugContrib = Con::getVariable("$Probes::showProbeContrib", "0");
  696. mProbeArrayEffect->setShaderMacro("DEBUGVIZ_CONTRIB", useDebugContrib);
  697. if(mHasSkylight && mProbeData.effectiveProbeCount == 0)
  698. mProbeArrayEffect->setShaderMacro("SKYLIGHT_ONLY", "1");
  699. else
  700. mProbeArrayEffect->setShaderMacro("SKYLIGHT_ONLY", "0");
  701. String probePerFrame = Con::getVariable("$pref::MaxProbesPerFrame", "8");
  702. mProbeArrayEffect->setShaderMacro("MAX_PROBES", probePerFrame);
  703. mProbeArrayEffect->setTexture(3, mBRDFTexture);
  704. mProbeArrayEffect->setCubemapArrayTexture(4, mPrefilterArray);
  705. mProbeArrayEffect->setCubemapArrayTexture(5, mIrradianceArray);
  706. mProbeArrayEffect->setTexture(6, mWetnessTexture);
  707. //ssao mask
  708. if (AdvancedLightBinManager::smUseSSAOMask)
  709. {
  710. //find ssaoMask
  711. NamedTexTargetRef ssaoTarget = NamedTexTarget::find("ssaoMask");
  712. GFXTextureObject* pTexObj = ssaoTarget->getTexture();
  713. if (pTexObj)
  714. {
  715. mProbeArrayEffect->setShaderMacro("USE_SSAO_MASK");
  716. mProbeArrayEffect->setTexture(7, pTexObj);
  717. }
  718. }
  719. else
  720. {
  721. mProbeArrayEffect->setTexture(7, GFXTexHandle(NULL));
  722. }
  723. mProbeArrayEffect->setShaderConst("$numProbes", (S32)mProbeData.effectiveProbeCount);
  724. mProbeArrayEffect->setShaderConst("$skylightCubemapIdx", (S32)mProbeData.skyLightIdx);
  725. mProbeArrayEffect->setShaderConst(ShaderGenVars::skylightDamp, mProbeData.skyLightDamp);
  726. mProbeArrayEffect->setShaderConst("$cubeMips", (float)mPrefilterArray->getMipMapLevels());
  727. //also set up some colors
  728. Vector<Point4F> contribColors;
  729. contribColors.setSize(mProbeData.effectiveProbeCount);
  730. if (mProbeData.effectiveProbeCount != 0)
  731. {
  732. if (useDebugContrib == String("1"))
  733. {
  734. MRandomLCG RandomGen;
  735. RandomGen.setSeed(mProbeData.effectiveProbeCount);
  736. for (U32 i = 0; i < mProbeData.effectiveProbeCount; i++)
  737. {
  738. //we're going to cheat here a little for consistent debugging behavior. The first 3 probes will always have R G and then B for their colors, every other will be random
  739. if (i == 0)
  740. contribColors[i] = Point4F(1, 0, 0, 1);
  741. else if (i == 1)
  742. contribColors[i] = Point4F(0, 1, 0, 1);
  743. else if (i == 2)
  744. contribColors[i] = Point4F(0, 0, 1, 1);
  745. else
  746. contribColors[i] = Point4F(RandomGen.randF(0, 1), RandomGen.randF(0, 1), RandomGen.randF(0, 1), 1);
  747. }
  748. }
  749. }
  750. mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);
  751. mProbeArrayEffect->setShaderConst("$probePosArray", mProbeData.probePositionArray);
  752. mProbeArrayEffect->setShaderConst("$refPosArray", mProbeData.probeRefPositionArray);
  753. mProbeArrayEffect->setShaderConst("$worldToObjArray", mProbeData.probeWorldToObjArray);
  754. mProbeArrayEffect->setShaderConst("$refScaleArray", mProbeData.refScaleArray);
  755. mProbeArrayEffect->setShaderConst("$probeConfigData", mProbeData.probeConfigArray);
  756. mProbeArrayEffect->setShaderConst("$maxProbeDrawDistance", smMaxProbeDrawDistance);
  757. // Make sure the effect is gonna render.
  758. getProbeArrayEffect()->setSkip(false);
  759. }
  760. //=============================================================================
  761. // Console functions
  762. //=============================================================================
  763. DefineEngineMethod(RenderProbeMgr, bakeProbe, void, (ReflectionProbe* probe), (nullAsType< ReflectionProbe*>()),
  764. "@brief Bakes the cubemaps for a reflection probe\n\n.")
  765. {
  766. object->preBake();
  767. if(probe != nullptr)
  768. object->bakeProbe(probe);
  769. object->postBake();
  770. }
  771. DefineEngineMethod(RenderProbeMgr, bakeProbes, void, (),, "@brief Iterates over all reflection probes in the scene and bakes their cubemaps\n\n.")
  772. {
  773. object->preBake();
  774. object->bakeProbes();
  775. object->postBake();
  776. }