renderProbeMgr.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  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 "console/consoleTypes.h"
  24. #include "scene/sceneObject.h"
  25. #include "materials/materialManager.h"
  26. #include "scene/sceneRenderState.h"
  27. #include "math/util/sphereMesh.h"
  28. #include "math/util/matrixSet.h"
  29. #include "materials/processedMaterial.h"
  30. #include "renderInstance/renderDeferredMgr.h"
  31. #include "math/mPolyhedron.impl.h"
  32. #include "gfx/gfxTransformSaver.h"
  33. #include "gfx/gfxDebugEvent.h"
  34. #include "shaderGen/shaderGenVars.h"
  35. #include "materials/shaderData.h"
  36. #include "gfx/gfxTextureManager.h"
  37. #include "postFx/postEffect.h"
  38. #include "T3D/lighting/reflectionProbe.h"
  39. #include "T3D/lighting/IBLUtilities.h"
  40. //For our cameraQuery setup
  41. #include "T3D/gameTSCtrl.h"
  42. #define TORQUE_GFX_VISUAL_DEBUG //renderdoc debugging
  43. IMPLEMENT_CONOBJECT(RenderProbeMgr);
  44. ConsoleDocClass( RenderProbeMgr,
  45. "@brief A render bin which uses object callbacks for rendering.\n\n"
  46. "This render bin gathers object render instances and calls its delegate "
  47. "method to perform rendering. It is used infrequently for specialized "
  48. "scene objects which perform custom rendering.\n\n"
  49. "@ingroup RenderBin\n" );
  50. RenderProbeMgr *RenderProbeMgr::smProbeManager = NULL;
  51. bool RenderProbeMgr::smRenderReflectionProbes = true;
  52. S32 QSORT_CALLBACK AscendingReflectProbeInfluence(const void* a, const void* b)
  53. {
  54. // Debug Profiling.
  55. PROFILE_SCOPE(AdvancedLightBinManager_AscendingReflectProbeInfluence);
  56. // Fetch asset definitions.
  57. const ProbeRenderInst* pReflectProbeA = (*(ProbeRenderInst**)a);
  58. const ProbeRenderInst* pReflectProbeB = (*(ProbeRenderInst**)b);
  59. //sort by score
  60. return pReflectProbeA->mScore - pReflectProbeB->mScore;
  61. }
  62. //
  63. //
  64. ProbeRenderInst::ProbeRenderInst() : SystemInterface(),
  65. mTransform(true),
  66. mDirty(false),
  67. mPriority(1.0f),
  68. mScore(0.0f),
  69. mPrefilterCubemap(NULL),
  70. mIrradianceCubemap(NULL),
  71. mRadius(1.0f),
  72. mProbeRefOffset(0, 0, 0),
  73. mProbeRefScale(1,1,1),
  74. mAtten(0.0),
  75. mCubemapIndex(0),
  76. mIsSkylight(false)
  77. {
  78. }
  79. ProbeRenderInst::~ProbeRenderInst()
  80. {
  81. if (mPrefilterCubemap && mPrefilterCubemap.isValid())
  82. {
  83. mPrefilterCubemap.free();
  84. }
  85. if (mIrradianceCubemap && mIrradianceCubemap.isValid())
  86. {
  87. mIrradianceCubemap.free();
  88. }
  89. }
  90. void ProbeRenderInst::set(const ProbeRenderInst *probeInfo)
  91. {
  92. mTransform = probeInfo->mTransform;
  93. mPrefilterCubemap = probeInfo->mPrefilterCubemap;
  94. mIrradianceCubemap = probeInfo->mIrradianceCubemap;
  95. mRadius = probeInfo->mRadius;
  96. mProbeShapeType = probeInfo->mProbeShapeType;
  97. mBounds = probeInfo->mBounds;
  98. mIsSkylight = probeInfo->mIsSkylight;
  99. mScore = probeInfo->mScore;
  100. mAtten = probeInfo->mAtten;
  101. }
  102. //
  103. //
  104. ProbeShaderConstants::ProbeShaderConstants()
  105. : mInit(false),
  106. mShader(NULL),
  107. mProbePositionSC(NULL),
  108. mProbeRefPosSC(NULL),
  109. mProbeBoxMinSC(NULL),
  110. mProbeBoxMaxSC(NULL),
  111. mProbeConfigDataSC(NULL),
  112. mProbeSpecularCubemapSC(NULL),
  113. mProbeIrradianceCubemapSC(NULL),
  114. mProbeCountSC(NULL),
  115. mSkylightSpecularMap(NULL),
  116. mSkylightIrradMap(NULL),
  117. mHasSkylight(NULL)
  118. {
  119. }
  120. ProbeShaderConstants::~ProbeShaderConstants()
  121. {
  122. if (mShader.isValid())
  123. {
  124. mShader->getReloadSignal().remove(this, &ProbeShaderConstants::_onShaderReload);
  125. mShader = NULL;
  126. }
  127. }
  128. void ProbeShaderConstants::init(GFXShader* shader)
  129. {
  130. if (mShader.getPointer() != shader)
  131. {
  132. if (mShader.isValid())
  133. mShader->getReloadSignal().remove(this, &ProbeShaderConstants::_onShaderReload);
  134. mShader = shader;
  135. mShader->getReloadSignal().notify(this, &ProbeShaderConstants::_onShaderReload);
  136. }
  137. //Reflection Probes
  138. mProbePositionSC = shader->getShaderConstHandle(ShaderGenVars::probePosition);
  139. mProbeRefPosSC = shader->getShaderConstHandle(ShaderGenVars::probeRefPos);
  140. mProbeBoxMinSC = shader->getShaderConstHandle(ShaderGenVars::probeBoxMin);
  141. mProbeBoxMaxSC = shader->getShaderConstHandle(ShaderGenVars::probeBoxMax);
  142. mWorldToObjArraySC = shader->getShaderConstHandle(ShaderGenVars::worldToObjArray);
  143. mProbeConfigDataSC = shader->getShaderConstHandle(ShaderGenVars::probeConfigData);
  144. mProbeSpecularCubemapSC = shader->getShaderConstHandle(ShaderGenVars::specularCubemapAR);
  145. mProbeIrradianceCubemapSC = shader->getShaderConstHandle(ShaderGenVars::irradianceCubemapAR);
  146. mProbeCountSC = shader->getShaderConstHandle(ShaderGenVars::probeCount);
  147. mSkylightSpecularMap = shader->getShaderConstHandle(ShaderGenVars::skylightPrefilterMap);
  148. mSkylightIrradMap = shader->getShaderConstHandle(ShaderGenVars::skylightIrradMap);
  149. mHasSkylight = shader->getShaderConstHandle(ShaderGenVars::hasSkylight);
  150. mInit = true;
  151. }
  152. void ProbeShaderConstants::_onShaderReload()
  153. {
  154. if (mShader.isValid())
  155. init(mShader);
  156. }
  157. //
  158. //
  159. RenderProbeMgr::RenderProbeMgr()
  160. : RenderBinManager(RenderPassManager::RIT_Probes, 1.0f, 1.0f),
  161. mLastShader(nullptr),
  162. mLastConstants(nullptr),
  163. mProbesDirty(false)
  164. {
  165. mEffectiveProbeCount = 0;
  166. mMipCount = 0;
  167. mProbeArrayEffect = nullptr;
  168. smProbeManager = this;
  169. mCubeMapCount = 0;
  170. for (U32 i = 0; i < PROBE_MAX_COUNT; i++)
  171. {
  172. mCubeMapSlots[i] = false;
  173. }
  174. }
  175. RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder)
  176. : RenderBinManager(riType, renderOrder, processAddOrder)
  177. {
  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. //pre-allocate a few slots
  197. mIrradianceArray->init(PROBE_ARRAY_SLOT_BUFFER_SIZE, PROBE_IRRAD_SIZE, PROBE_FORMAT);
  198. mPrefilterArray->init(PROBE_ARRAY_SLOT_BUFFER_SIZE, PROBE_PREFILTER_SIZE, PROBE_FORMAT);
  199. mCubeSlotCount = PROBE_ARRAY_SLOT_BUFFER_SIZE;
  200. //create our own default default skylight
  201. mDefaultSkyLight = new ProbeRenderInst;
  202. mDefaultSkyLight->mProbeShapeType = ProbeRenderInst::Skylight;
  203. if (!mDefaultSkyLight->mIrradianceCubemap.set("core/art/pbr/default_irradiance.dds"))
  204. {
  205. Con::errorf("RenderProbeMgr::onAdd: Failed to load default irradiance cubemap");
  206. return false;
  207. }
  208. if (!mDefaultSkyLight->mPrefilterCubemap.set("core/art/pbr/default_prefilter.dds"))
  209. {
  210. Con::errorf("RenderProbeMgr::onAdd: Failed to load default prefilter cubemap");
  211. return false;
  212. }
  213. return true;
  214. }
  215. void RenderProbeMgr::onRemove()
  216. {
  217. Parent::onRemove();
  218. }
  219. void RenderProbeMgr::initPersistFields()
  220. {
  221. Parent::initPersistFields();
  222. }
  223. void RenderProbeMgr::addElement(RenderInst *inst)
  224. {
  225. // If this instance is translucent handle it in RenderTranslucentMgr
  226. //if (inst->translucentSort)
  227. return;
  228. //AssertFatal(inst->defaultKey != 0, "RenderMeshMgr::addElement() - Got null sort key... did you forget to set it?");
  229. /*internalAddElement(inst);
  230. ProbeRenderInst* probeInst = static_cast<ProbeRenderInst*>(inst);
  231. if (probeInst->mIsSkylight)
  232. {
  233. addSkylightProbe(probeInst);
  234. }
  235. else
  236. {
  237. if (probeInst->mProbeShapeType == ProbeInfo::Sphere)
  238. addSphereReflectionProbe(probeInst);
  239. else
  240. addConvexReflectionProbe(probeInst);
  241. }*/
  242. }
  243. void RenderProbeMgr::registerProbe(U32 probeIdx)
  244. {
  245. //Mostly for consolidation, but also lets us sanity check or prep any other data we need for rendering this in one place at time of flagging for render
  246. if (probeIdx >= ProbeRenderInst::all.size())
  247. return;
  248. mRegisteredProbes.push_back_unique(probeIdx);
  249. if (!ProbeRenderInst::all[probeIdx]->mIsSkylight)
  250. {
  251. const U32 cubeIndex = _findNextEmptyCubeSlot();
  252. if (cubeIndex == INVALID_CUBE_SLOT)
  253. {
  254. Con::warnf("RenderProbeMgr::addProbe: Invalid cubemap slot.");
  255. return;
  256. }
  257. //check if we need to resize the cubemap array
  258. if (cubeIndex >= mCubeSlotCount)
  259. {
  260. //alloc temp array handles
  261. GFXCubemapArrayHandle irr = GFXCubemapArrayHandle(GFX->createCubemapArray());
  262. GFXCubemapArrayHandle prefilter = GFXCubemapArrayHandle(GFX->createCubemapArray());
  263. irr->init(mCubeSlotCount + PROBE_ARRAY_SLOT_BUFFER_SIZE, PROBE_IRRAD_SIZE, PROBE_FORMAT);
  264. prefilter->init(mCubeSlotCount + PROBE_ARRAY_SLOT_BUFFER_SIZE, PROBE_PREFILTER_SIZE, PROBE_FORMAT);
  265. mIrradianceArray->copyTo(irr);
  266. mPrefilterArray->copyTo(prefilter);
  267. //assign the temp handles to the new ones, this will destroy the old ones as well
  268. mIrradianceArray = irr;
  269. mPrefilterArray = prefilter;
  270. mCubeSlotCount += PROBE_ARRAY_SLOT_BUFFER_SIZE;
  271. }
  272. ProbeRenderInst::all[probeIdx]->mCubemapIndex = cubeIndex;
  273. //mark cubemap slot as taken
  274. mCubeMapSlots[cubeIndex] = true;
  275. mCubeMapCount++;
  276. Con::warnf("RenderProbeMgr::registerProbe: Registered probe %u to cubeIndex %u", probeIdx, cubeIndex);
  277. }
  278. //rebuild our probe data
  279. _setupStaticParameters();
  280. }
  281. void RenderProbeMgr::unregisterProbe(U32 probeIdx)
  282. {
  283. //Mostly for consolidation, but also lets us sanity check or prep any other data we need for rendering this in one place at time of flagging for render
  284. if (probeIdx >= ProbeRenderInst::all.size())
  285. return;
  286. mRegisteredProbes.remove(probeIdx);
  287. if (ProbeRenderInst::all[probeIdx]->mCubemapIndex == INVALID_CUBE_SLOT)
  288. return;
  289. //mark cubemap slot as available now
  290. mCubeMapSlots[ProbeRenderInst::all[probeIdx]->mCubemapIndex] = false;
  291. mCubeMapCount--;
  292. //rebuild our probe data
  293. _setupStaticParameters();
  294. }
  295. //
  296. //
  297. PostEffect* RenderProbeMgr::getProbeArrayEffect()
  298. {
  299. if (!mProbeArrayEffect)
  300. {
  301. mProbeArrayEffect = dynamic_cast<PostEffect*>(Sim::findObject("reflectionProbeArrayPostFX"));
  302. if (!mProbeArrayEffect)
  303. return nullptr;
  304. }
  305. return mProbeArrayEffect;
  306. }
  307. //remove
  308. //Con::setIntVariable("lightMetrics::activeReflectionProbes", mReflectProbeBin.size());
  309. //Con::setIntVariable("lightMetrics::culledReflectProbes", 0/*mNumLightsCulled*/);
  310. //
  311. void RenderProbeMgr::updateProbes()
  312. {
  313. mProbesDirty = true;
  314. }
  315. void RenderProbeMgr::_setupStaticParameters()
  316. {
  317. //Array rendering
  318. U32 probeCount = ProbeRenderInst::all.size();
  319. mEffectiveProbeCount = 0;
  320. mMipCount = 0;
  321. if (probePositionsData.size() != MAXPROBECOUNT)
  322. {
  323. probePositionsData.setSize(MAXPROBECOUNT);
  324. probeRefPositionsData.setSize(MAXPROBECOUNT);
  325. probeWorldToObjData.setSize(MAXPROBECOUNT);
  326. probeBBMinData.setSize(MAXPROBECOUNT);
  327. probeBBMaxData.setSize(MAXPROBECOUNT);
  328. probeConfigData.setSize(MAXPROBECOUNT);
  329. }
  330. probePositionsData.fill(Point4F::Zero);
  331. probeRefPositionsData.fill(Point4F::Zero);
  332. probeWorldToObjData.fill(MatrixF::Identity);
  333. probeBBMinData.fill(Point4F::Zero);
  334. probeBBMaxData.fill(Point4F::Zero);
  335. probeConfigData.fill(Point4F::Zero);
  336. cubeMaps.clear();
  337. irradMaps.clear();
  338. Vector<U32> cubemapIdxes;
  339. if (probeCount != 0 && ProbeRenderInst::all[0]->mPrefilterCubemap != nullptr)
  340. {
  341. //Get our mipCount
  342. mMipCount = ProbeRenderInst::all[0]->mPrefilterCubemap.getPointer()->getMipMapLevels();
  343. }
  344. else
  345. {
  346. mMipCount = 1;
  347. }
  348. for (U32 i = 0; i < probeCount; i++)
  349. {
  350. if (mEffectiveProbeCount >= MAXPROBECOUNT)
  351. break;
  352. const ProbeRenderInst& curEntry = *ProbeRenderInst::all[i];
  353. if (!curEntry.mIsEnabled)
  354. continue;
  355. if (curEntry.mProbeShapeType == ProbeRenderInst::ProbeShapeType::Skylight || curEntry.mIsSkylight)
  356. {
  357. skylightPos = curEntry.getPosition();
  358. skylightPrefilterMap = curEntry.mPrefilterCubemap;
  359. skylightIrradMap = curEntry.mIrradianceCubemap;
  360. hasSkylight = true;
  361. continue;
  362. }
  363. //Setup
  364. Point3F probePos = curEntry.getPosition();
  365. Point3F refPos = curEntry.getPosition() +curEntry.mProbeRefOffset;
  366. probePositionsData[mEffectiveProbeCount] = Point4F(probePos.x, probePos.y, probePos.z,0);
  367. probeRefPositionsData[mEffectiveProbeCount] = Point4F(refPos.x, refPos.y, refPos.z, 0);
  368. probeWorldToObjData[mEffectiveProbeCount] = curEntry.getTransform();
  369. Point3F bbMin = refPos - curEntry.mProbeRefScale/2 * curEntry.getTransform().getScale();
  370. Point3F bbMax = refPos + curEntry.mProbeRefScale/2 * curEntry.getTransform().getScale();
  371. probeBBMinData[mEffectiveProbeCount] = Point4F(bbMin.x, bbMin.y, bbMin.z, 0);
  372. probeBBMaxData[mEffectiveProbeCount] = Point4F(bbMax.x, bbMax.y, bbMax.z, 0);
  373. probeConfigData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType,
  374. curEntry.mRadius,
  375. curEntry.mAtten,
  376. curEntry.mCubemapIndex);
  377. cubeMaps.push_back(curEntry.mPrefilterCubemap);
  378. irradMaps.push_back(curEntry.mIrradianceCubemap);
  379. cubemapIdxes.push_back(i);
  380. mEffectiveProbeCount++;
  381. }
  382. mProbesDirty = false;
  383. }
  384. void RenderProbeMgr::updateProbeTexture(ProbeRenderInst* probe)
  385. {
  386. //We don't stuff skylights into the array, so we can just skip out on this if it's a skylight
  387. if (probe->mIsSkylight)
  388. return;
  389. S32 probeIdx = ProbeRenderInst::all.find_next(probe);
  390. if (probeIdx != -1) //i mean, the opposite shouldn't even be possible
  391. updateProbeTexture(probeIdx);
  392. }
  393. void RenderProbeMgr::updateProbeTexture(U32 probeIdx)
  394. {
  395. if (probeIdx >= ProbeRenderInst::all.size())
  396. return;
  397. const U32 cubeIndex = ProbeRenderInst::all[probeIdx]->mCubemapIndex;
  398. mIrradianceArray->updateTexture(ProbeRenderInst::all[probeIdx]->mIrradianceCubemap, cubeIndex);
  399. mPrefilterArray->updateTexture(ProbeRenderInst::all[probeIdx]->mPrefilterCubemap, cubeIndex);
  400. Con::warnf("UpdatedProbeTexture - probeIdx: %u on cubeIndex %u, Irrad validity: %d, Prefilter validity: %d", probeIdx, cubeIndex,
  401. ProbeRenderInst::all[probeIdx]->mIrradianceCubemap->isInitialized(), ProbeRenderInst::all[probeIdx]->mPrefilterCubemap->isInitialized());
  402. }
  403. void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
  404. {
  405. PROFILE_SCOPE(RenderProbeMgr_SetupPerFrameParameters);
  406. }
  407. ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuffer* buffer)
  408. {
  409. if (!buffer)
  410. return NULL;
  411. PROFILE_SCOPE(ProbeManager_GetProbeShaderConstants);
  412. GFXShader* shader = buffer->getShader();
  413. // Check to see if this is the same shader, we'll get hit repeatedly by
  414. // the same one due to the render bin loops.
  415. if (mLastShader.getPointer() != shader)
  416. {
  417. ProbeConstantMap::Iterator iter = mConstantLookup.find(shader);
  418. if (iter != mConstantLookup.end())
  419. {
  420. mLastConstants = iter->value;
  421. }
  422. else
  423. {
  424. ProbeShaderConstants* psc = new ProbeShaderConstants();
  425. mConstantLookup[shader] = psc;
  426. mLastConstants = psc;
  427. }
  428. // Set our new shader
  429. mLastShader = shader;
  430. }
  431. // Make sure that our current lighting constants are initialized
  432. if (mLastConstants && !mLastConstants->mInit)
  433. mLastConstants->init(shader);
  434. return mLastConstants;
  435. }
  436. void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
  437. MatrixSet &matSet,
  438. ProbeShaderConstants *probeShaderConsts,
  439. GFXShaderConstBuffer *shaderConsts)
  440. {
  441. PROFILE_SCOPE(ProbeManager_Update4ProbeConsts);
  442. // Skip over gathering lights if we don't have to!
  443. if (probeShaderConsts->mProbePositionSC->isValid() ||
  444. probeShaderConsts->mProbeConfigDataSC->isValid() ||
  445. probeShaderConsts->mProbeBoxMinSC->isValid() ||
  446. probeShaderConsts->mProbeBoxMaxSC->isValid() ||
  447. probeShaderConsts->mProbeSpecularCubemapSC->isValid() ||
  448. probeShaderConsts->mProbeIrradianceCubemapSC->isValid()/* && (!ProbeRenderInst::all.empty())*/)
  449. {
  450. PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
  451. const U32 MAX_FORWARD_PROBES = 4;
  452. static AlignedArray<Point4F> probePositionArray(MAX_FORWARD_PROBES, sizeof(Point4F));
  453. static AlignedArray<Point4F> probeBoxMinArray(MAX_FORWARD_PROBES, sizeof(Point4F));
  454. static AlignedArray<Point4F> probeBoxMaxArray(MAX_FORWARD_PROBES, sizeof(Point4F));
  455. static AlignedArray<Point4F> probeRefPositionArray(MAX_FORWARD_PROBES, sizeof(Point4F));
  456. static AlignedArray<Point4F> probeConfigArray(MAX_FORWARD_PROBES, sizeof(Point4F));
  457. Vector<MatrixF> probeWorldToObjArray;
  458. probeWorldToObjArray.setSize(MAX_FORWARD_PROBES);
  459. //static AlignedArray<CubemapData> probeCubemap(4, sizeof(CubemapData));
  460. //F32 range;
  461. // Need to clear the buffers so that we don't leak
  462. // lights from previous passes or have NaNs.
  463. dMemset(probePositionArray.getBuffer(), 0, probePositionArray.getBufferSize());
  464. dMemset(probeBoxMinArray.getBuffer(), 0, probeBoxMinArray.getBufferSize());
  465. dMemset(probeBoxMaxArray.getBuffer(), 0, probeBoxMaxArray.getBufferSize());
  466. dMemset(probeRefPositionArray.getBuffer(), 0, probeRefPositionArray.getBufferSize());
  467. dMemset(probeConfigArray.getBuffer(), 0, probeConfigArray.getBufferSize());
  468. matSet.restoreSceneViewProjection();
  469. // Gather the data for the first 4 probes.
  470. /*const ProbeRenderInst *probe;
  471. for (U32 i = 0; i < 4; i++)
  472. {
  473. if (i >= ProbeRenderInst::all.size())
  474. break;
  475. probe = ProbeRenderInst::all[i];
  476. if (!probe)
  477. continue;
  478. if (!probe->mIsEnabled)
  479. continue;
  480. // The light positions and spot directions are
  481. // in SoA order to make optimal use of the GPU.
  482. const Point3F &probePos = probe->getPosition();
  483. probePositions[i].x = probePos.x;
  484. probePositions[i].y = probePos.y;
  485. probePositions[i].z = probePos.z;
  486. probeRadius[i] = probe->mRadius;
  487. const Point3F &minExt = probe->mBounds.minExtents;
  488. probeBoxMins[i].x = minExt.x;
  489. probeBoxMins[i].y = minExt.y;
  490. probeBoxMins[i].z = minExt.z;
  491. const Point3F &maxExt = probe->mBounds.maxExtents;
  492. probeBoxMaxs[i].x = maxExt.x;
  493. probeBoxMaxs[i].y = maxExt.y;
  494. probeBoxMaxs[i].z = maxExt.z;
  495. probeIsSphere[i] = probe->mProbeShapeType == ProbeRenderInst::Sphere ? 1.0 : 0.0;
  496. Point3F localProbePos;
  497. worldToCameraXfm.mulP(probe->getPosition(), &localProbePos);
  498. probeLocalPositions[i].x = localProbePos.x;
  499. probeLocalPositions[i].y = localProbePos.y;
  500. probeLocalPositions[i].z = localProbePos.z;
  501. if (probe->mCubemap && !probe->mCubemap.isNull())
  502. {
  503. S32 samplerReg = probeCubemapSC->getSamplerRegister();
  504. if (samplerReg != -1)
  505. GFX->setCubeTexture(samplerReg + i, probe->mCubemap.getPointer());
  506. }
  507. }*/
  508. //Array rendering
  509. U32 probeCount = ProbeRenderInst::all.size();
  510. //mEffectiveProbeCount = 0;
  511. //mMipCount = 0;
  512. /*if (probePositionArray.size() != MAX_FORWARD_PROBES)
  513. {
  514. probePositionArray.setSize(MAX_FORWARD_PROBES);
  515. probeBoxMinArray.setSize(MAX_FORWARD_PROBES);
  516. probeBoxMaxArray.setSize(MAX_FORWARD_PROBES);
  517. probeBoxMaxArray.setSize(MAX_FORWARD_PROBES);
  518. probeRefPositionArray.setSize(MAX_FORWARD_PROBES);
  519. probeConfigArray.setSize(MAX_FORWARD_PROBES);
  520. probeWorldToObjArray.setSize(MAX_FORWARD_PROBES);
  521. }*/
  522. //cubeMaps.clear();
  523. //irradMaps.clear();
  524. //Vector<U32> cubemapIdxes;
  525. U32 effectiveProbeCount = 0;
  526. bool hasSkylight = false;
  527. for (U32 i = 0; i < probeCount; i++)
  528. {
  529. if (effectiveProbeCount >= 4)
  530. break;
  531. const ProbeRenderInst& curEntry = *ProbeRenderInst::all[i];
  532. if (!curEntry.mIsEnabled)
  533. continue;
  534. if (curEntry.mIsSkylight)
  535. {
  536. if (curEntry.mPrefilterCubemap.isValid() && curEntry.mPrefilterCubemap.isValid())
  537. {
  538. GFX->setCubeTexture(probeShaderConsts->mSkylightSpecularMap->getSamplerRegister(), curEntry.mPrefilterCubemap);
  539. GFX->setCubeTexture(probeShaderConsts->mSkylightIrradMap->getSamplerRegister(), curEntry.mIrradianceCubemap);
  540. shaderConsts->setSafe(probeShaderConsts->mHasSkylight, 1.0f);
  541. hasSkylight = true;
  542. continue;
  543. }
  544. }
  545. else
  546. {
  547. /*probePositions[effectiveProbeCount] = curEntry.getPosition();
  548. probeRefPositions[effectiveProbeCount] = curEntry.mProbeRefOffset;
  549. probeWorldToObj[effectiveProbeCount] = curEntry.getTransform();
  550. probeBBMin[effectiveProbeCount] = curEntry.mBounds.minExtents;
  551. probeBBMax[effectiveProbeCount] = curEntry.mBounds.maxExtents;
  552. probeConfig[effectiveProbeCount] = Point4F(curEntry.mProbeShapeType,
  553. curEntry.mRadius,
  554. curEntry.mAtten,
  555. curEntry.mCubemapIndex);*/
  556. }
  557. effectiveProbeCount++;
  558. }
  559. shaderConsts->setSafe(probeShaderConsts->mProbeCountSC, (float)effectiveProbeCount);
  560. shaderConsts->setSafe(probeShaderConsts->mProbePositionSC, probePositionArray);
  561. shaderConsts->setSafe(probeShaderConsts->mProbeRefPosSC, probeRefPositionArray);
  562. shaderConsts->set(probeShaderConsts->mWorldToObjArraySC, probeWorldToObjArray.address(), effectiveProbeCount, GFXSCT_Float4x4);
  563. shaderConsts->setSafe(probeShaderConsts->mProbeBoxMinSC, probeBoxMinArray);
  564. shaderConsts->setSafe(probeShaderConsts->mProbeBoxMaxSC, probeBoxMaxArray);
  565. shaderConsts->setSafe(probeShaderConsts->mProbeConfigDataSC, probeConfigArray);
  566. //GFX->setCubeArrayTexture(probeShaderConsts->mProbeSpecularCubemapSC->getSamplerRegister(), mPrefilterArray);
  567. //GFX->setCubeArrayTexture(probeShaderConsts->mProbeIrradianceCubemapSC->getSamplerRegister(), mIrradianceArray);
  568. if (!hasSkylight)
  569. shaderConsts->setSafe(probeShaderConsts->mHasSkylight, 0.0f);
  570. }
  571. /*else
  572. {
  573. if (probeCubemapSC->isValid())
  574. {
  575. for (U32 i = 0; i < 4; ++i)
  576. GFX->setCubeTexture(probeCubemapSC->getSamplerRegister() + i, NULL);
  577. }
  578. }*/
  579. }
  580. void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,
  581. const Material *mat,
  582. const SceneData &sgData,
  583. const SceneRenderState *state,
  584. U32 pass,
  585. GFXShaderConstBuffer *shaderConsts)
  586. {
  587. // Skip this if we're rendering from the deferred bin.
  588. if (sgData.binType == SceneData::DeferredBin)
  589. return;
  590. // if (mRegisteredProbes.empty())
  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. //-----------------------------------------------------------------------------
  607. // render objects
  608. //-----------------------------------------------------------------------------
  609. void RenderProbeMgr::render( SceneRenderState *state )
  610. {
  611. //PROFILE_SCOPE(RenderProbeMgr_render);
  612. if (getProbeArrayEffect() == nullptr)
  613. return;
  614. if (mProbesDirty)
  615. _setupStaticParameters();
  616. // Early out if nothing to draw.
  617. if (!RenderProbeMgr::smRenderReflectionProbes || !state->isDiffusePass() || (!ProbeRenderInst::all.size() || mEffectiveProbeCount == 0 || mCubeMapCount != 0 ) && !hasSkylight)
  618. {
  619. getProbeArrayEffect()->setSkip(true);
  620. return;
  621. }
  622. GFXTransformSaver saver;
  623. GFXDEBUGEVENT_SCOPE(RenderProbeMgr_render, ColorI::WHITE);
  624. // Initialize and set the per-frame parameters after getting
  625. // the vector light material as we use lazy creation.
  626. //_setupPerFrameParameters(state);
  627. //Visualization
  628. String useDebugAtten = Con::getVariable("$Probes::showAttenuation", "0");
  629. mProbeArrayEffect->setShaderMacro("DEBUGVIZ_ATTENUATION", useDebugAtten);
  630. String useDebugSpecCubemap = Con::getVariable("$Probes::showSpecularCubemaps", "0");
  631. mProbeArrayEffect->setShaderMacro("DEBUGVIZ_SPECCUBEMAP", useDebugSpecCubemap);
  632. String useDebugDiffuseCubemap = Con::getVariable("$Probes::showDiffuseCubemaps", "0");
  633. mProbeArrayEffect->setShaderMacro("DEBUGVIZ_DIFFCUBEMAP", useDebugDiffuseCubemap);
  634. String useDebugContrib = Con::getVariable("$Probes::showProbeContrib", "0");
  635. mProbeArrayEffect->setShaderMacro("DEBUGVIZ_CONTRIB", useDebugContrib);
  636. //Array rendering
  637. //U32 probeCount = ProbeRenderInst::all.size();
  638. mProbeArrayEffect->setShaderConst("$hasSkylight", (float)hasSkylight);
  639. if (hasSkylight)
  640. {
  641. mProbeArrayEffect->setCubemapTexture(6, skylightPrefilterMap);
  642. mProbeArrayEffect->setCubemapTexture(7, skylightIrradMap);
  643. }
  644. mProbeArrayEffect->setShaderConst("$numProbes", (float)mEffectiveProbeCount);
  645. mProbeArrayEffect->setShaderConst("$cubeMips", (float)mMipCount);
  646. if (mEffectiveProbeCount != 0)
  647. {
  648. mProbeArrayEffect->setCubemapArrayTexture(4, mPrefilterArray);
  649. mProbeArrayEffect->setCubemapArrayTexture(5, mIrradianceArray);
  650. if (useDebugContrib == String("1"))
  651. {
  652. MRandomLCG RandomGen;
  653. RandomGen.setSeed(mEffectiveProbeCount);
  654. //also set up some colors
  655. Vector<Point4F> contribColors;
  656. contribColors.setSize(MAXPROBECOUNT);
  657. for (U32 i = 0; i < mEffectiveProbeCount; i++)
  658. {
  659. //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
  660. if (i == 0)
  661. contribColors[i] = Point4F(1, 0, 0, 1);
  662. else if (i == 1)
  663. contribColors[i] = Point4F(0, 1, 0, 1);
  664. else if (i == 2)
  665. contribColors[i] = Point4F(0, 0, 1, 1);
  666. else
  667. contribColors[i] = Point4F(RandomGen.randF(0, 1), RandomGen.randF(0, 1), RandomGen.randF(0, 1), 1);
  668. }
  669. mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);
  670. }
  671. mProbeArrayEffect->setShaderConst("$inProbePosArray", probePositionsData);
  672. mProbeArrayEffect->setShaderConst("$inRefPosArray", probeRefPositionsData);
  673. mProbeArrayEffect->setShaderConst("$worldToObjArray", probeWorldToObjData);
  674. mProbeArrayEffect->setShaderConst("$bbMinArray", probeBBMinData);
  675. mProbeArrayEffect->setShaderConst("$bbMaxArray", probeBBMaxData);
  676. mProbeArrayEffect->setShaderConst("$probeConfigData", probeConfigData);
  677. }
  678. // Make sure the effect is gonna render.
  679. getProbeArrayEffect()->setSkip(false);
  680. //PROFILE_END();
  681. }
  682. void RenderProbeMgr::bakeProbe(ReflectionProbe *probe)
  683. {
  684. GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
  685. Con::warnf("RenderProbeMgr::bakeProbe() - Beginning bake!");
  686. U32 startMSTime = Platform::getRealMilliseconds();
  687. String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
  688. U32 resolution = Con::getIntVariable("$pref::ReflectionProbes::BakeResolution", 64);
  689. U32 prefilterMipLevels = mLog2(F32(resolution));
  690. bool renderWithProbes = Con::getIntVariable("$pref::ReflectionProbes::RenderWithProbes", false);
  691. ReflectionProbe *clientProbe = static_cast<ReflectionProbe*>(probe->getClientObject());
  692. if (clientProbe == nullptr)
  693. return;
  694. String probePrefilterPath = clientProbe->getPrefilterMapPath();
  695. String probeIrradPath = clientProbe->getIrradianceMapPath();
  696. if (clientProbe->mReflectionModeType != ReflectionProbe::DynamicCubemap)
  697. {
  698. //Prep our bake path
  699. if (probePrefilterPath.isEmpty() || probeIrradPath.isEmpty())
  700. {
  701. Con::errorf("RenderProbeMgr::bake() - Unable to bake our captures because probe doesn't have a path set");
  702. return;
  703. }
  704. }
  705. // Save the current transforms so we can restore
  706. // it for child control rendering below.
  707. GFXTransformSaver saver;
  708. bool probeRenderState = RenderProbeMgr::smRenderReflectionProbes;
  709. F32 farPlane = 1000.0f;
  710. ReflectorDesc reflDesc;
  711. reflDesc.texSize = resolution;
  712. reflDesc.farDist = farPlane;
  713. reflDesc.detailAdjust = 1;
  714. reflDesc.objectTypeMask = -1;
  715. CubeReflector cubeRefl;
  716. cubeRefl.registerReflector(probe, &reflDesc);
  717. ReflectParams reflParams;
  718. //need to get the query somehow. Likely do some sort of get function to fetch from the guiTSControl that's active
  719. CameraQuery query; //need to get the last cameraQuery
  720. query.fov = 90; //90 degree slices for each of the 6 sides
  721. query.nearPlane = 0.1f;
  722. query.farPlane = farPlane;
  723. query.headMatrix = MatrixF();
  724. query.cameraMatrix = clientProbe->getTransform();
  725. Frustum culler;
  726. culler.set(false,
  727. query.fov,
  728. (F32)resolution / (F32)resolution,
  729. query.nearPlane,
  730. query.farPlane,
  731. query.cameraMatrix);
  732. S32 stereoTarget = GFX->getCurrentStereoTarget();
  733. Point2I maxRes(2048, 2048); //basically a boundary so we don't go over this and break stuff
  734. reflParams.culler = culler;
  735. reflParams.eyeId = stereoTarget;
  736. reflParams.query = &query;
  737. reflParams.startOfUpdateMs = startMSTime;
  738. reflParams.viewportExtent = maxRes;
  739. if (!renderWithProbes)
  740. RenderProbeMgr::smRenderReflectionProbes = false;
  741. cubeRefl.updateReflection(reflParams);
  742. //Now, save out the maps
  743. //create irridiance cubemap
  744. if (cubeRefl.getCubemap())
  745. {
  746. //Just to ensure we're prepped for the generation
  747. clientProbe->createClientResources();
  748. //Prep it with whatever resolution we've dictated for our bake
  749. if (clientProbe->mUseHDRCaptures)
  750. {
  751. clientProbe->mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
  752. clientProbe->mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
  753. }
  754. else
  755. {
  756. clientProbe->mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
  757. clientProbe->mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
  758. }
  759. GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
  760. IBLUtilities::GenerateIrradianceMap(renderTarget, cubeRefl.getCubemap(), clientProbe->mIrridianceMap->mCubemap);
  761. IBLUtilities::GeneratePrefilterMap(renderTarget, cubeRefl.getCubemap(), prefilterMipLevels, clientProbe->mPrefilterMap->mCubemap);
  762. U32 endMSTime = Platform::getRealMilliseconds();
  763. F32 diffTime = F32(endMSTime - startMSTime);
  764. Con::warnf("RenderProbeMgr::bake() - Finished Capture! Took %g milliseconds", diffTime);
  765. Con::warnf("RenderProbeMgr::bake() - Beginning save now!");
  766. IBLUtilities::SaveCubeMap(clientProbe->getIrradianceMapPath(), clientProbe->mIrridianceMap->mCubemap);
  767. IBLUtilities::SaveCubeMap(clientProbe->getPrefilterMapPath(), clientProbe->mPrefilterMap->mCubemap);
  768. }
  769. else
  770. {
  771. Con::errorf("RenderProbeMgr::bake() - Didn't generate a valid scene capture cubemap, unable to generate prefilter and irradiance maps!");
  772. }
  773. if (!renderWithProbes)
  774. RenderProbeMgr::smRenderReflectionProbes = probeRenderState;
  775. cubeRefl.unregisterReflector();
  776. U32 endMSTime = Platform::getRealMilliseconds();
  777. F32 diffTime = F32(endMSTime - startMSTime);
  778. Con::warnf("RenderProbeMgr::bake() - Finished bake! Took %g milliseconds", diffTime);
  779. }
  780. void RenderProbeMgr::bakeProbes()
  781. {
  782. //TODO: make this just find every probe in the current missionGroup and run the bake on it automagically
  783. }
  784. DefineEngineMethod(RenderProbeMgr, bakeProbe, void, (ReflectionProbe* probe), (nullAsType< ReflectionProbe*>()),
  785. "@brief returns true if control object is inside the fog\n\n.")
  786. {
  787. if(probe != nullptr)
  788. object->bakeProbe(probe);
  789. }