lldrawpoolbump.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:33k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lldrawpoolbump.cpp
  3.  * @brief LLDrawPoolBump class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2003&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2003-2010, 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 "lldrawpoolbump.h"
  34. #include "llstl.h"
  35. #include "llviewercontrol.h"
  36. #include "lldir.h"
  37. #include "m3math.h"
  38. #include "m4math.h"
  39. #include "v4math.h"
  40. #include "llglheaders.h"
  41. #include "llrender.h"
  42. #include "llcubemap.h"
  43. #include "lldrawable.h"
  44. #include "llface.h"
  45. #include "llsky.h"
  46. #include "lltextureentry.h"
  47. #include "llviewercamera.h"
  48. #include "llviewertexturelist.h"
  49. #include "pipeline.h"
  50. #include "llspatialpartition.h"
  51. #include "llviewershadermgr.h"
  52. //#include "llimagebmp.h"
  53. //#include "../tools/imdebug/imdebug.h"
  54. // static
  55. LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT]; 
  56. // static
  57. U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
  58. // static
  59. LLBumpImageList gBumpImageList;
  60. const S32 STD_BUMP_LATEST_FILE_VERSION = 1;
  61. const U32 VERTEX_MASK_SHINY = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
  62. const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
  63. U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY;
  64. static LLGLSLShader* shader = NULL;
  65. static S32 cube_channel = -1;
  66. static S32 diffuse_channel = -1;
  67. static S32 bump_channel = -1;
  68. // static 
  69. void LLStandardBumpmap::init()
  70. {
  71. LLStandardBumpmap::restoreGL();
  72. }
  73. // static 
  74. void LLStandardBumpmap::shutdown()
  75. {
  76. LLStandardBumpmap::destroyGL();
  77. }
  78. // static 
  79. void LLStandardBumpmap::restoreGL()
  80. {
  81. llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 );
  82. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("None"); // BE_NO_BUMP
  83. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Brightness"); // BE_BRIGHTNESS
  84. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness"); // BE_DARKNESS
  85. std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" );
  86. LLFILE* file = LLFile::fopen( file_name, "rt" );  /*Flawfinder: ignore*/
  87. if( !file )
  88. {
  89. llwarns << "Could not open std_bump <" << file_name << ">" << llendl;
  90. return;
  91. }
  92. S32 file_version = 0;
  93. S32 fields_read = fscanf( file, "LLStandardBumpmap version %d", &file_version );
  94. if( fields_read != 1 )
  95. {
  96. llwarns << "Bad LLStandardBumpmap header" << llendl;
  97. return;
  98. }
  99. if( file_version > STD_BUMP_LATEST_FILE_VERSION )
  100. {
  101. llwarns << "LLStandardBumpmap has newer version (" << file_version << ") than viewer (" << STD_BUMP_LATEST_FILE_VERSION << ")" << llendl;
  102. return;
  103. }
  104. while( !feof(file) && (LLStandardBumpmap::sStandardBumpmapCount < (U32)TEM_BUMPMAP_COUNT) )
  105. {
  106. // *NOTE: This buffer size is hard coded into scanf() below.
  107. char label[2048] = ""; /* Flawfinder: ignore */
  108. char bump_image_id[2048] = ""; /* Flawfinder: ignore */
  109. fields_read = fscanf( /* Flawfinder: ignore */
  110. file, "n%2047s %2047s", label, bump_image_id);
  111. if( EOF == fields_read )
  112. {
  113. break;
  114. }
  115. if( fields_read != 2 )
  116. {
  117. llwarns << "Bad LLStandardBumpmap entry" << llendl;
  118. return;
  119. }
  120. //  llinfos << "Loading bumpmap: " << bump_image_id << " from viewerart" << llendl;
  121. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label;
  122. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = 
  123. LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id),
  124. TRUE, 
  125. LLViewerTexture::BOOST_NONE, 
  126. LLViewerTexture::LOD_TEXTURE,
  127. 0, 
  128. 0);
  129. gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL );
  130. LLStandardBumpmap::sStandardBumpmapCount++;
  131. }
  132. fclose( file );
  133. }
  134. // static
  135. void LLStandardBumpmap::destroyGL()
  136. {
  137. for( U32 i = 0; i < LLStandardBumpmap::sStandardBumpmapCount; i++ )
  138. {
  139. gStandardBumpmapList[i].mLabel.assign("");
  140. gStandardBumpmapList[i].mImage = NULL;
  141. }
  142. sStandardBumpmapCount = 0;
  143. }
  144. ////////////////////////////////////////////////////////////////
  145. LLDrawPoolBump::LLDrawPoolBump() 
  146. :  LLRenderPass(LLDrawPool::POOL_BUMP)
  147. {
  148. mShiny = FALSE;
  149. }
  150. void LLDrawPoolBump::prerender()
  151. {
  152. mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
  153. }
  154. // static
  155. S32 LLDrawPoolBump::numBumpPasses()
  156. {
  157. if (gSavedSettings.getBOOL("RenderObjectBump"))
  158. {
  159. if (mVertexShaderLevel > 1)
  160. {
  161. if (LLPipeline::sImpostorRender)
  162. {
  163. return 2;
  164. }
  165. else
  166. {
  167. return 3;
  168. }
  169. }
  170. else if (LLPipeline::sImpostorRender)
  171. {
  172. return 1;
  173. }
  174. else
  175. {
  176. return 2;
  177. }
  178. }
  179.     else
  180. {
  181. return 0;
  182. }
  183. }
  184. S32 LLDrawPoolBump::getNumPasses()
  185. {
  186. return numBumpPasses();
  187. }
  188. void LLDrawPoolBump::beginRenderPass(S32 pass)
  189. {
  190. LLFastTimer t(FTM_RENDER_BUMP);
  191. switch( pass )
  192. {
  193. case 0:
  194. beginShiny();
  195. break;
  196. case 1:
  197. if (mVertexShaderLevel > 1)
  198. {
  199. beginFullbrightShiny();
  200. }
  201. else 
  202. {
  203. beginBump();
  204. }
  205. break;
  206. case 2:
  207. beginBump();
  208. break;
  209. default:
  210. llassert(0);
  211. break;
  212. }
  213. }
  214. void LLDrawPoolBump::render(S32 pass)
  215. {
  216. LLFastTimer t(FTM_RENDER_BUMP);
  217. if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE))
  218. {
  219. return;
  220. }
  221. switch( pass )
  222. {
  223. case 0:
  224. renderShiny();
  225. break;
  226. case 1:
  227. if (mVertexShaderLevel > 1)
  228. {
  229. renderFullbrightShiny();
  230. }
  231. else 
  232. {
  233. renderBump(); 
  234. }
  235. break;
  236. case 2:
  237. renderBump();
  238. break;
  239. default:
  240. llassert(0);
  241. break;
  242. }
  243. }
  244. void LLDrawPoolBump::endRenderPass(S32 pass)
  245. {
  246. LLFastTimer t(FTM_RENDER_BUMP);
  247. switch( pass )
  248. {
  249. case 0:
  250. endShiny();
  251. break;
  252. case 1:
  253. if (mVertexShaderLevel > 1)
  254. {
  255. endFullbrightShiny();
  256. }
  257. else 
  258. {
  259. endBump();
  260. }
  261. break;
  262. case 2:
  263. endBump();
  264. break;
  265. default:
  266. llassert(0);
  267. break;
  268. }
  269. }
  270. //static
  271. void LLDrawPoolBump::beginShiny(bool invisible)
  272. {
  273. LLFastTimer t(FTM_RENDER_SHINY);
  274. if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| 
  275. (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
  276. {
  277. return;
  278. }
  279. mShiny = TRUE;
  280. sVertexMask = VERTEX_MASK_SHINY;
  281. // Second pass: environment map
  282. if (!invisible && mVertexShaderLevel > 1)
  283. {
  284. sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
  285. }
  286. if (LLPipeline::sUnderWaterRender)
  287. {
  288. shader = &gObjectShinyWaterProgram;
  289. }
  290. else
  291. {
  292. shader = &gObjectShinyProgram;
  293. }
  294. LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
  295. if( cube_map )
  296. {
  297. if (!invisible && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0 )
  298. {
  299. LLMatrix4 mat;
  300. mat.initRows(LLVector4(gGLModelView+0),
  301.  LLVector4(gGLModelView+4),
  302.  LLVector4(gGLModelView+8),
  303.  LLVector4(gGLModelView+12));
  304. shader->bind();
  305. LLVector3 vec = LLVector3(gShinyOrigin) * mat;
  306. LLVector4 vec4(vec, gShinyOrigin.mV[3]);
  307. shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
  308. if (mVertexShaderLevel > 1)
  309. {
  310. cube_map->setMatrix(1);
  311. // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for 
  312. // the cube map in the one pass shiny shaders
  313. cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
  314. cube_map->enableTexture(cube_channel);
  315. cube_map->enableTextureCoords(1);
  316. diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  317. }
  318. else
  319. {
  320. cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
  321. diffuse_channel = -1;
  322. cube_map->setMatrix(0);
  323. cube_map->enable(cube_channel);
  324. }
  325. gGL.getTexUnit(cube_channel)->bind(cube_map);
  326. gGL.getTexUnit(0)->activate();
  327. }
  328. else
  329. {
  330. cube_channel = 0;
  331. diffuse_channel = -1;
  332. gGL.getTexUnit(0)->disable();
  333. cube_map->enable(0);
  334. cube_map->setMatrix(0);
  335. gGL.getTexUnit(0)->bind(cube_map);
  336. gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
  337. gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_VERT_ALPHA);
  338. }
  339. }
  340. }
  341. void LLDrawPoolBump::renderShiny(bool invisible)
  342. {
  343. LLFastTimer t(FTM_RENDER_SHINY);
  344. if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| 
  345. (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
  346. {
  347. return;
  348. }
  349. if( gSky.mVOSkyp->getCubeMap() )
  350. {
  351. LLGLEnable blend_enable(GL_BLEND);
  352. if (!invisible && mVertexShaderLevel > 1)
  353. {
  354. LLRenderPass::renderTexture(LLRenderPass::PASS_SHINY, sVertexMask);
  355. }
  356. else if (!invisible)
  357. {
  358. renderGroups(LLRenderPass::PASS_SHINY, sVertexMask);
  359. }
  360. else // invisible
  361. {
  362. renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask);
  363. }
  364. }
  365. }
  366. void LLDrawPoolBump::endShiny(bool invisible)
  367. {
  368. LLFastTimer t(FTM_RENDER_SHINY);
  369. if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| 
  370. (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
  371. {
  372. return;
  373. }
  374. LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
  375. if( cube_map )
  376. {
  377. cube_map->disable();
  378. cube_map->restoreMatrix();
  379. if (!invisible && mVertexShaderLevel > 1)
  380. {
  381. shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
  382. if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
  383. {
  384. if (diffuse_channel != 0)
  385. {
  386. shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  387. }
  388. }
  389. shader->unbind();
  390. }
  391. }
  392. gGL.getTexUnit(diffuse_channel)->disable();
  393. gGL.getTexUnit(cube_channel)->disable();
  394. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  395. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  396. diffuse_channel = -1;
  397. cube_channel = 0;
  398. mShiny = FALSE;
  399. }
  400. void LLDrawPoolBump::beginFullbrightShiny()
  401. {
  402. LLFastTimer t(FTM_RENDER_SHINY);
  403. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
  404. {
  405. return;
  406. }
  407. sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
  408. // Second pass: environment map
  409. if (LLPipeline::sUnderWaterRender)
  410. {
  411. shader = &gObjectShinyWaterProgram;
  412. }
  413. else
  414. {
  415. shader = &gObjectFullbrightShinyProgram;
  416. }
  417. LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
  418. if( cube_map )
  419. {
  420. LLMatrix4 mat;
  421. mat.initRows(LLVector4(gGLModelView+0),
  422.  LLVector4(gGLModelView+4),
  423.  LLVector4(gGLModelView+8),
  424.  LLVector4(gGLModelView+12));
  425. shader->bind();
  426. LLVector3 vec = LLVector3(gShinyOrigin) * mat;
  427. LLVector4 vec4(vec, gShinyOrigin.mV[3]);
  428. shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
  429. cube_map->setMatrix(1);
  430. // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for 
  431. // the cube map in the one pass shiny shaders
  432. gGL.getTexUnit(1)->disable();
  433. cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
  434. cube_map->enableTexture(cube_channel);
  435. cube_map->enableTextureCoords(1);
  436. diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  437. gGL.getTexUnit(cube_channel)->bind(cube_map);
  438. gGL.getTexUnit(0)->activate();
  439. }
  440. mShiny = TRUE;
  441. }
  442. void LLDrawPoolBump::renderFullbrightShiny()
  443. {
  444. LLFastTimer t(FTM_RENDER_SHINY);
  445. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
  446. {
  447. return;
  448. }
  449. if( gSky.mVOSkyp->getCubeMap() )
  450. {
  451. LLGLEnable blend_enable(GL_BLEND);
  452. LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
  453. }
  454. }
  455. void LLDrawPoolBump::endFullbrightShiny()
  456. {
  457. LLFastTimer t(FTM_RENDER_SHINY);
  458. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
  459. {
  460. return;
  461. }
  462. LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
  463. if( cube_map )
  464. {
  465. cube_map->disable();
  466. cube_map->restoreMatrix();
  467. if (diffuse_channel != 0)
  468. {
  469. shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  470. }
  471. gGL.getTexUnit(0)->activate();
  472. gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
  473. shader->unbind();
  474. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  475. }
  476. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  477. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  478. diffuse_channel = -1;
  479. cube_channel = 0;
  480. mShiny = FALSE;
  481. }
  482. void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE)
  483. {
  484. LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
  485. for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) 
  486. {
  487. LLDrawInfo& params = **k;
  488. applyModelMatrix(params);
  489. if (params.mGroup)
  490. {
  491. params.mGroup->rebuildMesh();
  492. }
  493. params.mVertexBuffer->setBuffer(mask);
  494. params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
  495. gPipeline.addTrianglesDrawn(params.mCount/3);
  496. }
  497. }
  498. // static
  499. BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel)
  500. {
  501. LLViewerTexture* bump = NULL;
  502. U8 bump_code = params.mBump;
  503. //Note: texture atlas does not support bump texture now.
  504. LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params.mTexture) ;
  505. if(!tex)
  506. {
  507. //if the texture is not a fetched texture
  508. return FALSE;
  509. }
  510. switch( bump_code )
  511. {
  512. case BE_NO_BUMP:
  513. break;
  514. case BE_BRIGHTNESS: 
  515. case BE_DARKNESS:
  516. bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
  517. break;
  518. default:
  519. if( bump_code < LLStandardBumpmap::sStandardBumpmapCount )
  520. {
  521. bump = gStandardBumpmapList[bump_code].mImage;
  522. gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize);
  523. }
  524. break;
  525. }
  526. if (bump)
  527. {
  528. if (channel == -2)
  529. {
  530. gGL.getTexUnit(1)->bind(bump);
  531. gGL.getTexUnit(0)->bind(bump);
  532. }
  533. else
  534. {
  535. gGL.getTexUnit(channel)->bind(bump);
  536. }
  537. return TRUE;
  538. }
  539. return FALSE;
  540. }
  541. //static
  542. void LLDrawPoolBump::beginBump()
  543. {
  544. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
  545. {
  546. return;
  547. }
  548. sVertexMask = VERTEX_MASK_BUMP;
  549. LLFastTimer t(FTM_RENDER_BUMP);
  550. // Optional second pass: emboss bump map
  551. stop_glerror();
  552. // TEXTURE UNIT 0
  553. // Output.rgb = texture at texture coord 0
  554. gGL.getTexUnit(0)->activate();
  555. gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
  556. gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
  557. // TEXTURE UNIT 1
  558. gGL.getTexUnit(1)->activate();
  559.  
  560. gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
  561. gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA);
  562. gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
  563. // src = tex0 + (1 - tex1) - 0.5
  564. // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5
  565. // = (1 + bump0 - bump1) / 2
  566. // Blend: src * dst + dst * src
  567. // = 2 * src * dst
  568. // = 2 * ((1 + bump0 - bump1) / 2) * dst   [0 - 2 * dst]
  569. // = (1 + bump0 - bump1) * dst.rgb
  570. // = dst.rgb + dst.rgb * (bump0 - bump1)
  571. gGL.setSceneBlendType(LLRender::BT_MULT_X2);
  572. gGL.getTexUnit(0)->activate();
  573. stop_glerror();
  574. gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
  575. }
  576. //static
  577. void LLDrawPoolBump::renderBump()
  578. {
  579. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
  580. {
  581. return;
  582. }
  583. LLFastTimer ftm(FTM_RENDER_BUMP);
  584. LLGLDisable fog(GL_FOG);
  585. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL);
  586. LLGLEnable blend(GL_BLEND);
  587. glColor4f(1,1,1,1);
  588. /// Get rid of z-fighting with non-bump pass.
  589. LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
  590. glPolygonOffset(-1.0f, -1.0f);
  591. renderBump(LLRenderPass::PASS_BUMP, sVertexMask);
  592. }
  593. //static
  594. void LLDrawPoolBump::endBump()
  595. {
  596. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
  597. {
  598. return;
  599. }
  600. // Disable texture unit 1
  601. gGL.getTexUnit(1)->activate();
  602. gGL.getTexUnit(1)->disable();
  603. gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
  604. // Disable texture unit 0
  605. gGL.getTexUnit(0)->activate();
  606. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  607. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  608. }
  609. void LLDrawPoolBump::beginDeferredPass(S32 pass)
  610. {
  611. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
  612. {
  613. return;
  614. }
  615. LLFastTimer ftm(FTM_RENDER_BUMP);
  616. mShiny = TRUE;
  617. gDeferredBumpProgram.bind();
  618. diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  619. bump_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::BUMP_MAP);
  620. gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
  621. gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE);
  622. }
  623. void LLDrawPoolBump::endDeferredPass(S32 pass)
  624. {
  625. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
  626. {
  627. return;
  628. }
  629. LLFastTimer ftm(FTM_RENDER_BUMP);
  630. mShiny = FALSE;
  631. gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
  632. gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP);
  633. gDeferredBumpProgram.unbind();
  634. gGL.getTexUnit(0)->activate();
  635. }
  636. void LLDrawPoolBump::renderDeferred(S32 pass)
  637. {
  638. if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
  639. {
  640. return;
  641. }
  642. LLFastTimer ftm(FTM_RENDER_BUMP);
  643. U32 type = LLRenderPass::PASS_BUMP;
  644. LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type);
  645. LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type);
  646. U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
  647. for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i)
  648. {
  649. LLDrawInfo& params = **i;
  650. LLDrawPoolBump::bindBumpMap(params, bump_channel);
  651. pushBatch(params, mask, TRUE);
  652. }
  653. }
  654. void LLDrawPoolBump::beginPostDeferredPass(S32 pass)
  655. {
  656. beginFullbrightShiny();
  657. }
  658. void LLDrawPoolBump::endPostDeferredPass(S32 pass)
  659. {
  660. endFullbrightShiny();
  661. }
  662. void LLDrawPoolBump::renderPostDeferred(S32 pass)
  663. {
  664. renderFullbrightShiny();
  665. }
  666. ////////////////////////////////////////////////////////////////
  667. // List of one-component bump-maps created from other texures.
  668. //const LLUUID TEST_BUMP_ID("3d33eaf2-459c-6f97-fd76-5fce3fc29447");
  669. void LLBumpImageList::init()
  670. {
  671. llassert( mBrightnessEntries.size() == 0 );
  672. llassert( mDarknessEntries.size() == 0 );
  673. LLStandardBumpmap::init();
  674. }
  675. void LLBumpImageList::shutdown()
  676. {
  677. mBrightnessEntries.clear();
  678. mDarknessEntries.clear();
  679. LLStandardBumpmap::shutdown();
  680. }
  681. void LLBumpImageList::destroyGL()
  682. {
  683. mBrightnessEntries.clear();
  684. mDarknessEntries.clear();
  685. LLStandardBumpmap::destroyGL();
  686. }
  687. void LLBumpImageList::restoreGL()
  688. {
  689. // Images will be recreated as they are needed.
  690. LLStandardBumpmap::restoreGL();
  691. }
  692. LLBumpImageList::~LLBumpImageList()
  693. {
  694. // Shutdown should have already been called.
  695. llassert( mBrightnessEntries.size() == 0 );
  696. llassert( mDarknessEntries.size() == 0 );
  697. }
  698. // Note: Does nothing for entries in gStandardBumpmapList that are not actually standard bump images (e.g. none, brightness, and darkness)
  699. void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id, F32 virtual_size)
  700. {
  701. bump &= TEM_BUMP_MASK;
  702. LLViewerFetchedTexture* bump_image = gStandardBumpmapList[bump].mImage;
  703. if( bump_image )
  704. {
  705. bump_image->addTextureStats(virtual_size);
  706. }
  707. }
  708. void LLBumpImageList::updateImages()
  709. {
  710. llpushcallstacks ;
  711. for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); )
  712. {
  713. bump_image_map_t::iterator curiter = iter++;
  714. LLViewerTexture* image = curiter->second;
  715. if( image )
  716. {
  717. BOOL destroy = TRUE;
  718. if( image->hasGLTexture())
  719. {
  720. if( image->getBoundRecently() )
  721. {
  722. destroy = FALSE;
  723. }
  724. else
  725. {
  726. image->destroyGLTexture();
  727. }
  728. }
  729. if( destroy )
  730. {
  731. //llinfos << "*** Destroying bright " << (void*)image << llendl;
  732. mBrightnessEntries.erase(curiter);   // deletes the image thanks to reference counting
  733. }
  734. }
  735. }
  736. llpushcallstacks ;
  737. for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); )
  738. {
  739. bump_image_map_t::iterator curiter = iter++;
  740. LLViewerTexture* image = curiter->second;
  741. if( image )
  742. {
  743. BOOL destroy = TRUE;
  744. if( image->hasGLTexture())
  745. {
  746. if( image->getBoundRecently() )
  747. {
  748. destroy = FALSE;
  749. }
  750. else
  751. {
  752. image->destroyGLTexture();
  753. }
  754. }
  755. if( destroy )
  756. {
  757. //llinfos << "*** Destroying dark " << (void*)image << llendl;;
  758. mDarknessEntries.erase(curiter);  // deletes the image thanks to reference counting
  759. }
  760. }
  761. }
  762. llpushcallstacks ;
  763. }
  764. // Note: the caller SHOULD NOT keep the pointer that this function returns.  It may be updated as more data arrives.
  765. LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedTexture* src_image, U8 bump_code )
  766. {
  767. llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
  768. LLViewerTexture* bump = NULL;
  769. const F32 BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD = 1000;
  770. if( src_image->getMaxVirtualSize() > BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD )
  771. {
  772. bump_image_map_t* entries_list = NULL;
  773. void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
  774. switch( bump_code )
  775. {
  776. case BE_BRIGHTNESS:
  777. entries_list = &mBrightnessEntries;
  778. callback_func = LLBumpImageList::onSourceBrightnessLoaded;
  779. break;
  780. case BE_DARKNESS:
  781. entries_list = &mDarknessEntries;
  782. callback_func = LLBumpImageList::onSourceDarknessLoaded;
  783. break;
  784. default:
  785. llassert(0);
  786. return NULL;
  787. }
  788. bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
  789. if (iter != entries_list->end())
  790. {
  791. bump = iter->second;
  792. }
  793. else
  794. {
  795. LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
  796. raw->clear(0x77, 0x77, 0x77, 0xFF);
  797. (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
  798. (*entries_list)[src_image->getID()]->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
  799. // Note: this may create an LLImageGL immediately
  800. src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()) );
  801. bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
  802. // bump_total++;
  803. // llinfos << "*** Creating " << (void*)bump << " " << bump_total << llendl;
  804. }
  805. }
  806. return bump;
  807. }
  808. // static
  809. void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
  810. {
  811. LLUUID* source_asset_id = (LLUUID*)userdata;
  812. LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS );
  813. if( final )
  814. {
  815. delete source_asset_id;
  816. }
  817. }
  818. // static
  819. void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
  820. {
  821. LLUUID* source_asset_id = (LLUUID*)userdata;
  822. LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS );
  823. if( final )
  824. {
  825. delete source_asset_id;
  826. }
  827. }
  828. void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
  829. {
  830. if (success && LLPipeline::sRenderDeferred)
  831. {
  832. LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4);
  833. generateNormalMapFromAlpha(src, nrm_image);
  834. src_vi->setExplicitFormat(GL_RGBA, GL_RGBA);
  835. src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image);
  836. }
  837. }
  838. void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image)
  839. {
  840. U8* nrm_data = nrm_image->getData();
  841. S32 resX = src->getWidth();
  842. S32 resY = src->getHeight();
  843. U8* src_data = src->getData();
  844. S32 src_cmp = src->getComponents();
  845. F32 norm_scale = gSavedSettings.getF32("RenderNormalMapScale");
  846. U32 idx = 0;
  847. //generate normal map from pseudo-heightfield
  848. for (S32 j = 0; j < resY; ++j)
  849. {
  850. for (S32 i = 0; i < resX; ++i)
  851. {
  852. S32 rX = (i+1)%resX;
  853. S32 rY = (j+1)%resY;
  854. S32 lX = (i-1)%resX;
  855. S32 lY = (j-1)%resY;
  856. if (lX < 0)
  857. {
  858. lX += resX;
  859. }
  860. if (lY < 0)
  861. {
  862. lY += resY;
  863. }
  864. F32 cH = (F32) src_data[(j*resX+i)*src_cmp+src_cmp-1];
  865. LLVector3 right = LLVector3(norm_scale, 0, (F32) src_data[(j*resX+rX)*src_cmp+src_cmp-1]-cH);
  866. LLVector3 left = LLVector3(-norm_scale, 0, (F32) src_data[(j*resX+lX)*src_cmp+src_cmp-1]-cH);
  867. LLVector3 up = LLVector3(0, -norm_scale, (F32) src_data[(rY*resX+i)*src_cmp+src_cmp-1]-cH);
  868. LLVector3 down = LLVector3(0, norm_scale, (F32) src_data[(lY*resX+i)*src_cmp+src_cmp-1]-cH);
  869. LLVector3 norm = right%down + down%left + left%up + up%right;
  870. norm.normVec();
  871. norm *= 0.5f;
  872. norm += LLVector3(0.5f,0.5f,0.5f);
  873. idx = (j*resX+i)*4;
  874. nrm_data[idx+0]= (U8) (norm.mV[0]*255);
  875. nrm_data[idx+1]= (U8) (norm.mV[1]*255);
  876. nrm_data[idx+2]= (U8) (norm.mV[2]*255);
  877. nrm_data[idx+3]= src_data[(j*resX+i)*src_cmp+src_cmp-1];
  878. }
  879. }
  880. }
  881. // static
  882. void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
  883. {
  884. if( success )
  885. {
  886. bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries );
  887. bump_image_map_t::iterator iter = entries_list.find(source_asset_id);
  888. if (iter != entries_list.end())
  889. {
  890. LLPointer<LLImageRaw> dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1);
  891. U8* dst_data = dst_image->getData();
  892. S32 dst_data_size = dst_image->getDataSize();
  893. U8* src_data = src->getData();
  894. S32 src_data_size = src->getDataSize();
  895. S32 src_components = src->getComponents();
  896. // Convert to luminance and then scale and bias that to get ready for
  897. // embossed bump mapping.  (0-255 maps to 127-255)
  898. // Convert to fixed point so we don't have to worry about precision/clamping.
  899. const S32 FIXED_PT = 8;
  900. const S32 R_WEIGHT = S32(0.2995f * (1<<FIXED_PT));
  901. const S32 G_WEIGHT = S32(0.5875f * (1<<FIXED_PT));
  902. const S32 B_WEIGHT = S32(0.1145f * (1<<FIXED_PT));
  903. S32 minimum = 255;
  904. S32 maximum = 0;
  905. switch( src_components )
  906. {
  907. case 1:
  908. case 2:
  909. if( src_data_size == dst_data_size * src_components )
  910. {
  911. for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
  912. {
  913. dst_data[i] = src_data[j];
  914. if( dst_data[i] < minimum )
  915. {
  916. minimum = dst_data[i];
  917. }
  918. if( dst_data[i] > maximum )
  919. {
  920. maximum = dst_data[i];
  921. }
  922. }
  923. }
  924. else
  925. {
  926. llassert(0);
  927. dst_image->clear();
  928. }
  929. break;
  930. case 3:
  931. case 4:
  932. if( src_data_size == dst_data_size * src_components )
  933. {
  934. for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
  935. {
  936. // RGB to luminance
  937. dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT;
  938. //llassert( dst_data[i] <= 255 );true because it's 8bit
  939. if( dst_data[i] < minimum )
  940. {
  941. minimum = dst_data[i];
  942. }
  943. if( dst_data[i] > maximum )
  944. {
  945. maximum = dst_data[i];
  946. }
  947. }
  948. }
  949. else
  950. {
  951. llassert(0);
  952. dst_image->clear();
  953. }
  954. break;
  955. default:
  956. llassert(0);
  957. dst_image->clear();
  958. break;
  959. }
  960. if( maximum > minimum )
  961. {
  962. U8 bias_and_scale_lut[256];
  963. F32 twice_one_over_range = 2.f / (maximum - minimum);
  964. S32 i;
  965. const F32 ARTIFICIAL_SCALE = 2.f;  // Advantage: exagerates the effect in midrange.  Disadvantage: clamps at the extremes.
  966. if( BE_DARKNESS == bump_code )
  967. {
  968. for( i = minimum; i <= maximum; i++ )
  969. {
  970. F32 minus_one_to_one = F32(maximum - i) * twice_one_over_range - 1.f;
  971. bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
  972. }
  973. }
  974. else
  975. {
  976. // BE_LIGHTNESS
  977. for( i = minimum; i <= maximum; i++ )
  978. {
  979. F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f;
  980. bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
  981. }
  982. }
  983. for( i = 0; i < dst_data_size; i++ )
  984. {
  985. dst_data[i] = bias_and_scale_lut[dst_data[i]];
  986. }
  987. }
  988. //---------------------------------------------------
  989. //immediately assign bump to a global smart pointer in case some local smart pointer
  990. //accidently releases it.
  991. LLPointer<LLViewerTexture> bump = LLViewerTextureManager::getLocalTexture( TRUE);
  992. if (!LLPipeline::sRenderDeferred)
  993. {
  994. bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
  995. bump->createGLTexture(0, dst_image);
  996. }
  997. else
  998. {
  999. LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4);
  1000. generateNormalMapFromAlpha(src, nrm_image);
  1001. bump->setExplicitFormat(GL_RGBA, GL_RGBA);
  1002. bump->createGLTexture(0, nrm_image);
  1003. }
  1004. iter->second = bump; // derefs (and deletes) old image
  1005. //---------------------------------------------------
  1006. }
  1007. else
  1008. {
  1009. // entry should have been added in LLBumpImageList::getImage().
  1010. // Not a legit assertion - the bump texture could have been flushed by the bump image manager
  1011. //llassert(0);
  1012. }
  1013. }
  1014. }
  1015. void LLDrawPoolBump::renderBump(U32 type, U32 mask)
  1016. {
  1017. LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type);
  1018. LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type);
  1019. for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i)
  1020. {
  1021. LLDrawInfo& params = **i;
  1022. if (LLDrawPoolBump::bindBumpMap(params))
  1023. {
  1024. pushBatch(params, mask, FALSE);
  1025. }
  1026. }
  1027. }
  1028. void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
  1029. {
  1030. applyModelMatrix(params);
  1031. if (params.mTextureMatrix)
  1032. {
  1033. if (mShiny)
  1034. {
  1035. gGL.getTexUnit(0)->activate();
  1036. glMatrixMode(GL_TEXTURE);
  1037. }
  1038. else
  1039. {
  1040. gGL.getTexUnit(1)->activate();
  1041. glMatrixMode(GL_TEXTURE);
  1042. glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
  1043. gPipeline.mTextureMatrixOps++;
  1044. gGL.getTexUnit(0)->activate();
  1045. }
  1046. glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
  1047. gPipeline.mTextureMatrixOps++;
  1048. }
  1049. if (mShiny && mVertexShaderLevel > 1 && texture)
  1050. {
  1051. if (params.mTexture.notNull())
  1052. {
  1053. gGL.getTexUnit(diffuse_channel)->bind(params.mTexture) ;
  1054. params.mTexture->addTextureStats(params.mVSize);
  1055. }
  1056. else
  1057. {
  1058. gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
  1059. }
  1060. }
  1061. if (params.mGroup)
  1062. {
  1063. params.mGroup->rebuildMesh();
  1064. }
  1065. params.mVertexBuffer->setBuffer(mask);
  1066. params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
  1067. gPipeline.addTrianglesDrawn(params.mCount/3);
  1068. if (params.mTextureMatrix)
  1069. {
  1070. if (mShiny)
  1071. {
  1072. gGL.getTexUnit(0)->activate();
  1073. }
  1074. else
  1075. {
  1076. gGL.getTexUnit(1)->activate();
  1077. glLoadIdentity();
  1078. gGL.getTexUnit(0)->activate();
  1079. }
  1080. glLoadIdentity();
  1081. glMatrixMode(GL_MODELVIEW);
  1082. }
  1083. }
  1084. void LLDrawPoolInvisible::render(S32 pass)
  1085. { //render invisiprims
  1086. LLFastTimer t(FTM_RENDER_INVISIBLE);
  1087.   
  1088. U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
  1089. glStencilMask(0);
  1090. gGL.setColorMask(false, false);
  1091. pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE);
  1092. gGL.setColorMask(true, false);
  1093. glStencilMask(0xFFFFFFFF);
  1094. if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
  1095. {
  1096. beginShiny(true);
  1097. renderShiny(true);
  1098. endShiny(true);
  1099. }
  1100. }
  1101. void LLDrawPoolInvisible::beginDeferredPass(S32 pass)
  1102. {
  1103. beginRenderPass(pass);
  1104. }
  1105. void LLDrawPoolInvisible::endDeferredPass( S32 pass )
  1106. {
  1107. endRenderPass(pass);
  1108. }
  1109. void LLDrawPoolInvisible::renderDeferred( S32 pass )
  1110. { //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff
  1111. LLFastTimer t(FTM_RENDER_INVISIBLE);
  1112.   
  1113. U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
  1114. glStencilMask(0);
  1115. glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE);
  1116. gGL.setColorMask(false, false);
  1117. pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE);
  1118. gGL.setColorMask(true, true);
  1119. glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  1120. glStencilMask(0xFFFFFFFF);
  1121. if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
  1122. {
  1123. beginShiny(true);
  1124. renderShiny(true);
  1125. endShiny(true);
  1126. }
  1127. }