lldrawpoolbump.cpp

Go to the documentation of this file.
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 //#include "llimagebmp.h"
00057 //#include "../tools/imdebug/imdebug.h"
00058 
00059 // static
00060 LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT]; 
00061 
00062 // static
00063 U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
00064 
00065 // static
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 // static 
00077 void LLStandardBumpmap::init()
00078 {
00079         LLStandardBumpmap::restoreGL();
00080 }
00081 
00082 // static 
00083 void LLStandardBumpmap::shutdown()
00084 {
00085         LLStandardBumpmap::destroyGL();
00086 }
00087 
00088 // static 
00089 void LLStandardBumpmap::restoreGL()
00090 {
00091         llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 );
00092         gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("None");           // BE_NO_BUMP
00093         gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Brightness");     // BE_BRIGHTNESS
00094         gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness");       // BE_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" );   /*Flawfinder: ignore*/
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                 // *NOTE: This buffer size is hard coded into scanf() below.
00122                 char label[2048] = "";  /* Flawfinder: ignore */
00123                 char bump_file[2048] = "";      /* Flawfinder: ignore */
00124                 fields_read = fscanf(   /* Flawfinder: ignore */
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 //              llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl;
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 // static
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 // static
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 //static
00251 void LLDrawPoolBump::beginShiny()
00252 {
00253         sVertexMask = VERTEX_MASK_SHINY;
00254         // Second pass: environment map
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                         //use RGB from texture
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                         // use alpha from color
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 // static
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 //static
00451 void LLDrawPoolBump::beginBump()
00452 {       
00453         sVertexMask = VERTEX_MASK_BUMP;
00454         LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
00455         // Optional second pass: emboss bump map
00456         stop_glerror();
00457 
00458         // TEXTURE UNIT 0
00459         // Output.rgb = texture at texture coord 0
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         // Don't care about alpha output
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         // TEXTURE UNIT 1
00476         glActiveTextureARB(GL_TEXTURE1_ARB);
00477         glClientActiveTextureARB(GL_TEXTURE1_ARB);
00478         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00479 
00480         glEnable(GL_TEXTURE_2D); // Texture unit 1
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         // Don't care about alpha output
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         // src  = tex0 + (1 - tex1) - 0.5
00497         //              = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5
00498         //              = (1 + bump0 - bump1) / 2
00499 
00500 
00501         // Blend: src * dst + dst * src
00502         //              = 2 * src * dst
00503         //              = 2 * ((1 + bump0 - bump1) / 2) * dst   [0 - 2 * dst]
00504         //              = (1 + bump0 - bump1) * dst.rgb
00505         //              = dst.rgb + dst.rgb * (bump0 - bump1)
00506         glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
00507 //      glBlendFunc(GL_ONE, GL_ZERO);  // temp
00508         glActiveTextureARB(GL_TEXTURE0_ARB);
00509         stop_glerror();
00510 }
00511 
00512 //static
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 //static
00526 void LLDrawPoolBump::endBump()
00527 {
00528         // Disable texture unit 1
00529         glActiveTextureARB(GL_TEXTURE1_ARB);
00530         glClientActiveTextureARB(GL_TEXTURE1_ARB);
00531         glDisable(GL_TEXTURE_2D); // Texture unit 1
00532         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00533         glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00534 
00535         // Disable texture unit 0
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 // List of one-component bump-maps created from other texures.
00546 
00547 
00548 //const LLUUID TEST_BUMP_ID("3d33eaf2-459c-6f97-fd76-5fce3fc29447");
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         // Images will be recreated as they are needed.
00575         LLStandardBumpmap::restoreGL();
00576 }
00577 
00578 
00579 LLBumpImageList::~LLBumpImageList()
00580 {
00581         // Shutdown should have already been called.
00582         llassert( mBrightnessEntries.size() == 0 );
00583         llassert( mDarknessEntries.size() == 0 );
00584 }
00585 
00586 
00587 // Note: Does nothing for entries in gStandardBumpmapList that are not actually standard bump images (e.g. none, brightness, and darkness)
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                                 //llinfos << "*** Destroying bright " << (void*)image << llendl;
00624                                 mBrightnessEntries.erase(curiter);   // deletes the image thanks to reference counting
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                                 //llinfos << "*** Destroying dark " << (void*)image << llendl;;
00651                                 mDarknessEntries.erase(curiter);  // deletes the image thanks to reference counting
00652                         }
00653                 }
00654         }
00655 
00656 }
00657 
00658 
00659 // Note: the caller SHOULD NOT keep the pointer that this function returns.  It may be updated as more data arrives.
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                         // Note: this may create an LLImageGL immediately
00700                         src_image->setLoadedCallback( callback_func, 0, TRUE, new LLUUID(src_image->getID()) );
00701                         bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
00702 
00703 //                      bump_total++;
00704 //                      llinfos << "*** Creating " << (void*)bump << " " << bump_total << llendl;
00705                 }
00706         }
00707 
00708         return bump;
00709 }
00710 
00711 
00712 // static
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 // static
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 // static
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                         // Convert to luminance and then scale and bias that to get ready for
00754                         // embossed bump mapping.  (0-255 maps to 127-255)
00755 
00756                         // Convert to fixed point so we don't have to worry about precision/clamping.
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                                                 // RGB to luminance
00797                                                 dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT;
00798                                                 //llassert( dst_data[i] <= 255 );true because it's 8bit
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;  // Advantage: exagerates the effect in midrange.  Disadvantage: clamps at the extremes.
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                                         // BE_LIGHTNESS
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; // derefs (and deletes) old image
00856                 }
00857                 else
00858                 {
00859                         // entry should have been added in LLBumpImageList::getImage().
00860 
00861                         // Not a legit assertion - the bump texture could have been flushed by the bump image manager
00862                         //llassert(0);
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 }

Generated on Thu Jul 1 06:08:26 2010 for Second Life Viewer by  doxygen 1.4.7