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 #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 //#include "llimagebmp.h"
00059 //#include "../tools/imdebug/imdebug.h"
00060 
00061 // static
00062 LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT]; 
00063 
00064 // static
00065 U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
00066 
00067 // static
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 // static 
00083 void LLStandardBumpmap::init()
00084 {
00085         LLStandardBumpmap::restoreGL();
00086 }
00087 
00088 // static 
00089 void LLStandardBumpmap::shutdown()
00090 {
00091         LLStandardBumpmap::destroyGL();
00092 }
00093 
00094 // static 
00095 void LLStandardBumpmap::restoreGL()
00096 {
00097         llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 );
00098         gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("None");           // BE_NO_BUMP
00099         gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Brightness");     // BE_BRIGHTNESS
00100         gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness");       // BE_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" );         /*Flawfinder: ignore*/
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                 // *NOTE: This buffer size is hard coded into scanf() below.
00128                 char label[2048] = "";  /* Flawfinder: ignore */
00129                 char bump_file[2048] = "";      /* Flawfinder: ignore */
00130                 fields_read = fscanf(   /* Flawfinder: ignore */
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 //              llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl;
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 // static
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 // static
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 //static
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         // Second pass: environment map
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                                 // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for 
00351                                 // the cube map in the one pass shiny shaders
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                         //use RGB from texture
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                         // use alpha from color
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 // invisible
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         // Second pass: environment map
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                 // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for 
00497                 // the cube map in the one pass shiny shaders
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 // static
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 //static
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         // Optional second pass: emboss bump map
00649         stop_glerror();
00650 
00651         // TEXTURE UNIT 0
00652         // Output.rgb = texture at texture coord 0
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         // Don't care about alpha output
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         // TEXTURE UNIT 1
00667         glActiveTextureARB(GL_TEXTURE1_ARB);
00668 
00669         glEnable(GL_TEXTURE_2D); // Texture unit 1
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         // Don't care about alpha output
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         // src  = tex0 + (1 - tex1) - 0.5
00686         //              = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5
00687         //              = (1 + bump0 - bump1) / 2
00688 
00689 
00690         // Blend: src * dst + dst * src
00691         //              = 2 * src * dst
00692         //              = 2 * ((1 + bump0 - bump1) / 2) * dst   [0 - 2 * dst]
00693         //              = (1 + bump0 - bump1) * dst.rgb
00694         //              = dst.rgb + dst.rgb * (bump0 - bump1)
00695         gGL.blendFunc(GL_DST_COLOR, GL_SRC_COLOR);
00696 //      gGL.blendFunc(GL_ONE, GL_ZERO);  // temp
00697         glActiveTextureARB(GL_TEXTURE0_ARB);
00698         stop_glerror();
00699 
00700         LLViewerImage::unbindTexture(1, GL_TEXTURE_2D);
00701 }
00702 
00703 //static
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 //static
00723 void LLDrawPoolBump::endBump()
00724 {
00725         if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
00726         {
00727                 return;
00728         }
00729 
00730         // Disable texture unit 1
00731         glActiveTextureARB(GL_TEXTURE1_ARB);
00732         glDisable(GL_TEXTURE_2D); // Texture unit 1
00733         glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00734 
00735         // Disable texture unit 0
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 // List of one-component bump-maps created from other texures.
00744 
00745 
00746 //const LLUUID TEST_BUMP_ID("3d33eaf2-459c-6f97-fd76-5fce3fc29447");
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         // Images will be recreated as they are needed.
00773         LLStandardBumpmap::restoreGL();
00774 }
00775 
00776 
00777 LLBumpImageList::~LLBumpImageList()
00778 {
00779         // Shutdown should have already been called.
00780         llassert( mBrightnessEntries.size() == 0 );
00781         llassert( mDarknessEntries.size() == 0 );
00782 }
00783 
00784 
00785 // Note: Does nothing for entries in gStandardBumpmapList that are not actually standard bump images (e.g. none, brightness, and darkness)
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                                 //llinfos << "*** Destroying bright " << (void*)image << llendl;
00822                                 mBrightnessEntries.erase(curiter);   // deletes the image thanks to reference counting
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                                 //llinfos << "*** Destroying dark " << (void*)image << llendl;;
00849                                 mDarknessEntries.erase(curiter);  // deletes the image thanks to reference counting
00850                         }
00851                 }
00852         }
00853 
00854 }
00855 
00856 
00857 // Note: the caller SHOULD NOT keep the pointer that this function returns.  It may be updated as more data arrives.
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                         // Note: this may create an LLImageGL immediately
00898                         src_image->setLoadedCallback( callback_func, 0, TRUE, new LLUUID(src_image->getID()) );
00899                         bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
00900 
00901 //                      bump_total++;
00902 //                      llinfos << "*** Creating " << (void*)bump << " " << bump_total << llendl;
00903                 }
00904         }
00905 
00906         return bump;
00907 }
00908 
00909 
00910 // static
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 // static
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 // static
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                         // Convert to luminance and then scale and bias that to get ready for
00952                         // embossed bump mapping.  (0-255 maps to 127-255)
00953 
00954                         // Convert to fixed point so we don't have to worry about precision/clamping.
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                                                 // RGB to luminance
00995                                                 dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT;
00996                                                 //llassert( dst_data[i] <= 255 );true because it's 8bit
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;  // Advantage: exagerates the effect in midrange.  Disadvantage: clamps at the extremes.
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                                         // BE_LIGHTNESS
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; // derefs (and deletes) old image
01054                 }
01055                 else
01056                 {
01057                         // entry should have been added in LLBumpImageList::getImage().
01058 
01059                         // Not a legit assertion - the bump texture could have been flushed by the bump image manager
01060                         //llassert(0);
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 { //render invisiprims
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 

Generated on Fri May 16 08:33:18 2008 for SecondLife by  doxygen 1.5.5