00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "pipeline.h"
00035
00036
00037 #include "audioengine.h"
00038 #include "imageids.h"
00039 #include "llerror.h"
00040 #include "llviewercontrol.h"
00041 #include "llfasttimer.h"
00042 #include "llfontgl.h"
00043 #include "llmemory.h"
00044 #include "llmemtype.h"
00045 #include "llnamevalue.h"
00046 #include "llprimitive.h"
00047 #include "llvolume.h"
00048 #include "material_codes.h"
00049 #include "timing.h"
00050 #include "v3color.h"
00051 #include "llui.h"
00052 #include "llglheaders.h"
00053
00054
00055 #include "llagent.h"
00056 #include "lldrawable.h"
00057 #include "lldrawpoolalpha.h"
00058 #include "lldrawpoolavatar.h"
00059 #include "lldrawpoolground.h"
00060 #include "lldrawpoolsimple.h"
00061 #include "lldrawpoolbump.h"
00062 #include "lldrawpooltree.h"
00063 #include "lldrawpoolwater.h"
00064 #include "llface.h"
00065 #include "llfeaturemanager.h"
00066 #include "llfloatertelehub.h"
00067 #include "llfloatereventlog.h"
00068 #include "llframestats.h"
00069 #include "llgldbg.h"
00070 #include "llhudmanager.h"
00071 #include "lllightconstants.h"
00072 #include "llresmgr.h"
00073 #include "llselectmgr.h"
00074 #include "llsky.h"
00075 #include "lltracker.h"
00076 #include "lltool.h"
00077 #include "lltoolmgr.h"
00078 #include "llviewercamera.h"
00079 #include "llviewerimagelist.h"
00080 #include "llviewerobject.h"
00081 #include "llviewerobjectlist.h"
00082 #include "llviewerpartsource.h"
00083 #include "llviewerparcelmgr.h"
00084 #include "llviewerregion.h"
00085 #include "llviewerwindow.h"
00086 #include "llvoavatar.h"
00087 #include "llvoground.h"
00088 #include "llvosky.h"
00089 #include "llvotree.h"
00090 #include "llvovolume.h"
00091 #include "llvosurfacepatch.h"
00092 #include "llvowater.h"
00093 #include "llvotree.h"
00094 #include "llvopartgroup.h"
00095 #include "llworld.h"
00096 #include "viewer.h"
00097 #include "llcubemap.h"
00098 #include "llfloateravatarlist.h"
00099 #include "lldebugmessagebox.h"
00100 #include "llglslshader.h"
00101 #include "llviewerjoystick.h"
00102
00103 #ifdef _DEBUG
00104
00105
00106 #else
00107
00108 #endif
00109
00110 #define AGGRESSIVE_OCCLUSION 0
00111
00112 const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
00113 const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
00114 const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
00115 const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
00116 const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40;
00117 const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
00118
00119
00120
00121 const S32 ESTIMATED_VISIBLE_OBJECT_COUNT = 8192;
00122
00123
00124
00125
00126 const F32 OCCLUDE_SCALE_SUM_THRESHOLD = 8.f;
00127
00128
00129 const S32 MAX_OCCLUDER_COUNT = 2;
00130
00131 extern S32 gBoxFrame;
00132 extern BOOL gRenderLightGlows;
00133 extern BOOL gHideSelectedObjects;
00134
00135 BOOL gAvatarBacklight = FALSE;
00136
00137 S32 gTrivialAccepts = 0;
00138
00139 BOOL gRenderForSelect = FALSE;
00140
00141
00142
00143 void stamp(F32 x, F32 y, F32 xs, F32 ys)
00144 {
00145 glBegin(GL_QUADS);
00146 glTexCoord2f(0,0);
00147 glVertex3f(x, y, 0.0f);
00148 glTexCoord2f(1,0);
00149 glVertex3f(x+xs,y, 0.0f);
00150 glTexCoord2f(1,1);
00151 glVertex3f(x+xs,y+ys,0.0f);
00152 glTexCoord2f(0,1);
00153 glVertex3f(x, y+ys,0.0f);
00154 glEnd();
00155 }
00156
00157 U32 nhpo2(U32 v)
00158 {
00159 U32 r = 1;
00160 while (r < v) {
00161 r *= 2;
00162 }
00163 return r;
00164 }
00165
00166
00167
00168
00169 S32 LLPipeline::sCompiles = 0;
00170
00171 BOOL LLPipeline::sShowHUDAttachments = TRUE;
00172 BOOL LLPipeline::sRenderPhysicalBeacons = TRUE;
00173 BOOL LLPipeline::sRenderScriptedBeacons = FALSE;
00174 BOOL LLPipeline::sRenderScriptedTouchBeacons = TRUE;
00175 BOOL LLPipeline::sRenderParticleBeacons = FALSE;
00176 BOOL LLPipeline::sRenderSoundBeacons = FALSE;
00177 BOOL LLPipeline::sRenderBeacons = FALSE;
00178 BOOL LLPipeline::sRenderHighlight = TRUE;
00179 BOOL LLPipeline::sRenderProcessBeacons = FALSE;
00180 BOOL LLPipeline::sUseOcclusion = FALSE;
00181 BOOL LLPipeline::sSkipUpdate = FALSE;
00182 BOOL LLPipeline::sDynamicReflections = FALSE;
00183 BOOL LLPipeline::sRenderGlow = FALSE;
00184
00185 LLPipeline::LLPipeline() :
00186 mScreenTex(0),
00187 mGlowMap(0),
00188 mGlowBuffer(0),
00189 mVertexShadersEnabled(FALSE),
00190 mVertexShadersLoaded(0),
00191 mLastRebuildPool(NULL),
00192 mAlphaPool(NULL),
00193 mAlphaPoolPostWater(NULL),
00194 mSkyPool(NULL),
00195 mStarsPool(NULL),
00196 mTerrainPool(NULL),
00197 mWaterPool(NULL),
00198 mGroundPool(NULL),
00199 mSimplePool(NULL),
00200 mGlowPool(NULL),
00201 mBumpPool(NULL),
00202 mLightMask(0),
00203 mLightMovingMask(0)
00204 {
00205 mFramebuffer[0] = mFramebuffer[1] = 0;
00206 mCubeFrameBuffer = 0;
00207 mCubeDepth = 0;
00208 }
00209
00210 void LLPipeline::init()
00211 {
00212 LLMemType mt(LLMemType::MTYPE_PIPELINE);
00213
00214 mInitialized = TRUE;
00215
00216 stop_glerror();
00217
00218
00219
00220 mObjectPartition.push_back(new LLVolumePartition());
00221 mObjectPartition.push_back(new LLBridgePartition());
00222 mObjectPartition.push_back(new LLHUDPartition());
00223 mObjectPartition.push_back(new LLTerrainPartition());
00224 mObjectPartition.push_back(new LLWaterPartition());
00225 mObjectPartition.push_back(new LLTreePartition());
00226 mObjectPartition.push_back(new LLParticlePartition());
00227 mObjectPartition.push_back(new LLCloudPartition());
00228 mObjectPartition.push_back(new LLGrassPartition());
00229 mObjectPartition.push_back(NULL);
00230
00231
00232 getPool(LLDrawPool::POOL_ALPHA);
00233 getPool(LLDrawPool::POOL_ALPHA_POST_WATER);
00234 getPool(LLDrawPool::POOL_SIMPLE);
00235 getPool(LLDrawPool::POOL_BUMP);
00236 getPool(LLDrawPool::POOL_GLOW);
00237
00238 mTrianglesDrawnStat.reset();
00239 resetFrameStats();
00240
00241 mRenderTypeMask = 0xffffffff;
00242 mRenderDebugFeatureMask = 0xffffffff;
00243 mRenderFeatureMask = 0;
00244 mRenderDebugMask = 0;
00245
00246 mOldRenderDebugMask = mRenderDebugMask;
00247
00248 mBackfaceCull = TRUE;
00249
00250 stop_glerror();
00251
00252
00253 stop_glerror();
00254
00255 LLShaderMgr::setShaders();
00256 }
00257
00258 LLPipeline::~LLPipeline()
00259 {
00260
00261 }
00262
00263 void LLPipeline::cleanup()
00264 {
00265 for(pool_set_t::iterator iter = mPools.begin();
00266 iter != mPools.end(); )
00267 {
00268 pool_set_t::iterator curiter = iter++;
00269 LLDrawPool* poolp = *curiter;
00270 if (poolp->isFacePool())
00271 {
00272 LLFacePool* face_pool = (LLFacePool*) poolp;
00273 if (face_pool->mReferences.empty())
00274 {
00275 mPools.erase(curiter);
00276 removeFromQuickLookup( poolp );
00277 delete poolp;
00278 }
00279 }
00280 else
00281 {
00282 mPools.erase(curiter);
00283 removeFromQuickLookup( poolp );
00284 delete poolp;
00285 }
00286 }
00287
00288 if (!mTerrainPools.empty())
00289 {
00290 llwarns << "Terrain Pools not cleaned up" << llendl;
00291 }
00292 if (!mTreePools.empty())
00293 {
00294 llwarns << "Tree Pools not cleaned up" << llendl;
00295 }
00296
00297 delete mAlphaPool;
00298 mAlphaPool = NULL;
00299 delete mAlphaPoolPostWater;
00300 mAlphaPoolPostWater = NULL;
00301 delete mSkyPool;
00302 mSkyPool = NULL;
00303 delete mStarsPool;
00304 mStarsPool = NULL;
00305 delete mTerrainPool;
00306 mTerrainPool = NULL;
00307 delete mWaterPool;
00308 mWaterPool = NULL;
00309 delete mGroundPool;
00310 mGroundPool = NULL;
00311 delete mSimplePool;
00312 mSimplePool = NULL;
00313 delete mGlowPool;
00314 mGlowPool = NULL;
00315 delete mBumpPool;
00316 mBumpPool = NULL;
00317
00318 releaseGLBuffers();
00319
00320 mBloomImagep = NULL;
00321 mBloomImage2p = NULL;
00322 mFaceSelectImagep = NULL;
00323 mAlphaSizzleImagep = NULL;
00324
00325 for (S32 i = 0; i < NUM_PARTITIONS-1; i++)
00326 {
00327 delete mObjectPartition[i];
00328 }
00329 mObjectPartition.clear();
00330
00331 mVisibleList.clear();
00332 mVisibleGroups.clear();
00333 mDrawableGroups.clear();
00334 mActiveGroups.clear();
00335 mVisibleBridge.clear();
00336 mMovedBridge.clear();
00337 mOccludedBridge.clear();
00338 mAlphaGroups.clear();
00339 clearRenderMap();
00340 }
00341
00342
00343
00344 void LLPipeline::destroyGL()
00345 {
00346 stop_glerror();
00347 unloadShaders();
00348 mHighlightFaces.clear();
00349 mVisibleList.clear();
00350 mVisibleGroups.clear();
00351 mDrawableGroups.clear();
00352 mActiveGroups.clear();
00353 mVisibleBridge.clear();
00354 mOccludedBridge.clear();
00355 mAlphaGroups.clear();
00356 clearRenderMap();
00357 resetVertexBuffers();
00358
00359 releaseGLBuffers();
00360 }
00361
00362 void LLPipeline::releaseGLBuffers()
00363 {
00364 if (mGlowMap)
00365 {
00366 glDeleteTextures(1, &mGlowMap);
00367 mGlowMap = 0;
00368 }
00369
00370 if (mGlowBuffer)
00371 {
00372 glDeleteTextures(1, &mGlowBuffer);
00373 mGlowBuffer = 0;
00374 }
00375
00376 if (mScreenTex)
00377 {
00378 glDeleteTextures(1, &mScreenTex);
00379 mScreenTex = 0;
00380 }
00381
00382 if (mCubeBuffer)
00383 {
00384 mCubeBuffer = NULL;
00385 }
00386
00387 if (mCubeFrameBuffer)
00388 {
00389 #if !defined(__sparc)
00390 glDeleteFramebuffersEXT(1, &mCubeFrameBuffer);
00391 glDeleteRenderbuffersEXT(1, &mCubeDepth);
00392 #else
00393 #error Can we generalize this without a CPU architecture test?
00394 #endif
00395 mCubeDepth = mCubeFrameBuffer = 0;
00396 }
00397
00398 if (mFramebuffer[0])
00399 {
00400 #if !defined(__sparc)
00401 glDeleteFramebuffersEXT(2, mFramebuffer);
00402 #else
00403 #error Can we generalize this without a CPU architecture test?
00404 #endif
00405 mFramebuffer[0] = mFramebuffer[1] = 0;
00406 }
00407 }
00408
00409 void LLPipeline::restoreGL()
00410 {
00411 resetVertexBuffers();
00412
00413 if (mVertexShadersEnabled)
00414 {
00415 LLShaderMgr::setShaders();
00416 }
00417
00418 for (U32 i = 0; i < mObjectPartition.size()-1; i++)
00419 {
00420 if (mObjectPartition[i])
00421 {
00422 mObjectPartition[i]->restoreGL();
00423 }
00424 }
00425 }
00426
00427
00428 BOOL LLPipeline::canUseVertexShaders()
00429 {
00430 if (!gGLManager.mHasVertexShader ||
00431 !gGLManager.mHasFragmentShader ||
00432 !gFeatureManagerp->isFeatureAvailable("VertexShaderEnable") ||
00433 mVertexShadersLoaded == -1)
00434 {
00435 return FALSE;
00436 }
00437 else
00438 {
00439 return TRUE;
00440 }
00441 }
00442
00443 void LLPipeline::unloadShaders()
00444 {
00445 LLShaderMgr::unloadShaders();
00446 mVertexShadersLoaded = 0;
00447 }
00448
00449
00450
00451 void LLPipeline::enableShadows(const BOOL enable_shadows)
00452 {
00453
00454 }
00455
00456 S32 LLPipeline::getMaxLightingDetail() const
00457 {
00458
00459
00460
00461
00462
00463 {
00464 return 1;
00465 }
00466 }
00467
00468 S32 LLPipeline::setLightingDetail(S32 level)
00469 {
00470 if (level < 0)
00471 {
00472 level = gSavedSettings.getS32("RenderLightingDetail");
00473 }
00474 level = llclamp(level, 0, getMaxLightingDetail());
00475 if (level != mLightingDetail)
00476 {
00477 gSavedSettings.setS32("RenderLightingDetail", level);
00478 if (level >= 2)
00479 {
00480 gObjectList.relightAllObjects();
00481 }
00482 mLightingDetail = level;
00483
00484 if (mVertexShadersLoaded == 1)
00485 {
00486 LLShaderMgr::setShaders();
00487 }
00488 }
00489 return mLightingDetail;
00490 }
00491
00492 class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
00493 {
00494 public:
00495 const std::set<LLViewerImage*>& mTextures;
00496
00497 LLOctreeDirtyTexture(const std::set<LLViewerImage*>& textures) : mTextures(textures) { }
00498
00499 virtual void visit(const LLOctreeState<LLDrawable>* state)
00500 {
00501 LLSpatialGroup* group = (LLSpatialGroup*) state->getNode()->getListener(0);
00502
00503 if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
00504 {
00505 for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
00506 {
00507 for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
00508 {
00509 LLDrawInfo* params = *j;
00510 if (mTextures.find(params->mTexture) != mTextures.end())
00511 {
00512 group->setState(LLSpatialGroup::GEOM_DIRTY);
00513 }
00514 }
00515 }
00516 }
00517
00518 for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
00519 {
00520 LLSpatialBridge* bridge = *i;
00521 traverse(bridge->mOctree);
00522 }
00523 }
00524 };
00525
00526
00527 void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerImage*>& textures)
00528 {
00529
00530
00531
00532 for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
00533 {
00534 LLDrawPool *poolp = *iter;
00535 if (poolp->isFacePool())
00536 {
00537 ((LLFacePool*) poolp)->dirtyTextures(textures);
00538 }
00539 }
00540
00541 LLOctreeDirtyTexture dirty(textures);
00542 for (U32 i = 0; i < mObjectPartition.size(); i++)
00543 {
00544 if (mObjectPartition[i])
00545 {
00546 dirty.traverse(mObjectPartition[i]->mOctree);
00547 }
00548 }
00549 }
00550
00551 LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
00552 {
00553 LLDrawPool *poolp = NULL;
00554 switch( type )
00555 {
00556 case LLDrawPool::POOL_SIMPLE:
00557 poolp = mSimplePool;
00558 break;
00559
00560 case LLDrawPool::POOL_GLOW:
00561 poolp = mGlowPool;
00562 break;
00563
00564 case LLDrawPool::POOL_TREE:
00565 poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
00566 break;
00567
00568 case LLDrawPool::POOL_TERRAIN:
00569 poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
00570 break;
00571
00572 case LLDrawPool::POOL_BUMP:
00573 poolp = mBumpPool;
00574 break;
00575
00576 case LLDrawPool::POOL_ALPHA:
00577 poolp = mAlphaPool;
00578 break;
00579
00580 case LLDrawPool::POOL_ALPHA_POST_WATER:
00581 poolp = mAlphaPoolPostWater;
00582 break;
00583
00584 case LLDrawPool::POOL_AVATAR:
00585 break;
00586
00587 case LLDrawPool::POOL_SKY:
00588 poolp = mSkyPool;
00589 break;
00590
00591 case LLDrawPool::POOL_STARS:
00592 poolp = mStarsPool;
00593 break;
00594
00595 case LLDrawPool::POOL_WATER:
00596 poolp = mWaterPool;
00597 break;
00598
00599 case LLDrawPool::POOL_GROUND:
00600 poolp = mGroundPool;
00601 break;
00602
00603 default:
00604 llassert(0);
00605 llerrs << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl;
00606 break;
00607 }
00608
00609 return poolp;
00610 }
00611
00612
00613 LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerImage *tex0)
00614 {
00615 LLMemType mt(LLMemType::MTYPE_PIPELINE);
00616 LLDrawPool *poolp = findPool(type, tex0);
00617 if (poolp)
00618 {
00619 return poolp;
00620 }
00621
00622 LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0);
00623 addPool( new_poolp );
00624
00625 return new_poolp;
00626 }
00627
00628
00629
00630 LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
00631 {
00632 LLMemType mt(LLMemType::MTYPE_PIPELINE);
00633 U32 type = getPoolTypeFromTE(te, imagep);
00634 return gPipeline.getPool(type, imagep);
00635 }
00636
00637
00638 U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
00639 {
00640 LLMemType mt(LLMemType::MTYPE_PIPELINE);
00641
00642 if (!te || !imagep)
00643 {
00644 return 0;
00645 }
00646
00647 bool alpha = te->getColor().mV[3] < 0.999f;
00648 if (imagep)
00649 {
00650 alpha = alpha || (imagep->getComponents() == 4) || (imagep->getComponents() == 2);
00651 }
00652
00653 if (alpha)
00654 {
00655 return LLDrawPool::POOL_ALPHA;
00656 }
00657 else if ((te->getBumpmap() || te->getShiny()))
00658 {
00659 return LLDrawPool::POOL_BUMP;
00660 }
00661 else
00662 {
00663 return LLDrawPool::POOL_SIMPLE;
00664 }
00665 }
00666
00667
00668 void LLPipeline::addPool(LLDrawPool *new_poolp)
00669 {
00670 LLMemType mt(LLMemType::MTYPE_PIPELINE);
00671 mPools.insert(new_poolp);
00672 addToQuickLookup( new_poolp );
00673 }
00674
00675 void LLPipeline::allocDrawable(LLViewerObject *vobj)
00676 {
00677 LLMemType mt(LLMemType::MTYPE_DRAWABLE);
00678 LLDrawable *drawable = new LLDrawable();
00679 vobj->mDrawable = drawable;
00680
00681 drawable->mVObjp = vobj;
00682
00683
00684
00685 drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).magVec());
00686 if (vobj->isOrphaned())
00687 {
00688 drawable->setState(LLDrawable::FORCE_INVISIBLE);
00689 }
00690 drawable->updateXform(TRUE);
00691 }
00692
00693
00694 void LLPipeline::unlinkDrawable(LLDrawable *drawable)
00695 {
00696 LLFastTimer t(LLFastTimer::FTM_PIPELINE);
00697
00698 LLPointer<LLDrawable> drawablep = drawable;
00699
00700
00701 if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
00702 {
00703 LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
00704 if (iter != mMovedList.end())
00705 {
00706 mMovedList.erase(iter);
00707 }
00708 }
00709
00710 if (drawablep->getSpatialGroup())
00711 {
00712 if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
00713 {
00714 #ifdef LL_RELEASE_FOR_DOWNLOAD
00715 llwarns << "Couldn't remove object from spatial group!" << llendl;
00716 #else
00717 llerrs << "Couldn't remove object from spatial group!" << llendl;
00718 #endif
00719 }
00720 }
00721
00722 mLights.erase(drawablep);
00723 }
00724
00725 U32 LLPipeline::addObject(LLViewerObject *vobj)
00726 {
00727 LLMemType mt(LLMemType::MTYPE_DRAWABLE);
00728 if (gNoRender)
00729 {
00730 return 0;
00731 }
00732
00733 LLDrawable *drawablep = vobj->createDrawable(this);
00734
00735 llassert(drawablep);
00736
00737 if (vobj->getParent())
00738 {
00739 vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable);
00740 }
00741 else
00742 {
00743 vobj->setDrawableParent(NULL);
00744 }
00745
00746 markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
00747
00748 return 1;
00749 }
00750
00751
00752 void LLPipeline::resetFrameStats()
00753 {
00754 mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
00755
00756 mTrianglesDrawn = 0;
00757 sCompiles = 0;
00758 mVerticesRelit = 0;
00759 mLightingChanges = 0;
00760 mGeometryChanges = 0;
00761 mNumVisibleFaces = 0;
00762
00763 if (mOldRenderDebugMask != mRenderDebugMask)
00764 {
00765 gObjectList.clearDebugText();
00766 mOldRenderDebugMask = mRenderDebugMask;
00767 }
00768
00769 }
00770
00771
00772 void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
00773 {
00774 if (gSavedSettings.getBOOL("FreezeTime"))
00775 {
00776 return;
00777 }
00778 if (!drawablep)
00779 {
00780 llerrs << "updateMove called with NULL drawablep" << llendl;
00781 return;
00782 }
00783 if (drawablep->isState(LLDrawable::EARLY_MOVE))
00784 {
00785 return;
00786 }
00787
00788 drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
00789 drawablep->updateMove();
00790 drawablep->setState(LLDrawable::EARLY_MOVE);
00791
00792 if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
00793 {
00794 mMovedList.push_back(drawablep);
00795 drawablep->setState(LLDrawable::ON_MOVE_LIST);
00796 }
00797 }
00798
00799 void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
00800 {
00801 if (gSavedSettings.getBOOL("FreezeTime"))
00802 {
00803 return;
00804 }
00805 if (!drawablep)
00806 {
00807 llerrs << "updateMove called with NULL drawablep" << llendl;
00808 }
00809 if (drawablep->isState(LLDrawable::EARLY_MOVE))
00810 {
00811 return;
00812 }
00813
00814 drawablep->setState(LLDrawable::MOVE_UNDAMPED);
00815 drawablep->updateMove();
00816 drawablep->setState(LLDrawable::EARLY_MOVE);
00817
00818 if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
00819 {
00820 mMovedList.push_back(drawablep);
00821 drawablep->setState(LLDrawable::ON_MOVE_LIST);
00822 }
00823 }
00824
00825 void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
00826 {
00827 for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
00828 iter != moved_list.end(); )
00829 {
00830 LLDrawable::drawable_vector_t::iterator curiter = iter++;
00831 LLDrawable *drawablep = *curiter;
00832 BOOL done = TRUE;
00833 if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
00834 {
00835 done = drawablep->updateMove();
00836 }
00837 drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
00838 if (done)
00839 {
00840 drawablep->clearState(LLDrawable::ON_MOVE_LIST);
00841 iter = moved_list.erase(curiter);
00842 }
00843 }
00844 }
00845
00846 void LLPipeline::updateMove()
00847 {
00848
00849 LLMemType mt(LLMemType::MTYPE_PIPELINE);
00850
00851 if (gSavedSettings.getBOOL("FreezeTime"))
00852 {
00853 return;
00854 }
00855
00856 for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
00857 iter != mRetexturedList.end(); ++iter)
00858 {
00859 LLDrawable* drawablep = *iter;
00860 if (drawablep && !drawablep->isDead())
00861 {
00862 drawablep->updateTexture();
00863 }
00864 }
00865 mRetexturedList.clear();
00866
00867 updateMovedList(mMovedList);
00868
00869 for (LLDrawable::drawable_set_t::iterator iter = mActiveQ.begin();
00870 iter != mActiveQ.end(); )
00871 {
00872 LLDrawable::drawable_set_t::iterator curiter = iter++;
00873 LLDrawable* drawablep = *curiter;
00874 if (drawablep && !drawablep->isDead())
00875 {
00876 if (drawablep->isRoot() &&
00877 drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES &&
00878 (!drawablep->getParent() || !drawablep->getParent()->isActive()))
00879 {
00880 drawablep->makeStatic();
00881 iter = mActiveQ.upper_bound(drawablep);
00882 }
00883 }
00884 else
00885 {
00886 mActiveQ.erase(curiter);
00887 }
00888 }
00889
00890
00891 {
00892 LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE);
00893 for (U32 i = 0; i < mObjectPartition.size()-1; i++)
00894 {
00895 if (mObjectPartition[i])
00896 {
00897 mObjectPartition[i]->mOctree->balance();
00898 }
00899 }
00900 }
00901 }
00902
00904
00906
00907
00908 F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
00909 {
00910 LLVector3 lookAt = center - camera.getOrigin();
00911 F32 dist = lookAt.magVec();
00912
00913
00914 if (dist < 16.f)
00915 {
00916 dist /= 16.f;
00917 dist *= dist;
00918 dist *= 16.f;
00919 }
00920
00921
00922 F32 app_angle = atanf(size.magVec()/dist);
00923 F32 radius = app_angle*LLDrawable::sCurPixelAngle;
00924 return radius*radius * 3.14159f;
00925 }
00926
00927 void LLPipeline::updateCull(LLCamera& camera)
00928 {
00929 LLFastTimer t(LLFastTimer::FTM_CULL);
00930 LLMemType mt(LLMemType::MTYPE_PIPELINE);
00931
00932 mVisibleList.clear();
00933 mVisibleGroups.clear();
00934 mDrawableGroups.clear();
00935 mActiveGroups.clear();
00936 gTrivialAccepts = 0;
00937 mVisibleBridge.clear();
00938
00939 processOcclusion(camera);
00940
00941 for (U32 i = 0; i < mObjectPartition.size(); i++)
00942 {
00943 if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
00944 {
00945 mObjectPartition[i]->cull(camera);
00946 }
00947 }
00948
00949 if (gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull())
00950 {
00951
00952 if (hasRenderType(LLPipeline::RENDER_TYPE_SKY))
00953 {
00954 gSky.mVOSkyp->mDrawable->setVisible(camera);
00955 mVisibleList.push_back(gSky.mVOSkyp->mDrawable);
00956 gSky.updateCull();
00957 stop_glerror();
00958 }
00959 }
00960 else
00961 {
00962 llinfos << "No sky drawable!" << llendl;
00963 }
00964
00965 if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && gSky.mVOGroundp.notNull() && gSky.mVOGroundp->mDrawable.notNull())
00966 {
00967 gSky.mVOGroundp->mDrawable->setVisible(camera);
00968 mVisibleList.push_back(gSky.mVOGroundp->mDrawable);
00969 }
00970 }
00971
00972 void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera, BOOL active)
00973 {
00974 if (group->getData().empty())
00975 {
00976 return;
00977 }
00978
00979 if (!sSkipUpdate)
00980 {
00981 group->updateDistance(camera);
00982 }
00983
00984 const F32 MINIMUM_PIXEL_AREA = 16.f;
00985
00986 if (group->mPixelArea < MINIMUM_PIXEL_AREA)
00987 {
00988 return;
00989 }
00990
00991 group->mLastRenderTime = gFrameTimeSeconds;
00992 if (!group->mSpatialPartition->mRenderByGroup)
00993 {
00994 mDrawableGroups.push_back(group);
00995 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
00996 {
00997 markVisible(*i, camera);
00998 }
00999 }
01000 else
01001 {
01002 if (active)
01003 {
01004 mActiveGroups.push_back(group);
01005 }
01006 else
01007 {
01008 mVisibleGroups.push_back(group);
01009 for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
01010 {
01011 LLSpatialBridge* bridge = *i;
01012 markVisible(bridge, camera);
01013 }
01014 }
01015 }
01016 }
01017
01018 void LLPipeline::doOcclusion(LLCamera& camera)
01019 {
01020 if (sUseOcclusion)
01021 {
01022 for (U32 i = 0; i < mObjectPartition.size(); i++)
01023 {
01024 if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
01025 {
01026 mObjectPartition[i]->doOcclusion(&camera);
01027 }
01028 }
01029
01030 #if AGGRESSIVE_OCCLUSION
01031 for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
01032 {
01033 LLSpatialBridge* bridge = *i;
01034 if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
01035 {
01036 glPushMatrix();
01037 glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
01038 LLCamera trans = bridge->transformCamera(camera);
01039 bridge->doOcclusion(&trans);
01040 glPopMatrix();
01041 mOccludedBridge.push_back(bridge);
01042 }
01043 }
01044 #endif
01045 }
01046 }
01047
01048 BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
01049 {
01050 BOOL update_complete = drawablep->updateGeometry(priority);
01051 if (update_complete)
01052 {
01053 drawablep->setState(LLDrawable::BUILT);
01054 mGeometryChanges++;
01055 }
01056 return update_complete;
01057 }
01058
01059 void LLPipeline::updateGeom(F32 max_dtime)
01060 {
01061 LLTimer update_timer;
01062 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01063 LLPointer<LLDrawable> drawablep;
01064
01065 LLFastTimer t(LLFastTimer::FTM_GEO_UPDATE);
01066
01067
01068
01069 LLVOVolume::preUpdateGeom();
01070
01071
01072 for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
01073 iter != mBuildQ1.end();)
01074 {
01075 LLDrawable::drawable_list_t::iterator curiter = iter++;
01076 LLDrawable* drawablep = *curiter;
01077 if (drawablep && !drawablep->isDead())
01078 {
01079 if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
01080 {
01081 drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
01082 LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
01083 if (find != mBuildQ2.end())
01084 {
01085 mBuildQ2.erase(find);
01086 }
01087 }
01088
01089 if (updateDrawableGeom(drawablep, TRUE))
01090 {
01091 drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
01092 mBuildQ1.erase(curiter);
01093 }
01094 }
01095 else
01096 {
01097 mBuildQ1.erase(curiter);
01098 }
01099 }
01100
01101
01102 S32 min_count = 16;
01103 if (mBuildQ2.size() > 1000)
01104 {
01105 min_count = mBuildQ2.size();
01106 }
01107
01108 S32 count = 0;
01109
01110 max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
01111 LLSpatialGroup* last_group = NULL;
01112 LLSpatialBridge* last_bridge = NULL;
01113
01114 for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
01115 iter != mBuildQ2.end(); )
01116 {
01117 LLDrawable::drawable_list_t::iterator curiter = iter++;
01118 LLDrawable* drawablep = *curiter;
01119
01120 LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
01121 drawablep->getParent()->getSpatialBridge();
01122
01123 if (drawablep->getSpatialGroup() != last_group &&
01124 (!last_bridge || bridge != last_bridge) &&
01125 (update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
01126 {
01127 break;
01128 }
01129
01130
01131
01132 last_group = drawablep->getSpatialGroup();
01133 last_bridge = bridge;
01134
01135 BOOL update_complete = TRUE;
01136 if (!drawablep->isDead())
01137 {
01138 update_complete = updateDrawableGeom(drawablep, FALSE);
01139 count++;
01140 }
01141 if (update_complete)
01142 {
01143 drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
01144 mBuildQ2.erase(curiter);
01145 }
01146 }
01147
01148 updateMovedList(mMovedBridge);
01149 }
01150
01151 void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
01152 {
01153 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01154 if(!drawablep || drawablep->isDead())
01155 {
01156 llwarns << "LLPipeline::markVisible called with NULL drawablep" << llendl;
01157 return;
01158 }
01159
01160
01161 #if LL_DEBUG
01162 if (drawablep->isSpatialBridge())
01163 {
01164 if (std::find(mVisibleBridge.begin(), mVisibleBridge.end(), (LLSpatialBridge*) drawablep) !=
01165 mVisibleBridge.end())
01166 {
01167 llerrs << "Spatial bridge marked visible redundantly." << llendl;
01168 }
01169 }
01170 else
01171 {
01172 if (std::find(mVisibleList.begin(), mVisibleList.end(), drawablep) !=
01173 mVisibleList.end())
01174 {
01175 llerrs << "Drawable marked visible redundantly." << llendl;
01176 }
01177 }
01178 #endif
01179
01180 if (drawablep->isSpatialBridge())
01181 {
01182 mVisibleBridge.push_back((LLSpatialBridge*) drawablep);
01183 }
01184 else
01185 {
01186 mVisibleList.push_back(drawablep);
01187 }
01188 drawablep->setVisible(camera);
01189 }
01190
01191 void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
01192 {
01193 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01194 if (!drawablep)
01195 {
01196 llerrs << "Sending null drawable to moved list!" << llendl;
01197 return;
01198 }
01199
01200 if (drawablep->isDead())
01201 {
01202 llwarns << "Marking NULL or dead drawable moved!" << llendl;
01203 return;
01204 }
01205
01206 if (drawablep->getParent())
01207 {
01208
01209 markMoved(drawablep->getParent(), damped_motion);
01210 }
01211
01212
01213 if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
01214 {
01215 if (drawablep->isSpatialBridge())
01216 {
01217 mMovedBridge.push_back(drawablep);
01218 }
01219 else
01220 {
01221 mMovedList.push_back(drawablep);
01222 }
01223 drawablep->setState(LLDrawable::ON_MOVE_LIST);
01224 }
01225 if (damped_motion == FALSE)
01226 {
01227 drawablep->setState(LLDrawable::MOVE_UNDAMPED);
01228 }
01229 else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
01230 {
01231 drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
01232 }
01233 }
01234
01235 void LLPipeline::markShift(LLDrawable *drawablep)
01236 {
01237 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01238 if (!drawablep || drawablep->isDead())
01239 {
01240 return;
01241 }
01242
01243 if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST))
01244 {
01245 drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE);
01246 if (drawablep->getParent())
01247 {
01248 markShift(drawablep->getParent());
01249 }
01250 mShiftList.push_back(drawablep);
01251 drawablep->setState(LLDrawable::ON_SHIFT_LIST);
01252 }
01253 }
01254
01255 void LLPipeline::shiftObjects(const LLVector3 &offset)
01256 {
01257 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01258 for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
01259 iter != mShiftList.end(); iter++)
01260 {
01261 LLDrawable *drawablep = *iter;
01262 if (drawablep->isDead())
01263 {
01264 continue;
01265 }
01266 drawablep->shiftPos(offset);
01267 drawablep->clearState(LLDrawable::ON_SHIFT_LIST);
01268 }
01269 mShiftList.resize(0);
01270
01271 for (U32 i = 0; i < mObjectPartition.size()-1; i++)
01272 {
01273 if (mObjectPartition[i])
01274 {
01275 mObjectPartition[i]->shift(offset);
01276 }
01277 }
01278 }
01279
01280 void LLPipeline::markTextured(LLDrawable *drawablep)
01281 {
01282 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01283 if (drawablep && !drawablep->isDead())
01284 {
01285 mRetexturedList.insert(drawablep);
01286 }
01287 }
01288
01289 void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
01290 {
01291 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01292
01293 if (drawablep && !drawablep->isDead())
01294 {
01295 if (!drawablep->isState(LLDrawable::BUILT))
01296 {
01297 priority = TRUE;
01298 }
01299 if (priority)
01300 {
01301 if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
01302 {
01303 mBuildQ1.push_back(drawablep);
01304 drawablep->setState(LLDrawable::IN_REBUILD_Q1);
01305 }
01306 }
01307 else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
01308 {
01309 mBuildQ2.push_back(drawablep);
01310 drawablep->setState(LLDrawable::IN_REBUILD_Q2);
01311 }
01312 if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
01313 {
01314 drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
01315 }
01316 drawablep->setState(flag);
01317 if ((flag & LLDrawable::REBUILD_LIGHTING) && drawablep->getLit())
01318 {
01319 if (drawablep->isLight())
01320 {
01321 drawablep->clearState(LLDrawable::LIGHTING_BUILT);
01322 }
01323 else
01324 {
01325 drawablep->clearState(LLDrawable::LIGHTING_BUILT);
01326 }
01327 }
01328 }
01329 }
01330
01331 void LLPipeline::markRelight(LLDrawable *drawablep, const BOOL priority)
01332 {
01333 if (getLightingDetail() >= 2)
01334 {
01335 markRebuild(drawablep, LLDrawable::REBUILD_LIGHTING, FALSE);
01336 }
01337 }
01338
01339 void LLPipeline::stateSort(LLCamera& camera)
01340 {
01341 LLFastTimer ftm(LLFastTimer::FTM_STATESORT);
01342 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01343
01344 for (LLSpatialGroup::sg_vector_t::iterator iter = mVisibleGroups.begin(); iter != mVisibleGroups.end(); ++iter)
01345 {
01346 stateSort(*iter, camera);
01347 }
01348
01349 for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
01350 {
01351 LLSpatialBridge* bridge = *i;
01352 if (!bridge->isDead())
01353 {
01354 stateSort(bridge, camera);
01355 }
01356 }
01357
01358 for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin();
01359 iter != mVisibleList.end(); iter++)
01360 {
01361 LLDrawable *drawablep = *iter;
01362 if (!drawablep->isDead())
01363 {
01364 stateSort(drawablep, camera);
01365 }
01366 }
01367
01368 for (LLSpatialGroup::sg_vector_t::iterator iter = mActiveGroups.begin(); iter != mActiveGroups.end(); ++iter)
01369 {
01370 stateSort(*iter, camera);
01371 }
01372
01373 postSort(camera);
01374 }
01375
01376 void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
01377 {
01378 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01379 if (!sSkipUpdate && group->changeLOD())
01380 {
01381 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
01382 {
01383 LLDrawable* drawablep = *i;
01384 stateSort(drawablep, camera);
01385 }
01386 }
01387
01388 #if !LL_DARWIN
01389 if (gFrameTimeSeconds - group->mLastUpdateTime > 4.f)
01390 {
01391 group->makeStatic();
01392 }
01393 #endif
01394 }
01395
01396 void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
01397 {
01398 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01399 if (!sSkipUpdate)
01400 {
01401 bridge->updateDistance(camera);
01402 }
01403 }
01404
01405 void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
01406 {
01407 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01408 LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE);
01409
01410 if (!drawablep
01411 || drawablep->isDead()
01412 || !hasRenderType(drawablep->getRenderType()))
01413 {
01414 return;
01415 }
01416
01417 if (gHideSelectedObjects)
01418 {
01419 if (drawablep->getVObj().notNull() &&
01420 drawablep->getVObj()->isSelected())
01421 {
01422 return;
01423 }
01424 }
01425
01426 if (hasRenderType(drawablep->mRenderType))
01427 {
01428 if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
01429 {
01430 drawablep->setVisible(camera, NULL, FALSE);
01431 }
01432 else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
01433 {
01434
01435 drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
01436 }
01437 }
01438
01439 if (!drawablep->isActive() && drawablep->isVisible())
01440 {
01441 if (!sSkipUpdate)
01442 {
01443 drawablep->updateDistance(camera);
01444 }
01445 }
01446 else if (drawablep->isAvatar() && drawablep->isVisible())
01447 {
01448 LLVOAvatar* vobj = (LLVOAvatar*) drawablep->getVObj().get();
01449 vobj->updateVisibility(FALSE);
01450 }
01451
01452 for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
01453 iter != drawablep->mFaces.end(); iter++)
01454 {
01455 LLFace* facep = *iter;
01456
01457 if (facep->hasGeometry())
01458 {
01459 if (facep->getPool())
01460 {
01461 facep->getPool()->enqueue(facep);
01462 }
01463 else
01464 {
01465 break;
01466 }
01467 }
01468 }
01469
01470
01471 mNumVisibleFaces += drawablep->getNumFaces();
01472 }
01473
01474
01475 void LLPipeline::forAllDrawables(LLSpatialGroup::sg_vector_t& groups, void (*func)(LLDrawable*))
01476 {
01477 for (LLSpatialGroup::sg_vector_t::iterator i = groups.begin(); i != groups.end(); ++i)
01478 {
01479 for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
01480 {
01481 func(*j);
01482 }
01483 }
01484 }
01485
01486 void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
01487 {
01488 forAllDrawables(mDrawableGroups, func);
01489 forAllDrawables(mVisibleGroups, func);
01490 forAllDrawables(mActiveGroups, func);
01491 }
01492
01493
01494 void renderScriptedBeacons(LLDrawable* drawablep)
01495 {
01496 LLViewerObject *vobj = drawablep->getVObj();
01497 if (vobj
01498 && !vobj->isAvatar()
01499 && !vobj->getParent()
01500 && vobj->flagScripted())
01501 {
01502 if (gPipeline.sRenderBeacons)
01503 {
01504 gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01505 }
01506
01507 if (gPipeline.sRenderHighlight)
01508 {
01509 S32 face_id;
01510 for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
01511 {
01512 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01513 }
01514 }
01515 }
01516 }
01517
01518 void renderScriptedTouchBeacons(LLDrawable* drawablep)
01519 {
01520 LLViewerObject *vobj = drawablep->getVObj();
01521 if (vobj
01522 && !vobj->isAvatar()
01523 && !vobj->getParent()
01524 && vobj->flagScripted()
01525 && vobj->flagHandleTouch())
01526 {
01527 if (gPipeline.sRenderBeacons)
01528 {
01529 gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01530 }
01531
01532 if (gPipeline.sRenderHighlight)
01533 {
01534 S32 face_id;
01535 for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
01536 {
01537 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01538 }
01539 }
01540 }
01541 }
01542
01543 void renderPhysicalBeacons(LLDrawable* drawablep)
01544 {
01545 LLViewerObject *vobj = drawablep->getVObj();
01546 if (vobj
01547 && !vobj->isAvatar()
01548 && !vobj->getParent()
01549 && vobj->usePhysics())
01550 {
01551 if (gPipeline.sRenderBeacons)
01552 {
01553 gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01554 }
01555
01556 if (gPipeline.sRenderHighlight)
01557 {
01558 S32 face_id;
01559 for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
01560 {
01561 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01562 }
01563 }
01564 }
01565 }
01566
01567 void addSourcesToEventLog(LLDrawable *drawablep)
01568 {
01569 if ( NULL != gFloaterEventLog )
01570 {
01571 LLViewerObject *vobj = drawablep->getVObj();
01572 if ( vobj )
01573 {
01574
01575
01576 gFloaterEventLog->logObject( vobj );
01577 }
01578 }
01579 }
01580
01581
01582 void renderParticleBeacons(LLDrawable* drawablep)
01583 {
01584
01585 LLViewerObject *vobj = drawablep->getVObj();
01586 if (vobj
01587 && vobj->isParticleSource())
01588 {
01589 if (gPipeline.sRenderBeacons)
01590 {
01591 LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
01592 gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01593 }
01594
01595 if (gPipeline.sRenderHighlight)
01596 {
01597 S32 face_id;
01598 for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++)
01599 {
01600 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01601 }
01602 }
01603 }
01604 }
01605
01610 void addParticleSourcesToList(LLDrawable *drawablep)
01611 {
01612 if ( NULL != gFloaterAvatarList )
01613 {
01614 LLViewerObject *vobj = drawablep->getVObj();
01615 if (vobj && vobj->isParticleSource())
01616 {
01617 LLUUID id = vobj->mPartSourcep->getOwnerUUID();
01618 LLAvatarListEntry *ent = gFloaterAvatarList->getAvatarEntry(id);
01619 if ( NULL != ent )
01620 {
01621 ent->setActivity(ACTIVITY_PARTICLES);
01622 }
01623 }
01624 }
01625 }
01626
01627 void LLPipeline::postSort(LLCamera& camera)
01628 {
01629 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01630 LLFastTimer ftm(LLFastTimer::FTM_STATESORT_POSTSORT);
01631
01632 clearRenderMap();
01633 mAlphaGroups.clear();
01634 mAlphaGroupsPostWater.clear();
01635
01636 if (!gSavedSettings.getBOOL("RenderRippleWater") && hasRenderType(LLDrawPool::POOL_ALPHA))
01637 {
01638 toggleRenderType(LLDrawPool::POOL_ALPHA);
01639 }
01640
01641 F32 water_height = gAgent.getRegion()->getWaterHeight();
01642 BOOL above_water = gCamera->getOrigin().mV[2] > water_height ? TRUE : FALSE;
01643
01644
01645 if (sUseOcclusion)
01646 {
01647 for (U32 i = 0; i < mObjectPartition.size(); i++)
01648 {
01649 if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
01650 {
01651 mObjectPartition[i]->buildOcclusion();
01652 }
01653 }
01654
01655 #if AGGRESSIVE_OCCLUSION
01656 for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
01657 {
01658 LLSpatialBridge* bridge = *i;
01659 if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
01660 {
01661 bridge->buildOcclusion();
01662 }
01663 }
01664 #endif
01665 }
01666
01667
01668 if (!sSkipUpdate)
01669 {
01670
01671 for (LLSpatialGroup::sg_vector_t::iterator i = mDrawableGroups.begin(); i != mDrawableGroups.end(); ++i)
01672 {
01673 LLSpatialGroup* group = *i;
01674 group->rebuildGeom();
01675 }
01676 }
01677
01678
01679 for (LLSpatialGroup::sg_vector_t::iterator i = mVisibleGroups.begin(); i != mVisibleGroups.end(); ++i)
01680 {
01681 LLSpatialGroup* group = *i;
01682 if (!sSkipUpdate)
01683 {
01684 group->rebuildGeom();
01685 }
01686 for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
01687 {
01688 LLSpatialGroup::drawmap_elem_t& src_vec = j->second;
01689 LLSpatialGroup::drawmap_elem_t& dest_vec = mRenderMap[j->first];
01690
01691 for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
01692 {
01693 dest_vec.push_back(*k);
01694 }
01695 }
01696
01697 LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
01698
01699 if (alpha != group->mDrawMap.end())
01700 {
01701 if (!sSkipUpdate)
01702 {
01703 group->updateDistance(camera);
01704 }
01705
01706 if (hasRenderType(LLDrawPool::POOL_ALPHA))
01707 {
01708 BOOL above = group->mObjectBounds[0].mV[2] + group->mObjectBounds[1].mV[2] > water_height ? TRUE : FALSE;
01709 BOOL below = group->mObjectBounds[0].mV[2] - group->mObjectBounds[1].mV[2] < water_height ? TRUE : FALSE;
01710
01711 if (below == above_water || above == below)
01712 {
01713 mAlphaGroups.push_back(group);
01714 }
01715
01716 if (above == above_water || below == above)
01717 {
01718 mAlphaGroupsPostWater.push_back(group);
01719 }
01720 }
01721 else
01722 {
01723 mAlphaGroupsPostWater.push_back(group);
01724 }
01725 }
01726 }
01727
01728
01729 for (LLSpatialGroup::sg_vector_t::iterator i = mActiveGroups.begin(); i != mActiveGroups.end(); ++i)
01730 {
01731 LLSpatialGroup* group = *i;
01732 if (!sSkipUpdate)
01733 {
01734 group->rebuildGeom();
01735 }
01736 LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
01737
01738 if (alpha != group->mDrawMap.end())
01739 {
01740 LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
01741 LLCamera trans_camera = bridge->transformCamera(camera);
01742 if (!sSkipUpdate)
01743 {
01744 group->updateDistance(trans_camera);
01745 }
01746
01747 if (hasRenderType(LLDrawPool::POOL_ALPHA))
01748 {
01749 LLSpatialGroup* bridge_group = bridge->getSpatialGroup();
01750 BOOL above = bridge_group->mObjectBounds[0].mV[2] + bridge_group->mObjectBounds[1].mV[2] > water_height ? TRUE : FALSE;
01751 BOOL below = bridge_group->mObjectBounds[0].mV[2] - bridge_group->mObjectBounds[1].mV[2] < water_height ? TRUE : FALSE;
01752
01753
01754 if (below == above_water || above == below)
01755 {
01756 mAlphaGroups.push_back(group);
01757 }
01758
01759 if (above == above_water || below == above)
01760 {
01761 mAlphaGroupsPostWater.push_back(group);
01762 }
01763 }
01764 else
01765 {
01766 mAlphaGroupsPostWater.push_back(group);
01767 }
01768 }
01769 }
01770
01771
01772 for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i)
01773 {
01774 if (!mRenderMap[i].empty())
01775 {
01776 if (i == LLRenderPass::PASS_BUMP)
01777 {
01778 std::sort(mRenderMap[i].begin(), mRenderMap[i].end(), LLDrawInfo::CompareBump());
01779 }
01780 else
01781 {
01782 std::sort(mRenderMap[i].begin(), mRenderMap[i].end(), LLDrawInfo::CompareTexturePtr());
01783 }
01784 }
01785 }
01786
01787 std::sort(mAlphaGroups.begin(), mAlphaGroups.end(), LLSpatialGroup::CompareDepthGreater());
01788 std::sort(mAlphaGroupsPostWater.begin(), mAlphaGroupsPostWater.end(), LLSpatialGroup::CompareDepthGreater());
01789
01790 forAllVisibleDrawables(addParticleSourcesToList);
01791 forAllVisibleDrawables(addSourcesToEventLog);
01792
01793
01794 if (sRenderProcessBeacons)
01795 {
01796 if (sRenderScriptedTouchBeacons)
01797 {
01798
01799 forAllVisibleDrawables(renderScriptedTouchBeacons);
01800 }
01801 else
01802 if (sRenderScriptedBeacons)
01803 {
01804
01805 forAllVisibleDrawables(renderScriptedBeacons);
01806 }
01807
01808 if (sRenderPhysicalBeacons)
01809 {
01810
01811 forAllVisibleDrawables(renderPhysicalBeacons);
01812 }
01813
01814 if (sRenderParticleBeacons)
01815 {
01816 forAllVisibleDrawables(renderParticleBeacons);
01817 }
01818
01819
01820 if (sRenderSoundBeacons && gAudiop)
01821 {
01822
01823 LLAudioEngine::source_map::iterator iter;
01824 for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
01825 {
01826 LLAudioSource *sourcep = iter->second;
01827
01828 LLVector3d pos_global = sourcep->getPositionGlobal();
01829 LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
01830 if (gPipeline.sRenderBeacons)
01831 {
01832
01833 gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01834 }
01835 }
01836 }
01837 }
01838
01839
01840 if ( gFloaterAvatarList && gAudiop )
01841 {
01842 LLAudioEngine::source_map::iterator iter;
01843 for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
01844 {
01845 LLAudioSource *sourcep = iter->second;
01846 LLUUID uuid = sourcep->getOwnerID();
01847 LLAvatarListEntry *ent = gFloaterAvatarList->getAvatarEntry(uuid);
01848
01849 if ( ent )
01850 {
01851 ent->setActivity(ACTIVITY_SOUND);
01852 }
01853 }
01854 }
01855
01856
01857 if (LLFloaterTelehub::renderBeacons())
01858 {
01859 LLFloaterTelehub::addBeacons();
01860 }
01861
01862 mSelectedFaces.clear();
01863
01864
01865 if (gSelectMgr->getTEMode())
01866 {
01867 struct f : public LLSelectedTEFunctor
01868 {
01869 virtual bool apply(LLViewerObject* object, S32 te)
01870 {
01871 if (object->mDrawable)
01872 {
01873 gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
01874 }
01875 return true;
01876 }
01877 } func;
01878 gSelectMgr->getSelection()->applyToTEs(&func);
01879 }
01880 }
01881
01882
01883 static void render_hud_elements()
01884 {
01885 LLFastTimer t(LLFastTimer::FTM_RENDER_UI);
01886 gPipeline.disableLights();
01887
01888 gPipeline.renderDebug();
01889
01890 LLGLDisable fog(GL_FOG);
01891 LLGLSUIDefault gls_ui;
01892
01893 if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
01894 {
01895 gViewerWindow->renderSelections(FALSE, FALSE, FALSE);
01896
01897
01898 LLTracker::render3D();
01899
01900
01901 if (gWorldp)
01902 {
01903 gWorldp->renderPropertyLines();
01904 }
01905 if (gParcelMgr)
01906 {
01907 gParcelMgr->render();
01908 gParcelMgr->renderParcelCollision();
01909 }
01910
01911
01912 gObjectList.renderObjectBeacons();
01913 LLHUDObject::renderAll();
01914 gObjectList.resetObjectBeacons();
01915 }
01916 else if (gForceRenderLandFence)
01917 {
01918
01919 gParcelMgr->render();
01920 }
01921 else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
01922 {
01923 LLHUDText::renderAllHUD();
01924 }
01925 }
01926
01927 void LLPipeline::renderHighlights()
01928 {
01929 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01930
01931
01932 LLColor4 color(1.f, 1.f, 1.f, 0.5f);
01933 LLGLEnable color_mat(GL_COLOR_MATERIAL);
01934 disableLights();
01935
01936 if ((LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0))
01937 {
01938 gHighlightProgram.bind();
01939 gHighlightProgram.vertexAttrib4f(LLShaderMgr::MATERIAL_COLOR,1,0,0,0.5f);
01940 }
01941
01942 if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
01943 {
01944
01945 if (!mFaceSelectImagep)
01946 {
01947 mFaceSelectImagep = gImageList.getImage(IMG_FACE_SELECT);
01948 }
01949 mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
01950
01951 for (U32 i = 0; i < mSelectedFaces.size(); i++)
01952 {
01953 LLFace *facep = mSelectedFaces[i];
01954 if (!facep || facep->getDrawable()->isDead())
01955 {
01956 llerrs << "Bad face on selection" << llendl;
01957 return;
01958 }
01959
01960 facep->renderSelected(mFaceSelectImagep, color);
01961 }
01962 }
01963
01964 if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
01965 {
01966
01967 color.setVec(1.f, 0.f, 0.f, 0.5f);
01968 for (U32 i = 0; i < mHighlightFaces.size(); i++)
01969 {
01970 LLFace* facep = mHighlightFaces[i];
01971 facep->renderSelected(LLViewerImage::sNullImagep, color);
01972 }
01973 }
01974
01975
01976
01977 mHighlightFaces.clear();
01978
01979 if (LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0)
01980 {
01981 gHighlightProgram.unbind();
01982 }
01983 }
01984
01985 void LLPipeline::renderGeom(LLCamera& camera)
01986 {
01987 LLMemType mt(LLMemType::MTYPE_PIPELINE);
01988 LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY);
01989
01990 if (!mAlphaSizzleImagep)
01991 {
01992 mAlphaSizzleImagep = gImageList.getImage(LLUUID(gViewerArt.getString("alpha_sizzle.tga")), MIPMAP_TRUE, TRUE);
01993 }
01994
01996
01997
01998
01999
02000
02001 glEnableClientState(GL_VERTEX_ARRAY);
02002
02003 stop_glerror();
02004 gFrameStats.start(LLFrameStats::RENDER_SYNC);
02005
02006
02007 #ifndef LL_RELEASE_FOR_DOWNLOAD
02008 LLGLState::checkStates();
02009 LLGLState::checkTextureChannels();
02010 LLGLState::checkClientArrays();
02011 #endif
02012 if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
02013 {
02014 if (!verify())
02015 {
02016 llerrs << "Pipeline verification failed!" << llendl;
02017 }
02018 }
02019
02020 {
02021
02022 LLVertexBuffer::startRender();
02023 }
02024
02025 for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
02026 {
02027 LLDrawPool *poolp = *iter;
02028 if (hasRenderType(poolp->getType()))
02029 {
02030 poolp->prerender();
02031 }
02032 }
02033
02034 gFrameStats.start(LLFrameStats::RENDER_GEOM);
02035
02036
02037 glMatrixMode(GL_TEXTURE);
02038 glLoadIdentity();
02039 glMatrixMode(GL_MODELVIEW);
02040
02041 LLGLSPipeline gls_pipeline;
02042
02043 LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
02044
02045
02046
02047 LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
02048
02049 LLGLEnable fog_enable(hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG) ? GL_FOG : 0);
02050 gSky.updateFog(camera.getFar());
02051
02052 LLViewerImage::sDefaultImagep->bind(0);
02053 LLViewerImage::sDefaultImagep->setClamp(FALSE, FALSE);
02054
02056
02057
02058
02059
02060 stop_glerror();
02061 BOOL did_hud_elements = LLDrawPoolWater::sSkipScreenCopy;
02062 BOOL occlude = sUseOcclusion;
02063
02064 U32 cur_type = 0;
02065
02066
02067
02068 GLboolean mask[4];
02069 glGetBooleanv(GL_COLOR_WRITEMASK, mask);
02070 glColorMask(mask[0], mask[1], mask[2], GL_FALSE);
02071
02072
02073 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING))
02074 {
02075 gObjectList.renderObjectsForSelect(camera);
02076 }
02077 else
02078 {
02079 LLFastTimer t(LLFastTimer::FTM_POOLS);
02080 calcNearbyLights(camera);
02081 pool_set_t::iterator iter1 = mPools.begin();
02082 while ( iter1 != mPools.end() )
02083 {
02084 LLDrawPool *poolp = *iter1;
02085
02086 cur_type = poolp->getType();
02087
02088 if (occlude && cur_type > LLDrawPool::POOL_AVATAR)
02089 {
02090 occlude = FALSE;
02091 doOcclusion(camera);
02092 }
02093
02094 if (cur_type > LLDrawPool::POOL_ALPHA_POST_WATER && !did_hud_elements)
02095 {
02096 renderHighlights();
02097
02098 render_hud_elements();
02099 did_hud_elements = TRUE;
02100 }
02101
02102 pool_set_t::iterator iter2 = iter1;
02103 if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
02104 {
02105 LLFastTimer t(LLFastTimer::FTM_POOLRENDER);
02106
02107 setupHWLights(poolp);
02108
02109 for( S32 i = 0; i < poolp->getNumPasses(); i++ )
02110 {
02111 poolp->beginRenderPass(i);
02112 for (iter2 = iter1; iter2 != mPools.end(); iter2++)
02113 {
02114 LLDrawPool *p = *iter2;
02115 if (p->getType() != cur_type)
02116 {
02117 break;
02118 }
02119
02120 p->resetTrianglesDrawn();
02121 p->render(i);
02122 mTrianglesDrawn += p->getTrianglesDrawn();
02123 }
02124 poolp->endRenderPass(i);
02125 #ifndef LL_RELEASE_FOR_DOWNLOAD
02126 #if LL_DEBUG_GL
02127 GLint depth;
02128 glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
02129 if (depth > 3)
02130 {
02131 llerrs << "GL matrix stack corrupted!" << llendl;
02132 }
02133 LLGLState::checkStates();
02134 LLGLState::checkTextureChannels();
02135 LLGLState::checkClientArrays();
02136 #endif
02137 #endif
02138 }
02139 }
02140 else
02141 {
02142
02143 for (iter2 = iter1; iter2 != mPools.end(); iter2++)
02144 {
02145 LLDrawPool *p = *iter2;
02146 if (p->getType() != cur_type)
02147 {
02148 break;
02149 }
02150 }
02151 }
02152 iter1 = iter2;
02153 stop_glerror();
02154 }
02155 }
02156
02157 #ifndef LL_RELEASE_FOR_DOWNLOAD
02158 LLGLState::checkStates();
02159 LLGLState::checkTextureChannels();
02160 LLGLState::checkClientArrays();
02161 #endif
02162
02163 if (occlude)
02164 {
02165 doOcclusion(camera);
02166 occlude = FALSE;
02167 }
02168
02169 if (!did_hud_elements)
02170 {
02171 renderHighlights();
02172 render_hud_elements();
02173 }
02174
02175 stop_glerror();
02176
02177 {
02178 LLVertexBuffer::stopRender();
02179 }
02180
02181 #ifndef LL_RELEASE_FOR_DOWNLOAD
02182 LLGLState::checkStates();
02183 LLGLState::checkTextureChannels();
02184 LLGLState::checkClientArrays();
02185 #endif
02186
02187
02188
02189 mHighlightFaces.clear();
02190
02191
02192
02193 glGetBooleanv(GL_COLOR_WRITEMASK, mask);
02194 glColorMask(mask[0], mask[1], mask[2], GL_FALSE);
02195
02196
02197 if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) &&
02198 !LLDrawPoolWater::sSkipScreenCopy &&
02199 sRenderGlow &&
02200 gGLManager.mHasFramebufferObject)
02201 {
02202 const U32 glow_res = nhpo2(gSavedSettings.getS32("RenderGlowResolution"));
02203 if (mGlowMap == 0)
02204 {
02205 glGenTextures(1, &mGlowMap);
02206 glBindTexture(GL_TEXTURE_2D, mGlowMap);
02207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
02208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
02209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
02210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
02211 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glow_res, glow_res, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
02212 }
02213
02214 if (mGlowBuffer == 0)
02215 {
02216 glGenTextures(1, &mGlowBuffer);
02217 glBindTexture(GL_TEXTURE_2D, mGlowBuffer);
02218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
02219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
02220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
02221 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
02222 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glow_res, glow_res, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
02223 }
02224
02225 bindScreenToTexture();
02226 renderBloom(mScreenTex, mGlowMap, mGlowBuffer, glow_res, LLVector2(0,0), mScreenScale);
02227 }
02228 }
02229
02230 void LLPipeline::processOcclusion(LLCamera& camera)
02231 {
02232
02233 if (sUseOcclusion)
02234 {
02235 for (U32 i = 0; i < mObjectPartition.size(); i++)
02236 {
02237 if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
02238 {
02239 mObjectPartition[i]->processOcclusion(&camera);
02240 }
02241 }
02242
02243 #if AGGRESSIVE_OCCLUSION
02244 for (LLSpatialBridge::bridge_vector_t::iterator i = mOccludedBridge.begin(); i != mOccludedBridge.end(); ++i)
02245 {
02246 LLSpatialBridge* bridge = *i;
02247 if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
02248 {
02249 LLCamera trans = bridge->transformCamera(camera);
02250 bridge->processOcclusion(&trans);
02251 }
02252 }
02253 #endif
02254 mOccludedBridge.clear();
02255 }
02256 }
02257
02258 void LLPipeline::renderDebug()
02259 {
02260 LLMemType mt(LLMemType::MTYPE_PIPELINE);
02261
02262
02263 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
02264 glDisableClientState(GL_NORMAL_ARRAY);
02265 glDisableClientState(GL_COLOR_ARRAY);
02266
02267
02268 for (U32 i = 0; i < mObjectPartition.size(); i++)
02269 {
02270 if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType))
02271 {
02272 mObjectPartition[i]->renderDebug();
02273 }
02274 }
02275
02276 for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i)
02277 {
02278 LLSpatialBridge* bridge = *i;
02279 if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
02280 {
02281 glPushMatrix();
02282 glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
02283 bridge->renderDebug();
02284 glPopMatrix();
02285 }
02286 }
02287
02288 if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_LIGHT_TRACE)
02289 {
02290 LLGLSNoTexture no_texture;
02291
02292 LLVector3 pos, pos1;
02293
02294 for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin();
02295 iter != mVisibleList.end(); iter++)
02296 {
02297 LLDrawable *drawablep = *iter;
02298 if (drawablep->isDead())
02299 {
02300 continue;
02301 }
02302 for (LLDrawable::drawable_set_t::iterator iter = drawablep->mLightSet.begin();
02303 iter != drawablep->mLightSet.end(); iter++)
02304 {
02305 LLDrawable *targetp = *iter;
02306 if (targetp->isDead() || !targetp->getVObj()->getNumTEs())
02307 {
02308 continue;
02309 }
02310 else
02311 {
02312 if (targetp->getTextureEntry(0))
02313 {
02314 if (drawablep->getVObj()->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
02315 {
02316 glColor4f(0.f, 1.f, 0.f, 1.f);
02317 gObjectList.addDebugBeacon(drawablep->getPositionAgent(), "TC");
02318 }
02319 else
02320 {
02321 glColor4fv (targetp->getTextureEntry(0)->getColor().mV);
02322 }
02323 glBegin(GL_LINES);
02324 glVertex3fv(targetp->getPositionAgent().mV);
02325 glVertex3fv(drawablep->getPositionAgent().mV);
02326 glEnd();
02327 }
02328 }
02329 }
02330 }
02331 }
02332
02333 if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
02334 {
02335
02336 F32 x, y;
02337
02338 LLGLSNoTexture gls_no_texture;
02339
02340 glBegin(GL_POINTS);
02341 if (gAgent.getRegion())
02342 {
02343
02344 for (x = 0; x <= 260; x++)
02345 {
02346 for (y = 0; y <= 260; y++)
02347 {
02348 if ((x > 255) || (y > 255))
02349 {
02350 glColor4f(1.f, 0.f, 0.f, 1.f);
02351 }
02352 else
02353 {
02354 glColor4f(0.f, 0.f, 1.f, 1.f);
02355 }
02356 F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y);
02357 z *= 5.f;
02358 z += 50.f;
02359 glVertex3f(x, y, z);
02360 }
02361 }
02362 }
02363 glEnd();
02364 }
02365 }
02366
02367 void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects)
02368 {
02369 LLMemType mt(LLMemType::MTYPE_PIPELINE);
02370
02371 LLVertexBuffer::startRender();
02372
02373 glMatrixMode(GL_MODELVIEW);
02374
02375 LLGLSDefault gls_default;
02376 LLGLSObjectSelect gls_object_select;
02377 LLGLDepthTest gls_depth(GL_TRUE,GL_TRUE);
02378 disableLights();
02379
02380 glEnableClientState ( GL_VERTEX_ARRAY );
02381
02382
02383 #ifndef LL_RELEASE_FOR_DOWNLOAD
02384 LLGLState::checkStates();
02385 LLGLState::checkTextureChannels();
02386 LLGLState::checkClientArrays();
02387 U32 last_type = 0;
02388 #endif
02389 for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
02390 {
02391 LLDrawPool *poolp = *iter;
02392 if (poolp->isFacePool() && hasRenderType(poolp->getType()))
02393 {
02394 LLFacePool* face_pool = (LLFacePool*) poolp;
02395 face_pool->renderForSelect();
02396
02397 #ifndef LL_RELEASE_FOR_DOWNLOAD
02398 if (poolp->getType() != last_type)
02399 {
02400 last_type = poolp->getType();
02401 LLGLState::checkStates();
02402 LLGLState::checkTextureChannels();
02403 LLGLState::checkClientArrays();
02404 }
02405 #endif
02406 }
02407 }
02408
02409 LLGLEnable tex(GL_TEXTURE_2D);
02410 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
02411 LLGLEnable alpha_test(GL_ALPHA_TEST);
02412 if (gPickTransparent)
02413 {
02414 glAlphaFunc(GL_GEQUAL, 0.0f);
02415 }
02416 else
02417 {
02418 glAlphaFunc(GL_GREATER, 0.2f);
02419 }
02420
02421 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
02422 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
02423 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
02424
02425 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR);
02426 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
02427
02428 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
02429 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
02430
02431 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
02432 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
02433
02434 U32 prim_mask = LLVertexBuffer::MAP_VERTEX |
02435 LLVertexBuffer::MAP_TEXCOORD;
02436
02437 for (std::set<LLViewerObject*>::iterator i = objects.begin(); i != objects.end(); ++i)
02438 {
02439 LLViewerObject* vobj = *i;
02440 LLDrawable* drawable = vobj->mDrawable;
02441 if (vobj->isDead() ||
02442 vobj->isHUDAttachment() ||
02443 (gHideSelectedObjects && vobj->isSelected()) ||
02444 drawable->isDead() ||
02445 !hasRenderType(drawable->getRenderType()))
02446 {
02447 continue;
02448 }
02449
02450 for (S32 j = 0; j < drawable->getNumFaces(); ++j)
02451 {
02452 LLFace* facep = drawable->getFace(j);
02453 if (!facep->getPool())
02454 {
02455 facep->renderForSelect(prim_mask);
02456 }
02457 }
02458 }
02459
02460
02461 LLVOAvatar* avatarp = gAgent.getAvatarObject();
02462 if (avatarp && sShowHUDAttachments)
02463 {
02464 glMatrixMode(GL_PROJECTION);
02465 glPushMatrix();
02466 glMatrixMode(GL_MODELVIEW);
02467 glPushMatrix();
02468
02469 setup_hud_matrices(TRUE);
02470 LLViewerJointAttachment* attachmentp;
02471 for (attachmentp = avatarp->mAttachmentPoints.getFirstData();
02472 attachmentp;
02473 attachmentp = avatarp->mAttachmentPoints.getNextData())
02474 {
02475 if (attachmentp->getIsHUDAttachment())
02476 {
02477 LLViewerObject* objectp = attachmentp->getObject();
02478 if (objectp)
02479 {
02480 LLDrawable* drawable = objectp->mDrawable;
02481 if (drawable->isDead())
02482 {
02483 continue;
02484 }
02485
02486 for (S32 j = 0; j < drawable->getNumFaces(); ++j)
02487 {
02488 LLFace* facep = drawable->getFace(j);
02489 if (!facep->getPool())
02490 {
02491 facep->renderForSelect(prim_mask);
02492 }
02493 }
02494
02495
02496 for (U32 k = 0; k < drawable->getChildCount(); ++k)
02497 {
02498 LLDrawable* child = drawable->getChild(k);
02499 for (S32 l = 0; l < child->getNumFaces(); ++l)
02500 {
02501 LLFace* facep = child->getFace(l);
02502 if (!facep->getPool())
02503 {
02504 facep->renderForSelect(prim_mask);
02505 }
02506 }
02507 }
02508 }
02509 }
02510 }
02511
02512 glMatrixMode(GL_PROJECTION);
02513 glPopMatrix();
02514 glMatrixMode(GL_MODELVIEW);
02515 glPopMatrix();
02516 }
02517
02518 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
02519 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
02520
02521 LLVertexBuffer::stopRender();
02522 }
02523
02524 void LLPipeline::renderFaceForUVSelect(LLFace* facep)
02525 {
02526 if (facep) facep->renderSelectedUV();
02527 }
02528
02529 void LLPipeline::rebuildPools()
02530 {
02531 LLMemType mt(LLMemType::MTYPE_PIPELINE);
02532 S32 max_count = mPools.size();
02533 pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
02534 while(max_count > 0 && mPools.size() > 0)
02535 {
02536 if (iter1 == mPools.end())
02537 {
02538 iter1 = mPools.begin();
02539 }
02540 LLDrawPool* poolp = *iter1;
02541
02542 if (poolp->isDead())
02543 {
02544 mPools.erase(iter1++);
02545 removeFromQuickLookup( poolp );
02546 if (poolp == mLastRebuildPool)
02547 {
02548 mLastRebuildPool = NULL;
02549 }
02550 delete poolp;
02551 }
02552 else
02553 {
02554 mLastRebuildPool = poolp;
02555 iter1++;
02556 }
02557 max_count--;
02558 }
02559
02560 if (gAgent.getAvatarObject())
02561 {
02562 gAgent.getAvatarObject()->rebuildHUD();
02563 }
02564 }
02565
02566 void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
02567 {
02568 LLMemType mt(LLMemType::MTYPE_PIPELINE);
02569 switch( new_poolp->getType() )
02570 {
02571 case LLDrawPool::POOL_SIMPLE:
02572 if (mSimplePool)
02573 {
02574 llassert(0);
02575 llwarns << "Ignoring duplicate simple pool." << llendl;
02576 }
02577 else
02578 {
02579 mSimplePool = (LLRenderPass*) new_poolp;
02580 }
02581 break;
02582
02583 case LLDrawPool::POOL_GLOW:
02584 if (mGlowPool)
02585 {
02586 llassert(0);
02587 llwarns << "Ignoring duplicate glow pool." << llendl;
02588 }
02589 else
02590 {
02591 mGlowPool = (LLRenderPass*) new_poolp;
02592 }
02593 break;
02594
02595 case LLDrawPool::POOL_TREE:
02596 mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
02597 break;
02598
02599 case LLDrawPool::POOL_TERRAIN:
02600 mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
02601 break;
02602
02603 case LLDrawPool::POOL_BUMP:
02604 if (mBumpPool)
02605 {
02606 llassert(0);
02607 llwarns << "Ignoring duplicate bump pool." << llendl;
02608 }
02609 else
02610 {
02611 mBumpPool = new_poolp;
02612 }
02613 break;
02614
02615 case LLDrawPool::POOL_ALPHA:
02616 if( mAlphaPool )
02617 {
02618 llassert(0);
02619 llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
02620 }
02621 else
02622 {
02623 mAlphaPool = new_poolp;
02624 }
02625 break;
02626
02627 case LLDrawPool::POOL_ALPHA_POST_WATER:
02628 if( mAlphaPoolPostWater )
02629 {
02630 llassert(0);
02631 llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
02632 }
02633 else
02634 {
02635 mAlphaPoolPostWater = new_poolp;
02636 }
02637 break;
02638
02639 case LLDrawPool::POOL_AVATAR:
02640 break;
02641
02642 case LLDrawPool::POOL_SKY:
02643 if( mSkyPool )
02644 {
02645 llassert(0);
02646 llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl;
02647 }
02648 else
02649 {
02650 mSkyPool = new_poolp;
02651 }
02652 break;
02653
02654 case LLDrawPool::POOL_STARS:
02655 if( mStarsPool )
02656 {
02657 llassert(0);
02658 llwarns << "LLPipeline::addPool(): Ignoring duplicate Stars pool" << llendl;
02659 }
02660 else
02661 {
02662 mStarsPool = new_poolp;
02663 }
02664 break;
02665
02666 case LLDrawPool::POOL_WATER:
02667 if( mWaterPool )
02668 {
02669 llassert(0);
02670 llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl;
02671 }
02672 else
02673 {
02674 mWaterPool = new_poolp;
02675 }
02676 break;
02677
02678 case LLDrawPool::POOL_GROUND:
02679 if( mGroundPool )
02680 {
02681 llassert(0);
02682 llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl;
02683 }
02684 else
02685 {
02686 mGroundPool = new_poolp;
02687 }
02688 break;
02689
02690 default:
02691 llassert(0);
02692 llwarns << "Invalid Pool Type in LLPipeline::addPool()" << llendl;
02693 break;
02694 }
02695 }
02696
02697 void LLPipeline::removePool( LLDrawPool* poolp )
02698 {
02699 removeFromQuickLookup(poolp);
02700 mPools.erase(poolp);
02701 delete poolp;
02702 }
02703
02704 void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
02705 {
02706 LLMemType mt(LLMemType::MTYPE_PIPELINE);
02707 switch( poolp->getType() )
02708 {
02709 case LLDrawPool::POOL_SIMPLE:
02710 llassert(mSimplePool == poolp);
02711 mSimplePool = NULL;
02712 break;
02713
02714 case LLDrawPool::POOL_GLOW:
02715 llassert(mGlowPool == poolp);
02716 mGlowPool = NULL;
02717 break;
02718
02719 case LLDrawPool::POOL_TREE:
02720 #ifdef _DEBUG
02721 {
02722 BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() );
02723 llassert( found );
02724 }
02725 #else
02726 mTreePools.erase( (uintptr_t)poolp->getTexture() );
02727 #endif
02728 break;
02729
02730 case LLDrawPool::POOL_TERRAIN:
02731 #ifdef _DEBUG
02732 {
02733 BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
02734 llassert( found );
02735 }
02736 #else
02737 mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
02738 #endif
02739 break;
02740
02741 case LLDrawPool::POOL_BUMP:
02742 llassert( poolp == mBumpPool );
02743 mBumpPool = NULL;
02744 break;
02745
02746 case LLDrawPool::POOL_ALPHA:
02747 llassert( poolp == mAlphaPool );
02748 mAlphaPool = NULL;
02749 break;
02750
02751 case LLDrawPool::POOL_ALPHA_POST_WATER:
02752 llassert( poolp == mAlphaPoolPostWater );
02753 mAlphaPoolPostWater = NULL;
02754 break;
02755
02756 case LLDrawPool::POOL_AVATAR:
02757 break;
02758
02759 case LLDrawPool::POOL_SKY:
02760 llassert( poolp == mSkyPool );
02761 mSkyPool = NULL;
02762 break;
02763
02764 case LLDrawPool::POOL_STARS:
02765 llassert( poolp == mStarsPool );
02766 mStarsPool = NULL;
02767 break;
02768
02769 case LLDrawPool::POOL_WATER:
02770 llassert( poolp == mWaterPool );
02771 mWaterPool = NULL;
02772 break;
02773
02774 case LLDrawPool::POOL_GROUND:
02775 llassert( poolp == mGroundPool );
02776 mGroundPool = NULL;
02777 break;
02778
02779 default:
02780 llassert(0);
02781 llwarns << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
02782 break;
02783 }
02784 }
02785
02786 void LLPipeline::resetDrawOrders()
02787 {
02788
02789 for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
02790 {
02791 LLDrawPool *poolp = *iter;
02792 poolp->resetDrawOrders();
02793 }
02794 }
02795
02796
02797
02798
02799
02800 void LLPipeline::setupAvatarLights(BOOL for_edit)
02801 {
02802 const LLColor4 black(0,0,0,1);
02803
02804 if (for_edit)
02805 {
02806 LLColor4 diffuse(0.8f, 0.8f, 0.8f, 0.f);
02807 LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f);
02808 LLMatrix4 camera_mat = gCamera->getModelview();
02809 LLMatrix4 camera_rot(camera_mat.getMat3());
02810 camera_rot.invert();
02811 LLVector4 light_pos = light_pos_cam * camera_rot;
02812
02813 light_pos.normVec();
02814
02815 mHWLightColors[1] = diffuse;
02816 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse.mV);
02817 glLightfv(GL_LIGHT1, GL_AMBIENT, black.mV);
02818 glLightfv(GL_LIGHT1, GL_SPECULAR, black.mV);
02819 glLightfv(GL_LIGHT1, GL_POSITION, light_pos.mV);
02820 glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0f);
02821 glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.0f);
02822 glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
02823 glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 0.0f);
02824 glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 180.0f);
02825 }
02826 else if (gAvatarBacklight)
02827 {
02828 LLVector3 opposite_pos = -1.f * mSunDir;
02829 LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
02830 LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
02831 backlight_pos.normVec();
02832
02833 LLColor4 light_diffuse = mSunDiffuse * mSunShadowFactor;
02834 LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
02835 F32 max_component = 0.001f;
02836 for (S32 i = 0; i < 3; i++)
02837 {
02838 if (backlight_diffuse.mV[i] > max_component)
02839 {
02840 max_component = backlight_diffuse.mV[i];
02841 }
02842 }
02843 F32 backlight_mag;
02844 if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS)
02845 {
02846 backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
02847 }
02848 else
02849 {
02850 backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT;
02851 }
02852 backlight_diffuse *= backlight_mag / max_component;
02853
02854 mHWLightColors[1] = backlight_diffuse;
02855 glLightfv(GL_LIGHT1, GL_POSITION, backlight_pos.mV);
02856 glLightfv(GL_LIGHT1, GL_DIFFUSE, backlight_diffuse.mV);
02857 glLightfv(GL_LIGHT1, GL_AMBIENT, black.mV);
02858 glLightfv(GL_LIGHT1, GL_SPECULAR, black.mV);
02859 glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0f);
02860 glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.0f);
02861 glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
02862 glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 0.0f);
02863 glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 180.0f);
02864 }
02865 else
02866 {
02867 mHWLightColors[1] = black;
02868 glLightfv(GL_LIGHT1, GL_DIFFUSE, black.mV);
02869 glLightfv(GL_LIGHT1, GL_AMBIENT, black.mV);
02870 glLightfv(GL_LIGHT1, GL_SPECULAR, black.mV);
02871 }
02872 }
02873
02874 static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
02875 {
02876 F32 inten = light->getLightIntensity();
02877 if (inten < .001f)
02878 {
02879 return max_dist;
02880 }
02881 F32 radius = light->getLightRadius();
02882 BOOL selected = light->isSelected();
02883 LLVector3 dpos = light->getRenderPosition() - cam_pos;
02884 F32 dist2 = dpos.magVecSquared();
02885 if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
02886 {
02887 return max_dist;
02888 }
02889 F32 dist = fsqrtf(dist2);
02890 dist *= 1.f / inten;
02891 dist -= radius;
02892 if (selected)
02893 {
02894 dist -= 10000.f;
02895 }
02896 if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
02897 {
02898
02899 dist -= light->getLightRadius()*0.25f;
02900 }
02901 return dist;
02902 }
02903
02904 void LLPipeline::calcNearbyLights(LLCamera& camera)
02905 {
02906 if (mLightingDetail >= 1)
02907 {
02908
02909
02910 const S32 MAX_LOCAL_LIGHTS = 6;
02911
02912 LLVector3 cam_pos = LLPipeline::sSkipUpdate || LLViewerJoystick::sOverrideCamera ?
02913 camera.getOrigin() :
02914 gAgent.getPositionAgent();
02915
02916 F32 max_dist = LIGHT_MAX_RADIUS * 4.f;
02917
02918
02919 if (!LLPipeline::sSkipUpdate)
02920 {
02921 light_set_t cur_nearby_lights;
02922 for (light_set_t::iterator iter = mNearbyLights.begin();
02923 iter != mNearbyLights.end(); iter++)
02924 {
02925 const Light* light = &(*iter);
02926 LLDrawable* drawable = light->drawable;
02927 LLVOVolume* volight = drawable->getVOVolume();
02928 if (!volight || !drawable->isState(LLDrawable::LIGHT))
02929 {
02930 drawable->clearState(LLDrawable::NEARBY_LIGHT);
02931 continue;
02932 }
02933 if (light->fade <= -LIGHT_FADE_TIME)
02934 {
02935 drawable->clearState(LLDrawable::NEARBY_LIGHT);
02936 }
02937 else
02938 {
02939 F32 dist = calc_light_dist(volight, cam_pos, max_dist);
02940 cur_nearby_lights.insert(Light(drawable, dist, light->fade));
02941 }
02942 }
02943 mNearbyLights = cur_nearby_lights;
02944 }
02945
02946
02947 light_set_t new_nearby_lights;
02948 for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
02949 iter != mLights.end(); ++iter)
02950 {
02951 LLDrawable* drawable = *iter;
02952 LLVOVolume* light = drawable->getVOVolume();
02953 if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT))
02954 {
02955 continue;
02956 }
02957 if (light->isHUDAttachment())
02958 {
02959 continue;
02960 }
02961 F32 dist = calc_light_dist(light, cam_pos, max_dist);
02962 if (dist >= max_dist)
02963 {
02964 continue;
02965 }
02966 new_nearby_lights.insert(Light(drawable, dist, 0.f));
02967 if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
02968 {
02969 new_nearby_lights.erase(--new_nearby_lights.end());
02970 const Light& last = *new_nearby_lights.rbegin();
02971 max_dist = last.dist;
02972 }
02973 }
02974
02975
02976 for (light_set_t::iterator iter = new_nearby_lights.begin();
02977 iter != new_nearby_lights.end(); iter++)
02978 {
02979 const Light* light = &(*iter);
02980 if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
02981 {
02982 mNearbyLights.insert(*light);
02983 ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
02984 }
02985 else
02986 {
02987
02988
02989
02990 Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
02991 if (light->dist < farthest_light->dist)
02992 {
02993 if (farthest_light->fade >= 0.f)
02994 {
02995 farthest_light->fade = -gFrameIntervalSeconds;
02996 }
02997 }
02998 else
02999 {
03000 break;
03001 }
03002 }
03003 }
03004
03005 }
03006 }
03007
03008 void LLPipeline::setupHWLights(LLDrawPool* pool)
03009 {
03010 const LLColor4 black(0,0,0,1);
03011
03012
03013 LLColor4 ambient = gSky.getTotalAmbientColor();
03014 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
03015
03016
03017 {
03018 mSunShadowFactor = 1.f;
03019 if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS)
03020 {
03021 mSunDir.setVec(gSky.getSunDirection());
03022 mSunDiffuse.setVec(gSky.getSunDiffuseColor());
03023 }
03024 else
03025 {
03026 mSunDir.setVec(gSky.getMoonDirection());
03027 mSunDiffuse.setVec(gSky.getMoonDiffuseColor() * 1.5f);
03028 }
03029
03030 F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
03031 if (max_color > 1.f)
03032 {
03033 mSunDiffuse *= 1.f/max_color;
03034 }
03035 mSunDiffuse.clamp();
03036
03037 LLVector4 light_pos(mSunDir, 0.0f);
03038 LLColor4 light_diffuse = mSunDiffuse * mSunShadowFactor;
03039 mHWLightColors[0] = light_diffuse;
03040 glLightfv(GL_LIGHT0, GL_POSITION, light_pos.mV);
03041 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse.mV);
03042 glLightfv(GL_LIGHT0, GL_AMBIENT, black.mV);
03043 glLightfv(GL_LIGHT0, GL_SPECULAR, black.mV);
03044 glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f);
03045 glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.0f);
03046 glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f);
03047 glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, 0.0f);
03048 glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, 180.0f);
03049 }
03050
03051
03052
03053
03054 S32 cur_light = 2;
03055
03056
03057
03058 mLightMovingMask = 0;
03059
03060 if (mLightingDetail >= 1)
03061 {
03062 for (light_set_t::iterator iter = mNearbyLights.begin();
03063 iter != mNearbyLights.end(); ++iter)
03064 {
03065 LLDrawable* drawable = iter->drawable;
03066 LLVOVolume* light = drawable->getVOVolume();
03067 if (!light)
03068 {
03069 continue;
03070 }
03071 if (drawable->isState(LLDrawable::ACTIVE))
03072 {
03073 mLightMovingMask |= (1<<cur_light);
03074 }
03075
03076 LLColor4 light_color = light->getLightColor();
03077 light_color.mV[3] = 0.0f;
03078
03079 F32 fade = LLPipeline::sSkipUpdate ? 1.f : iter->fade;
03080 if (fade < LIGHT_FADE_TIME)
03081 {
03082
03083 if (fade >= 0.f)
03084 {
03085 fade = fade / LIGHT_FADE_TIME;
03086 ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds;
03087 }
03088 else
03089 {
03090 fade = 1.f + fade / LIGHT_FADE_TIME;
03091 ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds;
03092 }
03093 fade = llclamp(fade,0.f,1.f);
03094 light_color *= fade;
03095 }
03096
03097 LLVector3 light_pos(light->getRenderPosition());
03098 LLVector4 light_pos_gl(light_pos, 1.0f);
03099
03100 F32 light_radius = llmax(light->getLightRadius(), 0.001f);
03101 F32 atten, quad;
03102
03103 #if 0 //1.9.1
03104 if (pool->getVertexShaderLevel() > 0)
03105 {
03106 atten = light_radius;
03107 quad = llmax(light->getLightFalloff(), 0.0001f);
03108 }
03109 else
03110 #endif
03111 {
03112 F32 x = (3.f * (1.f + light->getLightFalloff()));
03113 atten = x / (light_radius);
03114 quad = 0.0f;
03115 }
03116 mHWLightColors[cur_light] = light_color;
03117 S32 gllight = GL_LIGHT0+cur_light;
03118 glLightfv(gllight, GL_POSITION, light_pos_gl.mV);
03119 glLightfv(gllight, GL_DIFFUSE, light_color.mV);
03120 glLightfv(gllight, GL_AMBIENT, black.mV);
03121 glLightfv(gllight, GL_SPECULAR, black.mV);
03122 glLightf (gllight, GL_CONSTANT_ATTENUATION, 0.0f);
03123 glLightf (gllight, GL_LINEAR_ATTENUATION, atten);
03124 glLightf (gllight, GL_QUADRATIC_ATTENUATION, quad);
03125 glLightf (gllight, GL_SPOT_EXPONENT, 0.0f);
03126 glLightf (gllight, GL_SPOT_CUTOFF, 180.0f);
03127 cur_light++;
03128 if (cur_light >= 8)
03129 {
03130 break;
03131 }
03132 }
03133 }
03134 for ( ; cur_light < 8 ; cur_light++)
03135 {
03136 mHWLightColors[cur_light] = black;
03137 S32 gllight = GL_LIGHT0+cur_light;
03138 glLightfv(gllight, GL_DIFFUSE, black.mV);
03139 glLightfv(gllight, GL_AMBIENT, black.mV);
03140 glLightfv(gllight, GL_SPECULAR, black.mV);
03141 }
03142
03143
03144 glDisable(GL_LIGHTING);
03145 for (S32 gllight=GL_LIGHT0; gllight<=GL_LIGHT7; gllight++)
03146 {
03147 glDisable(gllight);
03148 }
03149 mLightMask = 0;
03150 }
03151
03152 void LLPipeline::enableLights(U32 mask, F32 shadow_factor)
03153 {
03154 if (mLightingDetail == 0)
03155 {
03156 mask &= 0xf003;
03157 }
03158 if (mLightMask != mask)
03159 {
03160 if (!mLightMask)
03161 {
03162 glEnable(GL_LIGHTING);
03163 }
03164 if (mask)
03165 {
03166 for (S32 i=0; i<8; i++)
03167 {
03168 if (mask & (1<<i))
03169 {
03170 glEnable(GL_LIGHT0 + i);
03171 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, mHWLightColors[i].mV);
03172 }
03173 else
03174 {
03175 glDisable(GL_LIGHT0 + i);
03176 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, LLColor4::black.mV);
03177 }
03178 }
03179 }
03180 else
03181 {
03182 glDisable(GL_LIGHTING);
03183 }
03184 mLightMask = mask;
03185 LLColor4 ambient = gSky.getTotalAmbientColor();
03186 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
03187 }
03188 }
03189
03190 void LLPipeline::enableLightsStatic(F32 shadow_factor)
03191 {
03192 U32 mask = 0x01;
03193 if (mLightingDetail >= 2)
03194 {
03195 mask |= mLightMovingMask;
03196 glColor4f(0.f, 0.f, 0.f, 1.0f);
03197 }
03198 else
03199 {
03200 mask |= 0xff & (~2);
03201 }
03202 enableLights(mask, shadow_factor);
03203 }
03204
03205 void LLPipeline::enableLightsDynamic(F32 shadow_factor)
03206 {
03207 U32 mask = 0xff & (~2);
03208 enableLights(mask, shadow_factor);
03209 if (mLightingDetail >= 2)
03210 {
03211 glColor4f(0.f, 0.f, 0.f, 1.f);
03212 }
03213 }
03214
03215 void LLPipeline::enableLightsAvatar(F32 shadow_factor)
03216 {
03217 U32 mask = 0xff;
03218 setupAvatarLights(FALSE);
03219 enableLights(mask, shadow_factor);
03220 }
03221
03222 void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
03223 {
03224 U32 mask = 0x2002;
03225 setupAvatarLights(TRUE);
03226 enableLights(mask, 1.0f);
03227
03228 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
03229 }
03230
03231 void LLPipeline::enableLightsFullbright(const LLColor4& color)
03232 {
03233 U32 mask = 0x1000;
03234 enableLights(mask, 1.f);
03235
03236 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
03237 if (mLightingDetail >= 2)
03238 {
03239 glColor4f(0.f, 0.f, 0.f, 1.f);
03240 }
03241 }
03242
03243 void LLPipeline::disableLights()
03244 {
03245 enableLights(0, 0.f);
03246 glColor4f(1.f, 1.f, 1.f, 1.f);
03247 }
03248
03249
03250 void LLPipeline::setAmbient(const LLColor4& ambient)
03251 {
03252 mLightMask |= 0x4000;
03253 LLColor4 amb = ambient + gSky.getTotalAmbientColor();
03254 amb.clamp();
03255 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb.mV);
03256 }
03257
03258
03259
03260 class LLMenuItemGL;
03261 class LLInvFVBridge;
03262 struct cat_folder_pair;
03263 class LLVOBranch;
03264 class LLVOLeaf;
03265 class Foo;
03266
03267 void scale_stamp(const F32 x, const F32 y, const F32 xs, const F32 ys)
03268 {
03269 stamp(0.25f + 0.5f*x,
03270 0.5f + 0.45f*y,
03271 0.5f*xs,
03272 0.45f*ys);
03273 }
03274
03275 void drawBars(const F32 begin, const F32 end, const F32 height = 1.f)
03276 {
03277 if (begin >= 0 && end <=1)
03278 {
03279 F32 lines = 40.0f;
03280 S32 ibegin = (S32)(begin * lines);
03281 S32 iend = (S32)(end * lines);
03282 F32 fbegin = begin * lines - ibegin;
03283 F32 fend = end * lines - iend;
03284
03285 F32 line_height = height/lines;
03286
03287 if (iend == ibegin)
03288 {
03289 scale_stamp(fbegin, (F32)ibegin/lines,fend-fbegin, line_height);
03290 }
03291 else
03292 {
03293
03294 scale_stamp(fbegin, (F32)ibegin/lines, 1.0f-fbegin, line_height);
03295
03296
03297 scale_stamp(0.0, (F32)iend/lines, fend, line_height);
03298
03299
03300 for (S32 l = (ibegin+1); l < iend; l++)
03301 {
03302 scale_stamp(0.0f, (F32)l/lines, 1.0f, line_height);
03303 }
03304 }
03305 }
03306 }
03307
03308 void LLPipeline::findReferences(LLDrawable *drawablep)
03309 {
03310 if (std::find(mVisibleList.begin(), mVisibleList.end(), drawablep) != mVisibleList.end())
03311 {
03312 llinfos << "In mVisibleList" << llendl;
03313 }
03314 if (mLights.find(drawablep) != mLights.end())
03315 {
03316 llinfos << "In mLights" << llendl;
03317 }
03318 if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
03319 {
03320 llinfos << "In mMovedList" << llendl;
03321 }
03322 if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end())
03323 {
03324 llinfos << "In mShiftList" << llendl;
03325 }
03326 if (mRetexturedList.find(drawablep) != mRetexturedList.end())
03327 {
03328 llinfos << "In mRetexturedList" << llendl;
03329 }
03330
03331 if (mActiveQ.find(drawablep) != mActiveQ.end())
03332 {
03333 llinfos << "In mActiveQ" << llendl;
03334 }
03335 if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
03336 {
03337 llinfos << "In mBuildQ1" << llendl;
03338 }
03339 if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
03340 {
03341 llinfos << "In mBuildQ2" << llendl;
03342 }
03343
03344 S32 count;
03345
03346 count = gObjectList.findReferences(drawablep);
03347 if (count)
03348 {
03349 llinfos << "In other drawables: " << count << " references" << llendl;
03350 }
03351 }
03352
03353 BOOL LLPipeline::verify()
03354 {
03355 BOOL ok = TRUE;
03356 for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
03357 {
03358 LLDrawPool *poolp = *iter;
03359 if (!poolp->verify())
03360 {
03361 ok = FALSE;
03362 }
03363 }
03364
03365 if (!ok)
03366 {
03367 llwarns << "Pipeline verify failed!" << llendl;
03368 }
03369 return ok;
03370 }
03371
03373
03374
03375
03376
03377
03379
03399
03400
03401 #define IR(x) ((U32&)x)
03402
03403 bool LLRayAABB(const LLVector3 ¢er, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon)
03404 {
03405 BOOL Inside = TRUE;
03406 LLVector3 MinB = center - size;
03407 LLVector3 MaxB = center + size;
03408 LLVector3 MaxT;
03409 MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f;
03410
03411
03412 for(U32 i=0;i<3;i++)
03413 {
03414 if(origin.mV[i] < MinB.mV[i])
03415 {
03416 coord.mV[i] = MinB.mV[i];
03417 Inside = FALSE;
03418
03419
03420 if(IR(dir.mV[i])) MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i];
03421 }
03422 else if(origin.mV[i] > MaxB.mV[i])
03423 {
03424 coord.mV[i] = MaxB.mV[i];
03425 Inside = FALSE;
03426
03427
03428 if(IR(dir.mV[i])) MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i];
03429 }
03430 }
03431
03432
03433 if(Inside)
03434 {
03435 coord = origin;
03436 return true;
03437 }
03438
03439
03440 U32 WhichPlane = 0;
03441 if(MaxT.mV[1] > MaxT.mV[WhichPlane]) WhichPlane = 1;
03442 if(MaxT.mV[2] > MaxT.mV[WhichPlane]) WhichPlane = 2;
03443
03444
03445 if(IR(MaxT.mV[WhichPlane])&0x80000000) return false;
03446
03447 for(U32 i=0;i<3;i++)
03448 {
03449 if(i!=WhichPlane)
03450 {
03451 coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i];
03452 if (epsilon > 0)
03453 {
03454 if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon) return false;
03455 }
03456 else
03457 {
03458 if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i]) return false;
03459 }
03460 }
03461 }
03462 return true;
03463 }
03464
03466
03467
03468
03469
03470
03471 void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
03472 {
03473 if (drawablep)
03474 {
03475 if (is_light)
03476 {
03477 mLights.insert(drawablep);
03478 drawablep->setState(LLDrawable::LIGHT);
03479 }
03480 else
03481 {
03482 drawablep->clearState(LLDrawable::LIGHT);
03483 mLights.erase(drawablep);
03484 }
03485 markRelight(drawablep);
03486 }
03487 }
03488
03489 void LLPipeline::setActive(LLDrawable *drawablep, BOOL active)
03490 {
03491 if (active)
03492 {
03493 mActiveQ.insert(drawablep);
03494 }
03495 else
03496 {
03497 mActiveQ.erase(drawablep);
03498 }
03499 }
03500
03501
03502 void LLPipeline::toggleRenderType(U32 type)
03503 {
03504 U32 bit = (1<<type);
03505 gPipeline.mRenderTypeMask ^= bit;
03506 }
03507
03508
03509 void LLPipeline::toggleRenderTypeControl(void* data)
03510 {
03511 U32 type = (U32)(intptr_t)data;
03512 U32 bit = (1<<type);
03513 if (gPipeline.hasRenderType(type))
03514 {
03515 llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl;
03516 }
03517 else
03518 {
03519 llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
03520 }
03521 gPipeline.toggleRenderType(type);
03522 }
03523
03524
03525 BOOL LLPipeline::hasRenderTypeControl(void* data)
03526 {
03527 U32 type = (U32)(intptr_t)data;
03528 return gPipeline.hasRenderType(type);
03529 }
03530
03531
03532
03533 BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
03534 {
03535 S32 type = (S32)(intptr_t)data;
03536 return !gPipeline.hasRenderType(type);
03537 }
03538
03539
03540 void LLPipeline::toggleRenderDebug(void* data)
03541 {
03542 U32 bit = (U32)(intptr_t)data;
03543 if (gPipeline.hasRenderDebugMask(bit))
03544 {
03545 llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl;
03546 }
03547 else
03548 {
03549 llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl;
03550 }
03551 gPipeline.mRenderDebugMask ^= bit;
03552 }
03553
03554
03555
03556 BOOL LLPipeline::toggleRenderDebugControl(void* data)
03557 {
03558 U32 bit = (U32)(intptr_t)data;
03559 return gPipeline.hasRenderDebugMask(bit);
03560 }
03561
03562
03563 void LLPipeline::toggleRenderDebugFeature(void* data)
03564 {
03565 U32 bit = (U32)(intptr_t)data;
03566 gPipeline.mRenderDebugFeatureMask ^= bit;
03567 }
03568
03569
03570
03571 BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
03572 {
03573 U32 bit = (U32)(intptr_t)data;
03574 return gPipeline.hasRenderDebugFeatureMask(bit);
03575 }
03576
03577
03578 void LLPipeline::setRenderScriptedBeacons(BOOL val)
03579 {
03580 sRenderScriptedBeacons = val;
03581 }
03582
03583
03584 void LLPipeline::toggleRenderScriptedBeacons(void*)
03585 {
03586 sRenderScriptedBeacons = !sRenderScriptedBeacons;
03587 }
03588
03589
03590 BOOL LLPipeline::getRenderScriptedBeacons(void*)
03591 {
03592 return sRenderScriptedBeacons;
03593 }
03594
03595
03596 void LLPipeline::setRenderScriptedTouchBeacons(BOOL val)
03597 {
03598 sRenderScriptedTouchBeacons = val;
03599 }
03600
03601
03602 void LLPipeline::toggleRenderScriptedTouchBeacons(void*)
03603 {
03604 sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons;
03605 }
03606
03607
03608 BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
03609 {
03610 return sRenderScriptedTouchBeacons;
03611 }
03612
03613
03614 void LLPipeline::setRenderPhysicalBeacons(BOOL val)
03615 {
03616 sRenderPhysicalBeacons = val;
03617 }
03618
03619
03620 void LLPipeline::toggleRenderPhysicalBeacons(void*)
03621 {
03622 sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
03623 }
03624
03625
03626 BOOL LLPipeline::getRenderPhysicalBeacons(void*)
03627 {
03628 return sRenderPhysicalBeacons;
03629 }
03630
03631
03632 void LLPipeline::setRenderParticleBeacons(BOOL val)
03633 {
03634 sRenderParticleBeacons = val;
03635 }
03636
03637
03638 void LLPipeline::toggleRenderParticleBeacons(void*)
03639 {
03640 sRenderParticleBeacons = !sRenderParticleBeacons;
03641 }
03642
03643
03644 BOOL LLPipeline::getRenderParticleBeacons(void*)
03645 {
03646 return sRenderParticleBeacons;
03647 }
03648
03649
03650 void LLPipeline::setRenderSoundBeacons(BOOL val)
03651 {
03652 sRenderSoundBeacons = val;
03653 }
03654
03655
03656 void LLPipeline::toggleRenderSoundBeacons(void*)
03657 {
03658 sRenderSoundBeacons = !sRenderSoundBeacons;
03659 }
03660
03661
03662 BOOL LLPipeline::getRenderSoundBeacons(void*)
03663 {
03664 return sRenderSoundBeacons;
03665 }
03666
03667
03668 void LLPipeline::setRenderBeacons(BOOL val)
03669 {
03670 sRenderBeacons = val;
03671 }
03672
03673
03674 void LLPipeline::toggleRenderBeacons(void*)
03675 {
03676 sRenderBeacons = !sRenderBeacons;
03677 }
03678
03679
03680 BOOL LLPipeline::getRenderBeacons(void*)
03681 {
03682 return sRenderBeacons;
03683 }
03684
03685
03686 void LLPipeline::setRenderHighlights(BOOL val)
03687 {
03688 sRenderHighlight = val;
03689 }
03690
03691
03692 void LLPipeline::toggleRenderHighlights(void*)
03693 {
03694 sRenderHighlight = !sRenderHighlight;
03695 }
03696
03697
03698 BOOL LLPipeline::getRenderHighlights(void*)
03699 {
03700 return sRenderHighlight;
03701 }
03702
03703
03704 BOOL LLPipeline::getProcessBeacons(void* data)
03705 {
03706 return sRenderProcessBeacons;
03707 }
03708
03709 LLViewerObject* LLPipeline::pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision)
03710 {
03711 LLDrawable* drawable = mObjectPartition[PARTITION_VOLUME]->pickDrawable(start, end, collision);
03712 return drawable ? drawable->getVObj().get() : NULL;
03713 }
03714
03715 LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
03716 {
03717 if (vobj)
03718 {
03719 return getSpatialPartition(vobj->getPartitionType());
03720 }
03721 return NULL;
03722 }
03723
03724 LLSpatialPartition* LLPipeline::getSpatialPartition(U32 type)
03725 {
03726 if (type < mObjectPartition.size())
03727 {
03728 return mObjectPartition[type];
03729 }
03730 return NULL;
03731 }
03732
03733 void LLPipeline::clearRenderMap()
03734 {
03735 for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++)
03736 {
03737 mRenderMap[i].clear();
03738 }
03739 }
03740
03741
03742 void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
03743 {
03744 for (S32 i = 0; i < drawable->getNumFaces(); i++)
03745 {
03746 LLFace* facep = drawable->getFace(i);
03747 facep->mVertexBuffer = NULL;
03748 facep->mLastVertexBuffer = NULL;
03749 }
03750 }
03751
03752 void LLPipeline::resetVertexBuffers()
03753 {
03754 for (U32 i = 0; i < mObjectPartition.size(); ++i)
03755 {
03756 if (mObjectPartition[i])
03757 {
03758 mObjectPartition[i]->resetVertexBuffers();
03759 }
03760 }
03761
03762 resetDrawOrders();
03763
03764 if (gSky.mVOSkyp.notNull())
03765 {
03766 resetVertexBuffers(gSky.mVOSkyp->mDrawable);
03767 resetVertexBuffers(gSky.mVOGroundp->mDrawable);
03768 resetVertexBuffers(gSky.mVOStarsp->mDrawable);
03769 markRebuild(gSky.mVOSkyp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
03770 markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
03771 markRebuild(gSky.mVOStarsp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
03772 }
03773
03774 if (LLVertexBuffer::sGLCount > 0)
03775 {
03776 LLVertexBuffer::cleanupClass();
03777 }
03778 }
03779
03780 void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture)
03781 {
03782 mSimplePool->renderStatic(type, mask, texture);
03783 mSimplePool->renderActive(type, mask, texture);
03784 }
03785
03786 void LLPipeline::setUseVBO(BOOL use_vbo)
03787 {
03788 if (use_vbo != LLVertexBuffer::sEnableVBOs)
03789 {
03790 if (use_vbo)
03791 {
03792 llinfos << "Enabling VBO." << llendl;
03793 }
03794 else
03795 {
03796 llinfos << "Disabling VBO." << llendl;
03797 }
03798
03799 resetVertexBuffers();
03800 LLVertexBuffer::initClass(use_vbo);
03801 }
03802 }
03803
03804 void apply_cube_face_rotation(U32 face)
03805 {
03806 switch (face)
03807 {
03808 case 0:
03809 glRotatef(90.f, 0, 1, 0);
03810 glRotatef(180.f, 1, 0, 0);
03811 break;
03812 case 2:
03813 glRotatef(-90.f, 1, 0, 0);
03814 break;
03815 case 4:
03816 glRotatef(180.f, 0, 1, 0);
03817 glRotatef(180.f, 0, 0, 1);
03818 break;
03819 case 1:
03820 glRotatef(-90.f, 0, 1, 0);
03821 glRotatef(180.f, 1, 0, 0);
03822 break;
03823 case 3:
03824 glRotatef(90, 1, 0, 0);
03825 break;
03826 case 5:
03827 glRotatef(180, 0, 0, 1);
03828 break;
03829 }
03830 }
03831 void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam, GLsizei res)
03832 {
03833
03834 U32 type_mask = gPipeline.getRenderTypeMask();
03835 BOOL use_occlusion = LLPipeline::sUseOcclusion;
03836 LLPipeline::sUseOcclusion = FALSE;
03837 LLPipeline::sSkipUpdate = TRUE;
03838 static GLuint blur_tex = 0;
03839 if (!blur_tex)
03840 {
03841 glGenTextures(1, &blur_tex);
03842 }
03843
03844 BOOL reattach = FALSE;
03845 if (mCubeFrameBuffer == 0)
03846 {
03847 #if !defined(__sparc)
03848 glGenFramebuffersEXT(1, &mCubeFrameBuffer);
03849 glGenRenderbuffersEXT(1, &mCubeDepth);
03850 #else
03851 #error Can we generalize this without a CPU architecture test?
03852 #endif
03853 reattach = TRUE;
03854 }
03855
03856 BOOL toggle_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
03857 if (toggle_ui)
03858 {
03859 gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
03860 }
03861
03862 U32 cube_mask = (1 << LLPipeline::RENDER_TYPE_SIMPLE) |
03863 (1 << LLPipeline::RENDER_TYPE_WATER) |
03864 (1 << LLPipeline::RENDER_TYPE_BUMP) |
03865 (1 << LLPipeline::RENDER_TYPE_ALPHA) |
03866 (1 << LLPipeline::RENDER_TYPE_TREE) |
03867 (1 << LLDrawPool::POOL_ALPHA_POST_WATER) |
03868
03869 (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
03870
03871
03872 (1 << LLPipeline::RENDER_TYPE_GLOW) |
03873 (1 << LLPipeline::RENDER_TYPE_GRASS) |
03874 (1 << LLPipeline::RENDER_TYPE_VOLUME) |
03875 (1 << LLPipeline::RENDER_TYPE_TERRAIN) |
03876 (1 << LLPipeline::RENDER_TYPE_SKY) |
03877 (1 << LLPipeline::RENDER_TYPE_GROUND);
03878
03879 LLDrawPoolWater::sSkipScreenCopy = TRUE;
03880 cube_mask = cube_mask & type_mask;
03881 gPipeline.setRenderTypeMask(cube_mask);
03882
03883 glMatrixMode(GL_PROJECTION);
03884 glPushMatrix();
03885 glMatrixMode(GL_MODELVIEW);
03886 glPushMatrix();
03887
03888 glViewport(0,0,res,res);
03889
03890 glClearColor(0,0,0,0);
03891
03892 U32 cube_face[] =
03893 {
03894 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
03895 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
03896 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
03897 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
03898 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
03899 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
03900 };
03901
03902 LLVector3 origin = cube_cam.getOrigin();
03903
03904 gPipeline.calcNearbyLights(cube_cam);
03905
03906 cube_map->bind();
03907 for (S32 i = 0; i < 6; i++)
03908 {
03909 GLint res_x, res_y;
03910 glGetTexLevelParameteriv(cube_face[i], 0, GL_TEXTURE_WIDTH, &res_x);
03911 glGetTexLevelParameteriv(cube_face[i], 0, GL_TEXTURE_HEIGHT, &res_y);
03912
03913 if (res_x != res || res_y != res)
03914 {
03915 glTexImage2D(cube_face[i],0,GL_RGBA,res,res,0,GL_RGBA,GL_FLOAT,NULL);
03916 reattach = TRUE;
03917 }
03918 }
03919 cube_map->disable();
03920
03921 if (reattach)
03922 {
03923 #if !defined(__sparc)
03924 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mCubeDepth);
03925 GLint res_x, res_y;
03926 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_WIDTH_EXT, &res_x);
03927 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &res_y);
03928
03929 if (res_x != res || res_y != res)
03930 {
03931 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,res,res);
03932 }
03933
03934 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
03935 #else
03936 #error Can we generalize this without a CPU architecture test?
03937 #endif
03938 }
03939
03940 for (S32 i = 0; i < 6; i++)
03941 {
03942 #if !defined(__sparc)
03943 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer);
03944 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
03945 cube_face[i], cube_map->getGLName(), 0);
03946 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
03947 GL_RENDERBUFFER_EXT, mCubeDepth);
03948 #else
03949 #error Can we generalize this without a CPU architecture test?
03950 #endif
03951 glMatrixMode(GL_PROJECTION);
03952 glLoadIdentity();
03953 gluPerspective(90.f, 1.f, 0.1f, 1024.f);
03954 glMatrixMode(GL_MODELVIEW);
03955 glLoadIdentity();
03956
03957 apply_cube_face_rotation(i);
03958
03959 glTranslatef(-origin.mV[0], -origin.mV[1], -origin.mV[2]);
03960 cube_cam.setOrigin(origin);
03961 LLViewerCamera::updateFrustumPlanes(cube_cam);
03962 cube_cam.setOrigin(gCamera->getOrigin());
03963 gPipeline.updateCull(cube_cam);
03964 gPipeline.stateSort(cube_cam);
03965
03966 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
03967 gPipeline.renderGeom(cube_cam);
03968 }
03969
03970 #if !defined(__sparc)
03971 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
03972 #else
03973 #error Can we generalize this without a CPU architecture test?
03974 #endif
03975
03976 cube_cam.setOrigin(origin);
03977 gPipeline.resetDrawOrders();
03978 gShinyOrigin.setVec(cube_cam.getOrigin(), cube_cam.getFar()*2.f);
03979 glMatrixMode(GL_PROJECTION);
03980 glPopMatrix();
03981 glMatrixMode(GL_MODELVIEW);
03982 glPopMatrix();
03983
03984 gPipeline.setRenderTypeMask(type_mask);
03985 LLPipeline::sUseOcclusion = use_occlusion;
03986 LLPipeline::sSkipUpdate = FALSE;
03987
03988 if (toggle_ui)
03989 {
03990 gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
03991 }
03992 LLDrawPoolWater::sSkipScreenCopy = FALSE;
03993 }
03994
03995
03996 void render_cube_map()
03997 {
03998 U32 idx[36];
03999
04000 idx[0] = 1; idx[1] = 0; idx[2] = 2;
04001 idx[3] = 3; idx[4] = 2; idx[5] = 0;
04002
04003 idx[6] = 4; idx[7] = 5; idx[8] = 1;
04004 idx[9] = 0; idx[10] = 1; idx[11] = 5;
04005
04006 idx[12] = 5; idx[13] = 4; idx[14] = 6;
04007 idx[15] = 7; idx[16] = 6; idx[17] = 4;
04008
04009 idx[18] = 6; idx[19] = 7; idx[20] = 3;
04010 idx[21] = 2; idx[22] = 3; idx[23] = 7;
04011
04012 idx[24] = 0; idx[25] = 5; idx[26] = 3;
04013 idx[27] = 6; idx[28] = 3; idx[29] = 5;
04014
04015 idx[30] = 4; idx[31] = 1; idx[32] = 7;
04016 idx[33] = 2; idx[34] = 7; idx[35] = 1;
04017
04018 LLVector3 vert[8];
04019 LLVector3 r = LLVector3(1,1,1);
04020
04021 vert[0] = r.scaledVec(LLVector3(-1,1,1));
04022 vert[1] = r.scaledVec(LLVector3(1,1,1));
04023 vert[2] = r.scaledVec(LLVector3(1,-1,1));
04024 vert[3] = r.scaledVec(LLVector3(-1,-1,1));
04025
04026 vert[4] = r.scaledVec(LLVector3(1,1,-1));
04027 vert[5] = r.scaledVec(LLVector3(-1,1,-1));
04028 vert[6] = r.scaledVec(LLVector3(-1,-1,-1));
04029 vert[7] = r.scaledVec(LLVector3(1,-1,-1));
04030
04031 glBegin(GL_TRIANGLES);
04032 for (U32 i = 0; i < 36; i++)
04033 {
04034 glTexCoord3fv(vert[idx[i]].mV);
04035 glVertex3fv(vert[idx[i]].mV);
04036 }
04037 glEnd();
04038 }
04039
04040 void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32 res)
04041 {
04042 LLGLEnable cube(GL_TEXTURE_CUBE_MAP_ARB);
04043 LLGLDepthTest depth(GL_FALSE);
04044
04045
04046 GLboolean mask[4];
04047 glGetBooleanv(GL_COLOR_WRITEMASK, mask);
04048 glColorMask(mask[0], mask[1], mask[2], GL_FALSE);
04049
04050 glMatrixMode(GL_PROJECTION);
04051 glPushMatrix();
04052 glLoadIdentity();
04053 gluPerspective(90.f+45.f/res, 1.f, 0.1f, 1024.f);
04054 glMatrixMode(GL_MODELVIEW);
04055 glPushMatrix();
04056
04057 glViewport(0, 0, res, res);
04058 LLGLEnable blend(GL_BLEND);
04059
04060 S32 kernel = 2;
04061 F32 step = 90.f/res;
04062 F32 alpha = 1.f/((kernel*2)+1);
04063
04064 glColor4f(alpha,alpha,alpha,alpha*1.25f);
04065
04066 S32 x = 0;
04067
04068 U32 cube_face[] =
04069 {
04070 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
04071 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
04072 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
04073 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
04074 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
04075 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
04076 };
04077
04078 LLVector3 axis[] =
04079 {
04080 LLVector3(1,0,0),
04081 LLVector3(0,1,0),
04082 LLVector3(0,0,1)
04083 };
04084
04085
04086 glBlendFunc(GL_ONE, GL_ONE);
04087
04088 for (U32 j = 0; j < 3; j++)
04089 {
04090 glViewport(0,0,res, res*6);
04091 glClear(GL_COLOR_BUFFER_BIT);
04092 if (j == 0)
04093 {
04094 cube_in->bind();
04095 }
04096
04097 for (U32 i = 0; i < 6; i++)
04098 {
04099 glViewport(0,i*res, res, res);
04100 glLoadIdentity();
04101 apply_cube_face_rotation(i);
04102 for (x = -kernel; x <= kernel; ++x)
04103 {
04104 glPushMatrix();
04105 glRotatef(x*step, axis[j].mV[0], axis[j].mV[1], axis[j].mV[2]);
04106 render_cube_map();
04107 glPopMatrix();
04108 }
04109 }
04110
04111
04112 if (j == 0)
04113 {
04114 cube_out->bind();
04115 }
04116 for (U32 i = 0; i < 6; i++)
04117 {
04118 glCopyTexImage2D(cube_face[i], 0, GL_RGBA, 0, i*res, res, res, 0);
04119 }
04120 }
04121
04122 glMatrixMode(GL_PROJECTION);
04123 glPopMatrix();
04124 glMatrixMode(GL_MODELVIEW);
04125 glPopMatrix();
04126
04127 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
04128 glClear(GL_COLOR_BUFFER_BIT);
04129 }
04130
04131 void LLPipeline::bindScreenToTexture()
04132 {
04133 LLGLEnable gl_texture_2d(GL_TEXTURE_2D);
04134
04135 GLint* viewport = (GLint*) gGLViewport;
04136 GLuint resX = nhpo2(viewport[2]);
04137 GLuint resY = nhpo2(viewport[3]);
04138
04139 if (mScreenTex == 0)
04140 {
04141 glGenTextures(1, &mScreenTex);
04142 glBindTexture(GL_TEXTURE_2D, mScreenTex);
04143
04144 gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
04145 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, resX, resY, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
04146
04147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
04148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
04149 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
04150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
04151 }
04152
04153 glBindTexture(GL_TEXTURE_2D, mScreenTex);
04154 GLint cResX;
04155 GLint cResY;
04156 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX);
04157 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY);
04158
04159 if (cResX != (GLint)resX || cResY != (GLint)resY)
04160 {
04161 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL);
04162 gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
04163 }
04164
04165 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]);
04166
04167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
04168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
04169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
04170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
04171
04172
04173 mScreenScale.mV[0] = (float) viewport[2]/resX;
04174 mScreenScale.mV[1] = (float) viewport[3]/resY;
04175
04176 LLImageGL::sBoundTextureMemory += resX * resY * 3;
04177 }
04178
04179 void LLPipeline::renderBloom(GLuint source, GLuint dest, GLuint buffer, U32 res, LLVector2 tc1, LLVector2 tc2)
04180 {
04181 gGlowProgram.bind();
04182
04183 LLGLEnable tex(GL_TEXTURE_2D);
04184 LLGLDepthTest depth(GL_FALSE);
04185 LLGLDisable blend(GL_BLEND);
04186 LLGLDisable cull(GL_CULL_FACE);
04187
04188 #if !defined(__sparc)
04189 if (mFramebuffer[0] == 0)
04190 {
04191 glGenFramebuffersEXT(2, mFramebuffer);
04192 }
04193 #else
04194 #error Can we generalize this without a CPU architecture test?
04195 #endif
04196
04197 GLint viewport[4];
04198 glGetIntegerv(GL_VIEWPORT, viewport);
04199 glViewport(0,0,res,res);
04200
04201 glMatrixMode(GL_PROJECTION);
04202 glPushMatrix();
04203 glLoadIdentity();
04204 glMatrixMode(GL_MODELVIEW);
04205 glPushMatrix();
04206 glLoadIdentity();
04207
04208 glBindTexture(GL_TEXTURE_2D, source);
04209
04210 S32 kernel = gSavedSettings.getS32("RenderGlowSize")*2;
04211
04212 LLGLDisable test(GL_ALPHA_TEST);
04213
04214 F32 delta = 1.f/(res*gSavedSettings.getF32("RenderGlowStrength"));
04215
04216 for (S32 i = 0; i < kernel; i++)
04217 {
04218 #if !defined(__sparc)
04219 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebuffer[i%2]);
04220 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
04221 GL_COLOR_ATTACHMENT0_EXT,
04222 GL_TEXTURE_2D,
04223 i%2 == 0 ? buffer : dest, 0);
04224 #else
04225 #error Can we generalize this without a CPU architecture test?
04226 #endif
04227
04228 glBindTexture(GL_TEXTURE_2D, i == 0 ? source :
04229 i%2==0 ? dest :
04230 buffer);
04231
04232 glUniform1fARB(gGlowProgram.mUniform[LLShaderMgr::GLOW_DELTA],delta);
04233
04234 glBegin(GL_TRIANGLE_STRIP);
04235 glTexCoord2f(tc1.mV[0], tc1.mV[1]);
04236 glVertex2f(-1,-1);
04237
04238 glTexCoord2f(tc1.mV[0], tc2.mV[1]);
04239 glVertex2f(-1,1);
04240
04241 glTexCoord2f(tc2.mV[0], tc1.mV[1]);
04242 glVertex2f(1,-1);
04243
04244 glTexCoord2f(tc2.mV[0], tc2.mV[1]);
04245 glVertex2f(1,1);
04246 glEnd();
04247
04248 tc1.setVec(0,0);
04249 tc2.setVec(1,1);
04250
04251 }
04252
04253 #if !defined(__sparc)
04254 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
04255 #else
04256 #error Can we generalize this without a CPU architecture test?
04257 #endif
04258 gGlowProgram.unbind();
04259
04260 glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
04261
04262 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_GLOW))
04263 {
04264 glClear(GL_COLOR_BUFFER_BIT);
04265 }
04266
04267 glBindTexture(GL_TEXTURE_2D, dest);
04268 {
04269 LLGLEnable blend(GL_BLEND);
04270 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
04271
04272 glBegin(GL_TRIANGLE_STRIP);
04273 glColor4f(1,1,1,1);
04274 glTexCoord2f(tc1.mV[0], tc1.mV[1]);
04275 glVertex2f(-1,-1);
04276
04277 glTexCoord2f(tc1.mV[0], tc2.mV[1]);
04278 glVertex2f(-1,1);
04279
04280 glTexCoord2f(tc2.mV[0], tc1.mV[1]);
04281 glVertex2f(1,-1);
04282
04283 glTexCoord2f(tc2.mV[0], tc2.mV[1]);
04284 glVertex2f(1,1);
04285 glEnd();
04286
04287 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
04288 }
04289
04290 glMatrixMode(GL_PROJECTION);
04291 glPopMatrix();
04292 glMatrixMode(GL_MODELVIEW);
04293 glPopMatrix();
04294 }