llvlcomposition.cpp 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. /**
  2. * @file llvlcomposition.cpp
  3. * @brief Viewer-side representation of a composition layer...
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llvlcomposition.h"
  34. #include "imageids.h"
  35. #include "llmutex.h"
  36. #include "llnoise.h"
  37. #include "llregionhandle.h" // For from_region_handle()
  38. #include "llgltfmateriallist.h"
  39. #include "llstartup.h"
  40. #include "llsurface.h"
  41. #include "llviewercontrol.h"
  42. #include "llviewerregion.h"
  43. #include "llviewertexturelist.h"
  44. constexpr S32 BASE_SIZE = 128;
  45. // Helper functions
  46. // Not sure if this is the right math... Takes the weighted average of all four
  47. // points (bilinear interpolation)
  48. static F32 bilinear(F32 v00, F32 v01, F32 v10, F32 v11, F32 x_frac, F32 y_frac)
  49. {
  50. F32 inv_x_frac = 1.f - x_frac;
  51. F32 inv_y_frac = 1.f - y_frac;
  52. return inv_x_frac * inv_y_frac * v00 + x_frac * inv_y_frac * v10 +
  53. inv_x_frac * y_frac * v01 + x_frac * y_frac * v11;
  54. }
  55. static void boost_terrain_texture(LLViewerFetchedTexture* texp,
  56. bool mega_texture = true)
  57. {
  58. constexpr F32 area_1k = 1024.f * 1024.f;
  59. constexpr F32 area_2k = 2048.f * 2048.f;
  60. if (texp)
  61. {
  62. texp->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
  63. if (mega_texture)
  64. {
  65. texp->addTextureStats(area_2k);
  66. texp->setMegaTexture(true);
  67. }
  68. else
  69. {
  70. texp->addTextureStats(area_1k);
  71. }
  72. }
  73. }
  74. static void unboost_terrain_texture(LLViewerFetchedTexture* texp)
  75. {
  76. if (texp)
  77. {
  78. texp->setBoostLevel(LLGLTexture::BOOST_NONE);
  79. texp->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1);
  80. texp->forceActive();
  81. }
  82. }
  83. static void boost_terrain_material(LLFetchedGLTFMaterial* matp)
  84. {
  85. if (matp)
  86. {
  87. boost_terrain_texture(matp->mBaseColorTexture);
  88. boost_terrain_texture(matp->mNormalTexture);
  89. boost_terrain_texture(matp->mMetallicRoughnessTexture);
  90. // Do not set emissive as a mega texture. HB
  91. boost_terrain_texture(matp->mEmissiveTexture, false);
  92. }
  93. }
  94. static void unboost_terrain_material(LLFetchedGLTFMaterial* matp)
  95. {
  96. if (matp)
  97. {
  98. unboost_terrain_texture(matp->mBaseColorTexture);
  99. unboost_terrain_texture(matp->mNormalTexture);
  100. unboost_terrain_texture(matp->mMetallicRoughnessTexture);
  101. unboost_terrain_texture(matp->mEmissiveTexture);
  102. }
  103. }
  104. static LLPointer<LLViewerFetchedTexture> fetch_terrain_tex(const LLUUID& id)
  105. {
  106. if (id.isNull())
  107. {
  108. return nullptr;
  109. }
  110. LLPointer<LLViewerFetchedTexture> texp =
  111. LLViewerTextureManager::getFetchedTexture(id);
  112. // Non-loading mini-map textures fixes follow...
  113. // We need the maximum resolution (lowest discard level) to avoid partly
  114. // loaded textures that would never complete (probably a race condition
  115. // issue in the fetcher, with loading textures and changing the discard
  116. // level while they load): the textures will get appropriately discarded
  117. // anyway, once the composition will have been created from them. HB.
  118. texp->setMinDiscardLevel(0);
  119. // We also need to give this kind of textures the highest (and appropriate)
  120. // priority from the start... HB.
  121. texp->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
  122. #if !LL_IMPLICIT_SETNODELETE
  123. texp->setNoDelete();
  124. #endif
  125. return texp;
  126. }
  127. ///////////////////////////////////////////////////////////////////////////////
  128. // LLViewerLayer class
  129. ///////////////////////////////////////////////////////////////////////////////
  130. LLViewerLayer::LLViewerLayer(S32 width, F32 scale)
  131. : mWidth(width),
  132. mScale(scale),
  133. mScaleInv(1.f / scale)
  134. {
  135. mDatap = new F32[width * width];
  136. for (S32 i = 0; i < width * width; ++i)
  137. {
  138. *(mDatap + i) = 0.f;
  139. }
  140. }
  141. LLViewerLayer::~LLViewerLayer()
  142. {
  143. delete[] mDatap;
  144. mDatap = NULL;
  145. }
  146. F32 LLViewerLayer::getValueScaled(F32 x, F32 y) const
  147. {
  148. F32 x_frac = x * mScaleInv;
  149. S32 x1 = llfloor(x_frac);
  150. S32 x2 = x1 + 1;
  151. x_frac -= x1;
  152. F32 y_frac = y * mScaleInv;
  153. S32 y1 = llfloor(y_frac);
  154. S32 y2 = y1 + 1;
  155. y_frac -= y1;
  156. S32 max = mWidth - 1;
  157. x1 = llclamp(x1, 0, max);
  158. x2 = llclamp(x2, 0, max);
  159. y1 = llclamp(y1, 0, max);
  160. y2 = llclamp(y2, 0, max);
  161. // Take weighted average of all four points (bilinear interpolation)
  162. S32 row1 = y1 * mWidth;
  163. S32 row2 = y2 * mWidth;
  164. // Access in squential order in memory, and do not use immediately.
  165. F32 row1_left = mDatap[row1 + x1];
  166. F32 row1_right = mDatap[row1 + x2];
  167. F32 row2_left = mDatap[row2 + x1];
  168. F32 row2_right = mDatap[row2 + x2];
  169. F32 row1_interp = row1_left - x_frac * (row1_left - row1_right);
  170. F32 row2_interp = row2_left - x_frac * (row2_left - row2_right);
  171. return row1_interp - y_frac * (row1_interp - row2_interp);
  172. }
  173. ///////////////////////////////////////////////////////////////////////////////
  174. // LLTerrain class
  175. ///////////////////////////////////////////////////////////////////////////////
  176. // We need a mutex to protect sGlobalAssets since while the latter is modified
  177. // only from the main thread, it is queried from the main thread and worker
  178. // threads. HB
  179. static LLMutex sAssetListMutex;
  180. // Since the same asset Id can be used in multiple regions, we must count the
  181. // number of times we have it in use to know when we can remove that Id from
  182. // the global list, thus the map... HB
  183. static fast_hmap<LLUUID, S32> sGlobalAssets;
  184. // *HACK: on login in main SL land, sim servers send a first set of terrain
  185. // textures Ids (estate terrains, perhaps ?) inside an inital "RegionHandshake"
  186. // message for the agent region in STATE_WORLD_INIT, then a second identical
  187. // message in STATE_AGENT_WAIT, but with the actual terrain assets... It means
  188. // that the fetch for the first set of assets will have started (and will fail
  189. // for the GLTF fetcher, since these are texture assets), but that the fetch
  190. // may not have yet completed when receiving the new set of Ids, at which point
  191. // we would remove the old Ids from our sGlobalAssets map, causing the GLTF
  192. // material assets fetcher to warn on fetch completion failure about missing
  193. // assets while this was expected and that this pointless warning was supposed
  194. // to be avoided... So, let's use a second list, for early asset fetches ! HB
  195. static uuid_list_t sEarlyAssets;
  196. //static
  197. void LLTerrain::addGlobalAsset(const LLUUID& id)
  198. {
  199. if (id.isNull())
  200. {
  201. return;
  202. }
  203. sAssetListMutex.lock();
  204. fast_hmap<LLUUID, S32>::iterator it = sGlobalAssets.find(id);
  205. if (it == sGlobalAssets.end())
  206. {
  207. LL_DEBUGS("RegionTexture") << "Registering new terrain Id: " << id
  208. << LL_ENDL;
  209. sGlobalAssets.emplace(id, 1);
  210. }
  211. else
  212. {
  213. ++(it->second);
  214. LL_DEBUGS("RegionTexture") << "Incremented usage (" << it->second
  215. <<") for terrain Id: " << id << LL_ENDL;
  216. }
  217. // *HACK: see the above comment for sEarlyAssets. HB
  218. if (LLStartUp::getStartupState() < EStartupState::STATE_AGENT_WAIT)
  219. {
  220. LL_DEBUGS("RegionTexture") << "Registering early terrain Id: " << id
  221. << LL_ENDL;
  222. sEarlyAssets.emplace(id);
  223. }
  224. sAssetListMutex.unlock();
  225. }
  226. //static
  227. void LLTerrain::removeGlobalAsset(const LLUUID& id)
  228. {
  229. if (id.isNull())
  230. {
  231. return;
  232. }
  233. sAssetListMutex.lock();
  234. fast_hmap<LLUUID, S32>::iterator it = sGlobalAssets.find(id);
  235. if (it != sGlobalAssets.end())
  236. {
  237. if (--(it->second) <= 0)
  238. {
  239. LL_DEBUGS("RegionTexture") << "Removing terrain Id: " << id
  240. << LL_ENDL;
  241. sGlobalAssets.erase(it);
  242. }
  243. }
  244. sAssetListMutex.unlock();
  245. }
  246. //static
  247. bool LLTerrain::isAsset(const LLUUID& id)
  248. {
  249. sAssetListMutex.lock();
  250. bool in_list = sGlobalAssets.count(id);
  251. #if 0 // Ideally, we should clear this easly assets list, after "a while",
  252. // but we cannot know, a priori, how long "a while" will actually
  253. // take; it depends on the asset fetch duration, and has been seen
  254. // happening even some time after login has completed, so... HB
  255. if (LLStartUp::isLoggedIn())
  256. {
  257. sEarlyAssets.clear();
  258. }
  259. else
  260. #endif
  261. if (!in_list)
  262. {
  263. in_list = sEarlyAssets.count(id);
  264. if (in_list)
  265. {
  266. LL_DEBUGS("RegionTexture") << "Early terrain Id recognized: " << id
  267. << LL_ENDL;
  268. }
  269. }
  270. sAssetListMutex.unlock();
  271. return in_list;
  272. }
  273. LLTerrain::LLTerrain()
  274. : mTerrainType(0)
  275. {
  276. for (U32 i = 0; i < ASSET_COUNT; ++i)
  277. {
  278. mMaterialTexturesSet[i] = false;
  279. }
  280. }
  281. //virtual
  282. LLTerrain::~LLTerrain()
  283. {
  284. for (U32 i = 0; i < ASSET_COUNT; ++i)
  285. {
  286. unboost_terrain_texture(mDetailTextures[i]);
  287. unboost_terrain_material(mDetailMaterials[i]);
  288. removeGlobalAsset(mAssetIds[i]);
  289. }
  290. }
  291. //virtual
  292. void LLTerrain::setDetailAssetID(U32 asset, const LLUUID& id)
  293. {
  294. if (asset >= ASSET_COUNT)
  295. {
  296. llassert(false);
  297. return;
  298. }
  299. if (mAssetIds[asset] == id)
  300. {
  301. return; // Nothing to do ! HB
  302. }
  303. // This must be reset, in case the terrain would have changed from textures
  304. // to PBR materials or vice versa. The next call to isPBR() will resync it
  305. // accordingly. HB
  306. mTerrainType = 0;
  307. // Tell the texture and material fetchers that we do not know, a priori,
  308. // whether this asset Id corresponds to a texture or a material, and that
  309. // the fetch may therefore fail (and will indeed fail for one of the two
  310. // fetchers)... So dirty ! I wish LL had added a flag in the RegionInfo
  311. // UDP message block to indicate a PBR material terrain type... HB
  312. addGlobalAsset(id);
  313. // And unregister any old asset Id (will be ignored if a null UUID).
  314. removeGlobalAsset(mAssetIds[asset]);
  315. // Keep track of our new asset Id.
  316. mAssetIds[asset] = id;
  317. mDetailTextures[asset] = fetch_terrain_tex(id);
  318. if (id.isNull())
  319. {
  320. mDetailMaterials[asset] = NULL;
  321. }
  322. else
  323. {
  324. mDetailMaterials[asset] = gGLTFMaterialList.getMaterial(id);
  325. }
  326. mMaterialTexturesSet[asset] = false;
  327. }
  328. bool LLTerrain::isPBR()
  329. {
  330. constexpr U32 TT_TEXTURES = 1;
  331. constexpr U32 TT_MATERIALS = 2;
  332. if (mTerrainType)
  333. {
  334. return mTerrainType == TT_MATERIALS;
  335. }
  336. if (texturesReady(false, false))
  337. {
  338. mTerrainType = TT_TEXTURES;
  339. return false;
  340. }
  341. if (materialsReady(false, false))
  342. {
  343. mTerrainType = TT_MATERIALS;
  344. return true;
  345. }
  346. return false;
  347. }
  348. bool LLTerrain::texturesReady(bool boost_it, bool strict)
  349. {
  350. bool one_ready = false;
  351. bool all_ready = true;
  352. // Note: calls to textureReady may boost textures. Do not early-return.
  353. for (U32 i = 0; i < ASSET_COUNT; i++)
  354. {
  355. if (mDetailTextures[i].notNull() &&
  356. textureReady(mDetailTextures[i], boost_it))
  357. {
  358. one_ready = true;
  359. }
  360. else
  361. {
  362. all_ready = false;
  363. }
  364. }
  365. return strict ? all_ready : one_ready;
  366. }
  367. bool LLTerrain::materialsReady(bool boost_it, bool strict)
  368. {
  369. bool one_ready = false;
  370. bool all_ready = true;
  371. // Note: calls to textureReady may boost textures. Do not early-return.
  372. for (U32 i = 0; i < ASSET_COUNT; i++)
  373. {
  374. if (materialReady(mDetailMaterials[i], mMaterialTexturesSet[i],
  375. boost_it, strict))
  376. {
  377. one_ready = true;
  378. }
  379. else
  380. {
  381. all_ready = false;
  382. }
  383. }
  384. return strict ? all_ready : one_ready;
  385. }
  386. //static
  387. bool LLTerrain::textureReady(LLViewerFetchedTexture* texp, bool boost_it)
  388. {
  389. if (!texp || texp->getComponents() == 0)
  390. {
  391. return false;
  392. }
  393. S32 discard = texp->getDiscardLevel();
  394. if (discard < 0)
  395. {
  396. if (boost_it)
  397. {
  398. texp->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
  399. texp->addTextureStats(BASE_SIZE * BASE_SIZE);
  400. }
  401. return false;
  402. }
  403. if (discard != 0 &&
  404. (texp->getWidth() < BASE_SIZE || texp->getHeight() < BASE_SIZE))
  405. {
  406. if (boost_it)
  407. {
  408. texp->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
  409. S32 min_dim = llmin(texp->getFullWidth(), texp->getFullHeight());
  410. S32 ddiscard = 0;
  411. while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
  412. {
  413. ++ddiscard;
  414. min_dim /= 2;
  415. }
  416. texp->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
  417. texp->setMinDiscardLevel(ddiscard);
  418. texp->addTextureStats(BASE_SIZE * BASE_SIZE);
  419. }
  420. return false;
  421. }
  422. return true;
  423. }
  424. //static
  425. bool LLTerrain::materialReady(LLFetchedGLTFMaterial* matp, bool& textures_set,
  426. bool boost_it, bool strict)
  427. {
  428. if (!matp || !matp->isLoaded())
  429. {
  430. return false;
  431. }
  432. // Material is loaded, but textures may not be
  433. if (!textures_set)
  434. {
  435. textures_set = true;
  436. // Note: these can sometimes be set to to NULL due to what happens in
  437. // updateTEMaterialTextures(). For the sake of robustness, we emulate
  438. // that fetching behavior by setting null UUID textures to NULL.
  439. const LLGLTFMaterial::uuid_array_t& texids = matp->mTextureId;
  440. matp->mBaseColorTexture = fetch_terrain_tex(texids[BASECOLIDX]);
  441. matp->mNormalTexture = fetch_terrain_tex(texids[NORMALIDX]);
  442. matp->mMetallicRoughnessTexture = fetch_terrain_tex(texids[MROUGHIDX]);
  443. matp->mEmissiveTexture = fetch_terrain_tex(texids[EMISSIVEIDX]);
  444. }
  445. // Note: calls to textureReady may boost textures; do not early-return.
  446. bool all_ready = true;
  447. if (matp->mTextureId[BASECOLIDX].notNull() &&
  448. !textureReady(matp->mBaseColorTexture, boost_it))
  449. {
  450. all_ready = false;
  451. }
  452. if (matp->mTextureId[NORMALIDX].notNull() &&
  453. !textureReady(matp->mNormalTexture, boost_it))
  454. {
  455. all_ready = false;
  456. }
  457. if (matp->mTextureId[MROUGHIDX].notNull() &&
  458. !textureReady(matp->mMetallicRoughnessTexture, boost_it))
  459. {
  460. all_ready = false;
  461. }
  462. if (matp->mTextureId[EMISSIVEIDX].notNull() &&
  463. !textureReady(matp->mEmissiveTexture, boost_it))
  464. {
  465. all_ready = false;
  466. }
  467. return all_ready || !strict;
  468. }
  469. void LLTerrain::getTextures(std::vector<LLViewerTexture*>& textures)
  470. {
  471. textures.resize(ASSET_COUNT);
  472. if (isPBR())
  473. {
  474. LLViewerTexture* default_texp = LLViewerFetchedTexture::sDefaultImagep;
  475. for (U32 i = 0; i < ASSET_COUNT; ++i)
  476. {
  477. LLFetchedGLTFMaterial* matp = mDetailMaterials[i].get();
  478. textures[i] = matp ? matp->mBaseColorTexture : default_texp;
  479. // It may happen there is not even a base color texture... HB
  480. if (!textures[i])
  481. {
  482. textures[i] = default_texp;
  483. }
  484. }
  485. }
  486. else
  487. {
  488. for (U32 i = 0; i < ASSET_COUNT; ++i)
  489. {
  490. textures[i] = mDetailTextures[i];
  491. }
  492. }
  493. }
  494. void LLTerrain::getGLTFMaterials(std::vector<LLGLTFMaterial*>& materials)
  495. {
  496. static LLGLTFMaterial default_mat(LLGLTFMaterial::sDefault);
  497. materials.resize(ASSET_COUNT);
  498. for (U32 i = 0; i < ASSET_COUNT; ++i)
  499. {
  500. LLGLTFMaterial* matp = mDetailMaterials[i].get();
  501. if (matp)
  502. {
  503. materials[i] = matp;
  504. }
  505. else
  506. {
  507. materials[i] = &default_mat;
  508. }
  509. }
  510. }
  511. void LLTerrain::boostTextures()
  512. {
  513. if (isPBR())
  514. {
  515. for (U32 i = 0; i < ASSET_COUNT; ++i)
  516. {
  517. boost_terrain_material(mDetailMaterials[i].get());
  518. }
  519. }
  520. else
  521. {
  522. for (U32 i = 0; i < ASSET_COUNT; ++i)
  523. {
  524. boost_terrain_texture(mDetailTextures[i].get());
  525. }
  526. }
  527. }
  528. ///////////////////////////////////////////////////////////////////////////////
  529. // LLVLComposition class
  530. ///////////////////////////////////////////////////////////////////////////////
  531. LLVLComposition::LLVLComposition(LLSurface* surfacep, U32 width, F32 scale)
  532. : LLTerrain(),
  533. LLViewerLayer(width, scale),
  534. mSurfacep(surfacep),
  535. mTexScaleX(16.f),
  536. mTexScaleY(16.f),
  537. mParamsReady(false)
  538. {
  539. // Load terrain textures - Original ones
  540. static const LLUUID default_textures[ASSET_COUNT] =
  541. {
  542. TERRAIN_DIRT_DETAIL,
  543. TERRAIN_GRASS_DETAIL,
  544. TERRAIN_MOUNTAIN_DETAIL,
  545. TERRAIN_ROCK_DETAIL
  546. };
  547. for (U32 i = 0; i < ASSET_COUNT; ++i)
  548. {
  549. setDetailAssetID(i, default_textures[i]);
  550. }
  551. static LLCachedControl<F32> color_start_height(gSavedSettings,
  552. "TerrainColorStartHeight");
  553. static LLCachedControl<F32> color_height_range(gSavedSettings,
  554. "TerrainColorHeightRange");
  555. F32 start_height = llmax(0.f, color_start_height);
  556. F32 height_range = llmax(0.f, color_height_range);
  557. // Initialize the texture matrix to defaults.
  558. for (U32 i = 0; i < CORNER_COUNT; ++i)
  559. {
  560. mStartHeight[i] = start_height;
  561. mHeightRange[i] = height_range;
  562. }
  563. }
  564. //virtual
  565. void LLVLComposition::setDetailAssetID(U32 asset, const LLUUID& id)
  566. {
  567. if (id.notNull())
  568. {
  569. mRawImages[asset] = NULL;
  570. LLTerrain::setDetailAssetID(asset, id);
  571. }
  572. }
  573. void LLVLComposition::forceRebuild()
  574. {
  575. if (isPBR())
  576. {
  577. for (U32 i = 0; i < ASSET_COUNT; ++i)
  578. {
  579. LLFetchedGLTFMaterial* matp = mDetailMaterials[i].get();
  580. if (!matp)
  581. {
  582. continue;
  583. }
  584. LLViewerFetchedTexture* texp = matp->mBaseColorTexture.get();
  585. if (texp)
  586. {
  587. texp->forceRefetch();
  588. }
  589. texp = matp->mNormalTexture.get();
  590. if (texp)
  591. {
  592. texp->forceRefetch();
  593. }
  594. texp = matp->mMetallicRoughnessTexture.get();
  595. if (texp)
  596. {
  597. texp->forceRefetch();
  598. }
  599. texp = matp->mEmissiveTexture.get();
  600. if (texp)
  601. {
  602. texp->forceRefetch();
  603. }
  604. }
  605. }
  606. else
  607. {
  608. for (U32 i = 0; i < ASSET_COUNT; ++i)
  609. {
  610. LLViewerFetchedTexture* texp = mDetailTextures[i];
  611. if (texp)
  612. {
  613. texp->forceRefetch();
  614. }
  615. }
  616. }
  617. }
  618. bool LLVLComposition::generateHeights(F32 x, F32 y, F32 width, F32 height)
  619. {
  620. if (!mParamsReady)
  621. {
  622. // All the parameters have not been set yet (we did not get the message
  623. // from the sim)
  624. return false;
  625. }
  626. if (!mSurfacep || !mSurfacep->getRegion())
  627. {
  628. llassert(mSurfacep);
  629. // We do not always have the region yet here....
  630. return false;
  631. }
  632. S32 x_begin, y_begin, x_end, y_end;
  633. x_begin = ll_round(x * mScaleInv);
  634. y_begin = ll_round(y * mScaleInv);
  635. x_end = ll_round((x + width) * mScaleInv);
  636. y_end = ll_round((y + width) * mScaleInv);
  637. if (x_end > mWidth)
  638. {
  639. x_end = mWidth;
  640. }
  641. if (y_end > mWidth)
  642. {
  643. y_end = mWidth;
  644. }
  645. LLVector3d origin_global =
  646. from_region_handle(mSurfacep->getRegion()->getHandle());
  647. // For perlin noise generation...
  648. constexpr F32 slope_squared = 1.5f * 1.5f;
  649. // Degree to which noise modulates composition layer (versus simple height)
  650. constexpr F32 noise_magnitude = 2.f;
  651. // Heights map into textures as 0-1 = first, 1-2 = second, etc.
  652. // So we need to compress heights into this range.
  653. constexpr S32 NUM_TEXTURES = 4;
  654. constexpr F32 xy_scale_inv = 1.f / 4.9215f;
  655. constexpr F32 z_scale_inv = 1.f / 4.f;
  656. const F32 inv_width = 1.f / (F32)mWidth;
  657. // OK, for now, just have the composition value equal the height at the
  658. // point
  659. for (S32 j = y_begin; j < y_end; ++j)
  660. {
  661. for (S32 i = x_begin; i < x_end; ++i)
  662. {
  663. F32 vec[3];
  664. F32 vec1[3];
  665. F32 twiddle;
  666. // Bilinearly interpolate the start height and height range of the
  667. // textures
  668. F32 start_height = bilinear(mStartHeight[SOUTHWEST],
  669. mStartHeight[SOUTHEAST],
  670. mStartHeight[NORTHWEST],
  671. mStartHeight[NORTHEAST],
  672. // These will be bilinearly interpolated
  673. i * inv_width, j * inv_width);
  674. F32 height_range = bilinear(mHeightRange[SOUTHWEST],
  675. mHeightRange[SOUTHEAST],
  676. mHeightRange[NORTHWEST],
  677. mHeightRange[NORTHEAST],
  678. // These will be bilinearly interpolated
  679. i * inv_width, j * inv_width);
  680. LLVector3 location(i * mScale, j * mScale, 0.f);
  681. F32 height = mSurfacep->resolveHeightRegion(location);
  682. // Step 0: Measure the exact height at this texel
  683. // Adjust to non-integer lattice
  684. vec[0] = (F32)(origin_global.mdV[VX] + location.mV[VX]) *
  685. xy_scale_inv;
  686. vec[1] = (F32)(origin_global.mdV[VY] + location.mV[VY]) *
  687. xy_scale_inv;
  688. vec[2] = height * z_scale_inv;
  689. // Choose material value by adding to the exact height a random
  690. // value
  691. vec1[0] = vec[0] * 0.2222222222f;
  692. vec1[1] = vec[1] * 0.2222222222f;
  693. vec1[2] = vec[2] * 0.2222222222f;
  694. // Low freq component for large divisions
  695. twiddle = noise2(vec1) * 6.5f;
  696. // High frequency component
  697. twiddle += turbulence2(vec, 2) * slope_squared;
  698. twiddle *= noise_magnitude;
  699. F32 scaled_noisy_height = (height + twiddle - start_height) *
  700. F32(NUM_TEXTURES) / height_range;
  701. scaled_noisy_height = llmax(0.f, scaled_noisy_height);
  702. scaled_noisy_height = llmin(3.f, scaled_noisy_height);
  703. *(mDatap + i + j * mWidth) = scaled_noisy_height;
  704. }
  705. }
  706. return true;
  707. }
  708. bool LLVLComposition::generateComposition()
  709. {
  710. return mParamsReady && LLTerrain::generateMaterials();
  711. }
  712. static bool set_desired_discard(LLViewerFetchedTexture* texp,
  713. S32& ddiscard, bool& delete_raw)
  714. {
  715. ddiscard = 0;
  716. S32 width = texp->getFullWidth();
  717. S32 height = texp->getFullHeight();
  718. S32 min_dim = llmin(width, height);
  719. while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
  720. {
  721. ++ddiscard;
  722. min_dim /= 2;
  723. }
  724. // Read back a raw image for this discard level, if it exists
  725. delete_raw = texp->reloadRawImage(ddiscard) != NULL;
  726. S32 cur_discard = texp->getRawImageLevel();
  727. if ((width == height && cur_discard > ddiscard) ||
  728. // *FIXME: for some reason, rectangular textures always get stuck one
  729. // discard level too high... HB
  730. (width != height && cur_discard > ddiscard + 1))
  731. {
  732. // Raw image is not detailed enough...
  733. LL_DEBUGS("RegionTexture") << "Cached raw data for terrain detail texture is not ready yet: "
  734. << texp->getID()
  735. << " - Discard level: " << cur_discard
  736. << " - Desired discard level: " << ddiscard
  737. << " - Full size: " << texp->getFullWidth()
  738. << "x" << texp->getFullHeight()
  739. << " - Current size: " << texp->getWidth()
  740. << "x" << texp->getHeight()
  741. << " - Shared raw image: "
  742. << (delete_raw ? "false" : "true")
  743. << LL_ENDL;
  744. if (texp->getDecodePriority() <= 0.f && !texp->hasSavedRawImage())
  745. {
  746. texp->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
  747. texp->forceToRefetchTexture(ddiscard);
  748. }
  749. if (delete_raw)
  750. {
  751. texp->destroyRawImage();
  752. }
  753. return false;
  754. }
  755. return true;
  756. }
  757. bool LLVLComposition::generateLandTile(F32 x, F32 y, F32 width, F32 height)
  758. {
  759. if (!mParamsReady)
  760. {
  761. // All the parameters have not been set yet (we did not get the message
  762. // from the sim)...
  763. return false;
  764. }
  765. if (!mSurfacep || x < 0.f || y < 0.f)
  766. {
  767. llwarns << "Invalid surface: mSurfacep = " << std::hex
  768. << (intptr_t)mSurfacep << std::dec << " - x = " << x
  769. << " - y = " << y << llendl;
  770. llassert(false);
  771. return false;
  772. }
  773. bool use_textures = true;
  774. if (isPBR())
  775. {
  776. if (!materialsReady(true, true))
  777. {
  778. return false;
  779. }
  780. use_textures = false;
  781. }
  782. else if (!texturesReady(true, true))
  783. {
  784. return false;
  785. }
  786. LLTimer gen_timer;
  787. // Generate raw data arrays for surface textures
  788. U8* st_data[ASSET_COUNT];
  789. S32 st_data_size[ASSET_COUNT];
  790. LLColor3 base_color, emissive_color;
  791. LLViewerFetchedTexture* texp;
  792. // These are the defaults and never change when using textures. HB
  793. LLViewerFetchedTexture* etexp = NULL;
  794. bool has_base_color = false;
  795. bool has_emissive_color = false;
  796. bool has_alpha = false;
  797. S32 ddiscard, eddiscard;
  798. bool delete_raw, edelete_raw;
  799. for (U32 i = 0; i < ASSET_COUNT; ++i)
  800. {
  801. if (mRawImages[i].isNull())
  802. {
  803. if (use_textures)
  804. {
  805. texp = mDetailTextures[i];
  806. }
  807. else
  808. {
  809. texp = mDetailMaterials[i]->mBaseColorTexture;
  810. if (!texp)
  811. {
  812. texp = LLViewerFetchedTexture::sWhiteImagep;
  813. }
  814. etexp = mDetailMaterials[i]->mEmissiveTexture;
  815. base_color = LLColor3(mDetailMaterials[i]->mBaseColor);
  816. // *HACK: treat alpha as black
  817. base_color *= mDetailMaterials[i]->mBaseColor.mV[VW];
  818. emissive_color = mDetailMaterials[i]->mEmissiveColor;
  819. has_base_color = base_color.mV[VX] != 1.f ||
  820. base_color.mV[VY] != 1.f ||
  821. base_color.mV[VZ] != 1.f;
  822. has_emissive_color = emissive_color.mV[VX] != 1.f ||
  823. emissive_color.mV[VY] != 1.f ||
  824. emissive_color.mV[VZ] != 1.f;
  825. has_alpha = mDetailMaterials[i]->mAlphaMode !=
  826. LLGLTFMaterial::ALPHA_MODE_OPAQUE;
  827. }
  828. // Compute the desired discard
  829. if (!set_desired_discard(texp, ddiscard, delete_raw))
  830. {
  831. return false; // Texture not ready
  832. }
  833. if (etexp && !set_desired_discard(etexp, eddiscard, edelete_raw))
  834. {
  835. return false; // Texture not ready
  836. }
  837. mRawImages[i] = texp->getRawImage(); // Deletes previous raw
  838. if (delete_raw)
  839. {
  840. texp->destroyRawImage();
  841. }
  842. LLPointer<LLImageRaw> eraw;
  843. if (etexp)
  844. {
  845. eraw = etexp->getRawImage();
  846. if (has_emissive_color ||
  847. etexp->getWidth(eddiscard) < BASE_SIZE ||
  848. etexp->getHeight(eddiscard) < BASE_SIZE ||
  849. etexp->getComponents() != 4)
  850. {
  851. LLPointer<LLImageRaw> enewraw = new LLImageRaw(BASE_SIZE,
  852. BASE_SIZE,
  853. 4);
  854. // Copy RGB, leave alpha alone (set to opaque by default)
  855. enewraw->copy(mRawImages[i]);
  856. if (has_emissive_color)
  857. {
  858. enewraw->tint(emissive_color);
  859. }
  860. eraw = enewraw; // Deletes previous raw
  861. }
  862. }
  863. if (has_base_color || has_alpha || eraw.notNull() ||
  864. texp->getWidth(ddiscard) < BASE_SIZE ||
  865. texp->getHeight(ddiscard) < BASE_SIZE ||
  866. texp->getComponents() != 3)
  867. {
  868. LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE,
  869. BASE_SIZE, 3);
  870. if (has_alpha)
  871. {
  872. // Approximate the water underneath terrain alpha with
  873. // solid water color.
  874. newraw->clear(MAX_WATER_COLOR.mV[VX],
  875. MAX_WATER_COLOR.mV[VY],
  876. MAX_WATER_COLOR.mV[VZ], 255);
  877. }
  878. newraw->composite(mRawImages[i]);
  879. if (has_base_color)
  880. {
  881. newraw->tint(base_color);
  882. }
  883. if (eraw.notNull())
  884. {
  885. newraw->composite(eraw);
  886. }
  887. mRawImages[i] = newraw; // Deletes previous raw
  888. }
  889. if (etexp && edelete_raw)
  890. {
  891. etexp->destroyRawImage();
  892. }
  893. }
  894. st_data[i] = mRawImages[i]->getData();
  895. st_data_size[i] = mRawImages[i]->getDataSize();
  896. }
  897. // Generate and clamp x/y bounding box.
  898. S32 x_begin = (S32)(x * mScaleInv);
  899. S32 y_begin = (S32)(y * mScaleInv);
  900. S32 x_end = ll_round((x + width) * mScaleInv);
  901. S32 y_end = ll_round((y + width) * mScaleInv);
  902. if (x_end > mWidth)
  903. {
  904. llwarns << "x end > width" << llendl;
  905. x_end = mWidth;
  906. }
  907. if (y_end > mWidth)
  908. {
  909. llwarns << "y end > width" << llendl;
  910. y_end = mWidth;
  911. }
  912. // Generate target texture information, stride ratios.
  913. LLViewerTexture* texturep = mSurfacep->getSTexture();
  914. S32 tex_width = texturep->getWidth();
  915. S32 tex_height = texturep->getHeight();
  916. S32 tex_comps = texturep->getComponents();
  917. S32 tex_stride = tex_width * tex_comps;
  918. S32 st_comps = 3;
  919. S32 st_width = BASE_SIZE;
  920. S32 st_height = BASE_SIZE;
  921. if (tex_comps != st_comps)
  922. {
  923. llwarns_sparse << "Base texture comps != input texture comps"
  924. << llendl;
  925. return false;
  926. }
  927. F32 tex_x_scalef = (F32)tex_width / (F32)mWidth;
  928. F32 tex_y_scalef = (F32)tex_height / (F32)mWidth;
  929. F32 tex_x_begin = (S32)((F32)x_begin * tex_x_scalef);
  930. F32 tex_y_begin = (S32)((F32)y_begin * tex_y_scalef);
  931. F32 tex_x_end = (S32)((F32)x_end * tex_x_scalef);
  932. F32 tex_y_end = (S32)((F32)y_end * tex_y_scalef);
  933. F32 tex_x_ratiof = (F32)mWidth * mScale / (F32)tex_width;
  934. F32 tex_y_ratiof = (F32)mWidth * mScale / (F32)tex_height;
  935. LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height,
  936. tex_comps);
  937. U8* rawp = raw->getData();
  938. F32 st_x_stride = ((F32)st_width / (F32)mTexScaleX) *
  939. ((F32)mWidth / (F32)tex_width);
  940. F32 st_y_stride = ((F32)st_height / (F32)mTexScaleY) *
  941. ((F32)mWidth / (F32)tex_height);
  942. llassert(st_x_stride > 0.f && st_y_stride > 0.f);
  943. // Iterate through the target texture, striding through the sub-textures
  944. // and interpolating appropriately.
  945. F32 sti = tex_x_begin * st_x_stride -
  946. st_width * llfloor(tex_x_begin * st_x_stride / st_width);
  947. F32 stj = tex_y_begin * st_y_stride -
  948. st_height * llfloor(tex_y_begin * st_y_stride / st_height);
  949. S32 st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps;
  950. for (S32 j = tex_y_begin; j < tex_y_end; ++j)
  951. {
  952. U32 offset = j * tex_stride + tex_x_begin * tex_comps;
  953. sti = tex_x_begin * st_x_stride -
  954. st_width * ((U32)(tex_x_begin * st_x_stride) / st_width);
  955. for (S32 i = tex_x_begin; i < tex_x_end; ++i)
  956. {
  957. F32 composition = getValueScaled(i * tex_x_ratiof,
  958. j * tex_y_ratiof);
  959. S32 tex0 = llfloor(composition);
  960. tex0 = llclamp(tex0, 0, 3);
  961. composition -= tex0;
  962. S32 tex1 = tex0 + 1;
  963. tex1 = llclamp(tex1, 0, 3);
  964. st_offset = (lltrunc(sti) + lltrunc(stj) * st_width) * st_comps;
  965. for (S32 k = 0; k < tex_comps; ++k)
  966. {
  967. // Linearly interpolate based on composition.
  968. if (st_offset < st_data_size[tex0] &&
  969. st_offset < st_data_size[tex1])
  970. {
  971. F32 a = *(st_data[tex0] + st_offset);
  972. F32 b = *(st_data[tex1] + st_offset);
  973. rawp[offset] = (U8)lltrunc(a + composition * (b - a));
  974. }
  975. ++offset;
  976. ++st_offset;
  977. }
  978. sti += st_x_stride;
  979. if (sti >= st_width)
  980. {
  981. sti -= st_width;
  982. }
  983. }
  984. stj += st_y_stride;
  985. if (stj >= st_height)
  986. {
  987. stj -= st_height;
  988. }
  989. }
  990. if (!texturep->hasGLTexture())
  991. {
  992. texturep->createGLTexture(0, raw);
  993. }
  994. texturep->setSubImage(raw, tex_x_begin, tex_y_begin,
  995. tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
  996. LLSurface::sTextureUpdateTime += gen_timer.getElapsedTimeF32();
  997. LLSurface::sTexelsUpdated += (tex_x_end - tex_x_begin) *
  998. (tex_y_end - tex_y_begin);
  999. // Un-boost detail textures (will get re-boosted if rendering in high
  1000. // detail)
  1001. for (U32 i = 0; i < ASSET_COUNT; ++i)
  1002. {
  1003. unboost_terrain_texture(mDetailTextures[i]);
  1004. unboost_terrain_material(mDetailMaterials[i]);
  1005. }
  1006. return true;
  1007. }