reflectionProbe.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  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 "T3D/lighting/reflectionProbe.h"
  23. #include "math/mathIO.h"
  24. #include "scene/sceneRenderState.h"
  25. #include "console/consoleTypes.h"
  26. #include "core/stream/bitStream.h"
  27. #include "materials/baseMatInstance.h"
  28. #include "console/engineAPI.h"
  29. #include "gfx/gfxDrawUtil.h"
  30. #include "gfx/gfxDebugEvent.h"
  31. #include "gfx/gfxTransformSaver.h"
  32. #include "math/mathUtils.h"
  33. #include "gfx/bitmap/gBitmap.h"
  34. #include "core/stream/fileStream.h"
  35. #include "core/fileObject.h"
  36. #include "core/resourceManager.h"
  37. #include "console/simPersistId.h"
  38. #include "T3D/gameFunctions.h"
  39. #include "postFx/postEffect.h"
  40. #include "renderInstance/renderProbeMgr.h"
  41. #include "renderInstance/renderProbeMgr.h"
  42. #include "math/util/sphereMesh.h"
  43. #include "materials/materialManager.h"
  44. #include "math/util/matrixSet.h"
  45. #include "gfx/bitmap/cubemapSaver.h"
  46. #include "materials/materialFeatureTypes.h"
  47. #include "gfx/gfxTextureManager.h"
  48. #include "T3D/lighting/IBLUtilities.h"
  49. #include "scene/reflector.h"
  50. extern bool gEditingMission;
  51. extern ColorI gCanvasClearColor;
  52. bool ReflectionProbe::smRenderPreviewProbes = true;
  53. IMPLEMENT_CO_NETOBJECT_V1(ReflectionProbe);
  54. ConsoleDocClass(ReflectionProbe,
  55. "@brief An example scene object which renders a mesh.\n\n"
  56. "This class implements a basic SceneObject that can exist in the world at a "
  57. "3D position and render itself. There are several valid ways to render an "
  58. "object in Torque. This class implements the preferred rendering method which "
  59. "is to submit a MeshRenderInst along with a Material, vertex buffer, "
  60. "primitive buffer, and transform and allow the RenderMeshMgr handle the "
  61. "actual setup and rendering for you.\n\n"
  62. "See the C++ code for implementation details.\n\n"
  63. "@ingroup Examples\n");
  64. ImplementEnumType(ReflectProbeType,
  65. "Type of mesh data available in a shape.\n"
  66. "@ingroup gameObjects")
  67. { ProbeRenderInst::Sphere, "Sphere", "Sphere shaped" },
  68. { ProbeRenderInst::Box, "Box", "Box shape" }
  69. EndImplementEnumType;
  70. ImplementEnumType(ReflectionModeEnum,
  71. "Type of mesh data available in a shape.\n"
  72. "@ingroup gameObjects")
  73. { ReflectionProbe::NoReflection, "No Reflections", "This probe does not provide any local reflection data"},
  74. { ReflectionProbe::StaticCubemap, "Static Cubemap", "Uses a static CubemapData" },
  75. { ReflectionProbe::BakedCubemap, "Baked Cubemap", "Uses a cubemap baked from the probe's current position" },
  76. //{ ReflectionProbe::DynamicCubemap, "Dynamic Cubemap", "Uses a cubemap baked from the probe's current position, updated at a set rate" },
  77. EndImplementEnumType;
  78. //-----------------------------------------------------------------------------
  79. // Object setup and teardown
  80. //-----------------------------------------------------------------------------
  81. ReflectionProbe::ReflectionProbe()
  82. {
  83. // Flag this object so that it will always
  84. // be sent across the network to clients
  85. mNetFlags.set(Ghostable | ScopeAlways);
  86. mTypeMask = LightObjectType | MarkerObjectType;
  87. mProbeShapeType = ProbeRenderInst::Box;
  88. mReflectionModeType = BakedCubemap;
  89. mEnabled = true;
  90. mBake = false;
  91. mDirty = false;
  92. mRadius = 10;
  93. mProbeRefScale = Point3F::One*10;
  94. mUseCubemap = false;
  95. mUseHDRCaptures = true;
  96. mStaticCubemap = NULL;
  97. mProbeUniqueID = "";
  98. mEditorShapeInst = NULL;
  99. mEditorShape = NULL;
  100. mRefreshRateMS = 200;
  101. mDynamicLastBakeMS = 0;
  102. mMaxDrawDistance = 75;
  103. mResourcesCreated = false;
  104. mProbeInfo = nullptr;
  105. mPrefilterSize = 64;
  106. mPrefilterMipLevels = mLog2(F32(mPrefilterSize));
  107. mPrefilterMap = nullptr;
  108. mIrridianceMap = nullptr;
  109. mProbeRefOffset = Point3F::Zero;
  110. mEditPosOffset = false;
  111. mProbeInfoIdx = -1;
  112. mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK;
  113. }
  114. ReflectionProbe::~ReflectionProbe()
  115. {
  116. if (mEditorShapeInst)
  117. SAFE_DELETE(mEditorShapeInst);
  118. if (mProbeInfo)
  119. SAFE_DELETE(mProbeInfo);
  120. if (mReflectionModeType != StaticCubemap && mStaticCubemap)
  121. mStaticCubemap->deleteObject();
  122. }
  123. //-----------------------------------------------------------------------------
  124. // Object Editing
  125. //-----------------------------------------------------------------------------
  126. void ReflectionProbe::initPersistFields()
  127. {
  128. addGroup("Rendering");
  129. addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe),
  130. &_setEnabled, &defaultProtectedGetFn, "Regenerate Voxel Grid");
  131. addField("radius", TypeF32, Offset(mRadius, ReflectionProbe), "The name of the material used to render the mesh.");
  132. //addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
  133. // &_toggleEditPosOffset, &defaultProtectedGetFn, "Toggle Edit Pos Offset Mode", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
  134. endGroup("Rendering");
  135. addGroup("Reflection");
  136. addField("refOffset", TypePoint3F, Offset(mProbeRefOffset, ReflectionProbe), "");
  137. addField("refScale", TypePoint3F, Offset(mProbeRefScale, ReflectionProbe), "");
  138. addField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe),
  139. "The type of mesh data to use for collision queries.");
  140. addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, ReflectionProbe), "Cubemap used instead of reflection texture if fullReflect is off.");
  141. addProtectedField("Bake", TypeBool, Offset(mBake, ReflectionProbe),
  142. &_doBake, &defaultProtectedGetFn, "Regenerate Voxel Grid", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
  143. endGroup("Reflection");
  144. Con::addVariable("$Light::renderReflectionProbes", TypeBool, &RenderProbeMgr::smRenderReflectionProbes,
  145. "Toggles rendering of light frustums when the light is selected in the editor.\n\n"
  146. "@note Only works for shadow mapped lights.\n\n"
  147. "@ingroup Lighting");
  148. Con::addVariable("$Light::renderPreviewProbes", TypeBool, &ReflectionProbe::smRenderPreviewProbes,
  149. "Toggles rendering of light frustums when the light is selected in the editor.\n\n"
  150. "@note Only works for shadow mapped lights.\n\n"
  151. "@ingroup Lighting");
  152. // SceneObject already handles exposing the transform
  153. Parent::initPersistFields();
  154. }
  155. void ReflectionProbe::inspectPostApply()
  156. {
  157. Parent::inspectPostApply();
  158. mDirty = true;
  159. // Flag the network mask to send the updates
  160. // to the client object
  161. setMaskBits(-1);
  162. }
  163. bool ReflectionProbe::_setEnabled(void *object, const char *index, const char *data)
  164. {
  165. ReflectionProbe* probe = reinterpret_cast< ReflectionProbe* >(object);
  166. probe->mEnabled = dAtob(data);
  167. probe->setMaskBits(-1);
  168. return true;
  169. }
  170. bool ReflectionProbe::_doBake(void *object, const char *index, const char *data)
  171. {
  172. ReflectionProbe* probe = reinterpret_cast< ReflectionProbe* >(object);
  173. //if (probe->mDirty)
  174. // probe->bake(probe->mReflectionPath, 256);
  175. ReflectionProbe *clientProbe = (ReflectionProbe*)probe->getClientObject();
  176. if (clientProbe)
  177. {
  178. clientProbe->bake();
  179. }
  180. return false;
  181. }
  182. bool ReflectionProbe::_toggleEditPosOffset(void *object, const char *index, const char *data)
  183. {
  184. ReflectionProbe* probe = reinterpret_cast< ReflectionProbe* >(object);
  185. probe->mEditPosOffset = !probe->mEditPosOffset;
  186. //if (probe->mDirty)
  187. // probe->bake(probe->mReflectionPath, 256);
  188. return false;
  189. }
  190. bool ReflectionProbe::onAdd()
  191. {
  192. if (!Parent::onAdd())
  193. return false;
  194. mEditPosOffset = false;
  195. mObjBox.minExtents.set(-1, -1, -1);
  196. mObjBox.maxExtents.set(1, 1, 1);
  197. //mObjScale.set(mRadius/2, mRadius/2, mRadius/2);
  198. // Skip our transform... it just dirties mask bits.
  199. Parent::setTransform(mObjToWorld);
  200. resetWorldBox();
  201. // Add this object to the scene
  202. addToScene();
  203. if (isServerObject())
  204. {
  205. if (!mPersistentId)
  206. mPersistentId = getOrCreatePersistentId();
  207. mProbeUniqueID = std::to_string(mPersistentId->getUUID().getHash()).c_str();
  208. }
  209. // Refresh this object's material (if any)
  210. if (isClientObject())
  211. {
  212. createGeometry();
  213. updateProbeParams();
  214. PROBEMGR->registerProbe(mProbeInfoIdx);
  215. }
  216. setMaskBits(-1);
  217. return true;
  218. }
  219. void ReflectionProbe::onRemove()
  220. {
  221. if (isClientObject())
  222. {
  223. PROBEMGR->unregisterProbe(mProbeInfoIdx);
  224. }
  225. // Remove this object from the scene
  226. removeFromScene();
  227. Parent::onRemove();
  228. }
  229. void ReflectionProbe::handleDeleteAction()
  230. {
  231. //we're deleting it?
  232. //Then we need to clear out the processed cubemaps(if we have them)
  233. String prefilPath = getPrefilterMapPath();
  234. if (Platform::isFile(prefilPath))
  235. {
  236. Platform::fileDelete(prefilPath);
  237. }
  238. String irrPath = getIrradianceMapPath();
  239. if (Platform::isFile(irrPath))
  240. {
  241. Platform::fileDelete(irrPath);
  242. }
  243. Parent::handleDeleteAction();
  244. }
  245. void ReflectionProbe::setTransform(const MatrixF & mat)
  246. {
  247. // Let SceneObject handle all of the matrix manipulation
  248. if (!mEditPosOffset)
  249. Parent::setTransform(mat);
  250. else
  251. mProbeRefOffset = mat.getPosition();
  252. mDirty = true;
  253. // Dirty our network mask so that the new transform gets
  254. // transmitted to the client object
  255. setMaskBits(TransformMask);
  256. }
  257. U32 ReflectionProbe::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
  258. {
  259. // Allow the Parent to get a crack at writing its info
  260. U32 retMask = Parent::packUpdate(conn, mask, stream);
  261. // Write our transform information
  262. if (stream->writeFlag(mask & TransformMask))
  263. {
  264. mathWrite(*stream, getTransform());
  265. mathWrite(*stream, getScale());
  266. mathWrite(*stream, mProbeRefOffset);
  267. mathWrite(*stream, mProbeRefScale);
  268. }
  269. if (stream->writeFlag(mask & ShapeTypeMask))
  270. {
  271. stream->write((U32)mProbeShapeType);
  272. }
  273. if (stream->writeFlag(mask & UpdateMask))
  274. {
  275. stream->write(mRadius);
  276. }
  277. if (stream->writeFlag(mask & BakeInfoMask))
  278. {
  279. stream->write(mProbeUniqueID);
  280. }
  281. if (stream->writeFlag(mask & EnabledMask))
  282. {
  283. stream->writeFlag(mEnabled);
  284. }
  285. if (stream->writeFlag(mask & ModeMask))
  286. {
  287. stream->write((U32)mReflectionModeType);
  288. }
  289. if (stream->writeFlag(mask & CubemapMask))
  290. {
  291. stream->writeFlag(mUseCubemap);
  292. stream->write(mCubemapName);
  293. }
  294. return retMask;
  295. }
  296. void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream)
  297. {
  298. // Let the Parent read any info it sent
  299. Parent::unpackUpdate(conn, stream);
  300. if (stream->readFlag()) // TransformMask
  301. {
  302. mathRead(*stream, &mObjToWorld);
  303. mathRead(*stream, &mObjScale);
  304. setTransform(mObjToWorld);
  305. mathRead(*stream, &mProbeRefOffset);
  306. mathRead(*stream, &mProbeRefScale);
  307. }
  308. if (stream->readFlag()) // ShapeTypeMask
  309. {
  310. U32 shapeType = ProbeRenderInst::Sphere;
  311. stream->read(&shapeType);
  312. mProbeShapeType = (ProbeRenderInst::ProbeShapeType)shapeType;
  313. createGeometry();
  314. }
  315. if (stream->readFlag()) // UpdateMask
  316. {
  317. stream->read(&mRadius);
  318. }
  319. if (stream->readFlag()) // BakeInfoMask
  320. {
  321. stream->read(&mProbeUniqueID);
  322. }
  323. if (stream->readFlag()) // EnabledMask
  324. {
  325. mEnabled = stream->readFlag();
  326. }
  327. bool isMaterialDirty = false;
  328. if (stream->readFlag()) // ModeMask
  329. {
  330. U32 reflectModeType = BakedCubemap;
  331. stream->read(&reflectModeType);
  332. mReflectionModeType = (ReflectionModeType)reflectModeType;
  333. isMaterialDirty = true;
  334. }
  335. updateProbeParams();
  336. if (stream->readFlag()) // CubemapMask
  337. {
  338. mUseCubemap = stream->readFlag();
  339. String newCubemapName;
  340. stream->read(&mCubemapName);
  341. //if (newCubemapName != mCubemapName)
  342. {
  343. processStaticCubemap();
  344. }
  345. isMaterialDirty = true;
  346. }
  347. if (isMaterialDirty)
  348. {
  349. updateMaterial();
  350. }
  351. PROBEMGR->updateProbes();
  352. }
  353. void ReflectionProbe::createGeometry()
  354. {
  355. // Clean up our previous shape
  356. if (mEditorShapeInst)
  357. SAFE_DELETE(mEditorShapeInst);
  358. mEditorShape = NULL;
  359. String shapeFile = "tools/resources/ReflectProbeSphere.dae";
  360. // Attempt to get the resource from the ResourceManager
  361. mEditorShape = ResourceManager::get().load(shapeFile);
  362. if (mEditorShape)
  363. {
  364. mEditorShapeInst = new TSShapeInstance(mEditorShape, isClientObject());
  365. }
  366. }
  367. //-----------------------------------------------------------------------------
  368. // Object Rendering
  369. //-----------------------------------------------------------------------------
  370. void ReflectionProbe::updateProbeParams()
  371. {
  372. if (mProbeInfo == nullptr)
  373. {
  374. mProbeInfo = new ProbeRenderInst();
  375. mProbeInfoIdx = ProbeRenderInst::all.size() - 1;
  376. mProbeInfo->mIsEnabled = false;
  377. }
  378. updateMaterial();
  379. mProbeInfo->mProbeShapeType = mProbeShapeType;
  380. mProbeInfo->mTransform = getWorldTransform();
  381. mProbeInfo->mPosition = getPosition();
  382. mObjScale.set(mRadius, mRadius, mRadius);
  383. // Skip our transform... it just dirties mask bits.
  384. Parent::setTransform(mObjToWorld);
  385. resetWorldBox();
  386. mProbeInfo->mBounds = mWorldBox;
  387. mProbeInfo->mRadius = mRadius;
  388. mProbeInfo->mIsSkylight = false;
  389. mProbeInfo->mProbeRefOffset = mProbeRefOffset;
  390. mProbeInfo->mProbeRefScale = mProbeRefScale;
  391. mProbeInfo->mDirty = true;
  392. mProbeInfo->mScore = mMaxDrawDistance;
  393. }
  394. void ReflectionProbe::processStaticCubemap()
  395. {
  396. if (mReflectionModeType != StaticCubemap)
  397. return;
  398. createClientResources();
  399. Sim::findObject(mCubemapName, mStaticCubemap);
  400. if (!mStaticCubemap)
  401. {
  402. Con::errorf("ReflectionProbe::updateMaterial() - unable to find static cubemap file!");
  403. return;
  404. }
  405. if (mStaticCubemap->mCubemap == nullptr)
  406. {
  407. mStaticCubemap->createMap();
  408. mStaticCubemap->updateFaces();
  409. }
  410. String prefilPath = getPrefilterMapPath();
  411. String irrPath = getIrradianceMapPath();
  412. if (mUseHDRCaptures)
  413. {
  414. mIrridianceMap->mCubemap->initDynamic(mPrefilterSize, GFXFormatR16G16B16A16F);
  415. mPrefilterMap->mCubemap->initDynamic(mPrefilterSize, GFXFormatR16G16B16A16F);
  416. }
  417. else
  418. {
  419. mIrridianceMap->mCubemap->initDynamic(mPrefilterSize, GFXFormatR8G8B8A8);
  420. mPrefilterMap->mCubemap->initDynamic(mPrefilterSize, GFXFormatR8G8B8A8);
  421. }
  422. //if (!Platform::isFile(irrPath) || !Platform::isFile(prefilPath))
  423. {
  424. GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
  425. IBLUtilities::GenerateIrradianceMap(renderTarget, mStaticCubemap->mCubemap, mIrridianceMap->mCubemap);
  426. IBLUtilities::GeneratePrefilterMap(renderTarget, mStaticCubemap->mCubemap, mPrefilterMipLevels, mPrefilterMap->mCubemap);
  427. IBLUtilities::SaveCubeMap(getIrradianceMapPath(), mIrridianceMap->mCubemap);
  428. IBLUtilities::SaveCubeMap(getPrefilterMapPath(), mPrefilterMap->mCubemap);
  429. }
  430. mProbeInfo->mCubemap = mPrefilterMap->mCubemap;
  431. mProbeInfo->mIrradianceCubemap = mIrridianceMap->mCubemap;
  432. }
  433. void ReflectionProbe::updateMaterial()
  434. {
  435. createClientResources();
  436. if (mReflectionModeType != DynamicCubemap)
  437. {
  438. mProbeInfo->mCubeReflector.unregisterReflector();
  439. if ((mReflectionModeType == BakedCubemap) && !mProbeUniqueID.isEmpty())
  440. {
  441. if (mPrefilterMap != nullptr && mPrefilterMap->mCubemap.isValid())
  442. {
  443. mProbeInfo->mCubemap = mPrefilterMap->mCubemap;
  444. }
  445. else
  446. {
  447. mEnabled = false;
  448. }
  449. if (mIrridianceMap != nullptr && mIrridianceMap->mCubemap.isValid())
  450. {
  451. mProbeInfo->mIrradianceCubemap = mIrridianceMap->mCubemap;
  452. }
  453. else
  454. {
  455. mEnabled = false;
  456. }
  457. }
  458. }
  459. else
  460. {
  461. if (mReflectionModeType == DynamicCubemap && !mDynamicCubemap.isNull())
  462. {
  463. mProbeInfo->mCubemap = mDynamicCubemap;
  464. mProbeInfo->mCubeReflector.registerReflector(this, reflectorDesc); //need to decide how we wanna do the reflectorDesc. static name or a field
  465. }
  466. else
  467. {
  468. mEnabled = false;
  469. }
  470. }
  471. //Make us ready to render
  472. if (mEnabled)
  473. mProbeInfo->mIsEnabled = true;
  474. else
  475. mProbeInfo->mIsEnabled = false;
  476. PROBEMGR->updateProbes();
  477. }
  478. bool ReflectionProbe::createClientResources()
  479. {
  480. //irridiance resources
  481. if (!mIrridianceMap)
  482. {
  483. mIrridianceMap = new CubemapData();
  484. mIrridianceMap->registerObject();
  485. mIrridianceMap->createMap();
  486. }
  487. String irrPath = getIrradianceMapPath();
  488. if (Platform::isFile(irrPath))
  489. {
  490. mIrridianceMap->setCubemapFile(FileName(irrPath));
  491. mIrridianceMap->updateFaces();
  492. }
  493. if (mIrridianceMap->mCubemap.isNull())
  494. Con::errorf("ReflectionProbe::createClientResources() - Unable to load baked irradiance map at %s", getIrradianceMapPath().c_str());
  495. //
  496. if (!mPrefilterMap)
  497. {
  498. mPrefilterMap = new CubemapData();
  499. mPrefilterMap->registerObject();
  500. mPrefilterMap->createMap();
  501. }
  502. String prefilPath = getPrefilterMapPath();
  503. if (Platform::isFile(prefilPath))
  504. {
  505. mPrefilterMap->setCubemapFile(FileName(prefilPath));
  506. mPrefilterMap->updateFaces();
  507. }
  508. if (mPrefilterMap->mCubemap.isNull())
  509. Con::errorf("ReflectionProbe::createClientResources() - Unable to load baked prefilter map at %s", getPrefilterMapPath().c_str());
  510. mResourcesCreated = true;
  511. return true;
  512. }
  513. void ReflectionProbe::generateTextures()
  514. {
  515. }
  516. void ReflectionProbe::prepRenderImage(SceneRenderState *state)
  517. {
  518. if (!mEnabled || !RenderProbeMgr::smRenderReflectionProbes)
  519. return;
  520. Point3F distVec = getRenderPosition() - state->getCameraPosition();
  521. F32 dist = distVec.len();
  522. //Culling distance. Can be adjusted for performance options considerations via the scalar
  523. if (dist > mMaxDrawDistance * Con::getFloatVariable("$pref::GI::ProbeDrawDistScale", 1.0))
  524. {
  525. mProbeInfo->mScore = mMaxDrawDistance;
  526. return;
  527. }
  528. if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS))
  529. {
  530. bake();
  531. mDynamicLastBakeMS = Platform::getRealMilliseconds();
  532. }
  533. //Submit our probe to actually do the probe action
  534. // Get a handy pointer to our RenderPassmanager
  535. //RenderPassManager *renderPass = state->getRenderPass();
  536. //Update our score based on our radius, distance
  537. mProbeInfo->mScore = mProbeInfo->mRadius/mMax(dist,1.0f);
  538. Point3F vect = distVec;
  539. vect.normalizeSafe();
  540. mProbeInfo->mScore *= mMax(mAbs(mDot(vect, state->getCameraTransform().getForwardVector())),0.001f);
  541. //Register
  542. //PROBEMGR->registerProbe(mProbeInfoIdx);
  543. if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
  544. {
  545. GFXTransformSaver saver;
  546. // Calculate the distance of this object from the camera
  547. Point3F cameraOffset;
  548. getRenderTransform().getColumn(3, &cameraOffset);
  549. cameraOffset -= state->getDiffuseCameraPosition();
  550. dist = cameraOffset.len();
  551. if (dist < 0.01f)
  552. dist = 0.01f;
  553. // Set up the LOD for the shape
  554. F32 invScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
  555. mEditorShapeInst->setDetailFromDistance(state, dist * invScale);
  556. // Make sure we have a valid level of detail
  557. if (mEditorShapeInst->getCurrentDetail() < 0)
  558. return;
  559. BaseMatInstance* probePrevMat = mEditorShapeInst->getMaterialList()->getMaterialInst(0);
  560. setPreviewMatParameters(state, probePrevMat);
  561. // GFXTransformSaver is a handy helper class that restores
  562. // the current GFX matrices to their original values when
  563. // it goes out of scope at the end of the function
  564. // Set up our TS render state
  565. TSRenderState rdata;
  566. rdata.setSceneState(state);
  567. rdata.setFadeOverride(1.0f);
  568. if(mReflectionModeType != DynamicCubemap)
  569. rdata.setCubemap(mPrefilterMap->mCubemap);
  570. else
  571. rdata.setCubemap(mDynamicCubemap);
  572. // We might have some forward lit materials
  573. // so pass down a query to gather lights.
  574. LightQuery query;
  575. query.init(getWorldSphere());
  576. rdata.setLightQuery(&query);
  577. // Set the world matrix to the objects render transform
  578. MatrixF mat = getRenderTransform();
  579. mat.scale(Point3F(1, 1, 1));
  580. Point3F centerPos = mat.getPosition();
  581. centerPos += mProbeRefOffset;
  582. mat.setPosition(centerPos);
  583. GFX->setWorldMatrix(mat);
  584. // Animate the the shape
  585. mEditorShapeInst->animate();
  586. // Allow the shape to submit the RenderInst(s) for itself
  587. mEditorShapeInst->render(rdata);
  588. saver.restore();
  589. }
  590. // If the light is selected or light visualization
  591. // is enabled then register the callback.
  592. const bool isSelectedInEditor = (gEditingMission && isSelected());
  593. if (isSelectedInEditor)
  594. {
  595. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  596. ri->renderDelegate.bind(this, &ReflectionProbe::_onRenderViz);
  597. ri->type = RenderPassManager::RIT_Editor;
  598. state->getRenderPass()->addInst(ri);
  599. }
  600. }
  601. void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri,
  602. SceneRenderState *state,
  603. BaseMatInstance *overrideMat)
  604. {
  605. if (!RenderProbeMgr::smRenderReflectionProbes)
  606. return;
  607. GFXDrawUtil *draw = GFX->getDrawUtil();
  608. GFXStateBlockDesc desc;
  609. desc.setZReadWrite(true, false);
  610. desc.setCullMode(GFXCullNone);
  611. desc.setBlend(true);
  612. // Base the sphere color on the light color.
  613. ColorI color = ColorI::WHITE;
  614. color.alpha = 25;
  615. const MatrixF worldToObjectXfm = getTransform();
  616. if (mProbeShapeType == ProbeRenderInst::Sphere)
  617. {
  618. draw->drawSphere(desc, mRadius, getPosition(), color);
  619. }
  620. else
  621. {
  622. Box3F projCube(-Point3F(mRadius, mRadius, mRadius),Point3F(mRadius, mRadius, mRadius));
  623. projCube.setCenter(getPosition());
  624. draw->drawCube(desc, projCube, color, &worldToObjectXfm);
  625. }
  626. Box3F refCube = getWorldBox();
  627. refCube.set(mProbeRefScale);
  628. refCube.setCenter(getPosition() + mProbeRefOffset);
  629. color = ColorI::BLUE;
  630. color.alpha = 25;
  631. draw->drawCube(desc, refCube, color, &worldToObjectXfm);
  632. }
  633. void ReflectionProbe::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
  634. {
  635. if (!mat->getFeatures().hasFeature(MFT_isDeferred))
  636. return;
  637. //Set up the params
  638. MaterialParameters *matParams = mat->getMaterialParameters();
  639. //Get the deferred render target
  640. NamedTexTarget* deferredTexTarget = NamedTexTarget::find("deferred");
  641. GFXTextureObject *deferredTexObject = deferredTexTarget->getTexture();
  642. if (!deferredTexObject)
  643. return;
  644. GFX->setTexture(0, deferredTexObject);
  645. //Set the cubemap
  646. GFX->setCubeTexture(1, mPrefilterMap->mCubemap);
  647. //Set the invViewMat
  648. MatrixSet &matrixSet = renderState->getRenderPass()->getMatrixSet();
  649. const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();
  650. MaterialParameterHandle *invViewMat = mat->getMaterialParameterHandle("$invViewMat");
  651. matParams->setSafe(invViewMat, worldToCameraXfm);
  652. }
  653. DefineEngineMethod(ReflectionProbe, postApply, void, (), ,
  654. "A utility method for forcing a network update.\n")
  655. {
  656. object->inspectPostApply();
  657. }
  658. String ReflectionProbe::getPrefilterMapPath()
  659. {
  660. if (mProbeUniqueID.isEmpty())
  661. {
  662. Con::errorf("ReflectionProbe::getPrefilterMapPath() - We don't have a set output path or persistant id, so no valid path can be provided!");
  663. return "";
  664. }
  665. String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
  666. char fileName[256];
  667. dSprintf(fileName, 256, "%s%s_Prefilter.dds", path.c_str(), mProbeUniqueID.c_str());
  668. return fileName;
  669. }
  670. String ReflectionProbe::getIrradianceMapPath()
  671. {
  672. if (mProbeUniqueID.isEmpty())
  673. {
  674. Con::errorf("ReflectionProbe::getIrradianceMapPath() - We don't have a set output path or persistant id, so no valid path can be provided!");
  675. return "";
  676. }
  677. String path = Con::getVariable("$pref::ReflectionProbes::CurrentLevelPath", "levels/");
  678. char fileName[256];
  679. dSprintf(fileName, 256, "%s%s_Irradiance.dds", path.c_str(), mProbeUniqueID.c_str());
  680. return fileName;
  681. }
  682. void ReflectionProbe::bake()
  683. {
  684. if (mReflectionModeType == DynamicCubemap)
  685. return;
  686. PROBEMGR->bakeProbe(this);
  687. setMaskBits(CubemapMask);
  688. }
  689. DefineEngineMethod(ReflectionProbe, Bake, void, (), ,
  690. "@brief returns true if control object is inside the fog\n\n.")
  691. {
  692. ReflectionProbe *clientProbe = (ReflectionProbe*)object->getClientObject();
  693. if (clientProbe)
  694. {
  695. clientProbe->bake();
  696. }
  697. }