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
00044 #include "llagent.h"
00045 #include "llcubemap.h"
00046 #include "lldrawable.h"
00047 #include "lldrawpoolsimple.h"
00048 #include "llface.h"
00049 #include "llsky.h"
00050 #include "lltextureentry.h"
00051 #include "llviewercamera.h"
00052 #include "llviewerimagelist.h"
00053 #include "pipeline.h"
00054 #include "llglslshader.h"
00055
00056
00057
00058
00059
00060 LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT];
00061
00062
00063 U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
00064
00065
00066 LLBumpImageList gBumpImageList;
00067
00068 const S32 STD_BUMP_LATEST_FILE_VERSION = 1;
00069
00070 const U32 VERTEX_MASK_SHINY = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
00071 const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_TEXCOORD2;
00072
00073 U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY;
00074 static LLCubeMap* sCubeMap = NULL;
00075
00076
00077 void LLStandardBumpmap::init()
00078 {
00079 LLStandardBumpmap::restoreGL();
00080 }
00081
00082
00083 void LLStandardBumpmap::shutdown()
00084 {
00085 LLStandardBumpmap::destroyGL();
00086 }
00087
00088
00089 void LLStandardBumpmap::restoreGL()
00090 {
00091 llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 );
00092 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("None");
00093 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Brightness");
00094 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness");
00095
00096 std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" );
00097 FILE* file = LLFile::fopen( file_name.c_str(), "rt" );
00098 if( !file )
00099 {
00100 llwarns << "Could not open std_bump <" << file_name << ">" << llendl;
00101 return;
00102 }
00103
00104 S32 file_version = 0;
00105
00106 S32 fields_read = fscanf( file, "LLStandardBumpmap version %d", &file_version );
00107 if( fields_read != 1 )
00108 {
00109 llwarns << "Bad LLStandardBumpmap header" << llendl;
00110 return;
00111 }
00112
00113 if( file_version > STD_BUMP_LATEST_FILE_VERSION )
00114 {
00115 llwarns << "LLStandardBumpmap has newer version (" << file_version << ") than viewer (" << STD_BUMP_LATEST_FILE_VERSION << ")" << llendl;
00116 return;
00117 }
00118
00119 while( !feof(file) && (LLStandardBumpmap::sStandardBumpmapCount < (U32)TEM_BUMPMAP_COUNT) )
00120 {
00121
00122 char label[2048] = "";
00123 char bump_file[2048] = "";
00124 fields_read = fscanf(
00125 file, "\n%2047s %2047s", label, bump_file);
00126 if( EOF == fields_read )
00127 {
00128 break;
00129 }
00130 if( fields_read != 2 )
00131 {
00132 llwarns << "Bad LLStandardBumpmap entry" << llendl;
00133 return;
00134 }
00135
00136
00137 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label;
00138 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = gImageList.getImage( LLUUID(gViewerArt.getString(bump_file)) );
00139 LLStandardBumpmap::sStandardBumpmapCount++;
00140 }
00141
00142 fclose( file );
00143 }
00144
00145
00146 void LLStandardBumpmap::destroyGL()
00147 {
00148 for( U32 i = 0; i < LLStandardBumpmap::sStandardBumpmapCount; i++ )
00149 {
00150 gStandardBumpmapList[i].mLabel.assign("");
00151 gStandardBumpmapList[i].mImage = NULL;
00152 }
00153 sStandardBumpmapCount = 0;
00154 }
00155
00156
00157
00159
00160 LLDrawPoolBump::LLDrawPoolBump()
00161 : LLRenderPass(LLDrawPool::POOL_BUMP)
00162 {
00163 }
00164
00165
00166 void LLDrawPoolBump::prerender()
00167 {
00168 mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT);
00169 }
00170
00171
00172 S32 LLDrawPoolBump::numBumpPasses()
00173 {
00174 if (gSavedSettings.getBOOL("RenderObjectBump"))
00175 {
00176 return 2;
00177 }
00178 else
00179 {
00180 return 0;
00181 }
00182 }
00183
00184 S32 LLDrawPoolBump::getNumPasses()
00185 {
00186 return numBumpPasses();
00187 }
00188
00189 void LLDrawPoolBump::beginRenderPass(S32 pass)
00190 {
00191 switch( pass )
00192 {
00193 case 0:
00194 beginShiny();
00195 break;
00196 case 1:
00197 beginBump();
00198 break;
00199 default:
00200 llassert(0);
00201 break;
00202 }
00203 }
00204
00205 void LLDrawPoolBump::render(S32 pass)
00206 {
00207 LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
00208
00209 if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE))
00210 {
00211 return;
00212 }
00213
00214 switch( pass )
00215 {
00216 case 0:
00217 {
00218 renderShiny();
00219 break;
00220 }
00221 case 1:
00222 {
00223 renderBump();
00224 break;
00225 }
00226 default:
00227 {
00228 llassert(0);
00229 break;
00230 }
00231 }
00232 }
00233
00234 void LLDrawPoolBump::endRenderPass(S32 pass)
00235 {
00236 switch( pass )
00237 {
00238 case 0:
00239 endShiny();
00240 break;
00241 case 1:
00242 endBump();
00243 break;
00244 default:
00245 llassert(0);
00246 break;
00247 }
00248 }
00249
00250
00251 void LLDrawPoolBump::beginShiny()
00252 {
00253 sVertexMask = VERTEX_MASK_SHINY;
00254
00255 glEnableClientState(GL_VERTEX_ARRAY);
00256 glEnableClientState(GL_NORMAL_ARRAY);
00257 glEnableClientState(GL_COLOR_ARRAY);
00258
00259 LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
00260 if( cube_map )
00261 {
00262 cube_map->enable(0);
00263 cube_map->setMatrix(0);
00264 cube_map->bind();
00265
00266 if (LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT) > 0)
00267 {
00268 LLMatrix4 mat;
00269 mat.initRows(LLVector4(gGLModelView+0),
00270 LLVector4(gGLModelView+4),
00271 LLVector4(gGLModelView+8),
00272 LLVector4(gGLModelView+12));
00273 gObjectShinyProgram.bind();
00274 LLVector3 vec = LLVector3(gShinyOrigin) * mat;
00275 LLVector4 vec4(vec, gShinyOrigin.mV[3]);
00276 glUniform4fvARB(gObjectShinyProgram.mUniform[LLShaderMgr::SHINY_ORIGIN], 1,
00277 vec4.mV);
00278 }
00279 else
00280 {
00281 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
00282
00283
00284 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
00285 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
00286 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
00287
00288
00289 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
00290 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR);
00291 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
00292 }
00293 }
00294 }
00295
00296 void LLDrawPoolBump::renderShiny()
00297 {
00298 LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
00299
00300 sCubeMap = NULL;
00301
00302 if( gSky.mVOSkyp->getCubeMap() )
00303 {
00304 LLGLEnable blend_enable(GL_BLEND);
00305 renderStatic(LLRenderPass::PASS_SHINY, sVertexMask);
00306 renderActive(LLRenderPass::PASS_SHINY, sVertexMask);
00307 }
00308 }
00309
00310 void LLDrawPoolBump::renderActive(U32 type, U32 mask, BOOL texture)
00311 {
00312 #if !LL_RELEASE_FOR_DOWNLOAD
00313 LLGLState::checkClientArrays(mask);
00314 #endif
00315
00316 LLSpatialBridge* last_bridge = NULL;
00317 glPushMatrix();
00318
00319 for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mActiveGroups.begin(); i != gPipeline.mActiveGroups.end(); ++i)
00320 {
00321 LLSpatialGroup* group = *i;
00322 if (!group->isDead() &&
00323 gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
00324 group->mDrawMap.find(type) != group->mDrawMap.end())
00325 {
00326 LLSpatialBridge* bridge = (LLSpatialBridge*) group->mSpatialPartition;
00327 if (bridge != last_bridge)
00328 {
00329 glPopMatrix();
00330 glPushMatrix();
00331 glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix);
00332 last_bridge = bridge;
00333
00334 if (LLPipeline::sDynamicReflections)
00335 {
00336 LLSpatialPartition* part = gPipeline.getSpatialPartition(LLPipeline::PARTITION_VOLUME);
00337 LLSpatialGroup::OctreeNode* node = part->mOctree->getNodeAt(LLVector3d(bridge->mDrawable->getPositionAgent()), 32.0);
00338 if (node)
00339 {
00340 sCubeMap = ((LLSpatialGroup*) node->getListener(0))->mReflectionMap;
00341 }
00342 }
00343 }
00344
00345 renderGroup(group,type,mask,texture);
00346 }
00347 }
00348
00349 glPopMatrix();
00350 }
00351
00352
00353
00354 void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE)
00355 {
00356 LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
00357
00358 for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
00359 {
00360 LLDrawInfo& params = **k;
00361 if (LLPipeline::sDynamicReflections)
00362 {
00363 if (params.mReflectionMap.notNull())
00364 {
00365 params.mReflectionMap->bind();
00366 }
00367 else
00368 {
00369 if (sCubeMap)
00370 {
00371 sCubeMap->bind();
00372 }
00373 else
00374 {
00375 gSky.mVOSkyp->getCubeMap()->bind();
00376 }
00377 }
00378 }
00379
00380 params.mVertexBuffer->setBuffer(mask);
00381 U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
00382 glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
00383 GL_UNSIGNED_INT, indices_pointer+params.mOffset);
00384 gPipeline.mTrianglesDrawn += params.mCount/3;
00385 }
00386 }
00387
00388 void LLDrawPoolBump::endShiny()
00389 {
00390 LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
00391 if( cube_map )
00392 {
00393 cube_map->disable();
00394 cube_map->restoreMatrix();
00395
00396 if (LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT) > 0)
00397 {
00398 gObjectShinyProgram.unbind();
00399 }
00400
00401 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00402 }
00403
00404 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
00405 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00406 glDisableClientState(GL_NORMAL_ARRAY);
00407 glDisableClientState(GL_COLOR_ARRAY);
00408 }
00409
00410
00411
00412 BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params)
00413 {
00414 LLImageGL* bump = NULL;
00415
00416 U8 bump_code = params.mBump;
00417 LLViewerImage* tex = params.mTexture;
00418
00419 switch( bump_code )
00420 {
00421 case BE_NO_BUMP:
00422 bump = NULL;
00423 break;
00424 case BE_BRIGHTNESS:
00425 case BE_DARKNESS:
00426 if( tex )
00427 {
00428 bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
00429 }
00430 break;
00431
00432 default:
00433 if( bump_code < LLStandardBumpmap::sStandardBumpmapCount )
00434 {
00435 bump = gStandardBumpmapList[bump_code].mImage;
00436 gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize, 1, 1);
00437 }
00438 break;
00439 }
00440
00441 if (bump)
00442 {
00443 bump->bind(1);
00444 bump->bind(0);
00445 return TRUE;
00446 }
00447 return FALSE;
00448 }
00449
00450
00451 void LLDrawPoolBump::beginBump()
00452 {
00453 sVertexMask = VERTEX_MASK_BUMP;
00454 LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
00455
00456 stop_glerror();
00457
00458
00459
00460 glActiveTextureARB(GL_TEXTURE0_ARB);
00461 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00462 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00463
00464 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
00465 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
00466
00467 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
00468 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_ALPHA);
00469
00470
00471 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
00472 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
00473 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
00474
00475
00476 glActiveTextureARB(GL_TEXTURE1_ARB);
00477 glClientActiveTextureARB(GL_TEXTURE1_ARB);
00478 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00479
00480 glEnable(GL_TEXTURE_2D);
00481
00482 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
00483 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB);
00484
00485 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
00486 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
00487
00488 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
00489 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
00490
00491
00492 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
00493 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
00494 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
00507
00508 glActiveTextureARB(GL_TEXTURE0_ARB);
00509 stop_glerror();
00510 }
00511
00512
00513 void LLDrawPoolBump::renderBump()
00514 {
00515 LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP);
00516 LLGLDisable fog(GL_FOG);
00517 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_EQUAL);
00518 LLGLEnable tex2d(GL_TEXTURE_2D);
00519 LLGLEnable blend(GL_BLEND);
00520 glColor4f(1,1,1,1);
00521 renderBump(LLRenderPass::PASS_BUMP, sVertexMask);
00522 renderBumpActive(LLRenderPass::PASS_BUMP, sVertexMask);
00523 }
00524
00525
00526 void LLDrawPoolBump::endBump()
00527 {
00528
00529 glActiveTextureARB(GL_TEXTURE1_ARB);
00530 glClientActiveTextureARB(GL_TEXTURE1_ARB);
00531 glDisable(GL_TEXTURE_2D);
00532 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00533 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00534
00535
00536 glActiveTextureARB(GL_TEXTURE0_ARB);
00537 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00538 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00539 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00540
00541 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00542 }
00543
00545
00546
00547
00548
00549
00550 void LLBumpImageList::init()
00551 {
00552 llassert( mBrightnessEntries.size() == 0 );
00553 llassert( mDarknessEntries.size() == 0 );
00554
00555 LLStandardBumpmap::init();
00556 }
00557
00558 void LLBumpImageList::shutdown()
00559 {
00560 mBrightnessEntries.clear();
00561 mDarknessEntries.clear();
00562 LLStandardBumpmap::shutdown();
00563 }
00564
00565 void LLBumpImageList::destroyGL()
00566 {
00567 mBrightnessEntries.clear();
00568 mDarknessEntries.clear();
00569 LLStandardBumpmap::destroyGL();
00570 }
00571
00572 void LLBumpImageList::restoreGL()
00573 {
00574
00575 LLStandardBumpmap::restoreGL();
00576 }
00577
00578
00579 LLBumpImageList::~LLBumpImageList()
00580 {
00581
00582 llassert( mBrightnessEntries.size() == 0 );
00583 llassert( mDarknessEntries.size() == 0 );
00584 }
00585
00586
00587
00588 void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id,
00589 F32 pixel_area, F32 texel_area_ratio, F32 cos_center_angle)
00590 {
00591 bump &= TEM_BUMP_MASK;
00592 LLViewerImage* bump_image = gStandardBumpmapList[bump].mImage;
00593 if( bump_image )
00594 {
00595 bump_image->addTextureStats(pixel_area, texel_area_ratio, cos_center_angle);
00596 }
00597 }
00598
00599
00600 void LLBumpImageList::updateImages()
00601 {
00602 for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); )
00603 {
00604 bump_image_map_t::iterator curiter = iter++;
00605 LLImageGL* image = curiter->second;
00606 if( image )
00607 {
00608 BOOL destroy = TRUE;
00609 if( image->getHasGLTexture())
00610 {
00611 if( image->getBoundRecently() )
00612 {
00613 destroy = FALSE;
00614 }
00615 else
00616 {
00617 image->destroyGLTexture();
00618 }
00619 }
00620
00621 if( destroy )
00622 {
00623
00624 mBrightnessEntries.erase(curiter);
00625 }
00626 }
00627 }
00628
00629 for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); )
00630 {
00631 bump_image_map_t::iterator curiter = iter++;
00632 LLImageGL* image = curiter->second;
00633 if( image )
00634 {
00635 BOOL destroy = TRUE;
00636 if( image->getHasGLTexture())
00637 {
00638 if( image->getBoundRecently() )
00639 {
00640 destroy = FALSE;
00641 }
00642 else
00643 {
00644 image->destroyGLTexture();
00645 }
00646 }
00647
00648 if( destroy )
00649 {
00650
00651 mDarknessEntries.erase(curiter);
00652 }
00653 }
00654 }
00655
00656 }
00657
00658
00659
00660 LLImageGL* LLBumpImageList::getBrightnessDarknessImage(LLViewerImage* src_image, U8 bump_code )
00661 {
00662 llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
00663
00664 LLImageGL* bump = NULL;
00665 const F32 BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD = 1000;
00666 if( src_image->mMaxVirtualSize > BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD )
00667 {
00668 bump_image_map_t* entries_list = NULL;
00669 void (*callback_func)( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
00670
00671 switch( bump_code )
00672 {
00673 case BE_BRIGHTNESS:
00674 entries_list = &mBrightnessEntries;
00675 callback_func = LLBumpImageList::onSourceBrightnessLoaded;
00676 break;
00677 case BE_DARKNESS:
00678 entries_list = &mDarknessEntries;
00679 callback_func = LLBumpImageList::onSourceDarknessLoaded;
00680 break;
00681 default:
00682 llassert(0);
00683 return NULL;
00684 }
00685
00686 bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
00687 if (iter != entries_list->end())
00688 {
00689 bump = iter->second;
00690 }
00691 else
00692 {
00693 LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
00694 raw->clear(0x77, 0x77, 0x77, 0xFF);
00695 bump = new LLImageGL( raw, TRUE);
00696 bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
00697 (*entries_list)[src_image->getID()] = bump;
00698
00699
00700 src_image->setLoadedCallback( callback_func, 0, TRUE, new LLUUID(src_image->getID()) );
00701 bump = (*entries_list)[src_image->getID()];
00702
00703
00704
00705 }
00706 }
00707
00708 return bump;
00709 }
00710
00711
00712
00713 void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
00714 {
00715 LLUUID* source_asset_id = (LLUUID*)userdata;
00716 LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS );
00717 if( final )
00718 {
00719 delete source_asset_id;
00720 }
00721 }
00722
00723
00724 void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
00725 {
00726 LLUUID* source_asset_id = (LLUUID*)userdata;
00727 LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS );
00728 if( final )
00729 {
00730 delete source_asset_id;
00731 }
00732 }
00733
00734
00735
00736 void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
00737 {
00738 if( success )
00739 {
00740 bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries );
00741 bump_image_map_t::iterator iter = entries_list.find(source_asset_id);
00742 if (iter != entries_list.end())
00743 {
00744 LLPointer<LLImageRaw> dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1);
00745 U8* dst_data = dst_image->getData();
00746 S32 dst_data_size = dst_image->getDataSize();
00747
00748 U8* src_data = src->getData();
00749 S32 src_data_size = src->getDataSize();
00750
00751 S32 src_components = src->getComponents();
00752
00753
00754
00755
00756
00757 const S32 FIXED_PT = 8;
00758 const S32 R_WEIGHT = S32(0.2995f * (1<<FIXED_PT));
00759 const S32 G_WEIGHT = S32(0.5875f * (1<<FIXED_PT));
00760 const S32 B_WEIGHT = S32(0.1145f * (1<<FIXED_PT));
00761
00762 S32 minimum = 255;
00763 S32 maximum = 0;
00764
00765 switch( src_components )
00766 {
00767 case 1:
00768 case 2:
00769 if( src_data_size == dst_data_size * src_components )
00770 {
00771 for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
00772 {
00773 dst_data[i] = src_data[j];
00774 if( dst_data[i] < minimum )
00775 {
00776 minimum = dst_data[i];
00777 }
00778 if( dst_data[i] > maximum )
00779 {
00780 maximum = dst_data[i];
00781 }
00782 }
00783 }
00784 else
00785 {
00786 llassert(0);
00787 dst_image->clear();
00788 }
00789 break;
00790 case 3:
00791 case 4:
00792 if( src_data_size == dst_data_size * src_components )
00793 {
00794 for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
00795 {
00796
00797 dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT;
00798
00799 if( dst_data[i] < minimum )
00800 {
00801 minimum = dst_data[i];
00802 }
00803 if( dst_data[i] > maximum )
00804 {
00805 maximum = dst_data[i];
00806 }
00807 }
00808 }
00809 else
00810 {
00811 llassert(0);
00812 dst_image->clear();
00813 }
00814 break;
00815 default:
00816 llassert(0);
00817 dst_image->clear();
00818 break;
00819 }
00820
00821 if( maximum > minimum )
00822 {
00823 U8 bias_and_scale_lut[256];
00824 F32 twice_one_over_range = 2.f / (maximum - minimum);
00825 S32 i;
00826
00827 const F32 ARTIFICIAL_SCALE = 2.f;
00828 if( BE_DARKNESS == bump_code )
00829 {
00830 for( i = minimum; i <= maximum; i++ )
00831 {
00832 F32 minus_one_to_one = F32(maximum - i) * twice_one_over_range - 1.f;
00833 bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
00834 }
00835 }
00836 else
00837 {
00838
00839 for( i = minimum; i <= maximum; i++ )
00840 {
00841 F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f;
00842 bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
00843 }
00844 }
00845
00846 for( i = 0; i < dst_data_size; i++ )
00847 {
00848 dst_data[i] = bias_and_scale_lut[dst_data[i]];
00849 }
00850 }
00851
00852 LLImageGL* bump = new LLImageGL( TRUE);
00853 bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
00854 bump->createGLTexture(0, dst_image);
00855 iter->second = bump;
00856 }
00857 else
00858 {
00859
00860
00861
00862
00863 }
00864 }
00865 }
00866
00867 void LLDrawPoolBump::renderBumpActive(U32 type, U32 mask)
00868 {
00869 #if !LL_RELEASE_FOR_DOWNLOAD
00870 LLGLState::checkClientArrays(mask);
00871 #endif
00872
00873 LLSpatialBridge* last_bridge = NULL;
00874 glPushMatrix();
00875
00876 for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mActiveGroups.begin(); i != gPipeline.mActiveGroups.end(); ++i)
00877 {
00878 LLSpatialGroup* group = *i;
00879 if (!group->isDead() &&
00880 group->mSpatialPartition->mRenderByGroup &&
00881 group->mDrawMap.find(type) != group->mDrawMap.end())
00882 {
00883 LLSpatialBridge* bridge = (LLSpatialBridge*) group->mSpatialPartition;
00884 if (bridge != last_bridge)
00885 {
00886 glPopMatrix();
00887 glPushMatrix();
00888 glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix);
00889 last_bridge = bridge;
00890 }
00891
00892 renderGroupBump(group,type,mask);
00893 }
00894 }
00895
00896 glPopMatrix();
00897 }
00898
00899 void LLDrawPoolBump::renderBump(U32 type, U32 mask)
00900 {
00901 #if !LL_RELEASE_FOR_DOWNLOAD
00902 LLGLState::checkClientArrays(mask);
00903 #endif
00904
00905 LLSpatialGroup::drawmap_elem_t& draw_info = gPipeline.mRenderMap[type];
00906
00907 for (LLSpatialGroup::drawmap_elem_t::iterator i = draw_info.begin(); i != draw_info.end(); ++i)
00908 {
00909 LLDrawInfo& params = **i;
00910
00911 if (LLDrawPoolBump::bindBumpMap(params))
00912 {
00913 pushBatch(params, mask, FALSE);
00914 }
00915 }
00916 }
00917
00918 void LLDrawPoolBump::renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask)
00919 {
00920 LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
00921
00922 for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
00923 {
00924 LLDrawInfo& params = **k;
00925
00926 if (LLDrawPoolBump::bindBumpMap(params))
00927 {
00928 pushBatch(params, mask, FALSE);
00929 }
00930 }
00931 }
00932
00933 void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
00934 {
00935 if (params.mTextureMatrix)
00936 {
00937 glActiveTextureARB(GL_TEXTURE1_ARB);
00938 glMatrixMode(GL_TEXTURE);
00939 glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
00940 glActiveTextureARB(GL_TEXTURE0_ARB);
00941 glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
00942 }
00943 params.mVertexBuffer->setBuffer(mask);
00944 U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
00945 glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
00946 GL_UNSIGNED_INT, indices_pointer+params.mOffset);
00947 gPipeline.mTrianglesDrawn += params.mCount/3;
00948 if (params.mTextureMatrix)
00949 {
00950 glActiveTextureARB(GL_TEXTURE1_ARB);
00951 glLoadIdentity();
00952 glActiveTextureARB(GL_TEXTURE0_ARB);
00953 glLoadIdentity();
00954 glMatrixMode(GL_MODELVIEW);
00955 }
00956 }