00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "lldrawpoolbump.h"
00035
00036 #include "llstl.h"
00037 #include "llviewercontrol.h"
00038 #include "lldir.h"
00039 #include "llimagegl.h"
00040 #include "m3math.h"
00041 #include "m4math.h"
00042 #include "v4math.h"
00043 #include "llglheaders.h"
00044 #include "llglimmediate.h"
00045
00046 #include "llagent.h"
00047 #include "llcubemap.h"
00048 #include "lldrawable.h"
00049 #include "llface.h"
00050 #include "llsky.h"
00051 #include "lltextureentry.h"
00052 #include "llviewercamera.h"
00053 #include "llviewerimagelist.h"
00054 #include "pipeline.h"
00055 #include "llspatialpartition.h"
00056 #include "llglslshader.h"
00057
00058
00059
00060
00061
00062 LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT];
00063
00064
00065 U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
00066
00067
00068 LLBumpImageList gBumpImageList;
00069
00070 const S32 STD_BUMP_LATEST_FILE_VERSION = 1;
00071
00072 const U32 VERTEX_MASK_SHINY = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
00073 const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_TEXCOORD2;
00074
00075 U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY;
00076 static LLPointer<LLCubeMap> sCubeMap;
00077
00078 static LLGLSLShader* shader = NULL;
00079 static S32 cube_channel = -1;
00080 static S32 diffuse_channel = -1;
00081
00082
00083 void LLStandardBumpmap::init()
00084 {
00085 LLStandardBumpmap::restoreGL();
00086 }
00087
00088
00089 void LLStandardBumpmap::shutdown()
00090 {
00091 LLStandardBumpmap::destroyGL();
00092 }
00093
00094
00095 void LLStandardBumpmap::restoreGL()
00096 {
00097 llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 );
00098 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("None");
00099 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Brightness");
00100 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness");
00101
00102 std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" );
00103 LLFILE* file = LLFile::fopen( file_name.c_str(), "rt" );
00104 if( !file )
00105 {
00106 llwarns << "Could not open std_bump <" << file_name << ">" << llendl;
00107 return;
00108 }
00109
00110 S32 file_version = 0;
00111
00112 S32 fields_read = fscanf( file, "LLStandardBumpmap version %d", &file_version );
00113 if( fields_read != 1 )
00114 {
00115 llwarns << "Bad LLStandardBumpmap header" << llendl;
00116 return;
00117 }
00118
00119 if( file_version > STD_BUMP_LATEST_FILE_VERSION )
00120 {
00121 llwarns << "LLStandardBumpmap has newer version (" << file_version << ") than viewer (" << STD_BUMP_LATEST_FILE_VERSION << ")" << llendl;
00122 return;
00123 }
00124
00125 while( !feof(file) && (LLStandardBumpmap::sStandardBumpmapCount < (U32)TEM_BUMPMAP_COUNT) )
00126 {
00127
00128 char label[2048] = "";
00129 char bump_file[2048] = "";
00130 fields_read = fscanf(
00131 file, "\n%2047s %2047s", label, bump_file);
00132 if( EOF == fields_read )
00133 {
00134 break;
00135 }
00136 if( fields_read != 2 )
00137 {
00138 llwarns << "Bad LLStandardBumpmap entry" << llendl;
00139 return;
00140 }
00141
00142
00143 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label;
00144 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage =
00145 gImageList.getImageFromFile(bump_file,
00146 TRUE,
00147 FALSE,
00148 0,
00149 0);
00150 LLStandardBumpmap::sStandardBumpmapCount++;
00151 }
00152
00153 fclose( file );
00154 }
00155
00156
00157 void LLStandardBumpmap::destroyGL()
00158 {
00159 for( U32 i = 0; i < LLStandardBumpmap::sStandardBumpmapCount; i++ )
00160 {
00161 gStandardBumpmapList[i].mLabel.assign("");
00162 gStandardBumpmapList[i].mImage = NULL;
00163 }
00164 sStandardBumpmapCount = 0;
00165 }
00166
00167
00168
00170
00171 LLDrawPoolBump::LLDrawPoolBump()
00172 : LLRenderPass(LLDrawPool::POOL_BUMP)
00173 {
00174 mShiny = FALSE;
00175 }
00176
00177
00178 void LLDrawPoolBump::prerender()
00179 {
00180 mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT);
00181 }
00182
00183
00184 S32 LLDrawPoolBump::numBumpPasses()
00185 {
00186 if (gSavedSettings.getBOOL("RenderObjectBump"))
00187 {
00188 if (mVertexShaderLevel > 1)
00189 {
00190 if (LLPipeline::sImpostorRender)
00191 {
00192 return 2;
00193 }
00194 else
00195 {
00196 return 3;
00197 }
00198 }
00199 else if (LLPipeline::sImpostorRender)
00200 {
00201 return 1;
00202 }
00203 else
00204 {
00205 return 2;
00206 }
00207 }
00208 else
00209 {
00210 return 0;
00211 }
00212 }
00213
00214 S32 LLDrawPoolBump::getNumPasses()
00215 {
00216 return numBumpPasses();
00217 }
00218
00219 void LLDrawPoolBump::beginRenderPass(S32 pass)
00220 {
00221 LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
00222 switch( pass )
00223 {
00224 case 0:
00225 beginShiny();
00226 break;
00227 case 1:
00228 if (mVertexShaderLevel > 1)
00229 {
00230 beginFullbrightShiny();
00231 }
00232 else
00233 {
00234 beginBump();
00235 }
00236 break;
00237 case 2:
00238 beginBump();
00239 break;
00240 default:
00241 llassert(0);
00242 break;
00243 }
00244 }
00245
00246 void LLDrawPoolBump::render(S32 pass)
00247 {
00248 LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
00249
00250 if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE))
00251 {
00252 return;
00253 }
00254
00255 switch( pass )
00256 {
00257 case 0:
00258 renderShiny();
00259 break;
00260 case 1:
00261 if (mVertexShaderLevel > 1)
00262 {
00263 renderFullbrightShiny();
00264 }
00265 else
00266 {
00267 renderBump();
00268 }
00269 break;
00270 case 2:
00271 renderBump();
00272 break;
00273 default:
00274 llassert(0);
00275 break;
00276 }
00277 }
00278
00279 void LLDrawPoolBump::endRenderPass(S32 pass)
00280 {
00281 LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
00282 switch( pass )
00283 {
00284 case 0:
00285 endShiny();
00286 break;
00287 case 1:
00288 if (mVertexShaderLevel > 1)
00289 {
00290 endFullbrightShiny();
00291 }
00292 else
00293 {
00294 endBump();
00295 }
00296 break;
00297 case 2:
00298 endBump();
00299 break;
00300 default:
00301 llassert(0);
00302 break;
00303 }
00304 }
00305
00306
00307 void LLDrawPoolBump::beginShiny(bool invisible)
00308 {
00309 LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
00310 if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)||
00311 invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
00312 {
00313 return;
00314 }
00315
00316 mShiny = TRUE;
00317 sVertexMask = VERTEX_MASK_SHINY;
00318
00319 if (!invisible && mVertexShaderLevel > 1)
00320 {
00321 sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD;
00322 }
00323
00324 if (LLPipeline::sUnderWaterRender)
00325 {
00326 shader = &gObjectShinyWaterProgram;
00327 }
00328 else
00329 {
00330 shader = &gObjectShinyProgram;
00331 }
00332
00333 LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
00334 if( cube_map )
00335 {
00336 if (!invisible && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT) > 0 )
00337 {
00338 LLMatrix4 mat;
00339 mat.initRows(LLVector4(gGLModelView+0),
00340 LLVector4(gGLModelView+4),
00341 LLVector4(gGLModelView+8),
00342 LLVector4(gGLModelView+12));
00343 shader->bind();
00344 LLVector3 vec = LLVector3(gShinyOrigin) * mat;
00345 LLVector4 vec4(vec, gShinyOrigin.mV[3]);
00346 shader->uniform4fv(LLShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
00347 if (mVertexShaderLevel > 1)
00348 {
00349 cube_map->setMatrix(1);
00350
00351
00352 cube_channel = shader->enableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
00353 cube_map->enableTexture(cube_channel);
00354 cube_map->enableTextureCoords(1);
00355 diffuse_channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
00356 }
00357 else
00358 {
00359 cube_channel = 0;
00360 diffuse_channel = -1;
00361 cube_map->setMatrix(0);
00362 cube_map->enable(shader->enableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB));
00363 }
00364 cube_map->bind();
00365 }
00366 else
00367 {
00368 cube_channel = 0;
00369 diffuse_channel = -1;
00370 cube_map->enable(0);
00371 cube_map->setMatrix(0);
00372 cube_map->bind();
00373
00374 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
00375
00376
00377 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
00378 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
00379 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
00380
00381
00382 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
00383 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR);
00384 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
00385 }
00386 }
00387 }
00388
00389 void LLDrawPoolBump::renderShiny(bool invisible)
00390 {
00391 LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
00392 if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)||
00393 invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
00394 {
00395 return;
00396 }
00397
00398 sCubeMap = NULL;
00399
00400 if( gSky.mVOSkyp->getCubeMap() )
00401 {
00402 LLGLEnable blend_enable(GL_BLEND);
00403 if (!invisible && mVertexShaderLevel > 1)
00404 {
00405 LLRenderPass::renderTexture(LLRenderPass::PASS_SHINY, sVertexMask);
00406 }
00407 else if (!invisible)
00408 {
00409 renderGroups(LLRenderPass::PASS_SHINY, sVertexMask);
00410 }
00411 else
00412 {
00413 renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask);
00414 }
00415 }
00416 }
00417
00418 void LLDrawPoolBump::endShiny(bool invisible)
00419 {
00420 LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
00421 if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)||
00422 invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
00423 {
00424 return;
00425 }
00426
00427 LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
00428 if( cube_map )
00429 {
00430 cube_map->disable();
00431 cube_map->restoreMatrix();
00432
00433 if (!invisible && mVertexShaderLevel > 1)
00434 {
00435 shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
00436
00437 if (LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT) > 0)
00438 {
00439 if (diffuse_channel != 0)
00440 {
00441 shader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
00442 }
00443 }
00444
00445 shader->unbind();
00446 glActiveTextureARB(GL_TEXTURE0_ARB);
00447 glEnable(GL_TEXTURE_2D);
00448 }
00449
00450 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00451 }
00452
00453 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
00454 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00455
00456 diffuse_channel = -1;
00457 cube_channel = 0;
00458 mShiny = FALSE;
00459 }
00460
00461 void LLDrawPoolBump::beginFullbrightShiny()
00462 {
00463 LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
00464 if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
00465 {
00466 return;
00467 }
00468
00469 sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD;
00470
00471
00472
00473 if (LLPipeline::sUnderWaterRender)
00474 {
00475 shader = &gObjectShinyWaterProgram;
00476 }
00477 else
00478 {
00479 shader = &gObjectFullbrightShinyProgram;
00480 }
00481
00482 LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
00483 if( cube_map )
00484 {
00485 LLMatrix4 mat;
00486 mat.initRows(LLVector4(gGLModelView+0),
00487 LLVector4(gGLModelView+4),
00488 LLVector4(gGLModelView+8),
00489 LLVector4(gGLModelView+12));
00490 shader->bind();
00491 LLVector3 vec = LLVector3(gShinyOrigin) * mat;
00492 LLVector4 vec4(vec, gShinyOrigin.mV[3]);
00493 shader->uniform4fv(LLShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
00494
00495 cube_map->setMatrix(1);
00496
00497
00498 cube_channel = shader->enableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
00499 cube_map->enableTexture(cube_channel);
00500 cube_map->enableTextureCoords(1);
00501 diffuse_channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
00502
00503 cube_map->bind();
00504 }
00505 mShiny = TRUE;
00506 }
00507
00508 void LLDrawPoolBump::renderFullbrightShiny()
00509 {
00510 LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
00511 if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
00512 {
00513 return;
00514 }
00515
00516 sCubeMap = NULL;
00517
00518 if( gSky.mVOSkyp->getCubeMap() )
00519 {
00520 LLGLEnable blend_enable(GL_BLEND);
00521 LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
00522 }
00523 }
00524
00525 void LLDrawPoolBump::endFullbrightShiny()
00526 {
00527 LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
00528 if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
00529 {
00530 return;
00531 }
00532
00533 LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
00534 if( cube_map )
00535 {
00536 cube_map->disable();
00537 cube_map->restoreMatrix();
00538
00539 if (diffuse_channel != 0)
00540 {
00541 shader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
00542 }
00543 glActiveTextureARB(GL_TEXTURE0_ARB);
00544 glEnable(GL_TEXTURE_2D);
00545
00546 shader->unbind();
00547
00548 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00549 }
00550
00551 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
00552 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00553
00554 diffuse_channel = -1;
00555 cube_channel = 0;
00556 mShiny = FALSE;
00557 }
00558
00559 void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE)
00560 {
00561 LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
00562
00563 for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
00564 {
00565 LLDrawInfo& params = **k;
00566 if (LLPipeline::sDynamicReflections)
00567 {
00568 if (params.mReflectionMap.notNull())
00569 {
00570 params.mReflectionMap->bind();
00571 }
00572 else
00573 {
00574 if (params.mModelMatrix)
00575 {
00576 sCubeMap = gPipeline.findReflectionMap(params.mModelMatrix->getTranslation());
00577 }
00578
00579 if (sCubeMap)
00580 {
00581 sCubeMap->bind();
00582 }
00583 else if (gSky.mVOSkyp->getCubeMap())
00584 {
00585 gSky.mVOSkyp->getCubeMap()->bind();
00586 }
00587 }
00588 }
00589
00590 applyModelMatrix(params);
00591
00592 params.mVertexBuffer->setBuffer(mask);
00593 params.mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
00594 gPipeline.addTrianglesDrawn(params.mCount/3);
00595 }
00596 }
00597
00598
00599
00600 BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params)
00601 {
00602 LLImageGL* bump = NULL;
00603
00604 U8 bump_code = params.mBump;
00605 LLViewerImage* tex = params.mTexture;
00606
00607 switch( bump_code )
00608 {
00609 case BE_NO_BUMP:
00610 bump = NULL;
00611 break;
00612 case BE_BRIGHTNESS:
00613 case BE_DARKNESS:
00614 if( tex )
00615 {
00616 bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
00617 }
00618 break;
00619
00620 default:
00621 if( bump_code < LLStandardBumpmap::sStandardBumpmapCount )
00622 {
00623 bump = gStandardBumpmapList[bump_code].mImage;
00624 gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize, 1, 1);
00625 }
00626 break;
00627 }
00628
00629 if (bump)
00630 {
00631 bump->bind(1);
00632 bump->bind(0);
00633 return TRUE;
00634 }
00635 return FALSE;
00636 }
00637
00638
00639 void LLDrawPoolBump::beginBump()
00640 {
00641 if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
00642 {
00643 return;
00644 }
00645
00646 sVertexMask = VERTEX_MASK_BUMP;
00647 LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
00648
00649 stop_glerror();
00650
00651
00652
00653 glActiveTextureARB(GL_TEXTURE0_ARB);
00654
00655 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
00656 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
00657
00658 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
00659 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_ALPHA);
00660
00661
00662 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
00663 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
00664 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
00665
00666
00667 glActiveTextureARB(GL_TEXTURE1_ARB);
00668
00669 glEnable(GL_TEXTURE_2D);
00670
00671 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
00672 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB);
00673
00674 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
00675 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
00676
00677 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
00678 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
00679
00680
00681 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
00682 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
00683 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 gGL.blendFunc(GL_DST_COLOR, GL_SRC_COLOR);
00696
00697 glActiveTextureARB(GL_TEXTURE0_ARB);
00698 stop_glerror();
00699
00700 LLViewerImage::unbindTexture(1, GL_TEXTURE_2D);
00701 }
00702
00703
00704 void LLDrawPoolBump::renderBump()
00705 {
00706 if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
00707 {
00708 return;
00709 }
00710
00711 LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP);
00712 LLGLDisable fog(GL_FOG);
00713 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL);
00714 LLGLEnable blend(GL_BLEND);
00715 glColor4f(1,1,1,1);
00717 LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
00718 glPolygonOffset(-1.0f, -1.0f);
00719 renderBump(LLRenderPass::PASS_BUMP, sVertexMask);
00720 }
00721
00722
00723 void LLDrawPoolBump::endBump()
00724 {
00725 if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
00726 {
00727 return;
00728 }
00729
00730
00731 glActiveTextureARB(GL_TEXTURE1_ARB);
00732 glDisable(GL_TEXTURE_2D);
00733 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00734
00735
00736 glActiveTextureARB(GL_TEXTURE0_ARB);
00737 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00738
00739 gGL.blendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00740 }
00741
00743
00744
00745
00746
00747
00748 void LLBumpImageList::init()
00749 {
00750 llassert( mBrightnessEntries.size() == 0 );
00751 llassert( mDarknessEntries.size() == 0 );
00752
00753 LLStandardBumpmap::init();
00754 }
00755
00756 void LLBumpImageList::shutdown()
00757 {
00758 mBrightnessEntries.clear();
00759 mDarknessEntries.clear();
00760 LLStandardBumpmap::shutdown();
00761 }
00762
00763 void LLBumpImageList::destroyGL()
00764 {
00765 mBrightnessEntries.clear();
00766 mDarknessEntries.clear();
00767 LLStandardBumpmap::destroyGL();
00768 }
00769
00770 void LLBumpImageList::restoreGL()
00771 {
00772
00773 LLStandardBumpmap::restoreGL();
00774 }
00775
00776
00777 LLBumpImageList::~LLBumpImageList()
00778 {
00779
00780 llassert( mBrightnessEntries.size() == 0 );
00781 llassert( mDarknessEntries.size() == 0 );
00782 }
00783
00784
00785
00786 void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id,
00787 F32 pixel_area, F32 texel_area_ratio, F32 cos_center_angle)
00788 {
00789 bump &= TEM_BUMP_MASK;
00790 LLViewerImage* bump_image = gStandardBumpmapList[bump].mImage;
00791 if( bump_image )
00792 {
00793 bump_image->addTextureStats(pixel_area, texel_area_ratio, cos_center_angle);
00794 }
00795 }
00796
00797
00798 void LLBumpImageList::updateImages()
00799 {
00800 for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); )
00801 {
00802 bump_image_map_t::iterator curiter = iter++;
00803 LLImageGL* image = curiter->second;
00804 if( image )
00805 {
00806 BOOL destroy = TRUE;
00807 if( image->getHasGLTexture())
00808 {
00809 if( image->getBoundRecently() )
00810 {
00811 destroy = FALSE;
00812 }
00813 else
00814 {
00815 image->destroyGLTexture();
00816 }
00817 }
00818
00819 if( destroy )
00820 {
00821
00822 mBrightnessEntries.erase(curiter);
00823 }
00824 }
00825 }
00826
00827 for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); )
00828 {
00829 bump_image_map_t::iterator curiter = iter++;
00830 LLImageGL* image = curiter->second;
00831 if( image )
00832 {
00833 BOOL destroy = TRUE;
00834 if( image->getHasGLTexture())
00835 {
00836 if( image->getBoundRecently() )
00837 {
00838 destroy = FALSE;
00839 }
00840 else
00841 {
00842 image->destroyGLTexture();
00843 }
00844 }
00845
00846 if( destroy )
00847 {
00848
00849 mDarknessEntries.erase(curiter);
00850 }
00851 }
00852 }
00853
00854 }
00855
00856
00857
00858 LLImageGL* LLBumpImageList::getBrightnessDarknessImage(LLViewerImage* src_image, U8 bump_code )
00859 {
00860 llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
00861
00862 LLImageGL* bump = NULL;
00863 const F32 BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD = 1000;
00864 if( src_image->mMaxVirtualSize > BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD )
00865 {
00866 bump_image_map_t* entries_list = NULL;
00867 void (*callback_func)( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
00868
00869 switch( bump_code )
00870 {
00871 case BE_BRIGHTNESS:
00872 entries_list = &mBrightnessEntries;
00873 callback_func = LLBumpImageList::onSourceBrightnessLoaded;
00874 break;
00875 case BE_DARKNESS:
00876 entries_list = &mDarknessEntries;
00877 callback_func = LLBumpImageList::onSourceDarknessLoaded;
00878 break;
00879 default:
00880 llassert(0);
00881 return NULL;
00882 }
00883
00884 bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
00885 if (iter != entries_list->end())
00886 {
00887 bump = iter->second;
00888 }
00889 else
00890 {
00891 LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
00892 raw->clear(0x77, 0x77, 0x77, 0xFF);
00893 bump = new LLImageGL( raw, TRUE);
00894 bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
00895 (*entries_list)[src_image->getID()] = bump;
00896
00897
00898 src_image->setLoadedCallback( callback_func, 0, TRUE, new LLUUID(src_image->getID()) );
00899 bump = (*entries_list)[src_image->getID()];
00900
00901
00902
00903 }
00904 }
00905
00906 return bump;
00907 }
00908
00909
00910
00911 void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
00912 {
00913 LLUUID* source_asset_id = (LLUUID*)userdata;
00914 LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS );
00915 if( final )
00916 {
00917 delete source_asset_id;
00918 }
00919 }
00920
00921
00922 void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
00923 {
00924 LLUUID* source_asset_id = (LLUUID*)userdata;
00925 LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS );
00926 if( final )
00927 {
00928 delete source_asset_id;
00929 }
00930 }
00931
00932
00933
00934 void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
00935 {
00936 if( success )
00937 {
00938 bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries );
00939 bump_image_map_t::iterator iter = entries_list.find(source_asset_id);
00940 if (iter != entries_list.end())
00941 {
00942 LLPointer<LLImageRaw> dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1);
00943 U8* dst_data = dst_image->getData();
00944 S32 dst_data_size = dst_image->getDataSize();
00945
00946 U8* src_data = src->getData();
00947 S32 src_data_size = src->getDataSize();
00948
00949 S32 src_components = src->getComponents();
00950
00951
00952
00953
00954
00955 const S32 FIXED_PT = 8;
00956 const S32 R_WEIGHT = S32(0.2995f * (1<<FIXED_PT));
00957 const S32 G_WEIGHT = S32(0.5875f * (1<<FIXED_PT));
00958 const S32 B_WEIGHT = S32(0.1145f * (1<<FIXED_PT));
00959
00960 S32 minimum = 255;
00961 S32 maximum = 0;
00962
00963 switch( src_components )
00964 {
00965 case 1:
00966 case 2:
00967 if( src_data_size == dst_data_size * src_components )
00968 {
00969 for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
00970 {
00971 dst_data[i] = src_data[j];
00972 if( dst_data[i] < minimum )
00973 {
00974 minimum = dst_data[i];
00975 }
00976 if( dst_data[i] > maximum )
00977 {
00978 maximum = dst_data[i];
00979 }
00980 }
00981 }
00982 else
00983 {
00984 llassert(0);
00985 dst_image->clear();
00986 }
00987 break;
00988 case 3:
00989 case 4:
00990 if( src_data_size == dst_data_size * src_components )
00991 {
00992 for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
00993 {
00994
00995 dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT;
00996
00997 if( dst_data[i] < minimum )
00998 {
00999 minimum = dst_data[i];
01000 }
01001 if( dst_data[i] > maximum )
01002 {
01003 maximum = dst_data[i];
01004 }
01005 }
01006 }
01007 else
01008 {
01009 llassert(0);
01010 dst_image->clear();
01011 }
01012 break;
01013 default:
01014 llassert(0);
01015 dst_image->clear();
01016 break;
01017 }
01018
01019 if( maximum > minimum )
01020 {
01021 U8 bias_and_scale_lut[256];
01022 F32 twice_one_over_range = 2.f / (maximum - minimum);
01023 S32 i;
01024
01025 const F32 ARTIFICIAL_SCALE = 2.f;
01026 if( BE_DARKNESS == bump_code )
01027 {
01028 for( i = minimum; i <= maximum; i++ )
01029 {
01030 F32 minus_one_to_one = F32(maximum - i) * twice_one_over_range - 1.f;
01031 bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
01032 }
01033 }
01034 else
01035 {
01036
01037 for( i = minimum; i <= maximum; i++ )
01038 {
01039 F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f;
01040 bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
01041 }
01042 }
01043
01044 for( i = 0; i < dst_data_size; i++ )
01045 {
01046 dst_data[i] = bias_and_scale_lut[dst_data[i]];
01047 }
01048 }
01049
01050 LLImageGL* bump = new LLImageGL( TRUE);
01051 bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
01052 bump->createGLTexture(0, dst_image);
01053 iter->second = bump;
01054 }
01055 else
01056 {
01057
01058
01059
01060
01061 }
01062 }
01063 }
01064
01065 void LLDrawPoolBump::renderBump(U32 type, U32 mask)
01066 {
01067 LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type);
01068 LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type);
01069
01070 for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i)
01071 {
01072 LLDrawInfo& params = **i;
01073
01074 if (LLDrawPoolBump::bindBumpMap(params))
01075 {
01076 pushBatch(params, mask, FALSE);
01077 }
01078 }
01079 }
01080
01081 void LLDrawPoolBump::renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask)
01082 {
01083 LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
01084
01085 for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
01086 {
01087 LLDrawInfo& params = **k;
01088
01089 if (LLDrawPoolBump::bindBumpMap(params))
01090 {
01091 pushBatch(params, mask, FALSE);
01092 }
01093 }
01094 }
01095
01096 void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
01097 {
01098 applyModelMatrix(params);
01099
01100 if (params.mTextureMatrix)
01101 {
01102 if (mShiny)
01103 {
01104 glActiveTextureARB(GL_TEXTURE0_ARB);
01105 glMatrixMode(GL_TEXTURE);
01106 }
01107 else
01108 {
01109 glActiveTextureARB(GL_TEXTURE1_ARB);
01110 glMatrixMode(GL_TEXTURE);
01111 glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
01112 gPipeline.mTextureMatrixOps++;
01113 glActiveTextureARB(GL_TEXTURE0_ARB);
01114 }
01115
01116 glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
01117 gPipeline.mTextureMatrixOps++;
01118 }
01119
01120 if (mShiny && mVertexShaderLevel > 1 && texture)
01121 {
01122 if (params.mTexture.notNull())
01123 {
01124 params.mTexture->bind(diffuse_channel);
01125 params.mTexture->addTextureStats(params.mVSize);
01126 }
01127 else
01128 {
01129 LLImageGL::unbindTexture(0);
01130 }
01131
01132 if (LLPipeline::sDynamicReflections)
01133 {
01134 LLCubeMap* cube_map = params.mReflectionMap;
01135
01136 if (!cube_map && params.mModelMatrix)
01137 {
01138 cube_map = gPipeline.findReflectionMap(params.mModelMatrix->getTranslation());
01139 }
01140
01141 if (cube_map)
01142 {
01143 cube_map->enableTexture(cube_channel);
01144 cube_map->bind();
01145 }
01146 }
01147 }
01148
01149 params.mVertexBuffer->setBuffer(mask);
01150 params.mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
01151 gPipeline.addTrianglesDrawn(params.mCount/3);
01152 if (params.mTextureMatrix)
01153 {
01154 if (mShiny)
01155 {
01156 glActiveTextureARB(GL_TEXTURE0_ARB);
01157 }
01158 else
01159 {
01160 glActiveTextureARB(GL_TEXTURE1_ARB);
01161 glLoadIdentity();
01162 glActiveTextureARB(GL_TEXTURE0_ARB);
01163 }
01164 glLoadIdentity();
01165 glMatrixMode(GL_MODELVIEW);
01166 }
01167 }
01168
01169 void LLDrawPoolInvisible::render(S32 pass)
01170 {
01171 LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE);
01172
01173 U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
01174 glStencilMask(0);
01175 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
01176 pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE);
01177 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
01178 glStencilMask(0xFFFFFFFF);
01179
01180 if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
01181 {
01182 beginShiny(true);
01183 renderShiny(true);
01184 endShiny(true);
01185 }
01186 }
01187