PageRenderTime 43ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/lldrawpoolbump.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1611 lines | 1257 code | 235 blank | 119 comment | 170 complexity | 0f2cc2489411c961dc5f360581b4222f MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lldrawpoolbump.cpp
  3. * @brief LLDrawPoolBump class implementation
  4. *
  5. * $LicenseInfo:firstyear=2003&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "lldrawpoolbump.h"
  28. #include "llstl.h"
  29. #include "llviewercontrol.h"
  30. #include "lldir.h"
  31. #include "m3math.h"
  32. #include "m4math.h"
  33. #include "v4math.h"
  34. #include "llglheaders.h"
  35. #include "llrender.h"
  36. #include "llcubemap.h"
  37. #include "lldrawable.h"
  38. #include "llface.h"
  39. #include "llsky.h"
  40. #include "lltextureentry.h"
  41. #include "llviewercamera.h"
  42. #include "llviewertexturelist.h"
  43. #include "pipeline.h"
  44. #include "llspatialpartition.h"
  45. #include "llviewershadermgr.h"
  46. //#include "llimagebmp.h"
  47. //#include "../tools/imdebug/imdebug.h"
  48. // static
  49. LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT];
  50. // static
  51. U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
  52. // static
  53. LLBumpImageList gBumpImageList;
  54. const S32 STD_BUMP_LATEST_FILE_VERSION = 1;
  55. const U32 VERTEX_MASK_SHINY = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
  56. const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
  57. U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY;
  58. static LLGLSLShader* shader = NULL;
  59. static S32 cube_channel = -1;
  60. static S32 diffuse_channel = -1;
  61. static S32 bump_channel = -1;
  62. // static
  63. void LLStandardBumpmap::init()
  64. {
  65. LLStandardBumpmap::restoreGL();
  66. }
  67. // static
  68. void LLStandardBumpmap::shutdown()
  69. {
  70. LLStandardBumpmap::destroyGL();
  71. }
  72. // static
  73. void LLStandardBumpmap::restoreGL()
  74. {
  75. addstandard();
  76. }
  77. // static
  78. void LLStandardBumpmap::addstandard()
  79. {
  80. if(!gTextureList.isInitialized())
  81. {
  82. //Note: loading pre-configuration sometimes triggers this call.
  83. //But it is safe to return here because bump images will be reloaded during initialization later.
  84. return ;
  85. }
  86. // can't assert; we destroyGL and restoreGL a lot during *first* startup, which populates this list already, THEN we explicitly init the list as part of *normal* startup. Sigh. So clear the list every time before we (re-)add the standard bumpmaps.
  87. //llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 );
  88. clear();
  89. llinfos << "Adding standard bumpmaps." << llendl;
  90. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("None"); // BE_NO_BUMP
  91. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Brightness"); // BE_BRIGHTNESS
  92. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness"); // BE_DARKNESS
  93. std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" );
  94. LLFILE* file = LLFile::fopen( file_name, "rt" ); /*Flawfinder: ignore*/
  95. if( !file )
  96. {
  97. llwarns << "Could not open std_bump <" << file_name << ">" << llendl;
  98. return;
  99. }
  100. S32 file_version = 0;
  101. S32 fields_read = fscanf( file, "LLStandardBumpmap version %d", &file_version );
  102. if( fields_read != 1 )
  103. {
  104. llwarns << "Bad LLStandardBumpmap header" << llendl;
  105. return;
  106. }
  107. if( file_version > STD_BUMP_LATEST_FILE_VERSION )
  108. {
  109. llwarns << "LLStandardBumpmap has newer version (" << file_version << ") than viewer (" << STD_BUMP_LATEST_FILE_VERSION << ")" << llendl;
  110. return;
  111. }
  112. while( !feof(file) && (LLStandardBumpmap::sStandardBumpmapCount < (U32)TEM_BUMPMAP_COUNT) )
  113. {
  114. // *NOTE: This buffer size is hard coded into scanf() below.
  115. char label[2048] = ""; /* Flawfinder: ignore */
  116. char bump_image_id[2048] = ""; /* Flawfinder: ignore */
  117. fields_read = fscanf( /* Flawfinder: ignore */
  118. file, "\n%2047s %2047s", label, bump_image_id);
  119. if( EOF == fields_read )
  120. {
  121. break;
  122. }
  123. if( fields_read != 2 )
  124. {
  125. llwarns << "Bad LLStandardBumpmap entry" << llendl;
  126. return;
  127. }
  128. // llinfos << "Loading bumpmap: " << bump_image_id << " from viewerart" << llendl;
  129. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label;
  130. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage =
  131. LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id));
  132. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
  133. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL );
  134. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0) ;
  135. LLStandardBumpmap::sStandardBumpmapCount++;
  136. }
  137. fclose( file );
  138. }
  139. // static
  140. void LLStandardBumpmap::clear()
  141. {
  142. llinfos << "Clearing standard bumpmaps." << llendl;
  143. for( U32 i = 0; i < LLStandardBumpmap::sStandardBumpmapCount; i++ )
  144. {
  145. gStandardBumpmapList[i].mLabel.assign("");
  146. gStandardBumpmapList[i].mImage = NULL;
  147. }
  148. sStandardBumpmapCount = 0;
  149. }
  150. // static
  151. void LLStandardBumpmap::destroyGL()
  152. {
  153. clear();
  154. }
  155. ////////////////////////////////////////////////////////////////
  156. LLDrawPoolBump::LLDrawPoolBump()
  157. : LLRenderPass(LLDrawPool::POOL_BUMP)
  158. {
  159. mShiny = FALSE;
  160. }
  161. void LLDrawPoolBump::prerender()
  162. {
  163. mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
  164. }
  165. // static
  166. S32 LLDrawPoolBump::numBumpPasses()
  167. {
  168. if (gSavedSettings.getBOOL("RenderObjectBump"))
  169. {
  170. if (mVertexShaderLevel > 1)
  171. {
  172. if (LLPipeline::sImpostorRender)
  173. {
  174. return 2;
  175. }
  176. else
  177. {
  178. return 3;
  179. }
  180. }
  181. else if (LLPipeline::sImpostorRender)
  182. {
  183. return 1;
  184. }
  185. else
  186. {
  187. return 2;
  188. }
  189. }
  190. else
  191. {
  192. return 0;
  193. }
  194. }
  195. S32 LLDrawPoolBump::getNumPasses()
  196. {
  197. return numBumpPasses();
  198. }
  199. void LLDrawPoolBump::beginRenderPass(S32 pass)
  200. {
  201. LLFastTimer t(FTM_RENDER_BUMP);
  202. switch( pass )
  203. {
  204. case 0:
  205. beginShiny();
  206. break;
  207. case 1:
  208. if (mVertexShaderLevel > 1)
  209. {
  210. beginFullbrightShiny();
  211. }
  212. else
  213. {
  214. beginBump();
  215. }
  216. break;
  217. case 2:
  218. beginBump();
  219. break;
  220. default:
  221. llassert(0);
  222. break;
  223. }
  224. }
  225. void LLDrawPoolBump::render(S32 pass)
  226. {
  227. LLFastTimer t(FTM_RENDER_BUMP);
  228. if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE))
  229. {
  230. return;
  231. }
  232. switch( pass )
  233. {
  234. case 0:
  235. renderShiny();
  236. break;
  237. case 1:
  238. if (mVertexShaderLevel > 1)
  239. {
  240. renderFullbrightShiny();
  241. }
  242. else
  243. {
  244. renderBump();
  245. }
  246. break;
  247. case 2:
  248. renderBump();
  249. break;
  250. default:
  251. llassert(0);
  252. break;
  253. }
  254. }
  255. void LLDrawPoolBump::endRenderPass(S32 pass)
  256. {
  257. LLFastTimer t(FTM_RENDER_BUMP);
  258. switch( pass )
  259. {
  260. case 0:
  261. endShiny();
  262. break;
  263. case 1:
  264. if (mVertexShaderLevel > 1)
  265. {
  266. endFullbrightShiny();
  267. }
  268. else
  269. {
  270. endBump();
  271. }
  272. break;
  273. case 2:
  274. endBump();
  275. break;
  276. default:
  277. llassert(0);
  278. break;
  279. }
  280. //to cleanup texture channels
  281. LLRenderPass::endRenderPass(pass);
  282. }
  283. //static
  284. void LLDrawPoolBump::beginShiny(bool invisible)
  285. {
  286. LLFastTimer t(FTM_RENDER_SHINY);
  287. if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))||
  288. (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
  289. {
  290. return;
  291. }
  292. mShiny = TRUE;
  293. sVertexMask = VERTEX_MASK_SHINY;
  294. // Second pass: environment map
  295. if (!invisible && mVertexShaderLevel > 1)
  296. {
  297. sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
  298. }
  299. if (getVertexShaderLevel() > 0)
  300. {
  301. if (LLPipeline::sUnderWaterRender)
  302. {
  303. shader = &gObjectShinyWaterProgram;
  304. }
  305. else
  306. {
  307. shader = &gObjectShinyProgram;
  308. }
  309. shader->bind();
  310. }
  311. else
  312. {
  313. shader = NULL;
  314. }
  315. bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible);
  316. if (mVertexShaderLevel > 1)
  317. { //indexed texture rendering, channel 0 is always diffuse
  318. diffuse_channel = 0;
  319. }
  320. }
  321. //static
  322. void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible)
  323. {
  324. LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
  325. if( cube_map )
  326. {
  327. if (!invisible && shader )
  328. {
  329. LLMatrix4 mat;
  330. mat.initRows(LLVector4(gGLModelView+0),
  331. LLVector4(gGLModelView+4),
  332. LLVector4(gGLModelView+8),
  333. LLVector4(gGLModelView+12));
  334. LLVector3 vec = LLVector3(gShinyOrigin) * mat;
  335. LLVector4 vec4(vec, gShinyOrigin.mV[3]);
  336. shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
  337. if (shader_level > 1)
  338. {
  339. cube_map->setMatrix(1);
  340. // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for
  341. // the cube map in the one pass shiny shaders
  342. cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
  343. cube_map->enableTexture(cube_channel);
  344. cube_map->enableTextureCoords(1);
  345. diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  346. }
  347. else
  348. {
  349. cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
  350. diffuse_channel = -1;
  351. cube_map->setMatrix(0);
  352. cube_map->enable(cube_channel);
  353. }
  354. gGL.getTexUnit(cube_channel)->bind(cube_map);
  355. gGL.getTexUnit(0)->activate();
  356. }
  357. else
  358. {
  359. cube_channel = 0;
  360. diffuse_channel = -1;
  361. gGL.getTexUnit(0)->disable();
  362. cube_map->enable(0);
  363. cube_map->setMatrix(0);
  364. gGL.getTexUnit(0)->bind(cube_map);
  365. gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
  366. gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_VERT_ALPHA);
  367. }
  368. }
  369. }
  370. void LLDrawPoolBump::renderShiny(bool invisible)
  371. {
  372. LLFastTimer t(FTM_RENDER_SHINY);
  373. if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))||
  374. (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
  375. {
  376. return;
  377. }
  378. if( gSky.mVOSkyp->getCubeMap() )
  379. {
  380. LLGLEnable blend_enable(GL_BLEND);
  381. if (!invisible && mVertexShaderLevel > 1)
  382. {
  383. LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
  384. }
  385. else if (!invisible)
  386. {
  387. renderGroups(LLRenderPass::PASS_SHINY, sVertexMask);
  388. }
  389. //else // invisible (deprecated)
  390. //{
  391. //renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask);
  392. //}
  393. }
  394. }
  395. //static
  396. void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible)
  397. {
  398. LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
  399. if( cube_map )
  400. {
  401. cube_map->disable();
  402. cube_map->restoreMatrix();
  403. if (!invisible && shader_level > 1)
  404. {
  405. shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
  406. if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
  407. {
  408. if (diffuse_channel != 0)
  409. {
  410. shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  411. }
  412. }
  413. }
  414. }
  415. if (!LLGLSLShader::sNoFixedFunction)
  416. {
  417. gGL.getTexUnit(diffuse_channel)->disable();
  418. gGL.getTexUnit(cube_channel)->disable();
  419. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  420. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  421. }
  422. }
  423. void LLDrawPoolBump::endShiny(bool invisible)
  424. {
  425. LLFastTimer t(FTM_RENDER_SHINY);
  426. if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))||
  427. (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
  428. {
  429. return;
  430. }
  431. unbindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible);
  432. if (shader)
  433. {
  434. shader->unbind();
  435. }
  436. diffuse_channel = -1;
  437. cube_channel = 0;
  438. mShiny = FALSE;
  439. }
  440. void LLDrawPoolBump::beginFullbrightShiny()
  441. {
  442. LLFastTimer t(FTM_RENDER_SHINY);
  443. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
  444. {
  445. return;
  446. }
  447. sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
  448. // Second pass: environment map
  449. if (LLPipeline::sUnderWaterRender)
  450. {
  451. shader = &gObjectFullbrightShinyWaterProgram;
  452. }
  453. else
  454. {
  455. shader = &gObjectFullbrightShinyProgram;
  456. }
  457. LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
  458. if( cube_map )
  459. {
  460. LLMatrix4 mat;
  461. mat.initRows(LLVector4(gGLModelView+0),
  462. LLVector4(gGLModelView+4),
  463. LLVector4(gGLModelView+8),
  464. LLVector4(gGLModelView+12));
  465. shader->bind();
  466. LLVector3 vec = LLVector3(gShinyOrigin) * mat;
  467. LLVector4 vec4(vec, gShinyOrigin.mV[3]);
  468. shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
  469. cube_map->setMatrix(1);
  470. // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for
  471. // the cube map in the one pass shiny shaders
  472. gGL.getTexUnit(1)->disable();
  473. cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
  474. cube_map->enableTexture(cube_channel);
  475. cube_map->enableTextureCoords(1);
  476. diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  477. gGL.getTexUnit(cube_channel)->bind(cube_map);
  478. gGL.getTexUnit(0)->activate();
  479. }
  480. if (mVertexShaderLevel > 1)
  481. { //indexed texture rendering, channel 0 is always diffuse
  482. diffuse_channel = 0;
  483. }
  484. mShiny = TRUE;
  485. }
  486. void LLDrawPoolBump::renderFullbrightShiny()
  487. {
  488. LLFastTimer t(FTM_RENDER_SHINY);
  489. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
  490. {
  491. return;
  492. }
  493. if( gSky.mVOSkyp->getCubeMap() )
  494. {
  495. LLGLEnable blend_enable(GL_BLEND);
  496. if (mVertexShaderLevel > 1)
  497. {
  498. LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
  499. }
  500. else
  501. {
  502. LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
  503. }
  504. }
  505. }
  506. void LLDrawPoolBump::endFullbrightShiny()
  507. {
  508. LLFastTimer t(FTM_RENDER_SHINY);
  509. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
  510. {
  511. return;
  512. }
  513. LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
  514. if( cube_map )
  515. {
  516. cube_map->disable();
  517. cube_map->restoreMatrix();
  518. /*if (diffuse_channel != 0)
  519. {
  520. shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  521. }
  522. gGL.getTexUnit(0)->activate();
  523. gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);*/
  524. shader->unbind();
  525. //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  526. }
  527. //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  528. //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  529. diffuse_channel = -1;
  530. cube_channel = 0;
  531. mShiny = FALSE;
  532. }
  533. void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE)
  534. {
  535. LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
  536. for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
  537. {
  538. LLDrawInfo& params = **k;
  539. applyModelMatrix(params);
  540. if (params.mGroup)
  541. {
  542. params.mGroup->rebuildMesh();
  543. }
  544. params.mVertexBuffer->setBuffer(mask);
  545. params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
  546. gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
  547. }
  548. }
  549. // static
  550. BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel)
  551. {
  552. U8 bump_code = params.mBump;
  553. return bindBumpMap(bump_code, params.mTexture, params.mVSize, channel);
  554. }
  555. //static
  556. BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel)
  557. {
  558. const LLTextureEntry* te = face->getTextureEntry();
  559. if (te)
  560. {
  561. U8 bump_code = te->getBumpmap();
  562. return bindBumpMap(bump_code, face->getTexture(), face->getVirtualSize(), channel);
  563. }
  564. return FALSE;
  565. }
  566. //static
  567. BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsize, S32 channel)
  568. {
  569. //Note: texture atlas does not support bump texture now.
  570. LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ;
  571. if(!tex)
  572. {
  573. //if the texture is not a fetched texture
  574. return FALSE;
  575. }
  576. LLViewerTexture* bump = NULL;
  577. switch( bump_code )
  578. {
  579. case BE_NO_BUMP:
  580. break;
  581. case BE_BRIGHTNESS:
  582. case BE_DARKNESS:
  583. bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
  584. break;
  585. default:
  586. if( bump_code < LLStandardBumpmap::sStandardBumpmapCount )
  587. {
  588. bump = gStandardBumpmapList[bump_code].mImage;
  589. gBumpImageList.addTextureStats(bump_code, tex->getID(), vsize);
  590. }
  591. break;
  592. }
  593. if (bump)
  594. {
  595. if (channel == -2)
  596. {
  597. gGL.getTexUnit(1)->bind(bump);
  598. gGL.getTexUnit(0)->bind(bump);
  599. }
  600. else
  601. {
  602. gGL.getTexUnit(channel)->bind(bump);
  603. }
  604. return TRUE;
  605. }
  606. return FALSE;
  607. }
  608. //static
  609. void LLDrawPoolBump::beginBump(U32 pass)
  610. {
  611. if (!gPipeline.hasRenderBatches(pass))
  612. {
  613. return;
  614. }
  615. sVertexMask = VERTEX_MASK_BUMP;
  616. LLFastTimer t(FTM_RENDER_BUMP);
  617. // Optional second pass: emboss bump map
  618. stop_glerror();
  619. if (LLGLSLShader::sNoFixedFunction)
  620. {
  621. gObjectBumpProgram.bind();
  622. }
  623. else
  624. {
  625. // TEXTURE UNIT 0
  626. // Output.rgb = texture at texture coord 0
  627. gGL.getTexUnit(0)->activate();
  628. gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
  629. gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
  630. // TEXTURE UNIT 1
  631. gGL.getTexUnit(1)->activate();
  632. gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
  633. gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA);
  634. gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
  635. // src = tex0 + (1 - tex1) - 0.5
  636. // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5
  637. // = (1 + bump0 - bump1) / 2
  638. // Blend: src * dst + dst * src
  639. // = 2 * src * dst
  640. // = 2 * ((1 + bump0 - bump1) / 2) * dst [0 - 2 * dst]
  641. // = (1 + bump0 - bump1) * dst.rgb
  642. // = dst.rgb + dst.rgb * (bump0 - bump1)
  643. gGL.getTexUnit(0)->activate();
  644. gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
  645. }
  646. gGL.setSceneBlendType(LLRender::BT_MULT_X2);
  647. stop_glerror();
  648. }
  649. //static
  650. void LLDrawPoolBump::renderBump(U32 pass)
  651. {
  652. if (!gPipeline.hasRenderBatches(pass))
  653. {
  654. return;
  655. }
  656. LLFastTimer ftm(FTM_RENDER_BUMP);
  657. LLGLDisable fog(GL_FOG);
  658. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL);
  659. LLGLEnable blend(GL_BLEND);
  660. gGL.diffuseColor4f(1,1,1,1);
  661. /// Get rid of z-fighting with non-bump pass.
  662. LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
  663. glPolygonOffset(-1.0f, -1.0f);
  664. renderBump(pass, sVertexMask);
  665. }
  666. //static
  667. void LLDrawPoolBump::endBump(U32 pass)
  668. {
  669. if (!gPipeline.hasRenderBatches(pass))
  670. {
  671. return;
  672. }
  673. if (LLGLSLShader::sNoFixedFunction)
  674. {
  675. gObjectBumpProgram.unbind();
  676. }
  677. else
  678. {
  679. // Disable texture blending on unit 1
  680. gGL.getTexUnit(1)->activate();
  681. gGL.getTexUnit(1)->disable();
  682. gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
  683. // Disable texture blending on unit 0
  684. gGL.getTexUnit(0)->activate();
  685. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  686. }
  687. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  688. }
  689. S32 LLDrawPoolBump::getNumDeferredPasses()
  690. {
  691. if (gSavedSettings.getBOOL("RenderObjectBump"))
  692. {
  693. return 1;
  694. }
  695. else
  696. {
  697. return 0;
  698. }
  699. }
  700. void LLDrawPoolBump::beginDeferredPass(S32 pass)
  701. {
  702. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
  703. {
  704. return;
  705. }
  706. LLFastTimer ftm(FTM_RENDER_BUMP);
  707. mShiny = TRUE;
  708. gDeferredBumpProgram.bind();
  709. diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  710. bump_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::BUMP_MAP);
  711. gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
  712. gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE);
  713. }
  714. void LLDrawPoolBump::endDeferredPass(S32 pass)
  715. {
  716. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
  717. {
  718. return;
  719. }
  720. LLFastTimer ftm(FTM_RENDER_BUMP);
  721. mShiny = FALSE;
  722. gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  723. gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP);
  724. gDeferredBumpProgram.unbind();
  725. gGL.getTexUnit(0)->activate();
  726. }
  727. void LLDrawPoolBump::renderDeferred(S32 pass)
  728. {
  729. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
  730. {
  731. return;
  732. }
  733. LLFastTimer ftm(FTM_RENDER_BUMP);
  734. U32 type = LLRenderPass::PASS_BUMP;
  735. LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type);
  736. LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type);
  737. U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
  738. for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i)
  739. {
  740. LLDrawInfo& params = **i;
  741. LLDrawPoolBump::bindBumpMap(params, bump_channel);
  742. pushBatch(params, mask, TRUE);
  743. }
  744. }
  745. void LLDrawPoolBump::beginPostDeferredPass(S32 pass)
  746. {
  747. switch (pass)
  748. {
  749. case 0:
  750. beginFullbrightShiny();
  751. break;
  752. case 1:
  753. beginBump(LLRenderPass::PASS_POST_BUMP);
  754. break;
  755. }
  756. }
  757. void LLDrawPoolBump::endPostDeferredPass(S32 pass)
  758. {
  759. switch (pass)
  760. {
  761. case 0:
  762. endFullbrightShiny();
  763. break;
  764. case 1:
  765. endBump(LLRenderPass::PASS_POST_BUMP);
  766. break;
  767. }
  768. //to disable texture channels
  769. LLRenderPass::endRenderPass(pass);
  770. }
  771. void LLDrawPoolBump::renderPostDeferred(S32 pass)
  772. {
  773. switch (pass)
  774. {
  775. case 0:
  776. renderFullbrightShiny();
  777. break;
  778. case 1:
  779. renderBump(LLRenderPass::PASS_POST_BUMP);
  780. break;
  781. }
  782. }
  783. ////////////////////////////////////////////////////////////////
  784. // List of bump-maps created from other textures.
  785. //const LLUUID TEST_BUMP_ID("3d33eaf2-459c-6f97-fd76-5fce3fc29447");
  786. void LLBumpImageList::init()
  787. {
  788. llassert( mBrightnessEntries.size() == 0 );
  789. llassert( mDarknessEntries.size() == 0 );
  790. LLStandardBumpmap::init();
  791. }
  792. void LLBumpImageList::clear()
  793. {
  794. llinfos << "Clearing dynamic bumpmaps." << llendl;
  795. // these will be re-populated on-demand
  796. mBrightnessEntries.clear();
  797. mDarknessEntries.clear();
  798. LLStandardBumpmap::clear();
  799. }
  800. void LLBumpImageList::shutdown()
  801. {
  802. clear();
  803. LLStandardBumpmap::shutdown();
  804. }
  805. void LLBumpImageList::destroyGL()
  806. {
  807. clear();
  808. LLStandardBumpmap::destroyGL();
  809. }
  810. void LLBumpImageList::restoreGL()
  811. {
  812. if(!gTextureList.isInitialized())
  813. {
  814. //safe to return here because bump images will be reloaded during initialization later.
  815. return ;
  816. }
  817. LLStandardBumpmap::restoreGL();
  818. // Images will be recreated as they are needed.
  819. }
  820. LLBumpImageList::~LLBumpImageList()
  821. {
  822. // Shutdown should have already been called.
  823. llassert( mBrightnessEntries.size() == 0 );
  824. llassert( mDarknessEntries.size() == 0 );
  825. }
  826. // Note: Does nothing for entries in gStandardBumpmapList that are not actually standard bump images (e.g. none, brightness, and darkness)
  827. void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id, F32 virtual_size)
  828. {
  829. bump &= TEM_BUMP_MASK;
  830. LLViewerFetchedTexture* bump_image = gStandardBumpmapList[bump].mImage;
  831. if( bump_image )
  832. {
  833. bump_image->addTextureStats(virtual_size);
  834. }
  835. }
  836. void LLBumpImageList::updateImages()
  837. {
  838. for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); )
  839. {
  840. bump_image_map_t::iterator curiter = iter++;
  841. LLViewerTexture* image = curiter->second;
  842. if( image )
  843. {
  844. BOOL destroy = TRUE;
  845. if( image->hasGLTexture())
  846. {
  847. if( image->getBoundRecently() )
  848. {
  849. destroy = FALSE;
  850. }
  851. else
  852. {
  853. image->destroyGLTexture();
  854. }
  855. }
  856. if( destroy )
  857. {
  858. //llinfos << "*** Destroying bright " << (void*)image << llendl;
  859. mBrightnessEntries.erase(curiter); // deletes the image thanks to reference counting
  860. }
  861. }
  862. }
  863. for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); )
  864. {
  865. bump_image_map_t::iterator curiter = iter++;
  866. LLViewerTexture* image = curiter->second;
  867. if( image )
  868. {
  869. BOOL destroy = TRUE;
  870. if( image->hasGLTexture())
  871. {
  872. if( image->getBoundRecently() )
  873. {
  874. destroy = FALSE;
  875. }
  876. else
  877. {
  878. image->destroyGLTexture();
  879. }
  880. }
  881. if( destroy )
  882. {
  883. //llinfos << "*** Destroying dark " << (void*)image << llendl;;
  884. mDarknessEntries.erase(curiter); // deletes the image thanks to reference counting
  885. }
  886. }
  887. }
  888. }
  889. // Note: the caller SHOULD NOT keep the pointer that this function returns. It may be updated as more data arrives.
  890. LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedTexture* src_image, U8 bump_code )
  891. {
  892. llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
  893. LLViewerTexture* bump = NULL;
  894. bump_image_map_t* entries_list = NULL;
  895. void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
  896. switch( bump_code )
  897. {
  898. case BE_BRIGHTNESS:
  899. entries_list = &mBrightnessEntries;
  900. callback_func = LLBumpImageList::onSourceBrightnessLoaded;
  901. break;
  902. case BE_DARKNESS:
  903. entries_list = &mDarknessEntries;
  904. callback_func = LLBumpImageList::onSourceDarknessLoaded;
  905. break;
  906. default:
  907. llassert(0);
  908. return NULL;
  909. }
  910. bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
  911. if (iter != entries_list->end() && iter->second.notNull())
  912. {
  913. bump = iter->second;
  914. }
  915. else
  916. {
  917. LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
  918. raw->clear(0x77, 0x77, 0xFF, 0xFF);
  919. (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
  920. bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
  921. }
  922. if (!src_image->hasCallbacks())
  923. { //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again
  924. if (src_image->getWidth() != bump->getWidth() ||
  925. src_image->getHeight() != bump->getHeight())// ||
  926. //(LLPipeline::sRenderDeferred && bump->getComponents() != 4))
  927. {
  928. src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
  929. src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL );
  930. src_image->forceToSaveRawImage(0) ;
  931. }
  932. }
  933. return bump;
  934. }
  935. static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_STANDARD_LOADED("Bump Standard Callback");
  936. // static
  937. void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
  938. {
  939. LLUUID* source_asset_id = (LLUUID*)userdata;
  940. LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS );
  941. if( final )
  942. {
  943. delete source_asset_id;
  944. }
  945. }
  946. // static
  947. void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
  948. {
  949. LLUUID* source_asset_id = (LLUUID*)userdata;
  950. LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS );
  951. if( final )
  952. {
  953. delete source_asset_id;
  954. }
  955. }
  956. static LLFastTimer::DeclareTimer FTM_BUMP_GEN_NORMAL("Generate Normal Map");
  957. static LLFastTimer::DeclareTimer FTM_BUMP_CREATE_TEXTURE("Create GL Normal Map");
  958. void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
  959. {
  960. if (success && LLPipeline::sRenderDeferred)
  961. {
  962. LLFastTimer t(FTM_BUMP_SOURCE_STANDARD_LOADED);
  963. LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4);
  964. {
  965. LLFastTimer t(FTM_BUMP_GEN_NORMAL);
  966. generateNormalMapFromAlpha(src, nrm_image);
  967. }
  968. src_vi->setExplicitFormat(GL_RGBA, GL_RGBA);
  969. {
  970. LLFastTimer t(FTM_BUMP_CREATE_TEXTURE);
  971. src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image);
  972. }
  973. }
  974. }
  975. void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image)
  976. {
  977. U8* nrm_data = nrm_image->getData();
  978. S32 resX = src->getWidth();
  979. S32 resY = src->getHeight();
  980. U8* src_data = src->getData();
  981. S32 src_cmp = src->getComponents();
  982. F32 norm_scale = gSavedSettings.getF32("RenderNormalMapScale");
  983. U32 idx = 0;
  984. //generate normal map from pseudo-heightfield
  985. for (S32 j = 0; j < resY; ++j)
  986. {
  987. for (S32 i = 0; i < resX; ++i)
  988. {
  989. S32 rX = (i+1)%resX;
  990. S32 rY = (j+1)%resY;
  991. S32 lX = (i-1)%resX;
  992. S32 lY = (j-1)%resY;
  993. if (lX < 0)
  994. {
  995. lX += resX;
  996. }
  997. if (lY < 0)
  998. {
  999. lY += resY;
  1000. }
  1001. F32 cH = (F32) src_data[(j*resX+i)*src_cmp+src_cmp-1];
  1002. LLVector3 right = LLVector3(norm_scale, 0, (F32) src_data[(j*resX+rX)*src_cmp+src_cmp-1]-cH);
  1003. LLVector3 left = LLVector3(-norm_scale, 0, (F32) src_data[(j*resX+lX)*src_cmp+src_cmp-1]-cH);
  1004. LLVector3 up = LLVector3(0, -norm_scale, (F32) src_data[(lY*resX+i)*src_cmp+src_cmp-1]-cH);
  1005. LLVector3 down = LLVector3(0, norm_scale, (F32) src_data[(rY*resX+i)*src_cmp+src_cmp-1]-cH);
  1006. LLVector3 norm = right%down + down%left + left%up + up%right;
  1007. norm.normVec();
  1008. norm *= 0.5f;
  1009. norm += LLVector3(0.5f,0.5f,0.5f);
  1010. idx = (j*resX+i)*4;
  1011. nrm_data[idx+0]= (U8) (norm.mV[0]*255);
  1012. nrm_data[idx+1]= (U8) (norm.mV[1]*255);
  1013. nrm_data[idx+2]= (U8) (norm.mV[2]*255);
  1014. nrm_data[idx+3]= src_data[(j*resX+i)*src_cmp+src_cmp-1];
  1015. }
  1016. }
  1017. }
  1018. static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_LOADED("Bump Source Loaded");
  1019. static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_ENTRIES_UPDATE("Entries Update");
  1020. static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_MIN_MAX("Min/Max");
  1021. static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_RGB2LUM("RGB to Luminance");
  1022. static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_RESCALE("Rescale");
  1023. static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_GEN_NORMAL("Generate Normal");
  1024. static LLFastTimer::DeclareTimer FTM_BUMP_SOURCE_CREATE("Create");
  1025. // static
  1026. void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
  1027. {
  1028. if( success )
  1029. {
  1030. LLFastTimer t(FTM_BUMP_SOURCE_LOADED);
  1031. bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries );
  1032. bump_image_map_t::iterator iter = entries_list.find(source_asset_id);
  1033. {
  1034. LLFastTimer t(FTM_BUMP_SOURCE_ENTRIES_UPDATE);
  1035. if (iter == entries_list.end() ||
  1036. iter->second.isNull() ||
  1037. iter->second->getWidth() != src->getWidth() ||
  1038. iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
  1039. { //make sure an entry exists for this image
  1040. LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
  1041. raw->clear(0x77, 0x77, 0xFF, 0xFF);
  1042. entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
  1043. iter = entries_list.find(src_vi->getID());
  1044. }
  1045. }
  1046. //if (iter->second->getWidth() != src->getWidth() ||
  1047. // iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
  1048. {
  1049. LLPointer<LLImageRaw> dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1);
  1050. U8* dst_data = dst_image->getData();
  1051. S32 dst_data_size = dst_image->getDataSize();
  1052. U8* src_data = src->getData();
  1053. S32 src_data_size = src->getDataSize();
  1054. S32 src_components = src->getComponents();
  1055. // Convert to luminance and then scale and bias that to get ready for
  1056. // embossed bump mapping. (0-255 maps to 127-255)
  1057. // Convert to fixed point so we don't have to worry about precision/clamping.
  1058. const S32 FIXED_PT = 8;
  1059. const S32 R_WEIGHT = S32(0.2995f * (1<<FIXED_PT));
  1060. const S32 G_WEIGHT = S32(0.5875f * (1<<FIXED_PT));
  1061. const S32 B_WEIGHT = S32(0.1145f * (1<<FIXED_PT));
  1062. S32 minimum = 255;
  1063. S32 maximum = 0;
  1064. switch( src_components )
  1065. {
  1066. case 1:
  1067. case 2:
  1068. {
  1069. LLFastTimer t(FTM_BUMP_SOURCE_MIN_MAX);
  1070. if( src_data_size == dst_data_size * src_components )
  1071. {
  1072. for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
  1073. {
  1074. dst_data[i] = src_data[j];
  1075. if( dst_data[i] < minimum )
  1076. {
  1077. minimum = dst_data[i];
  1078. }
  1079. if( dst_data[i] > maximum )
  1080. {
  1081. maximum = dst_data[i];
  1082. }
  1083. }
  1084. }
  1085. else
  1086. {
  1087. llassert(0);
  1088. dst_image->clear();
  1089. }
  1090. }
  1091. break;
  1092. case 3:
  1093. case 4:
  1094. {
  1095. LLFastTimer t(FTM_BUMP_SOURCE_RGB2LUM);
  1096. if( src_data_size == dst_data_size * src_components )
  1097. {
  1098. for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
  1099. {
  1100. // RGB to luminance
  1101. dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT;
  1102. //llassert( dst_data[i] <= 255 );true because it's 8bit
  1103. if( dst_data[i] < minimum )
  1104. {
  1105. minimum = dst_data[i];
  1106. }
  1107. if( dst_data[i] > maximum )
  1108. {
  1109. maximum = dst_data[i];
  1110. }
  1111. }
  1112. }
  1113. else
  1114. {
  1115. llassert(0);
  1116. dst_image->clear();
  1117. }
  1118. }
  1119. break;
  1120. default:
  1121. llassert(0);
  1122. dst_image->clear();
  1123. break;
  1124. }
  1125. if( maximum > minimum )
  1126. {
  1127. LLFastTimer t(FTM_BUMP_SOURCE_RESCALE);
  1128. U8 bias_and_scale_lut[256];
  1129. F32 twice_one_over_range = 2.f / (maximum - minimum);
  1130. S32 i;
  1131. const F32 ARTIFICIAL_SCALE = 2.f; // Advantage: exaggerates the effect in midrange. Disadvantage: clamps at the extremes.
  1132. if (BE_DARKNESS == bump_code)
  1133. {
  1134. for( i = minimum; i <= maximum; i++ )
  1135. {
  1136. F32 minus_one_to_one = F32(maximum - i) * twice_one_over_range - 1.f;
  1137. bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
  1138. }
  1139. }
  1140. else
  1141. {
  1142. for( i = minimum; i <= maximum; i++ )
  1143. {
  1144. F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f;
  1145. bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
  1146. }
  1147. }
  1148. for( i = 0; i < dst_data_size; i++ )
  1149. {
  1150. dst_data[i] = bias_and_scale_lut[dst_data[i]];
  1151. }
  1152. }
  1153. //---------------------------------------------------
  1154. // immediately assign bump to a global smart pointer in case some local smart pointer
  1155. // accidentally releases it.
  1156. LLPointer<LLViewerTexture> bump = LLViewerTextureManager::getLocalTexture( TRUE );
  1157. if (!LLPipeline::sRenderDeferred)
  1158. {
  1159. LLFastTimer t(FTM_BUMP_SOURCE_CREATE);
  1160. bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
  1161. bump->createGLTexture(0, dst_image);
  1162. }
  1163. else
  1164. { //convert to normal map
  1165. {
  1166. LLFastTimer t(FTM_BUMP_SOURCE_CREATE);
  1167. bump->setExplicitFormat(GL_RGBA8, GL_ALPHA);
  1168. bump->createGLTexture(0, dst_image);
  1169. }
  1170. {
  1171. LLFastTimer t(FTM_BUMP_SOURCE_GEN_NORMAL);
  1172. gPipeline.mScreen.bindTarget();
  1173. LLGLDepthTest depth(GL_FALSE);
  1174. LLGLDisable cull(GL_CULL_FACE);
  1175. LLGLDisable blend(GL_BLEND);
  1176. gGL.setColorMask(TRUE, TRUE);
  1177. gNormalMapGenProgram.bind();
  1178. gNormalMapGenProgram.uniform1f("norm_scale", gSavedSettings.getF32("RenderNormalMapScale"));
  1179. gNormalMapGenProgram.uniform1f("stepX", 1.f/bump->getWidth());
  1180. gNormalMapGenProgram.uniform1f("stepY", 1.f/bump->getHeight());
  1181. LLVector2 v((F32) bump->getWidth()/gPipeline.mScreen.getWidth(),
  1182. (F32) bump->getHeight()/gPipeline.mScreen.getHeight());
  1183. gGL.getTexUnit(0)->bind(bump);
  1184. S32 width = bump->getWidth();
  1185. S32 height = bump->getHeight();
  1186. S32 screen_width = gPipeline.mScreen.getWidth();
  1187. S32 screen_height = gPipeline.mScreen.getHeight();
  1188. glViewport(0, 0, screen_width, screen_height);
  1189. for (S32 left = 0; left < width; left += screen_width)
  1190. {
  1191. S32 right = left + screen_width;
  1192. right = llmin(right, width);
  1193. F32 left_tc = (F32) left/ width;
  1194. F32 right_tc = (F32) right/width;
  1195. for (S32 bottom = 0; bottom < height; bottom += screen_height)
  1196. {
  1197. S32 top = bottom+screen_height;
  1198. top = llmin(top, height);
  1199. F32 bottom_tc = (F32) bottom/height;
  1200. F32 top_tc = (F32)(bottom+screen_height)/height;
  1201. top_tc = llmin(top_tc, 1.f);
  1202. F32 screen_right = (F32) (right-left)/screen_width;
  1203. F32 screen_top = (F32) (top-bottom)/screen_height;
  1204. gGL.begin(LLRender::TRIANGLE_STRIP);
  1205. gGL.texCoord2f(left_tc, bottom_tc);
  1206. gGL.vertex2f(0, 0);
  1207. gGL.texCoord2f(left_tc, top_tc);
  1208. gGL.vertex2f(0, screen_top);
  1209. gGL.texCoord2f(right_tc, bottom_tc);
  1210. gGL.vertex2f(screen_right, 0);
  1211. gGL.texCoord2f(right_tc, top_tc);
  1212. gGL.vertex2f(screen_right, screen_top);
  1213. gGL.end();
  1214. gGL.flush();
  1215. S32 w = right-left;
  1216. S32 h = top-bottom;
  1217. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, 0, 0, w, h);
  1218. }
  1219. }
  1220. glGenerateMipmap(GL_TEXTURE_2D);
  1221. gPipeline.mScreen.flush();
  1222. gNormalMapGenProgram.unbind();
  1223. //generateNormalMapFromAlpha(dst_image, nrm_image);
  1224. }
  1225. }
  1226. iter->second = bump; // derefs (and deletes) old image
  1227. //---------------------------------------------------
  1228. }
  1229. }
  1230. }
  1231. void LLDrawPoolBump::renderBump(U32 type, U32 mask)
  1232. {
  1233. LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type);
  1234. LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type);
  1235. for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i)
  1236. {
  1237. LLDrawInfo& params = **i;
  1238. if (LLDrawPoolBump::bindBumpMap(params))
  1239. {
  1240. pushBatch(params, mask, FALSE);
  1241. }
  1242. }
  1243. }
  1244. void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
  1245. {
  1246. applyModelMatrix(params);
  1247. bool tex_setup = false;
  1248. if (batch_textures && params.mTextureList.size() > 1)
  1249. {
  1250. for (U32 i = 0; i < params.mTextureList.size(); ++i)
  1251. {
  1252. if (params.mTextureList[i].notNull())
  1253. {
  1254. gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
  1255. }
  1256. }
  1257. }
  1258. else
  1259. { //not batching textures or batch has only 1 texture -- might need a texture matrix
  1260. if (params.mTextureMatrix)
  1261. {
  1262. if (mShiny)
  1263. {
  1264. gGL.getTexUnit(0)->activate();
  1265. gGL.matrixMode(LLRender::MM_TEXTURE);
  1266. }
  1267. else
  1268. {
  1269. if (!LLGLSLShader::sNoFixedFunction)
  1270. {
  1271. gGL.getTexUnit(1)->activate();
  1272. gGL.matrixMode(LLRender::MM_TEXTURE);
  1273. gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
  1274. }
  1275. gGL.getTexUnit(0)->activate();
  1276. gGL.matrixMode(LLRender::MM_TEXTURE);
  1277. gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
  1278. gPipeline.mTextureMatrixOps++;
  1279. }
  1280. gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
  1281. gPipeline.mTextureMatrixOps++;
  1282. tex_setup = true;
  1283. }
  1284. if (mShiny && mVertexShaderLevel > 1 && texture)
  1285. {
  1286. if (params.mTexture.notNull())
  1287. {
  1288. gGL.getTexUnit(diffuse_channel)->bind(params.mTexture);
  1289. params.mTexture->addTextureStats(params.mVSize);
  1290. }
  1291. else
  1292. {
  1293. gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
  1294. }
  1295. }
  1296. }
  1297. if (params.mGroup)
  1298. {
  1299. params.mGroup->rebuildMesh();
  1300. }
  1301. params.mVertexBuffer->setBuffer(mask);
  1302. params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
  1303. gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
  1304. if (tex_setup)
  1305. {
  1306. if (mShiny)
  1307. {
  1308. gGL.getTexUnit(0)->activate();
  1309. }
  1310. else
  1311. {
  1312. if (!LLGLSLShader::sNoFixedFunction)
  1313. {
  1314. gGL.getTexUnit(1)->activate();
  1315. gGL.matrixMode(LLRender::MM_TEXTURE);
  1316. gGL.loadIdentity();
  1317. }
  1318. gGL.getTexUnit(0)->activate();
  1319. gGL.matrixMode(LLRender::MM_TEXTURE);
  1320. }
  1321. gGL.loadIdentity();
  1322. gGL.matrixMode(LLRender::MM_MODELVIEW);
  1323. }
  1324. }
  1325. void LLDrawPoolInvisible::render(S32 pass)
  1326. { //render invisiprims
  1327. LLFastTimer t(FTM_RENDER_INVISIBLE);
  1328. if (gPipeline.canUseVertexShaders())
  1329. {
  1330. gOcclusionProgram.bind();
  1331. }
  1332. U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
  1333. glStencilMask(0);
  1334. gGL.setColorMask(false, false);
  1335. pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE);
  1336. gGL.setColorMask(true, false);
  1337. glStencilMask(0xFFFFFFFF);
  1338. if (gPipeline.canUseVertexShaders())
  1339. {
  1340. gOcclusionProgram.unbind();
  1341. }
  1342. if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
  1343. {
  1344. beginShiny(true);
  1345. renderShiny(true);
  1346. endShiny(true);
  1347. }
  1348. }
  1349. void LLDrawPoolInvisible::beginDeferredPass(S32 pass)
  1350. {
  1351. beginRenderPass(pass);
  1352. }
  1353. void LLDrawPoolInvisible::endDeferredPass( S32 pass )
  1354. {
  1355. endRenderPass(pass);
  1356. }
  1357. void LLDrawPoolInvisible::renderDeferred( S32 pass )
  1358. { //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff
  1359. #if 0
  1360. LLFastTimer t(FTM_RENDER_INVISIBLE);
  1361. U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
  1362. glStencilMask(0);
  1363. glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE);
  1364. gGL.setColorMask(false, false);
  1365. pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE);
  1366. gGL.setColorMask(true, true);
  1367. glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  1368. glStencilMask(0xFFFFFFFF);
  1369. if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
  1370. {
  1371. beginShiny(true);
  1372. renderShiny(true);
  1373. endShiny(true);
  1374. }
  1375. #endif
  1376. }