diff options
Diffstat (limited to 'indra/newview/pipeline.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/newview/pipeline.cpp | 2391 |
1 files changed, 1875 insertions, 516 deletions
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9f0e2906d0..03712c1065 100644..100755 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -30,7 +30,6 @@ // library includes #include "llaudioengine.h" // For debugging. -#include "imageids.h" #include "llerror.h" #include "llviewercontrol.h" #include "llfasttimer.h" @@ -40,7 +39,6 @@ #include "llprimitive.h" #include "llvolume.h" #include "material_codes.h" -#include "timing.h" #include "v3color.h" #include "llui.h" #include "llglheaders.h" @@ -71,6 +69,7 @@ #include "llhudtext.h" #include "lllightconstants.h" #include "llmeshrepository.h" +#include "llpipelinelistener.h" #include "llresmgr.h" #include "llselectmgr.h" #include "llsky.h" @@ -86,6 +85,7 @@ #include "llviewerregion.h" // for audio debugging. #include "llviewerwindow.h" // For getSpinAxis #include "llvoavatarself.h" +#include "llvocache.h" #include "llvoground.h" #include "llvosky.h" #include "llvotree.h" @@ -110,7 +110,11 @@ #include "llpathinglib.h" #include "llfloaterpathfindingconsole.h" #include "llfloaterpathfindingcharacters.h" +#include "llfloatertools.h" +#include "llpanelface.h" #include "llpathfindingpathtool.h" +#include "llscenemonitor.h" +#include "llprogressview.h" #ifdef _DEBUG // Debug indices is disabled for now for debug performance - djs 4/24/02 @@ -119,6 +123,10 @@ //#define DEBUG_INDICES #endif +// Expensive and currently broken +// +#define MATERIALS_IN_REFLECTIONS 0 + bool gShiftFrame = false; //cached settings @@ -162,6 +170,7 @@ S32 LLPipeline::RenderGlowIterations; F32 LLPipeline::RenderGlowWidth; F32 LLPipeline::RenderGlowStrength; BOOL LLPipeline::RenderDepthOfField; +BOOL LLPipeline::RenderDepthOfFieldInEditMode; F32 LLPipeline::CameraFocusTransitionTime; F32 LLPipeline::CameraFNumber; F32 LLPipeline::CameraFocalLength; @@ -196,16 +205,11 @@ BOOL LLPipeline::CameraOffset; F32 LLPipeline::CameraMaxCoF; F32 LLPipeline::CameraDoFResScale; F32 LLPipeline::RenderAutoHideSurfaceAreaLimit; +LLTrace::EventStatHandle<S64> LLPipeline::sStatBatchSize("renderbatchsize"); -const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f; -const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f; const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f; const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f; -const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10; -const U32 REFLECTION_MAP_RES = 128; const U32 DEFERRED_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1; -// Max number of occluders to search for. JC -const S32 MAX_OCCLUDER_COUNT = 2; extern S32 gBoxFrame; //extern BOOL gHideSelectedObjects; @@ -218,39 +222,51 @@ BOOL gDebugPipeline = FALSE; LLPipeline gPipeline; const LLMatrix4* gGLLastMatrix = NULL; -LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Render Geometry"); -LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass"); -LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible"); -LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion"); -LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny"); -LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple"); -LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain"); -LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees"); -LLFastTimer::DeclareTimer FTM_RENDER_UI("UI"); -LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water"); -LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky"); -LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects"); -LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars"); -LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump"); -LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright"); -LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow"); -LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update"); -LLFastTimer::DeclareTimer FTM_PIPELINE_CREATE("Pipeline Create"); -LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool"); -LLFastTimer::DeclareTimer FTM_POOLS("Pools"); -LLFastTimer::DeclareTimer FTM_DEFERRED_POOLRENDER("RenderPool (Deferred)"); -LLFastTimer::DeclareTimer FTM_DEFERRED_POOLS("Pools (Deferred)"); -LLFastTimer::DeclareTimer FTM_POST_DEFERRED_POOLRENDER("RenderPool (Post)"); -LLFastTimer::DeclareTimer FTM_POST_DEFERRED_POOLS("Pools (Post)"); -LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO"); -LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State"); -LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline"); -LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy"); -LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading"); - - -static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables"); -static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort"); +LLTrace::BlockTimerStatHandle FTM_RENDER_GEOMETRY("Render Geometry"); +LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS("Grass"); +LLTrace::BlockTimerStatHandle FTM_RENDER_INVISIBLE("Invisible"); +LLTrace::BlockTimerStatHandle FTM_RENDER_OCCLUSION("Occlusion"); +LLTrace::BlockTimerStatHandle FTM_RENDER_SHINY("Shiny"); +LLTrace::BlockTimerStatHandle FTM_RENDER_SIMPLE("Simple"); +LLTrace::BlockTimerStatHandle FTM_RENDER_TERRAIN("Terrain"); +LLTrace::BlockTimerStatHandle FTM_RENDER_TREES("Trees"); +LLTrace::BlockTimerStatHandle FTM_RENDER_UI("UI"); +LLTrace::BlockTimerStatHandle FTM_RENDER_WATER("Water"); +LLTrace::BlockTimerStatHandle FTM_RENDER_WL_SKY("Windlight Sky"); +LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA("Alpha Objects"); +LLTrace::BlockTimerStatHandle FTM_RENDER_CHARACTERS("Avatars"); +LLTrace::BlockTimerStatHandle FTM_RENDER_BUMP("Bump"); +LLTrace::BlockTimerStatHandle FTM_RENDER_MATERIALS("Render Materials"); +LLTrace::BlockTimerStatHandle FTM_RENDER_FULLBRIGHT("Fullbright"); +LLTrace::BlockTimerStatHandle FTM_RENDER_GLOW("Glow"); +LLTrace::BlockTimerStatHandle FTM_GEO_UPDATE("Geo Update"); +LLTrace::BlockTimerStatHandle FTM_PIPELINE_CREATE("Pipeline Create"); +LLTrace::BlockTimerStatHandle FTM_POOLRENDER("RenderPool"); +LLTrace::BlockTimerStatHandle FTM_POOLS("Pools"); +LLTrace::BlockTimerStatHandle FTM_DEFERRED_POOLRENDER("RenderPool (Deferred)"); +LLTrace::BlockTimerStatHandle FTM_DEFERRED_POOLS("Pools (Deferred)"); +LLTrace::BlockTimerStatHandle FTM_POST_DEFERRED_POOLRENDER("RenderPool (Post)"); +LLTrace::BlockTimerStatHandle FTM_POST_DEFERRED_POOLS("Pools (Post)"); +LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM_FBO("First FBO"); +LLTrace::BlockTimerStatHandle FTM_STATESORT("Sort Draw State"); +LLTrace::BlockTimerStatHandle FTM_PIPELINE("Pipeline"); +LLTrace::BlockTimerStatHandle FTM_CLIENT_COPY("Client Copy"); +LLTrace::BlockTimerStatHandle FTM_RENDER_DEFERRED("Deferred Shading"); + + +static LLTrace::BlockTimerStatHandle FTM_STATESORT_DRAWABLE("Sort Drawables"); +static LLTrace::BlockTimerStatHandle FTM_STATESORT_POSTSORT("Post Sort"); + +static LLStaticHashedString sTint("tint"); +static LLStaticHashedString sAmbiance("ambiance"); +static LLStaticHashedString sAlphaScale("alpha_scale"); +static LLStaticHashedString sNormMat("norm_mat"); +static LLStaticHashedString sOffset("offset"); +static LLStaticHashedString sScreenRes("screenRes"); +static LLStaticHashedString sDelta("delta"); +static LLStaticHashedString sDistFactor("dist_factor"); +static LLStaticHashedString sKern("kern"); +static LLStaticHashedString sKernScale("kern_scale"); //---------------------------------------- std::string gPoolNames[] = @@ -261,10 +277,13 @@ std::string gPoolNames[] = "POOL_GROUND", "POOL_FULLBRIGHT", "POOL_BUMP", + "POOL_MATERIALS", "POOL_TERRAIN," "POOL_SKY", "POOL_WL_SKY", "POOL_TREE", + "POOL_ALPHA_MASK", + "POOL_FULLBRIGHT_ALPHA_MASK", "POOL_GRASS", "POOL_INVISIBLE", "POOL_AVATAR", @@ -274,7 +293,7 @@ std::string gPoolNames[] = "POOL_ALPHA" }; -void drawBox(const LLVector3& c, const LLVector3& r); +void drawBox(const LLVector4a& c, const LLVector4a& r); void drawBoxOutline(const LLVector3& pos, const LLVector3& size); U32 nhpo2(U32 v); LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage); @@ -351,6 +370,7 @@ BOOL LLPipeline::sRenderParticleBeacons = FALSE; BOOL LLPipeline::sRenderSoundBeacons = FALSE; BOOL LLPipeline::sRenderBeacons = FALSE; BOOL LLPipeline::sRenderHighlight = TRUE; +LLRender::eTexIndex LLPipeline::sRenderHighlightTextureChannel = LLRender::DIFFUSE_MAP; BOOL LLPipeline::sForceOldBakedUpload = FALSE; S32 LLPipeline::sUseOcclusion = 0; BOOL LLPipeline::sDelayVBUpdate = TRUE; @@ -367,6 +387,7 @@ BOOL LLPipeline::sWaterReflections = FALSE; BOOL LLPipeline::sRenderGlow = FALSE; BOOL LLPipeline::sReflectionRender = FALSE; BOOL LLPipeline::sImpostorRender = FALSE; +BOOL LLPipeline::sImpostorRenderAlphaDepthPass = FALSE; BOOL LLPipeline::sUnderWaterRender = FALSE; BOOL LLPipeline::sTextureBindTest = FALSE; BOOL LLPipeline::sRenderFrameTest = FALSE; @@ -376,42 +397,27 @@ BOOL LLPipeline::sRenderDeferred = FALSE; BOOL LLPipeline::sMemAllocationThrottled = FALSE; S32 LLPipeline::sVisibleLightCount = 0; F32 LLPipeline::sMinRenderSize = 0.f; +BOOL LLPipeline::sRenderingHUDs; +// EventHost API LLPipeline listener. +static LLPipelineListener sPipelineListener; static LLCullResult* sCull = NULL; -static const U32 gl_cube_face[] = -{ - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, -}; - void validate_framebuffer_object(); bool addDeferredAttachments(LLRenderTarget& target) { - return target.addColorAttachment(GL_RGBA) && //specular - target.addColorAttachment(GL_RGBA); //normal+z + return target.addColorAttachment(GL_SRGB8_ALPHA8) && //specular + target.addColorAttachment(GL_RGB10_A2); //normal+z } LLPipeline::LLPipeline() : mBackfaceCull(FALSE), - mBatchCount(0), mMatrixOpCount(0), mTextureMatrixOps(0), - mMaxBatchSize(0), - mMinBatchSize(0), - mMeanBatchSize(0), - mTrianglesDrawn(0), mNumVisibleNodes(0), - mVerticesRelit(0), - mLightingChanges(0), - mGeometryChanges(0), mNumVisibleFaces(0), mInitialized(FALSE), @@ -432,10 +438,14 @@ LLPipeline::LLPipeline() : mWaterPool(NULL), mGroundPool(NULL), mSimplePool(NULL), + mGrassPool(NULL), + mAlphaMaskPool(NULL), + mFullbrightAlphaMaskPool(NULL), mFullbrightPool(NULL), mInvisiblePool(NULL), mGlowPool(NULL), mBumpPool(NULL), + mMaterialsPool(NULL), mWLSkyPool(NULL), mLightMask(0), mLightMovingMask(0), @@ -453,7 +463,7 @@ void LLPipeline::connectRefreshCachedSettingsSafe(const std::string name) LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl(name); if ( cntrl_ptr.isNull() ) { - llwarns << "Global setting name not found:" << name << llendl; + LL_WARNS() << "Global setting name not found:" << name << LL_ENDL; } else { @@ -466,6 +476,7 @@ void LLPipeline::init() refreshCachedSettings(); gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); + gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); @@ -482,28 +493,40 @@ void LLPipeline::init() //create render pass pools getPool(LLDrawPool::POOL_ALPHA); getPool(LLDrawPool::POOL_SIMPLE); + getPool(LLDrawPool::POOL_ALPHA_MASK); + getPool(LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK); getPool(LLDrawPool::POOL_GRASS); getPool(LLDrawPool::POOL_FULLBRIGHT); getPool(LLDrawPool::POOL_INVISIBLE); getPool(LLDrawPool::POOL_BUMP); + getPool(LLDrawPool::POOL_MATERIALS); getPool(LLDrawPool::POOL_GLOW); - LLViewerStats::getInstance()->mTrianglesDrawnStat.reset(); resetFrameStats(); - for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + if (gSavedSettings.getBOOL("DisableAllRenderFeatures")) { - mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled + clearAllRenderDebugFeatures(); } + else + { + setAllRenderDebugFeatures(); // By default, all debugging features on + } + clearAllRenderDebugDisplays(); // All debug displays off - mRenderDebugFeatureMask = 0xffffffff; // All debugging features on - mRenderDebugMask = 0; // All debug starts off - - // Don't turn on ground when this is set - // Mac Books with intel 950s need this - if(!gSavedSettings.getBOOL("RenderGround")) + if (gSavedSettings.getBOOL("DisableAllRenderTypes")) + { + clearAllRenderTypes(); + } + else { - toggleRenderType(RENDER_TYPE_GROUND); + setAllRenderTypes(); // By default, all rendering types start enabled + // Don't turn on ground when this is set + // Mac Books with intel 950s need this + if(!gSavedSettings.getBOOL("RenderGround")) + { + toggleRenderType(RENDER_TYPE_GROUND); + } } // make sure RenderPerformanceTest persists (hackity hack hack) @@ -589,6 +612,7 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderGlowWidth"); connectRefreshCachedSettingsSafe("RenderGlowStrength"); connectRefreshCachedSettingsSafe("RenderDepthOfField"); + connectRefreshCachedSettingsSafe("RenderDepthOfFieldInEditMode"); connectRefreshCachedSettingsSafe("CameraFocusTransitionTime"); connectRefreshCachedSettingsSafe("CameraFNumber"); connectRefreshCachedSettingsSafe("CameraFocalLength"); @@ -663,11 +687,11 @@ void LLPipeline::cleanup() if (!mTerrainPools.empty()) { - llwarns << "Terrain Pools not cleaned up" << llendl; + LL_WARNS() << "Terrain Pools not cleaned up" << LL_ENDL; } if (!mTreePools.empty()) { - llwarns << "Tree Pools not cleaned up" << llendl; + LL_WARNS() << "Tree Pools not cleaned up" << LL_ENDL; } delete mAlphaPool; @@ -733,7 +757,7 @@ void LLPipeline::destroyGL() } } -static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); +static LLTrace::BlockTimerStatHandle FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); //static void LLPipeline::throttleNewMemoryAllocation(BOOL disable) @@ -755,20 +779,28 @@ void LLPipeline::throttleNewMemoryAllocation(BOOL disable) void LLPipeline::resizeScreenTexture() { - LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE); + LL_RECORD_BLOCK_TIME(FTM_RESIZE_SCREEN_TEXTURE); if (gPipeline.canUseVertexShaders() && assertInitialized()) { GLuint resX = gViewerWindow->getWorldViewWidthRaw(); GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + if ((resX != mScreen.getWidth()) || (resY != mScreen.getHeight())) + { + releaseScreenBuffers(); if (!allocateScreenBuffer(resX,resY)) - { //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled + { +#if PROBABLE_FALSE_DISABLES_OF_ALM_HERE + //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled //NOTE: if the session closes successfully after this call, deferred rendering will be // disabled on future sessions if (LLPipeline::sRenderDeferred) { gSavedSettings.setBOOL("RenderDeferred", FALSE); LLPipeline::refreshCachedSettings(); + + } +#endif } } } @@ -868,7 +900,7 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY) releaseScreenBuffers(); } - llwarns << "Unable to allocate screen buffer at any resolution!" << llendl; + LL_WARNS() << "Unable to allocate screen buffer at any resolution!" << LL_ENDL; } return ret; @@ -903,12 +935,26 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) S32 shadow_detail = RenderShadowDetail; BOOL ssao = RenderDeferredSSAO; + const U32 occlusion_divisor = 3; + //allocate deferred rendering color buffers - if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; + if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; + if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; if (!addDeferredAttachments(mDeferredScreen)) return false; - if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; + GLuint screenFormat = GL_RGBA16; + if (gGLManager.mIsATI) + { + screenFormat = GL_RGBA12; + } + + if (gGLManager.mGLVersion < 4.f && gGLManager.mIsNVIDIA) + { + screenFormat = GL_RGBA16F_ARB; + } + + if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; if (samples > 0) { if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; @@ -935,6 +981,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 0; i < 4; i++) { if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false; + if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false; } } else @@ -942,6 +989,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 0; i < 4; i++) { mShadow[i].release(); + mShadowOcclusion[i].release(); } } @@ -954,6 +1002,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 4; i < 6; i++) { if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false; + if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE)) return false; } } else @@ -961,6 +1010,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 4; i < 6; i++) { mShadow[i].release(); + mShadowOcclusion[i].release(); } } @@ -977,11 +1027,13 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) for (U32 i = 0; i < 6; i++) { mShadow[i].release(); + mShadowOcclusion[i].release(); } mFXAABuffer.release(); mScreen.release(); mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first mDeferredDepth.release(); + mOcclusionDepth.release(); if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; } @@ -999,11 +1051,18 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) } //static +void LLPipeline::updateRenderBump() +{ + sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); +} + +//static void LLPipeline::updateRenderDeferred() { BOOL deferred = ((RenderDeferred && LLRenderTarget::sUseFBO && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + LLPipeline::sRenderBump && VertexShaderEnable && RenderAvatarVP && WindLightUseAtmosShaders) ? TRUE : FALSE) && @@ -1072,6 +1131,7 @@ void LLPipeline::refreshCachedSettings() RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth"); RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength"); RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField"); + RenderDepthOfFieldInEditMode = gSavedSettings.getBOOL("RenderDepthOfFieldInEditMode"); CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime"); CameraFNumber = gSavedSettings.getF32("CameraFNumber"); CameraFocalLength = gSavedSettings.getF32("CameraFocalLength"); @@ -1116,13 +1176,13 @@ void LLPipeline::releaseGLBuffers() if (mNoiseMap) { - LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mNoiseMap); + LLImageGL::deleteTextures(1, &mNoiseMap); mNoiseMap = 0; } if (mTrueNoiseMap) { - LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mTrueNoiseMap); + LLImageGL::deleteTextures(1, &mTrueNoiseMap); mTrueNoiseMap = 0; } @@ -1130,6 +1190,7 @@ void LLPipeline::releaseGLBuffers() mWaterRef.release(); mWaterDis.release(); + mHighlight.release(); for (U32 i = 0; i < 3; i++) { @@ -1146,7 +1207,7 @@ void LLPipeline::releaseLUTBuffers() { if (mLightFunc) { - LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_R8, 0, 1, &mLightFunc); + LLImageGL::deleteTextures(1, &mLightFunc); mLightFunc = 0; } } @@ -1160,12 +1221,12 @@ void LLPipeline::releaseScreenBuffers() mDeferredScreen.release(); mDeferredDepth.release(); mDeferredLight.release(); - - mHighlight.release(); + mOcclusionDepth.release(); for (U32 i = 0; i < 6; i++) { mShadow[i].release(); + mShadowOcclusion[i].release(); } } @@ -1177,14 +1238,31 @@ void LLPipeline::createGLBuffers() updateRenderDeferred(); + bool materials_in_water = false; + +#if MATERIALS_IN_REFLECTIONS + materials_in_water = gSavedSettings.getS32("RenderWaterMaterials"); +#endif + if (LLPipeline::sWaterReflections) { //water reflection texture U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512); + // Set up SRGB targets if we're doing deferred-path reflection rendering + // + if (LLPipeline::sRenderDeferred && materials_in_water) + { + mWaterRef.allocate(res,res,GL_SRGB8_ALPHA8,TRUE,FALSE); + //always use FBO for mWaterDis so it can be used for avatar texture bakes + mWaterDis.allocate(res,res,GL_SRGB8_ALPHA8,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true); + } + else + { mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE); //always use FBO for mWaterDis so it can be used for avatar texture bakes mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true); } + } mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); @@ -1223,7 +1301,7 @@ void LLPipeline::createGLBuffers() noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; } - LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mNoiseMap); + LLImageGL::generateTextures(1, &mNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); @@ -1239,7 +1317,7 @@ void LLPipeline::createGLBuffers() noise[i] = ll_frand()*2.0-1.0; } - LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mTrueNoiseMap); + LLImageGL::generateTextures(1, &mTrueNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); @@ -1251,6 +1329,11 @@ void LLPipeline::createGLBuffers() gBumpImageList.restoreGL(); } +F32 lerpf(F32 a, F32 b, F32 w) +{ + return a + w * (b - a); +} + void LLPipeline::createLUTBuffers() { if (sRenderDeferred) @@ -1259,9 +1342,9 @@ void LLPipeline::createLUTBuffers() { U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); - U8* ls = new U8[lightResX*lightResY]; + F32* ls = new F32[lightResX*lightResY]; F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); - // Calculate the (normalized) Blinn-Phong specular lookup texture. + // Calculate the (normalized) blinn-phong specular lookup texture. (with a few tweaks) for (U32 y = 0; y < lightResY; ++y) { for (U32 x = 0; x < lightResX; ++x) @@ -1277,29 +1360,27 @@ void LLPipeline::createLUTBuffers() // Apply our normalization function. // Note: This is the full equation that applies the full normalization curve, not an approximation. // This is fine, given we only need to create our LUT once per buffer initialization. - // The only trade off is we have a really low dynamic range. - // This means we have to account for things not being able to exceed 0 to 1 in our shaders. spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); - - // Always sample at a 1.0/2.2 curve. - // This "Gamma corrects" our specular term, boosting our lower exponent reflections. - spec = powf(spec, 1.f/2.2f); - - // Easy fix for our dynamic range problem: divide by 6 here, multiply by 6 in our shaders. - // This allows for our specular term to exceed a value of 1 in our shaders. - // This is something that can be important for energy conserving specular models where higher exponents can result in highlights that exceed a range of 0 to 1. - // Technically, we could just use an R16F texture, but driver support for R16F textures can be somewhat spotty at times. - // This works remarkably well for higher specular exponents, though banding can sometimes be seen on lower exponents. - // Combined with a bit of noise and trilinear filtering, the banding is hardly noticable. - ls[y*lightResX+x] = (U8)(llclamp(spec * (1.f / 6), 0.f, 1.f) * 255); + + // Since we use R16F, we no longer have a dynamic range issue we need to work around here. + // Though some older drivers may not like this, newer drivers shouldn't have this problem. + ls[y*lightResX+x] = spec; } } - LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R8, 1, &mLightFunc); + U32 pix_format = GL_R16F; +#if LL_DARWIN + // Need to work around limited precision with 10.6.8 and older drivers + // + pix_format = GL_R32F; +#endif + LLImageGL::generateTextures(1, &mLightFunc); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, pix_format, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); delete [] ls; } @@ -1377,7 +1458,7 @@ void LLPipeline::unloadShaders() void LLPipeline::assertInitializedDoError() { - llerrs << "LLPipeline used when uninitialized." << llendl; + LL_ERRS() << "LLPipeline used when uninitialized." << LL_ENDL; } //============================================================================ @@ -1420,18 +1501,18 @@ S32 LLPipeline::setLightingDetail(S32 level) return mLightingDetail; } -class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable> +class LLOctreeDirtyTexture : public OctreeTraveler { public: const std::set<LLViewerFetchedTexture*>& mTextures; LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { } - virtual void visit(const LLOctreeNode<LLDrawable>* node) + virtual void visit(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) + if (!group->hasState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) { for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { @@ -1503,6 +1584,14 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) poolp = mGrassPool; break; + case LLDrawPool::POOL_ALPHA_MASK: + poolp = mAlphaMaskPool; + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + poolp = mFullbrightAlphaMaskPool; + break; + case LLDrawPool::POOL_FULLBRIGHT: poolp = mFullbrightPool; break; @@ -1526,7 +1615,9 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) case LLDrawPool::POOL_BUMP: poolp = mBumpPool; break; - + case LLDrawPool::POOL_MATERIALS: + poolp = mMaterialsPool; + break; case LLDrawPool::POOL_ALPHA: poolp = mAlphaPool; break; @@ -1552,7 +1643,7 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) default: llassert(0); - llerrs << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl; + LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL; break; } @@ -1590,20 +1681,44 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima return 0; } - bool alpha = te->getColor().mV[3] < 0.999f; + LLMaterial* mat = te->getMaterialParams().get(); + + bool color_alpha = te->getColor().mV[3] < 0.999f; + bool alpha = color_alpha; if (imagep) { alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2); } + if (alpha && mat) + { + switch (mat->getDiffuseAlphaMode()) + { + case 1: + alpha = true; // Material's alpha mode is set to blend. Toss it into the alpha draw pool. + break; + case 0: //alpha mode set to none, never go to alpha pool + case 3: //alpha mode set to emissive, never go to alpha pool + alpha = color_alpha; + break; + default: //alpha mode set to "mask", go to alpha pool if fullbright + alpha = color_alpha; // Material's alpha mode is set to none, mask, or emissive. Toss it into the opaque material draw pool. + break; + } + } + if (alpha) { return LLDrawPool::POOL_ALPHA; } - else if ((te->getBumpmap() || te->getShiny())) + else if ((te->getBumpmap() || te->getShiny()) && (!mat || mat->getNormalID().isNull())) { return LLDrawPool::POOL_BUMP; } + else if (mat && !alpha) + { + return LLDrawPool::POOL_MATERIALS; + } else { return LLDrawPool::POOL_SIMPLE; @@ -1620,11 +1735,9 @@ void LLPipeline::addPool(LLDrawPool *new_poolp) void LLPipeline::allocDrawable(LLViewerObject *vobj) { - LLDrawable *drawable = new LLDrawable(); + LLDrawable *drawable = new LLDrawable(vobj); vobj->mDrawable = drawable; - drawable->mVObjp = vobj; - //encompass completely sheared objects by taking //the most extreme point possible (<1,1,0.5>) drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length()); @@ -1636,15 +1749,15 @@ void LLPipeline::allocDrawable(LLViewerObject *vobj) } -static LLFastTimer::DeclareTimer FTM_UNLINK("Unlink"); -static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_MOVE_LIST("Movelist"); -static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_SPATIAL_PARTITION("Spatial Partition"); -static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_LIGHT_SET("Light Set"); -static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Set"); +static LLTrace::BlockTimerStatHandle FTM_UNLINK("Unlink"); +static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_MOVE_LIST("Movelist"); +static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_SPATIAL_PARTITION("Spatial Partition"); +static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_LIGHT_SET("Light Set"); +static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Set"); void LLPipeline::unlinkDrawable(LLDrawable *drawable) { - LLFastTimer t(FTM_UNLINK); + LL_RECORD_BLOCK_TIME(FTM_UNLINK); assertInitialized(); @@ -1653,7 +1766,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) // Based on flags, remove the drawable from the queues that it's on. if (drawablep->isState(LLDrawable::ON_MOVE_LIST)) { - LLFastTimer t(FTM_REMOVE_FROM_MOVE_LIST); + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_MOVE_LIST); LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep); if (iter != mMovedList.end()) { @@ -1663,19 +1776,19 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) if (drawablep->getSpatialGroup()) { - LLFastTimer t(FTM_REMOVE_FROM_SPATIAL_PARTITION); - if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup())) + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_SPATIAL_PARTITION); + if (!drawablep->getSpatialGroup()->getSpatialPartition()->remove(drawablep, drawablep->getSpatialGroup())) { #ifdef LL_RELEASE_FOR_DOWNLOAD - llwarns << "Couldn't remove object from spatial group!" << llendl; + LL_WARNS() << "Couldn't remove object from spatial group!" << LL_ENDL; #else - llerrs << "Couldn't remove object from spatial group!" << llendl; + LL_ERRS() << "Couldn't remove object from spatial group!" << LL_ENDL; #endif } } { - LLFastTimer t(FTM_REMOVE_FROM_LIGHT_SET); + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); mLights.erase(drawablep); for (light_set_t::iterator iter = mNearbyLights.begin(); @@ -1690,7 +1803,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) } { - LLFastTimer t(FTM_REMOVE_FROM_HIGHLIGHT_SET); + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_HIGHLIGHT_SET); HighlightItem item(drawablep); mHighlightSet.erase(item); @@ -1719,7 +1832,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) //static void LLPipeline::removeMutedAVsLights(LLVOAvatar* muted_avatar) { - LLFastTimer t(FTM_REMOVE_FROM_LIGHT_SET); + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); for (light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); iter != gPipeline.mNearbyLights.end(); iter++) { @@ -1747,7 +1860,7 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) void LLPipeline::createObjects(F32 max_dtime) { - LLFastTimer ftm(FTM_PIPELINE_CREATE); + LL_RECORD_BLOCK_TIME(FTM_PIPELINE_CREATE); LLTimer update_timer; @@ -1779,7 +1892,7 @@ void LLPipeline::createObject(LLViewerObject* vobj) } else { - llerrs << "Redundant drawable creation!" << llendl; + LL_ERRS() << "Redundant drawable creation!" << LL_ENDL; } llassert(drawablep); @@ -1810,17 +1923,7 @@ void LLPipeline::resetFrameStats() { assertInitialized(); - LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f); - - if (mBatchCount > 0) - { - mMeanBatchSize = gPipeline.mTrianglesDrawn/gPipeline.mBatchCount; - } - mTrianglesDrawn = 0; sCompiles = 0; - mVerticesRelit = 0; - mLightingChanges = 0; - mGeometryChanges = 0; mNumVisibleFaces = 0; if (mOldRenderDebugMask != mRenderDebugMask) @@ -1828,7 +1931,6 @@ void LLPipeline::resetFrameStats() gObjectList.clearDebugText(); mOldRenderDebugMask = mRenderDebugMask; } - } //external functions for asynchronous updating @@ -1840,7 +1942,7 @@ void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) } if (!drawablep) { - llerrs << "updateMove called with NULL drawablep" << llendl; + LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; return; } if (drawablep->isState(LLDrawable::EARLY_MOVE)) @@ -1870,7 +1972,7 @@ void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep) } if (!drawablep) { - llerrs << "updateMove called with NULL drawablep" << llendl; + LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; return; } if (drawablep->isState(LLDrawable::EARLY_MOVE)) @@ -1927,12 +2029,14 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) } } -static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree"); -static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move"); +static LLTrace::BlockTimerStatHandle FTM_OCTREE_BALANCE("Balance Octree"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_MOVE("Update Move"); +static LLTrace::BlockTimerStatHandle FTM_RETEXTURE("Retexture"); +static LLTrace::BlockTimerStatHandle FTM_MOVED_LIST("Moved List"); void LLPipeline::updateMove() { - LLFastTimer t(FTM_UPDATE_MOVE); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_MOVE); if (FreezeTime) { @@ -1942,8 +2046,7 @@ void LLPipeline::updateMove() assertInitialized(); { - static LLFastTimer::DeclareTimer ftm("Retexture"); - LLFastTimer t(ftm); + LL_RECORD_BLOCK_TIME(FTM_RETEXTURE); for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); iter != mRetexturedList.end(); ++iter) @@ -1958,14 +2061,13 @@ void LLPipeline::updateMove() } { - static LLFastTimer::DeclareTimer ftm("Moved List"); - LLFastTimer t(ftm); + LL_RECORD_BLOCK_TIME(FTM_MOVED_LIST); updateMovedList(mMovedList); } //balance octrees { - LLFastTimer ot(FTM_OCTREE_BALANCE); + LL_RECORD_BLOCK_TIME(FTM_OCTREE_BALANCE); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -1979,6 +2081,13 @@ void LLPipeline::updateMove() part->mOctree->balance(); } } + + //balance the VO Cache tree + LLVOCachePartition* vo_part = region->getVOCachePartition(); + if(vo_part) + { + vo_part->mOctree->balance(); + } } } } @@ -2048,9 +2157,9 @@ void check_references(LLSpatialGroup* group, LLDrawable* drawable) { for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - if (drawable == *i) + if (drawable == (LLDrawable*)(*i)->getDrawable()) { - llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl; + LL_ERRS() << "LLDrawable deleted while actively reference by LLPipeline." << LL_ENDL; } } } @@ -2061,7 +2170,7 @@ void check_references(LLDrawable* drawable, LLFace* face) { if (drawable->getFace(i) == face) { - llerrs << "LLFace deleted while actively referenced by LLPipeline." << llendl; + LL_ERRS() << "LLFace deleted while actively referenced by LLPipeline." << LL_ENDL; } } } @@ -2070,10 +2179,13 @@ void check_references(LLSpatialGroup* group, LLFace* face) { for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawable = *i; + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(drawable) + { check_references(drawable, face); } } +} void LLPipeline::checkReferences(LLFace* face) { @@ -2134,7 +2246,7 @@ void LLPipeline::checkReferences(LLDrawable* drawable) { if (drawable == *iter) { - llerrs << "LLDrawable deleted while actively referenced by LLPipeline." << llendl; + LL_ERRS() << "LLDrawable deleted while actively referenced by LLPipeline." << LL_ENDL; } } } @@ -2151,7 +2263,7 @@ void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info) LLDrawInfo* params = *j; if (params == draw_info) { - llerrs << "LLDrawInfo deleted while actively referenced by LLPipeline." << llendl; + LL_ERRS() << "LLDrawInfo deleted while actively referenced by LLPipeline." << LL_ENDL; } } } @@ -2193,7 +2305,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) { if (group == *iter) { - llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl; + LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; } } @@ -2201,7 +2313,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) { if (group == *iter) { - llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl; + LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; } } @@ -2209,7 +2321,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) { if (group == *iter) { - llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl; + LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; } } } @@ -2250,7 +2362,7 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& min = LLVector3(X,X,X); max = LLVector3(-X,-X,-X); - U32 saved_camera_id = LLViewerCamera::sCurCameraID; + LLViewerCamera::eCameraID saved_camera_id = LLViewerCamera::sCurCameraID; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; BOOL res = TRUE; @@ -2281,11 +2393,16 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& return res; } -static LLFastTimer::DeclareTimer FTM_CULL("Object Culling"); +static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling"); void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep) { - LLFastTimer t(FTM_CULL); + static LLCachedControl<bool> use_occlusion(gSavedSettings,"UseOcclusion"); + static bool can_use_occlusion = LLGLSLShader::sNoFixedFunction + && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") + && gGLManager.mHasOcclusionQuery; + + LL_RECORD_BLOCK_TIME(FTM_CULL); grabReferences(result); @@ -2299,7 +2416,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl if (to_texture) { - mScreen.bindTarget(); + if (LLPipeline::sRenderDeferred) + { + mOcclusionDepth.bindTarget(); + } + else + { + mScreen.bindTarget(); + } } if (sUseOcclusion > 1) @@ -2395,6 +2519,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl } } } + + //scan the VO Cache tree + LLVOCachePartition* vo_part = region->getVOCachePartition(); + if(vo_part) + { + bool do_occlusion_cull = can_use_occlusion && use_occlusion && !gUseWireframe/* && !gViewerWindow->getProgressView()->getVisible()*/; + vo_part->cull(camera, do_occlusion_cull); + } } if (bound_shader) @@ -2437,7 +2569,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl if (to_texture) { - mScreen.flush(); + if (LLPipeline::sRenderDeferred) + { + mOcclusionDepth.flush(); + } + else + { + mScreen.flush(); + } } } @@ -2462,15 +2601,16 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) return; } + const LLVector4a* bounds = group->getBounds(); if (sMinRenderSize > 0.f && - llmax(llmax(group->mBounds[1][0], group->mBounds[1][1]), group->mBounds[1][2]) < sMinRenderSize) + llmax(llmax(bounds[1][0], bounds[1][1]), bounds[1][2]) < sMinRenderSize) { return; } assertInitialized(); - if (!group->mSpatialPartition->mRenderByGroup) + if (!group->getSpatialPartition()->mRenderByGroup) { //render by drawable sCull->pushDrawableGroup(group); } @@ -2505,9 +2645,77 @@ void LLPipeline::markOccluder(LLSpatialGroup* group) } } +void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space) +{ + LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr; + + LLGLSLShader* shader = NULL; + + if (scratch_space) + { + scratch_space->copyContents(source, + 0, 0, source.getWidth(), source.getHeight(), + 0, 0, scratch_space->getWidth(), scratch_space->getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } + + dest.bindTarget(); + dest.clear(GL_DEPTH_BUFFER_BIT); + + LLStrider<LLVector3> vert; + mDeferredVB->getVertexStrider(vert); + LLStrider<LLVector2> tc0; + + vert[0].set(-1,1,0); + vert[1].set(-1,-3,0); + vert[2].set(3,1,0); + + if (source.getUsage() == LLTexUnit::TT_RECT_TEXTURE) + { + shader = &gDownsampleDepthRectProgram; + shader->bind(); + shader->uniform2f(sDelta, 1.f, 1.f); + shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, source.getWidth(), source.getHeight()); + } + else + { + shader = &gDownsampleDepthProgram; + shader->bind(); + shader->uniform2f(sDelta, 1.f/source.getWidth(), 1.f/source.getHeight()); + shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, 1.f, 1.f); + } + + gGL.getTexUnit(0)->bind(scratch_space ? scratch_space : &source, TRUE); + + { + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + + dest.flush(); + + if (last_shader) + { + last_shader->bind(); + } + else + { + shader->unbind(); + } +} + +void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space) +{ + downsampleDepthBuffer(source, dest, scratch_space); + dest.bindTarget(); + doOcclusion(camera); + dest.flush(); +} + void LLPipeline::doOcclusion(LLCamera& camera) { - if (LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups()) + if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested && + (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) { LLVertexBuffer::unbind(); @@ -2553,6 +2761,17 @@ void LLPipeline::doOcclusion(LLCamera& camera) group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); } + //apply occlusion culling to object cache tree + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLVOCachePartition* vo_part = (*iter)->getVOCachePartition(); + if(vo_part) + { + vo_part->processOccluders(&camera); + } + } + if (bind_shader) { if (LLPipeline::sShadowRender) @@ -2575,19 +2794,18 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) if (update_complete && assertInitialized()) { drawablep->setState(LLDrawable::BUILT); - mGeometryChanges++; } return update_complete; } -static LLFastTimer::DeclareTimer FTM_SEED_VBO_POOLS("Seed VBO Pool"); +static LLTrace::BlockTimerStatHandle FTM_SEED_VBO_POOLS("Seed VBO Pool"); -static LLFastTimer::DeclareTimer FTM_UPDATE_GL("Update GL"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_GL("Update GL"); void LLPipeline::updateGL() { { - LLFastTimer t(FTM_UPDATE_GL); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_GL); while (!LLGLUpdate::sGLQ.empty()) { LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); @@ -2598,12 +2816,12 @@ void LLPipeline::updateGL() } { //seed VBO Pools - LLFastTimer t(FTM_SEED_VBO_POOLS); + LL_RECORD_BLOCK_TIME(FTM_SEED_VBO_POOLS); LLVertexBuffer::seedPools(); } } -static LLFastTimer::DeclareTimer FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups"); void LLPipeline::clearRebuildGroups() { @@ -2663,9 +2881,55 @@ void LLPipeline::clearRebuildGroups() mGroupQ2Locked = false; } +void LLPipeline::clearRebuildDrawables() +{ + // Clear all drawables on the priority build queue, + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); + iter != mBuildQ1.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (drawablep && !drawablep->isDead()) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q2); + drawablep->clearState(LLDrawable::IN_REBUILD_Q1); + } + } + mBuildQ1.clear(); + + // clear drawables on the non-priority build queue + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin(); + iter != mBuildQ2.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (!drawablep->isDead()) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q2); + } + } + mBuildQ2.clear(); + + //clear all moving bridges + for (LLDrawable::drawable_vector_t::iterator iter = mMovedBridge.begin(); + iter != mMovedBridge.end(); ++iter) + { + LLDrawable *drawablep = *iter; + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); + } + mMovedBridge.clear(); + + //clear all moving drawables + for (LLDrawable::drawable_vector_t::iterator iter = mMovedList.begin(); + iter != mMovedList.end(); ++iter) + { + LLDrawable *drawablep = *iter; + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); + } + mMovedList.clear(); +} + void LLPipeline::rebuildPriorityGroups() { - LLFastTimer t(FTM_REBUILD_PRIORITY_GROUPS); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_PRIORITY_GROUPS); LLTimer update_timer; assertInitialized(); @@ -2687,7 +2951,7 @@ void LLPipeline::rebuildPriorityGroups() } -static LLFastTimer::DeclareTimer FTM_REBUILD_GROUPS("Rebuild Groups"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_GROUPS("Rebuild Groups"); void LLPipeline::rebuildGroups() { @@ -2696,7 +2960,7 @@ void LLPipeline::rebuildGroups() return; } - LLFastTimer t(FTM_REBUILD_GROUPS); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_GROUPS); mGroupQ2Locked = true; // Iterate through some drawables on the non-priority build queue S32 size = (S32) mGroupQ2.size(); @@ -2719,7 +2983,7 @@ void LLPipeline::rebuildGroups() { group->rebuildGeom(); - if (group->mSpatialPartition->mRenderByGroup) + if (group->getSpatialPartition()->mRenderByGroup) { count++; } @@ -2740,7 +3004,7 @@ void LLPipeline::updateGeom(F32 max_dtime) LLTimer update_timer; LLPointer<LLDrawable> drawablep; - LLFastTimer t(FTM_GEO_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_GEO_UPDATE); assertInitialized(); @@ -2788,7 +3052,7 @@ void LLPipeline::updateGeom(F32 max_dtime) S32 count = 0; - max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime); + max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, F32SecondsImplicit(max_dtime)); LLSpatialGroup* last_group = NULL; LLSpatialBridge* last_bridge = NULL; @@ -2848,7 +3112,7 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) llassert(vobj); // trying to catch a bad assumption if (vobj) // this test may not be needed, see above { - const LLVOAvatar* av = vobj->asAvatar(); + LLVOAvatar* av = vobj->asAvatar(); if (av && av->isImpostor()) { return; @@ -2872,13 +3136,13 @@ void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) { if (!drawablep) { - //llerrs << "Sending null drawable to moved list!" << llendl; + //LL_ERRS() << "Sending null drawable to moved list!" << LL_ENDL; return; } if (drawablep->isDead()) { - llwarns << "Marking NULL or dead drawable moved!" << llendl; + LL_WARNS() << "Marking NULL or dead drawable moved!" << LL_ENDL; return; } @@ -2933,9 +3197,9 @@ void LLPipeline::markShift(LLDrawable *drawablep) } } -static LLFastTimer::DeclareTimer FTM_SHIFT_DRAWABLE("Shift Drawable"); -static LLFastTimer::DeclareTimer FTM_SHIFT_OCTREE("Shift Octree"); -static LLFastTimer::DeclareTimer FTM_SHIFT_HUD("Shift HUD"); +static LLTrace::BlockTimerStatHandle FTM_SHIFT_DRAWABLE("Shift Drawable"); +static LLTrace::BlockTimerStatHandle FTM_SHIFT_OCTREE("Shift Octree"); +static LLTrace::BlockTimerStatHandle FTM_SHIFT_HUD("Shift HUD"); void LLPipeline::shiftObjects(const LLVector3 &offset) { @@ -2948,7 +3212,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) offseta.load3(offset.mV); { - LLFastTimer t(FTM_SHIFT_DRAWABLE); + LL_RECORD_BLOCK_TIME(FTM_SHIFT_DRAWABLE); for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); iter != mShiftList.end(); iter++) @@ -2966,7 +3230,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) { - LLFastTimer t(FTM_SHIFT_OCTREE); + LL_RECORD_BLOCK_TIME(FTM_SHIFT_OCTREE); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -2983,7 +3247,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) } { - LLFastTimer t(FTM_SHIFT_HUD); + LL_RECORD_BLOCK_TIME(FTM_SHIFT_HUD); LLHUDText::shiftAll(offset); LLHUDNameTag::shiftAll(offset); } @@ -3017,10 +3281,10 @@ void LLPipeline::markPartitionMove(LLDrawable* drawable) } } -static LLFastTimer::DeclareTimer FTM_PROCESS_PARTITIONQ("PartitionQ"); +static LLTrace::BlockTimerStatHandle FTM_PROCESS_PARTITIONQ("PartitionQ"); void LLPipeline::processPartitionQ() { - LLFastTimer t(FTM_PROCESS_PARTITIONQ); + LL_RECORD_BLOCK_TIME(FTM_PROCESS_PARTITIONQ); for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter) { LLDrawable* drawable = *iter; @@ -3042,23 +3306,23 @@ void LLPipeline::markMeshDirty(LLSpatialGroup* group) void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) { - if (group && !group->isDead() && group->mSpatialPartition) + if (group && !group->isDead() && group->getSpatialPartition()) { - if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD) + if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD) { priority = TRUE; } if (priority) { - if (!group->isState(LLSpatialGroup::IN_BUILD_Q1)) + if (!group->hasState(LLSpatialGroup::IN_BUILD_Q1)) { llassert_always(!mGroupQ1Locked); mGroupQ1.push_back(group); group->setState(LLSpatialGroup::IN_BUILD_Q1); - if (group->isState(LLSpatialGroup::IN_BUILD_Q2)) + if (group->hasState(LLSpatialGroup::IN_BUILD_Q2)) { LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group); if (iter != mGroupQ2.end()) @@ -3069,7 +3333,7 @@ void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) } } } - else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) + else if (!group->hasState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) { llassert_always(!mGroupQ2Locked); mGroupQ2.push_back(group); @@ -3108,7 +3372,7 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f } } -static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order"); +static LLTrace::BlockTimerStatHandle FTM_RESET_DRAWORDER("Reset Draw Order"); void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { @@ -3122,11 +3386,11 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) LLPipeline::END_RENDER_TYPES)) { //clear faces from face pools - LLFastTimer t(FTM_RESET_DRAWORDER); + LL_RECORD_BLOCK_TIME(FTM_RESET_DRAWORDER); gPipeline.resetDrawOrders(); } - LLFastTimer ftm(FTM_STATESORT); + LL_RECORD_BLOCK_TIME(FTM_STATESORT); //LLVertexBuffer::unbind(); @@ -3144,7 +3408,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) group->setVisible(); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - markVisible(*i, camera); + markVisible((LLDrawable*)(*i)->getDrawable(), camera); } if (!sDelayVBUpdate) @@ -3210,7 +3474,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } { - LLFastTimer ftm(FTM_STATESORT_DRAWABLE); + LL_RECORD_BLOCK_TIME(FTM_STATESORT_DRAWABLE); for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { @@ -3231,8 +3495,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) { for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawablep = *i; - stateSort(drawablep, camera); + stateSort((LLDrawable*)(*i)->getDrawable(), camera); } if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) @@ -3293,11 +3556,6 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) { drawablep->setVisible(camera, NULL, FALSE); } - else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE)) - { - // clear invisible flag here to avoid single frame glitch - drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE); - } } if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) @@ -3338,7 +3596,6 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } } - mNumVisibleFaces += drawablep->getNumFaces(); } @@ -3351,7 +3608,10 @@ void forAllDrawables(LLCullResult::sg_iterator begin, { for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) { - func(*j); + if((*j)->hasDrawable()) + { + func((LLDrawable*)(*j)->getDrawable()); + } } } } @@ -3544,11 +3804,11 @@ void renderSoundHighlights(LLDrawable* drawablep) void LLPipeline::postSort(LLCamera& camera) { - LLFastTimer ftm(FTM_STATESORT_POSTSORT); + LL_RECORD_BLOCK_TIME(FTM_STATESORT_POSTSORT); assertInitialized(); - llpushcallstacks ; + LL_PUSH_CALLSTACKS(); //rebuild drawable geometry for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) { @@ -3559,27 +3819,27 @@ void LLPipeline::postSort(LLCamera& camera) group->rebuildGeom(); } } - llpushcallstacks ; + LL_PUSH_CALLSTACKS(); //rebuild groups sCull->assertDrawMapsEmpty(); rebuildPriorityGroups(); - llpushcallstacks ; + LL_PUSH_CALLSTACKS(); //build render map for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; - if (sUseOcclusion && - group->isOcclusionState(LLSpatialGroup::OCCLUDED) || + if ((sUseOcclusion && + group->isOcclusionState(LLSpatialGroup::OCCLUDED)) || (RenderAutoHideSurfaceAreaLimit > 0.f && group->mSurfaceArea > RenderAutoHideSurfaceAreaLimit*llmax(group->mObjectBoxSize, 10.f))) { continue; } - if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY)) + if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY)) { //no way this group is going to be drawable without a rebuild group->rebuildGeom(); } @@ -3617,7 +3877,7 @@ void LLPipeline::postSort(LLCamera& camera) if (alpha != group->mDrawMap.end()) { //store alpha groups for sorting - LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) { if (bridge) @@ -3675,7 +3935,7 @@ void LLPipeline::postSort(LLCamera& camera) std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater()); } - llpushcallstacks ; + LL_PUSH_CALLSTACKS(); // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender) { @@ -3728,7 +3988,7 @@ void LLPipeline::postSort(LLCamera& camera) forAllVisibleDrawables(renderSoundHighlights); } } - llpushcallstacks ; + LL_PUSH_CALLSTACKS(); // If managing your telehub, draw beacons at telehub and currently selected spawnpoint. if (LLFloaterTelehub::renderBeacons()) { @@ -3738,7 +3998,9 @@ void LLPipeline::postSort(LLCamera& camera) if (!sShadowRender) { mSelectedFaces.clear(); - + + LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + // Draw face highlights for selected faces. if (LLSelectMgr::getInstance()->getTEMode()) { @@ -3761,41 +4023,14 @@ void LLPipeline::postSort(LLCamera& camera) } } - /*static LLFastTimer::DeclareTimer FTM_TRANSFORM_WAIT("Transform Fence"); - static LLFastTimer::DeclareTimer FTM_TRANSFORM_DO_WORK("Transform Work"); - if (use_transform_feedback) - { //using transform feedback, wait for transform feedback to complete - LLFastTimer t(FTM_TRANSFORM_WAIT); - - S32 done = 0; - //glGetQueryivARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_CURRENT_QUERY, &count); - - glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); - - while (!done) - { - { - LLFastTimer t(FTM_TRANSFORM_DO_WORK); - F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); - //do some useful work while we wait - LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread - LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread - LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread - } - glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); - } - - mTransformFeedbackPrimitives = 0; - }*/ - //LLSpatialGroup::sNoDelete = FALSE; - llpushcallstacks ; + LL_PUSH_CALLSTACKS(); } void render_hud_elements() { - LLFastTimer t(FTM_RENDER_UI); + LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); gPipeline.disableLights(); LLGLDisable fog(GL_FOG); @@ -3961,13 +4196,14 @@ void LLPipeline::renderHighlights() gGL.diffuseColor4f(1,1,1,0.5f); } - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) - { - // Make sure the selection image gets downloaded and decoded - if (!mFaceSelectImagep) + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && !mFaceSelectImagep) { mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP)) + { + // Make sure the selection image gets downloaded and decoded mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); U32 count = mSelectedFaces.size(); @@ -3976,7 +4212,7 @@ void LLPipeline::renderHighlights() LLFace *facep = mSelectedFaces[i]; if (!facep || facep->getDrawable()->isDead()) { - llerrs << "Bad face on selection" << llendl; + LL_ERRS() << "Bad face on selection" << LL_ENDL; return; } @@ -4005,6 +4241,67 @@ void LLPipeline::renderHighlights() { gHighlightProgram.unbind(); } + + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)) + { + color.setVec(1.0f, 0.5f, 0.5f, 0.5f); + if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightNormalProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + LL_ERRS() << "Bad face on selection" << LL_ENDL; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + + if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightNormalProgram.unbind(); + } + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)) + { + color.setVec(0.0f, 0.3f, 1.0f, 0.8f); + if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightSpecularProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + LL_ERRS() << "Bad face on selection" << LL_ENDL; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + + if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightSpecularProgram.unbind(); + } + } } //debug use @@ -4012,7 +4309,7 @@ U32 LLPipeline::sCurRenderPoolType = 0 ; void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { - LLFastTimer t(FTM_RENDER_GEOMETRY); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); assertInitialized(); @@ -4047,7 +4344,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { if (!verify()) { - llerrs << "Pipeline verification failed!" << llendl; + LL_ERRS() << "Pipeline verification failed!" << LL_ENDL; } } @@ -4099,7 +4396,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } { - LLFastTimer t(FTM_POOLS); + LL_RECORD_BLOCK_TIME(FTM_POOLS); // HACK: don't calculate local lights if we're rendering the HUD! // Removing this check will cause bad flickering when there are @@ -4135,7 +4432,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0) { - LLFastTimer t(FTM_POOLRENDER); + LL_RECORD_BLOCK_TIME(FTM_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); @@ -4264,9 +4561,9 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) { LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); - LLFastTimer t(FTM_RENDER_GEOMETRY); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); - LLFastTimer t2(FTM_DEFERRED_POOLS); + LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS); LLGLEnable cull(GL_CULL_FACE); @@ -4308,7 +4605,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) { - LLFastTimer t(FTM_DEFERRED_POOLRENDER); + LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); @@ -4358,9 +4655,9 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) gGL.setColorMask(true, false); } -void LLPipeline::renderGeomPostDeferred(LLCamera& camera) +void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) { - LLFastTimer t(FTM_POST_DEFERRED_POOLS); + LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLS); U32 cur_type = 0; LLGLEnable cull(GL_CULL_FACE); @@ -4373,7 +4670,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) gGL.setColorMask(true, false); pool_set_t::iterator iter1 = mPools.begin(); - BOOL occlude = LLPipeline::sUseOcclusion > 1; + BOOL occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion; while ( iter1 != mPools.end() ) { @@ -4387,14 +4684,14 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); LLGLSLShader::bindNoShader(); - doOcclusion(camera); + doOcclusion(camera, mScreen, mOcclusionDepth, &mDeferredDepth); gGL.setColorMask(true, false); } pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) { - LLFastTimer t(FTM_POST_DEFERRED_POOLRENDER); + LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); @@ -4531,10 +4828,8 @@ void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type) count = index_count/3; } - mTrianglesDrawn += count; - mBatchCount++; - mMaxBatchSize = llmax(mMaxBatchSize, count); - mMinBatchSize = llmin(mMinBatchSize, count); + record(sStatBatchSize, count); + add(LLStatViewer::TRIANGLES_DRAWN, LLUnits::Triangles::fromValue(count)); if (LLPipeline::sRenderFrameTest) { @@ -4583,18 +4878,6 @@ void LLPipeline::renderPhysicsDisplay() } } - for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) - { - LLSpatialBridge* bridge = *i; - if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) - { - gGL.pushMatrix(); - gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); - bridge->renderPhysicsShapes(); - gGL.popMatrix(); - } - } - gGL.flush(); if (LLGLSLShader::sNoFixedFunction) @@ -4605,6 +4888,7 @@ void LLPipeline::renderPhysicsDisplay() mPhysicsDisplay.flush(); } +extern std::set<LLSpatialGroup*> visible_selected_groups; void LLPipeline::renderDebug() { @@ -4630,9 +4914,9 @@ void LLPipeline::renderDebug() if (LLGLSLShader::sNoFixedFunction) { gPathfindingProgram.bind(); - gPathfindingProgram.uniform1f("tint", 1.f); - gPathfindingProgram.uniform1f("ambiance", 1.f); - gPathfindingProgram.uniform1f("alpha_scale", 1.f); + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); } //Requried character physics capsule render parameters @@ -4649,7 +4933,7 @@ void LLPipeline::renderDebug() llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); gGL.setColorMask(true, false); LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f("alpha_scale", 0.90f); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); gPathfindingProgram.bind(); } @@ -4676,9 +4960,9 @@ void LLPipeline::renderDebug() { gPathfindingProgram.bind(); - gPathfindingProgram.uniform1f("tint", 1.f); - gPathfindingProgram.uniform1f("ambiance", ambiance); - gPathfindingProgram.uniform1f("alpha_scale", 1.f); + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); } if ( !pathfindingConsole->isRenderWorld() ) @@ -4702,7 +4986,7 @@ void LLPipeline::renderDebug() if ( pathfindingConsole->isRenderWorld() ) { LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f("alpha_scale", 0.66f); + gPathfindingProgram.uniform1f(sAlphaScale, 0.66f); llPathingLibInstance->renderNavMesh(); } else @@ -4714,8 +4998,8 @@ void LLPipeline::renderDebug() if (LLGLSLShader::sNoFixedFunction) { gPathfindingNoNormalsProgram.bind(); - gPathfindingNoNormalsProgram.uniform1f("tint", 1.f); - gPathfindingNoNormalsProgram.uniform1f("alpha_scale", 1.f); + gPathfindingNoNormalsProgram.uniform1f(sTint, 1.f); + gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, 1.f); llPathingLibInstance->renderNavMeshEdges(); gPathfindingProgram.bind(); } @@ -4755,7 +5039,7 @@ void LLPipeline::renderDebug() gGL.setColorMask(true, false); //render the bookends LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f("alpha_scale", 0.90f); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); gPathfindingProgram.bind(); @@ -4773,7 +5057,7 @@ void LLPipeline::renderDebug() if (LLGLSLShader::sNoFixedFunction) { LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f("alpha_scale", 0.90f); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); } else @@ -4821,7 +5105,7 @@ void LLPipeline::renderDebug() LLGLEnable blend(GL_BLEND); { - gPathfindingProgram.uniform1f("ambiance", ambiance); + gPathfindingProgram.uniform1f(sAmbiance, ambiance); { //draw solid overlay LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_LEQUAL); @@ -4836,8 +5120,8 @@ void LLPipeline::renderDebug() if (pathfindingConsole->isRenderXRay()) { - gPathfindingProgram.uniform1f("tint", gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingProgram.uniform1f("alpha_scale", gSavedSettings.getF32("PathfindingXRayOpacity")); + gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); LLGLEnable blend(GL_BLEND); LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); @@ -4845,13 +5129,13 @@ void LLPipeline::renderDebug() if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) { //draw hidden wireframe as darker and less opaque - gPathfindingProgram.uniform1f("ambiance", 1.f); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); } else { glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - gPathfindingProgram.uniform1f("ambiance", ambiance); + gPathfindingProgram.uniform1f(sAmbiance, ambiance); llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } @@ -4859,9 +5143,9 @@ void LLPipeline::renderDebug() { //draw visible wireframe as brighter, thicker and more opaque glPolygonOffset(offset, offset); - gPathfindingProgram.uniform1f("ambiance", 1.f); - gPathfindingProgram.uniform1f("tint", 1.f); - gPathfindingProgram.uniform1f("alpha_scale", 1.f); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); glLineWidth(gSavedSettings.getF32("PathfindingLineWidth")); LLGLDisable blendOut(GL_BLEND); @@ -4893,19 +5177,19 @@ void LLPipeline::renderDebug() glLineWidth(2.0f); LLGLEnable cull(GL_CULL_FACE); - gPathfindingProgram.uniform1f("tint", gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingProgram.uniform1f("alpha_scale", gSavedSettings.getF32("PathfindingXRayOpacity")); + gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) { //draw hidden wireframe as darker and less opaque glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - gPathfindingProgram.uniform1f("ambiance", 1.f); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); llPathingLibInstance->renderNavMesh(); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); } else { - gPathfindingProgram.uniform1f("ambiance", ambiance); + gPathfindingProgram.uniform1f(sAmbiance, ambiance); llPathingLibInstance->renderNavMesh(); } @@ -4913,8 +5197,8 @@ void LLPipeline::renderDebug() if (LLGLSLShader::sNoFixedFunction) { gPathfindingNoNormalsProgram.bind(); - gPathfindingNoNormalsProgram.uniform1f("tint", gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingNoNormalsProgram.uniform1f("alpha_scale", gSavedSettings.getF32("PathfindingXRayOpacity")); + gPathfindingNoNormalsProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); llPathingLibInstance->renderNavMeshEdges(); gPathfindingProgram.bind(); } @@ -4963,7 +5247,7 @@ void LLPipeline::renderDebug() { DebugBlip& blip = *iter; - blip.mAge += gFrameIntervalSeconds; + blip.mAge += gFrameIntervalSeconds.value(); if (blip.mAge > 2.f) { mDebugBlips.erase(iter++); @@ -4973,7 +5257,7 @@ void LLPipeline::renderDebug() iter++; } - blip.mPosition.mV[2] += gFrameIntervalSeconds*2.f; + blip.mPosition.mV[2] += gFrameIntervalSeconds.value()*2.f; gGL.color4fv(blip.mColor.mV); gGL.vertex3fv(blip.mPosition.mV); @@ -4994,8 +5278,8 @@ void LLPipeline::renderDebug() LLSpatialPartition* part = region->getSpatialPartition(i); if (part) { - if ( hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES) || - !hud_only && hasRenderType(part->mDrawableType) ) + if ( (hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES)) || + (!hud_only && hasRenderType(part->mDrawableType)) ) { part->renderDebug(); } @@ -5015,11 +5299,69 @@ void LLPipeline::renderDebug() } } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && LLGLSLShader::sNoFixedFunction) + { //render visible selected group occlusion geometry + gDebugProgram.bind(); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.diffuseColor3f(1,0,1); + for (std::set<LLSpatialGroup*>::iterator iter = visible_selected_groups.begin(); iter != visible_selected_groups.end(); ++iter) + { + LLSpatialGroup* group = *iter; + + LLVector4a fudge; + fudge.splat(0.25f); //SG_OCCLUSION_FUDGE + + LLVector4a size; + const LLVector4a* bounds = group->getBounds(); + size.setAdd(fudge, bounds[1]); + + drawBox(bounds[0], size); + } + } + + visible_selected_groups.clear(); + if (LLGLSLShader::sNoFixedFunction) { gUIProgram.bind(); } + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only) + { //draw crosshairs on particle intersection + if (gDebugRaycastParticle) + { + if (LLGLSLShader::sNoFixedFunction) + { //this debug display requires shaders + gDebugProgram.bind(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLVector3 center(gDebugRaycastParticleIntersection.getF32ptr()); + LLVector3 size(0.1f, 0.1f, 0.1f); + + LLVector3 p[6]; + + p[0] = center + size.scaledVec(LLVector3(1,0,0)); + p[1] = center + size.scaledVec(LLVector3(-1,0,0)); + p[2] = center + size.scaledVec(LLVector3(0,1,0)); + p[3] = center + size.scaledVec(LLVector3(0,-1,0)); + p[4] = center + size.scaledVec(LLVector3(0,0,1)); + p[5] = center + size.scaledVec(LLVector3(0,0,-1)); + + gGL.begin(LLRender::LINES); + gGL.diffuseColor3f(1.f, 1.f, 0.f); + for (U32 i = 0; i < 6; i++) + { + gGL.vertex3fv(p[i].mV); + } + gGL.end(); + gGL.flush(); + + gDebugProgram.unbind(); + } + } + } + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) { LLVertexBuffer::unbind(); @@ -5053,7 +5395,7 @@ void LLPipeline::renderDebug() if (i > 3) { //render shadow frusta as volumes if (mShadowFrustPoints[i-4].empty()) - { + { continue; } @@ -5215,7 +5557,7 @@ void LLPipeline::renderDebug() continue; } - LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead())) { @@ -5255,11 +5597,11 @@ void LLPipeline::renderDebug() } } -static LLFastTimer::DeclareTimer FTM_REBUILD_POOLS("Rebuild Pools"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_POOLS("Rebuild Pools"); void LLPipeline::rebuildPools() { - LLFastTimer t(FTM_REBUILD_POOLS); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_POOLS); assertInitialized(); @@ -5302,7 +5644,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) if (mSimplePool) { llassert(0); - llwarns << "Ignoring duplicate simple pool." << llendl; + LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; } else { @@ -5310,11 +5652,37 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) } break; + case LLDrawPool::POOL_ALPHA_MASK: + if (mAlphaMaskPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; + break; + } + else + { + mAlphaMaskPool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + if (mFullbrightAlphaMaskPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; + break; + } + else + { + mFullbrightAlphaMaskPool = (LLRenderPass*) new_poolp; + } + break; + case LLDrawPool::POOL_GRASS: if (mGrassPool) { llassert(0); - llwarns << "Ignoring duplicate grass pool." << llendl; + LL_WARNS() << "Ignoring duplicate grass pool." << LL_ENDL; } else { @@ -5326,7 +5694,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) if (mFullbrightPool) { llassert(0); - llwarns << "Ignoring duplicate simple pool." << llendl; + LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; } else { @@ -5338,7 +5706,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) if (mInvisiblePool) { llassert(0); - llwarns << "Ignoring duplicate simple pool." << llendl; + LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; } else { @@ -5350,7 +5718,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) if (mGlowPool) { llassert(0); - llwarns << "Ignoring duplicate glow pool." << llendl; + LL_WARNS() << "Ignoring duplicate glow pool." << LL_ENDL; } else { @@ -5370,23 +5738,33 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) if (mBumpPool) { llassert(0); - llwarns << "Ignoring duplicate bump pool." << llendl; + LL_WARNS() << "Ignoring duplicate bump pool." << LL_ENDL; } else { mBumpPool = new_poolp; } break; - + case LLDrawPool::POOL_MATERIALS: + if (mMaterialsPool) + { + llassert(0); + LL_WARNS() << "Ignorning duplicate materials pool." << LL_ENDL; + } + else + { + mMaterialsPool = new_poolp; + } + break; case LLDrawPool::POOL_ALPHA: if( mAlphaPool ) { llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl; + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << LL_ENDL; } else { - mAlphaPool = new_poolp; + mAlphaPool = (LLDrawPoolAlpha*) new_poolp; } break; @@ -5397,7 +5775,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) if( mSkyPool ) { llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl; + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << LL_ENDL; } else { @@ -5409,7 +5787,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) if( mWaterPool ) { llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl; + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Water pool" << LL_ENDL; } else { @@ -5421,7 +5799,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) if( mGroundPool ) { llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl; + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << LL_ENDL; } else { @@ -5433,7 +5811,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) if( mWLSkyPool ) { llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << llendl; + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << LL_ENDL; } else { @@ -5443,7 +5821,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) default: llassert(0); - llwarns << "Invalid Pool Type in LLPipeline::addPool()" << llendl; + LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL; break; } } @@ -5466,6 +5844,16 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) mSimplePool = NULL; break; + case LLDrawPool::POOL_ALPHA_MASK: + llassert(mAlphaMaskPool == poolp); + mAlphaMaskPool = NULL; + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + llassert(mFullbrightAlphaMaskPool == poolp); + mFullbrightAlphaMaskPool = NULL; + break; + case LLDrawPool::POOL_GRASS: llassert(mGrassPool == poolp); mGrassPool = NULL; @@ -5518,6 +5906,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) mBumpPool = NULL; break; + case LLDrawPool::POOL_MATERIALS: + llassert(poolp == mMaterialsPool); + mMaterialsPool = NULL; + break; + case LLDrawPool::POOL_ALPHA: llassert( poolp == mAlphaPool ); mAlphaPool = NULL; @@ -5543,7 +5936,7 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) default: llassert(0); - llwarns << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl; + LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL; break; } } @@ -5580,6 +5973,13 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) LLLightState* light = gGL.getLight(1); + if (LLPipeline::sRenderDeferred) + { + /*diffuse.mV[0] = powf(diffuse.mV[0], 2.2f); + diffuse.mV[1] = powf(diffuse.mV[1], 2.2f); + diffuse.mV[2] = powf(diffuse.mV[2], 2.2f);*/ + } + mHWLightColors[1] = diffuse; light->setDiffuse(diffuse); @@ -5620,6 +6020,13 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) } backlight_diffuse *= backlight_mag / max_component; + if (LLPipeline::sRenderDeferred) + { + /*backlight_diffuse.mV[0] = powf(backlight_diffuse.mV[0], 2.2f); + backlight_diffuse.mV[1] = powf(backlight_diffuse.mV[1], 2.2f); + backlight_diffuse.mV[2] = powf(backlight_diffuse.mV[2], 2.2f);*/ + } + mHWLightColors[1] = backlight_diffuse; LLLightState* light = gGL.getLight(1); @@ -5779,7 +6186,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) { if (farthest_light->fade >= 0.f) { - farthest_light->fade = -gFrameIntervalSeconds; + farthest_light->fade = -(gFrameIntervalSeconds.value()); } } else @@ -5789,6 +6196,13 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) } } + //mark nearby lights not-removable. + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); iter++) + { + const Light* light = &(*iter); + ((LLViewerOctreeEntryData*) light->drawable)->setVisible(); + } } } @@ -5826,6 +6240,14 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) LLVector4 light_pos(mSunDir, 0.0f); LLColor4 light_diffuse = mSunDiffuse; + + if (LLPipeline::sRenderDeferred) + { + /*light_diffuse.mV[0] = powf(light_diffuse.mV[0], 2.2f); + light_diffuse.mV[1] = powf(light_diffuse.mV[1], 2.2f); + light_diffuse.mV[2] = powf(light_diffuse.mV[2], 2.2f);*/ + } + mHWLightColors[0] = light_diffuse; LLLightState* light = gGL.getLight(0); @@ -5875,12 +6297,12 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) if (fade >= 0.f) { fade = fade / LIGHT_FADE_TIME; - ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds; + ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds.value(); } else { fade = 1.f + fade / LIGHT_FADE_TIME; - ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds; + ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds.value(); } fade = llclamp(fade,0.f,1.f); light_color *= fade; @@ -5904,7 +6326,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) if (sRenderDeferred) { F32 size = light_radius*1.5f; - light_state->setLinearAttenuation(size*size); + light_state->setLinearAttenuation(size); light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f); } else @@ -5917,7 +6339,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) if (light->isLightSpotlight() // directional (spot-)light && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on { - LLVector3 spotparams = light->getSpotLightParams(); LLQuaternion quat = light->getRenderRotation(); LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction at_axis *= quat; @@ -5968,6 +6389,13 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) F32 x = 3.f; float linatten = x / (light_radius); // % of brightness at radius + if (LLPipeline::sRenderDeferred) + { + /*light_color.mV[0] = powf(light_color.mV[0], 2.2f); + light_color.mV[1] = powf(light_color.mV[1], 2.2f); + light_color.mV[2] = powf(light_color.mV[2], 2.2f);*/ + } + mHWLightColors[2] = light_color; LLLightState* light = gGL.getLight(2); @@ -6186,28 +6614,28 @@ void LLPipeline::findReferences(LLDrawable *drawablep) assertInitialized(); if (mLights.find(drawablep) != mLights.end()) { - llinfos << "In mLights" << llendl; + LL_INFOS() << "In mLights" << LL_ENDL; } if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end()) { - llinfos << "In mMovedList" << llendl; + LL_INFOS() << "In mMovedList" << LL_ENDL; } if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end()) { - llinfos << "In mShiftList" << llendl; + LL_INFOS() << "In mShiftList" << LL_ENDL; } if (mRetexturedList.find(drawablep) != mRetexturedList.end()) { - llinfos << "In mRetexturedList" << llendl; + LL_INFOS() << "In mRetexturedList" << LL_ENDL; } if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) { - llinfos << "In mBuildQ1" << llendl; + LL_INFOS() << "In mBuildQ1" << LL_ENDL; } if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end()) { - llinfos << "In mBuildQ2" << llendl; + LL_INFOS() << "In mBuildQ2" << LL_ENDL; } S32 count; @@ -6215,7 +6643,7 @@ void LLPipeline::findReferences(LLDrawable *drawablep) count = gObjectList.findReferences(drawablep); if (count) { - llinfos << "In other drawables: " << count << " references" << llendl; + LL_INFOS() << "In other drawables: " << count << " references" << LL_ENDL; } } @@ -6236,7 +6664,7 @@ BOOL LLPipeline::verify() if (!ok) { - llwarns << "Pipeline verify failed!" << llendl; + LL_WARNS() << "Pipeline verify failed!" << LL_ENDL; } return ok; } @@ -6374,11 +6802,11 @@ void LLPipeline::toggleRenderTypeControl(void* data) U32 bit = (1<<type); if (gPipeline.hasRenderType(type)) { - llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl; + LL_INFOS() << "Toggling render type mask " << std::hex << bit << " off" << std::dec << LL_ENDL; } else { - llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl; + LL_INFOS() << "Toggling render type mask " << std::hex << bit << " on" << std::dec << LL_ENDL; } gPipeline.toggleRenderType(type); } @@ -6404,11 +6832,11 @@ void LLPipeline::toggleRenderDebug(void* data) U32 bit = (U32)(intptr_t)data; if (gPipeline.hasRenderDebugMask(bit)) { - llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl; + LL_INFOS() << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << LL_ENDL; } else { - llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl; + LL_INFOS() << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << LL_ENDL; } gPipeline.mRenderDebugMask ^= bit; } @@ -6448,6 +6876,22 @@ void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value) } } +void LLPipeline::pushRenderDebugFeatureMask() +{ + mRenderDebugFeatureStack.push(mRenderDebugFeatureMask); +} + +void LLPipeline::popRenderDebugFeatureMask() +{ + if (mRenderDebugFeatureStack.empty()) + { + LL_ERRS() << "Depleted render feature stack." << LL_ENDL; + } + + mRenderDebugFeatureMask = mRenderDebugFeatureStack.top(); + mRenderDebugFeatureStack.pop(); +} + // static void LLPipeline::setRenderScriptedBeacons(BOOL val) { @@ -6592,20 +7036,68 @@ BOOL LLPipeline::getRenderHighlights(void*) return sRenderHighlight; } -LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end, +// static +void LLPipeline::setRenderHighlightTextureChannel(LLRender::eTexIndex channel) +{ + sRenderHighlightTextureChannel = channel; +} + +LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, + S32* face_hit) +{ + LLVector4a local_end = end; + + LLVector4a position; + + LLDrawable* drawable = NULL; + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE); + if (part && hasRenderType(part->mDrawableType)) + { + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, face_hit, &position, NULL, NULL, NULL); + if (hit) + { + drawable = hit; + local_end = position; + } + } + } + + LLVOPartGroup* ret = NULL; + if (drawable) + { + //make sure we're returning an LLVOPartGroup + llassert(drawable->getVObj()->getPCode() == LLViewerObject::LL_VO_PART_GROUP); + ret = (LLVOPartGroup*) drawable->getVObj().get(); + } + + if (intersection) + { + *intersection = position; + } + + return ret; +} + +LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, S32* face_hit, - LLVector3* intersection, // return the intersection point + LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point - LLVector3* normal, // return the surface normal at the intersection point - LLVector3* bi_normal // return the surface bi-normal at the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point ) { LLDrawable* drawable = NULL; - LLVector3 local_end = end; + LLVector4a local_end = end; - LLVector3 position; + LLVector4a position; sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE; @@ -6625,7 +7117,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, LLSpatialPartition* part = region->getSpatialPartition(j); if (part && hasRenderType(part->mDrawableType)) { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal); + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, tangent); if (hit) { drawable = hit; @@ -6640,8 +7132,8 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, { //save hit info in case we need to restore //due to attachment override - LLVector3 local_normal; - LLVector3 local_binormal; + LLVector4a local_normal; + LLVector4a local_tangent; LLVector2 local_texcoord; S32 local_face_hit = -1; @@ -6653,14 +7145,22 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, { local_texcoord = *tex_coord; } - if (bi_normal) + if (tangent) { - local_binormal = *bi_normal; + local_tangent = *tangent; + } + else + { + local_tangent.clear(); } if (normal) { local_normal = *normal; } + else + { + local_normal.clear(); + } const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f; @@ -6674,12 +7174,15 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE); if (part && hasRenderType(part->mDrawableType)) { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal); + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, tangent); if (hit) { + LLVector4a delta; + delta.setSub(position, local_end); + if (!drawable || !drawable->getVObj()->isAttachment() || - (position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST) + delta.getLength3().getF32() > ATTACHMENT_OVERRIDE_DIST) { //avatar overrides if previously hit drawable is not an attachment or //attachment is far enough away from detected intersection drawable = hit; @@ -6697,9 +7200,9 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, { *tex_coord = local_texcoord; } - if (bi_normal) + if (tangent) { - *bi_normal = local_binormal; + *tangent = local_tangent; } if (normal) { @@ -6733,13 +7236,13 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, return drawable ? drawable->getVObj().get() : NULL; } -LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end, +LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, S32* face_hit, - LLVector3* intersection, // return the intersection point + LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point - LLVector3* normal, // return the surface normal at the intersection point - LLVector3* bi_normal // return the surface bi-normal at the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point ) { LLDrawable* drawable = NULL; @@ -6759,7 +7262,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, co LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD); if (part) { - LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, bi_normal); + LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, tangent); if (hit) { drawable = hit; @@ -6809,16 +7312,30 @@ void LLPipeline::resetVertexBuffers() mResetVertexBuffers = true; } -static LLFastTimer::DeclareTimer FTM_RESET_VB("Reset VB"); +static LLTrace::BlockTimerStatHandle FTM_RESET_VB("Reset VB"); -void LLPipeline::doResetVertexBuffers() +void LLPipeline::doResetVertexBuffers(bool forced) { if (!mResetVertexBuffers) { return; } + if(!forced && LLSpatialPartition::sTeleportRequested) + { + if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) + { + return; //wait for teleporting to finish + } + else + { + //teleporting aborted + LLSpatialPartition::sTeleportRequested = FALSE; + mResetVertexBuffers = false; + return; + } + } - LLFastTimer t(FTM_RESET_VB); + LL_RECORD_BLOCK_TIME(FTM_RESET_VB); mResetVertexBuffers = false; mCubeVB = NULL; @@ -6836,6 +7353,13 @@ void LLPipeline::doResetVertexBuffers() } } } + if(LLSpatialPartition::sTeleportRequested) + { + LLSpatialPartition::sTeleportRequested = FALSE; + + LLWorld::getInstance()->clearAllVisibleObjects(); + clearRebuildDrawables(); + } resetDrawOrders(); @@ -6858,12 +7382,14 @@ void LLPipeline::doResetVertexBuffers() if (LLVertexBuffer::sGLCount > 0) { - llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl; + LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << LL_ENDL; } LLVertexBuffer::unbind(); - sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); + updateRenderBump(); + updateRenderDeferred(); + sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO"); LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); @@ -6889,6 +7415,17 @@ void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_text gGLLastMatrix = NULL; } +void LLPipeline::renderMaskedObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture) +{ + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + mAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; +} + + void apply_cube_face_rotation(U32 face) { switch (face) @@ -6928,18 +7465,18 @@ void validate_framebuffer_object() break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: // frame buffer not OK: probably means unsupported depth buffer format - llerrs << "Framebuffer Incomplete Missing Attachment." << llendl; + LL_ERRS() << "Framebuffer Incomplete Missing Attachment." << LL_ENDL; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: // frame buffer not OK: probably means unsupported depth buffer format - llerrs << "Framebuffer Incomplete Attachment." << llendl; + LL_ERRS() << "Framebuffer Incomplete Attachment." << LL_ENDL; break; case GL_FRAMEBUFFER_UNSUPPORTED: /* choose different formats */ - llerrs << "Framebuffer unsupported." << llendl; + LL_ERRS() << "Framebuffer unsupported." << LL_ENDL; break; default: - llerrs << "Unknown framebuffer status." << llendl; + LL_ERRS() << "Unknown framebuffer status." << LL_ENDL; break; } } @@ -6949,7 +7486,7 @@ void LLPipeline::bindScreenToTexture() } -static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom"); +static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom"); void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { @@ -6974,7 +7511,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) LLVector2 tc2((F32) mScreen.getWidth()*2, (F32) mScreen.getHeight()*2); - LLFastTimer ftm(FTM_RENDER_BLOOM); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM); gGL.color4f(1,1,1,1); LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); @@ -6996,7 +7533,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { { - LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); mGlow[2].bindTarget(); mGlow[2].clear(); } @@ -7064,7 +7601,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) for (S32 i = 0; i < kernel; i++) { { - LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); mGlow[i%2].bindTarget(); mGlow[i%2].clear(); } @@ -7106,7 +7643,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) /*if (LLRenderTarget::sUseFBO) { - LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); glBindFramebuffer(GL_FRAMEBUFFER, 0); }*/ @@ -7127,7 +7664,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() && - !LLToolMgr::getInstance()->inBuildMode() && + (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && RenderDepthOfField; @@ -7165,18 +7702,27 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { if (LLViewerJoystick::getInstance()->getOverrideCamera()) { //focus on point under cursor - focus_point = gDebugRaycastIntersection; + focus_point.set(gDebugRaycastIntersection.getF32ptr()); } else if (gAgentCamera.cameraMouselook()) { //focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, NULL, - &focus_point); + &result); + + focus_point.set(result.getF32ptr()); } else { //focus on alt-zoom target - focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal()); + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal()-region->getOriginGlobal()); + } } } @@ -7195,7 +7741,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) } else if (transition_time < 1.f) { //currently in a transition, continue interpolating - transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds; + transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds.value(); transition_time = llmin(transition_time, 1.f); F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f; @@ -7332,6 +7878,13 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } + if (!LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2); + } else { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0); + } + shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width-1); @@ -7373,6 +7926,13 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) mScreen.bindTexture(0, channel); } + if (!LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2); + } else { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0); + } + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); gGL.vertex2f(-1,-1); @@ -7583,11 +8143,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) } -static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred"); +static LLTrace::BlockTimerStatHandle FTM_BIND_DEFERRED("Bind Deferred"); void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 noise_map) { - LLFastTimer t(FTM_BIND_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_BIND_DEFERRED); if (noise_map == 0xFFFFFFFF) { @@ -7785,23 +8345,39 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); - if (shader.getUniformLocation("norm_mat") >= 0) + if (shader.getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) { glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose(); - shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m); + shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); } } -static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace"); -static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather"); -static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map"); -static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften"); -static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges"); -static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights"); -static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics"); -static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights"); -static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors"); -static LLFastTimer::DeclareTimer FTM_POST("Post"); +LLColor3 pow3f(LLColor3 v, F32 f) +{ + v.mV[0] = powf(v.mV[0], f); + v.mV[1] = powf(v.mV[1], f); + v.mV[2] = powf(v.mV[2], f); + return v; +} + +LLVector4 pow4fsrgb(LLVector4 v, F32 f) +{ + v.mV[0] = powf(v.mV[0], f); + v.mV[1] = powf(v.mV[1], f); + v.mV[2] = powf(v.mV[2], f); + return v; +} + +static LLTrace::BlockTimerStatHandle FTM_GI_TRACE("Trace"); +static LLTrace::BlockTimerStatHandle FTM_GI_GATHER("Gather"); +static LLTrace::BlockTimerStatHandle FTM_SUN_SHADOW("Shadow Map"); +static LLTrace::BlockTimerStatHandle FTM_SOFTEN_SHADOW("Shadow Soften"); +static LLTrace::BlockTimerStatHandle FTM_EDGE_DETECTION("Find Edges"); +static LLTrace::BlockTimerStatHandle FTM_LOCAL_LIGHTS("Local Lights"); +static LLTrace::BlockTimerStatHandle FTM_ATMOSPHERICS("Atmospherics"); +static LLTrace::BlockTimerStatHandle FTM_FULLSCREEN_LIGHTS("Fullscreen Lights"); +static LLTrace::BlockTimerStatHandle FTM_PROJECTORS("Projectors"); +static LLTrace::BlockTimerStatHandle FTM_POST("Post"); void LLPipeline::renderDeferredLighting() @@ -7812,7 +8388,7 @@ void LLPipeline::renderDeferredLighting() } { - LLFastTimer ftm(FTM_RENDER_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED); LLViewerCamera* camera = LLViewerCamera::getInstance(); { @@ -7845,11 +8421,7 @@ void LLPipeline::renderDeferredLighting() LLStrider<LLVector3> vert; mDeferredVB->getVertexStrider(vert); - LLStrider<LLVector2> tc0; - LLStrider<LLVector2> tc1; - mDeferredVB->getTexCoord0Strider(tc0); - mDeferredVB->getTexCoord1Strider(tc1); - + vert[0].set(-1,1,0); vert[1].set(-1,-3,0); vert[2].set(3,1,0); @@ -7872,7 +8444,7 @@ void LLPipeline::renderDeferredLighting() { mDeferredLight.bindTarget(); { //paint shadow/SSAO light map (direct lighting lightmap) - LLFastTimer ftm(FTM_SUN_SHADOW); + LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW); bindDeferredShader(gDeferredSunProgram, 0); mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); glClearColor(1,1,1,1); @@ -7898,8 +8470,8 @@ void LLPipeline::renderDeferredLighting() } } - gDeferredSunProgram.uniform3fv("offset", slice, offset); - gDeferredSunProgram.uniform2f("screenRes", mDeferredLight.getWidth(), mDeferredLight.getHeight()); + gDeferredSunProgram.uniform3fv(sOffset, slice, offset); + gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight()); { LLGLDisable blend(GL_BLEND); @@ -7916,7 +8488,7 @@ void LLPipeline::renderDeferredLighting() if (RenderDeferredSSAO) { //soften direct lighting lightmap - LLFastTimer ftm(FTM_SOFTEN_SHADOW); + LL_RECORD_BLOCK_TIME(FTM_SOFTEN_SHADOW); //blur lightmap mScreen.bindTarget(); glClearColor(1,1,1,1); @@ -7943,10 +8515,10 @@ void LLPipeline::renderDeferredLighting() x += 1.f; } - gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); - gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); - gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f); + gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor); + gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length/2.f - 0.5f)); { LLGLDisable blend(GL_BLEND); @@ -7963,7 +8535,7 @@ void LLPipeline::renderDeferredLighting() mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); mDeferredLight.bindTarget(); - gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); + gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f); { LLGLDisable blend(GL_BLEND); @@ -7991,8 +8563,8 @@ void LLPipeline::renderDeferredLighting() if (RenderDeferredAtmospheric) { //apply sunlight contribution - LLFastTimer ftm(FTM_ATMOSPHERICS); - bindDeferredShader(gDeferredSoftenProgram); + LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS); + bindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram); { LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); @@ -8014,7 +8586,7 @@ void LLPipeline::renderDeferredLighting() gGL.popMatrix(); } - unbindDeferredShader(gDeferredSoftenProgram); + unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram); } { //render non-deferred geometry (fullbright, alpha, etc) @@ -8030,7 +8602,7 @@ void LLPipeline::renderDeferredLighting() LLPipeline::END_RENDER_TYPES); - renderGeomPostDeferred(*LLViewerCamera::getInstance()); + renderGeomPostDeferred(*LLViewerCamera::getInstance(), false); gPipeline.popRenderTypeMask(); } @@ -8124,9 +8696,13 @@ void LLPipeline::renderDeferredLighting() continue; } - LLFastTimer ftm(FTM_LOCAL_LIGHTS); + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ + + LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS); gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); - gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); @@ -8147,7 +8723,7 @@ void LLPipeline::renderDeferredLighting() glh::vec3f tc(c); mat.mult_matrix_vec(tc); - fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s)); + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s)); light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); } } @@ -8165,7 +8741,7 @@ void LLPipeline::renderDeferredLighting() for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter) { - LLFastTimer ftm(FTM_PROJECTORS); + LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); @@ -8180,9 +8756,12 @@ void LLPipeline::renderDeferredLighting() setupSpotLight(gDeferredSpotLightProgram, drawablep); LLColor3 col = volume->getLightColor(); + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); - gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); @@ -8200,10 +8779,6 @@ void LLPipeline::renderDeferredLighting() vert[2].set(3,1,0); { - bindDeferredShader(gDeferredMultiLightProgram); - - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - LLGLDepthTest depth(GL_FALSE); //full screen blit @@ -8215,7 +8790,7 @@ void LLPipeline::renderDeferredLighting() U32 count = 0; - const U32 max_count = 8; + const U32 max_count = LL_DEFERRED_MULTI_LIGHT_COUNT; LLVector4 light[max_count]; LLVector4 col[max_count]; @@ -8223,29 +8798,35 @@ void LLPipeline::renderDeferredLighting() while (!fullscreen_lights.empty()) { - LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS); + LL_RECORD_BLOCK_TIME(FTM_FULLSCREEN_LIGHTS); light[count] = fullscreen_lights.front(); fullscreen_lights.pop_front(); col[count] = light_colors.front(); light_colors.pop_front(); - far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z); - + /*col[count].mV[0] = powf(col[count].mV[0], 2.2f); + col[count].mV[1] = powf(col[count].mV[1], 2.2f); + col[count].mV[2] = powf(col[count].mV[2], 2.2f);*/ + + far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z); + //col[count] = pow4fsrgb(col[count], 2.2f); count++; if (count == max_count || fullscreen_lights.empty()) { - gDeferredMultiLightProgram.uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count); - gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light); - gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col); - gDeferredMultiLightProgram.uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z); + U32 idx = count-1; + bindDeferredShader(gDeferredMultiLightProgram[idx]); + gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count); + gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light); + gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col); + gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z); far_z = 0.f; count = 0; + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + unbindDeferredShader(gDeferredMultiLightProgram[idx]); } } - unbindDeferredShader(gDeferredMultiLightProgram); - bindDeferredShader(gDeferredMultiSpotLightProgram); gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); @@ -8254,7 +8835,7 @@ void LLPipeline::renderDeferredLighting() for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter) { - LLFastTimer ftm(FTM_PROJECTORS); + LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); @@ -8272,8 +8853,12 @@ void LLPipeline::renderDeferredLighting() LLColor3 col = volume->getLightColor(); + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ + gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); - gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); + gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -8291,6 +8876,65 @@ void LLPipeline::renderDeferredLighting() gGL.setColorMask(true, true); } + mScreen.flush(); + + //gamma correct lighting + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + + { + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + + LLVector2 tc1(0,0); + LLVector2 tc2((F32) mScreen.getWidth()*2, + (F32) mScreen.getHeight()*2); + + mScreen.bindTarget(); + // Apply gamma correction to the frame here. + gDeferredPostGammaCorrectProgram.bind(); + //mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + S32 channel = 0; + channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); + if (channel > -1) + { + mScreen.bindTexture(0,channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mScreen.getWidth(), mScreen.getHeight()); + + F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); + + gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + gGL.getTexUnit(channel)->unbind(mScreen.getUsage()); + gDeferredPostGammaCorrectProgram.unbind(); + mScreen.flush(); + } + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + + mScreen.bindTarget(); + { //render non-deferred geometry (alpha, fullbright, glow) LLGLDisable blend(GL_BLEND); LLGLDisable stencil(GL_STENCIL_TEST); @@ -8315,6 +8959,8 @@ void LLPipeline::renderDeferredLighting() LLPipeline::RENDER_TYPE_PASS_INVISIBLE, LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_ALPHA_MASK, + LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, END_RENDER_TYPES); renderGeomPostDeferred(*LLViewerCamera::getInstance()); @@ -8342,6 +8988,537 @@ void LLPipeline::renderDeferredLighting() } +void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target) +{ + if (!sCull) + { + return; + } + + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED); + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + + { + LLGLDepthTest depth(GL_TRUE); + mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } + + LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } + + //ati doesn't seem to love actually using the stencil buffer on FBO's + LLGLDisable stencil(GL_STENCIL_TEST); + //glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); + //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + gGL.setColorMask(true, true); + + //draw a cube around every light + LLVertexBuffer::unbind(); + + LLGLEnable cull(GL_CULL_FACE); + LLGLEnable blend(GL_BLEND); + + glh::matrix4f mat = glh_copy_matrix(gGLModelView); + + LLStrider<LLVector3> vert; + mDeferredVB->getVertexStrider(vert); + + vert[0].set(-1,1,0); + vert[1].set(-1,-3,0); + vert[2].set(3,1,0); + + { + setupHWLights(NULL); //to set mSunDir; + LLVector4 dir(mSunDir, 0.f); + glh::vec4f tc(dir.mV); + mat.mult_matrix_vec(tc); + mTransformedSunDir.set(tc.v); + } + + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + if (RenderDeferredSSAO || RenderShadowDetail > 0) + { + mDeferredLight.bindTarget(); + { //paint shadow/SSAO light map (direct lighting lightmap) + LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW); + bindDeferredShader(gDeferredSunProgram); + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + glClearColor(1,1,1,1); + mDeferredLight.clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); + + glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose(); + + const U32 slice = 32; + F32 offset[slice*3]; + for (U32 i = 0; i < 4; i++) + { + for (U32 j = 0; j < 8; j++) + { + glh::vec3f v; + v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i); + v.normalize(); + inv_trans.mult_matrix_vec(v); + v.normalize(); + offset[(i*8+j)*3+0] = v.v[0]; + offset[(i*8+j)*3+1] = v.v[2]; + offset[(i*8+j)*3+2] = v.v[1]; + } + } + + gDeferredSunProgram.uniform3fv(LLShaderMgr::DEFERRED_SHADOW_OFFSET, slice, offset); + gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight()); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + stop_glerror(); + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + stop_glerror(); + } + + unbindDeferredShader(gDeferredSunProgram); + } + mDeferredLight.flush(); + } + + stop_glerror(); + gGL.popMatrix(); + stop_glerror(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + stop_glerror(); + gGL.popMatrix(); + stop_glerror(); + + target->bindTarget(); + + //clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky + glClearColor(0,0,0,0); + target->clear(GL_COLOR_BUFFER_BIT); + + if (RenderDeferredAtmospheric) + { //apply sunlight contribution + LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS); + bindDeferredShader(gDeferredSoftenProgram); + { + LLGLDepthTest depth(GL_FALSE); + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + + //full screen blit + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } + + unbindDeferredShader(gDeferredSoftenProgram); + } + + { //render non-deferred geometry (fullbright, alpha, etc) + LLGLDisable blend(GL_BLEND); + LLGLDisable stencil(GL_STENCIL_TEST); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + gPipeline.pushRenderTypeMask(); + + gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_CLOUDS, + LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::END_RENDER_TYPES); + + + renderGeomPostDeferred(*LLViewerCamera::getInstance(), false); + gPipeline.popRenderTypeMask(); + } + + BOOL render_local = RenderLocalLights; + + if (render_local) + { + gGL.setSceneBlendType(LLRender::BT_ADD); + std::list<LLVector4> fullscreen_lights; + LLDrawable::drawable_list_t spot_lights; + LLDrawable::drawable_list_t fullscreen_spot_lights; + + for (U32 i = 0; i < 2; i++) + { + mTargetShadowSpotLight[i] = NULL; + } + + std::list<LLVector4> light_colors; + + LLVertexBuffer::unbind(); + + { + bindDeferredShader(gDeferredLightProgram); + + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) + { + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + if (!volume) + { + continue; + } + + if (volume->isAttachment()) + { + if (!sRenderAttachedLights) + { + continue; + } + } + + + LLVector4a center; + center.load3(drawablep->getPositionAgent().mV); + const F32* c = center.getF32ptr(); + F32 s = volume->getLightRadius()*1.5f; + + LLColor3 col = volume->getLightColor(); + + if (col.magVecSquared() < 0.001f) + { + continue; + } + + if (s <= 0.001f) + { + continue; + } + + LLVector4a sa; + sa.splat(s); + if (camera->AABBInFrustumNoFarClip(center, sa) == 0) + { + continue; + } + + sVisibleLightCount++; + + if (camera->getOrigin().mV[0] > c[0] + s + 0.2f || + camera->getOrigin().mV[0] < c[0] - s - 0.2f || + camera->getOrigin().mV[1] > c[1] + s + 0.2f || + camera->getOrigin().mV[1] < c[1] - s - 0.2f || + camera->getOrigin().mV[2] > c[2] + s + 0.2f || + camera->getOrigin().mV[2] < c[2] - s - 0.2f) + { //draw box if camera is outside box + if (render_local) + { + if (volume->isLightSpotlight()) + { + drawablep->getVOVolume()->updateSpotLightPriority(); + spot_lights.push_back(drawablep); + continue; + } + + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ + + LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS); + gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); + gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gGL.syncMatrices(); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); + stop_glerror(); + } + } + else + { + if (volume->isLightSpotlight()) + { + drawablep->getVOVolume()->updateSpotLightPriority(); + fullscreen_spot_lights.push_back(drawablep); + continue; + } + + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s)); + light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); + } + } + unbindDeferredShader(gDeferredLightProgram); + } + + if (!spot_lights.empty()) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + bindDeferredShader(gDeferredSpotLightProgram); + + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); + + for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter) + { + LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + + LLVector4a center; + center.load3(drawablep->getPositionAgent().mV); + const F32* c = center.getF32ptr(); + F32 s = volume->getLightRadius()*1.5f; + + sVisibleLightCount++; + + setupSpotLight(gDeferredSpotLightProgram, drawablep); + + LLColor3 col = volume->getLightColor(); + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ + + gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); + gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gGL.syncMatrices(); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); + } + gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION); + unbindDeferredShader(gDeferredSpotLightProgram); + } + + //reset mDeferredVB to fullscreen triangle + mDeferredVB->getVertexStrider(vert); + vert[0].set(-1,1,0); + vert[1].set(-1,-3,0); + vert[2].set(3,1,0); + + { + LLGLDepthTest depth(GL_FALSE); + + //full screen blit + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + U32 count = 0; + + const U32 max_count = LL_DEFERRED_MULTI_LIGHT_COUNT; + LLVector4 light[max_count]; + LLVector4 col[max_count]; + + F32 far_z = 0.f; + + while (!fullscreen_lights.empty()) + { + LL_RECORD_BLOCK_TIME(FTM_FULLSCREEN_LIGHTS); + light[count] = fullscreen_lights.front(); + fullscreen_lights.pop_front(); + col[count] = light_colors.front(); + light_colors.pop_front(); + + /*col[count].mV[0] = powf(col[count].mV[0], 2.2f); + col[count].mV[1] = powf(col[count].mV[1], 2.2f); + col[count].mV[2] = powf(col[count].mV[2], 2.2f);*/ + + far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z); + //col[count] = pow4fsrgb(col[count], 2.2f); + count++; + if (count == max_count || fullscreen_lights.empty()) + { + U32 idx = count-1; + bindDeferredShader(gDeferredMultiLightProgram[idx]); + gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count); + gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light); + gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col); + gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z); + far_z = 0.f; + count = 0; + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + } + + unbindDeferredShader(gDeferredMultiLightProgram[0]); + + bindDeferredShader(gDeferredMultiSpotLightProgram); + + gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); + + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter) + { + LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + + LLVector3 center = drawablep->getPositionAgent(); + F32* c = center.mV; + F32 s = volume->getLightRadius()*1.5f; + + sVisibleLightCount++; + + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + + setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); + + LLColor3 col = volume->getLightColor(); + + /*col.mV[0] = powf(col.mV[0], 2.2f); + col.mV[1] = powf(col.mV[1], 2.2f); + col.mV[2] = powf(col.mV[2], 2.2f);*/ + + gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); + gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); + gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); + gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + + gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION); + unbindDeferredShader(gDeferredMultiSpotLightProgram); + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } + } + + gGL.setColorMask(true, true); + } + + /*target->flush(); + + //gamma correct lighting + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + + { + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + + LLVector2 tc1(0,0); + LLVector2 tc2((F32) target->getWidth()*2, + (F32) target->getHeight()*2); + + target->bindTarget(); + // Apply gamma correction to the frame here. + gDeferredPostGammaCorrectProgram.bind(); + //mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + S32 channel = 0; + channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, target->getUsage()); + if (channel > -1) + { + target->bindTexture(0,channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, target->getWidth(), target->getHeight()); + + F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); + + gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + gGL.getTexUnit(channel)->unbind(target->getUsage()); + gDeferredPostGammaCorrectProgram.unbind(); + target->flush(); + } + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + + target->bindTarget();*/ + + { //render non-deferred geometry (alpha, fullbright, glow) + LLGLDisable blend(GL_BLEND); + LLGLDisable stencil(GL_STENCIL_TEST); + + pushRenderTypeMask(); + andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_GLOW, + LLPipeline::RENDER_TYPE_BUMP, + LLPipeline::RENDER_TYPE_PASS_SIMPLE, + LLPipeline::RENDER_TYPE_PASS_ALPHA, + LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_POST_BUMP, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_GLOW, + LLPipeline::RENDER_TYPE_PASS_GRASS, + LLPipeline::RENDER_TYPE_PASS_SHINY, + LLPipeline::RENDER_TYPE_PASS_INVISIBLE, + LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_ALPHA_MASK, + LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, + END_RENDER_TYPES); + + renderGeomPostDeferred(*LLViewerCamera::getInstance()); + popRenderTypeMask(); + } + + //target->flush(); +} + void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) { //construct frustum @@ -8588,6 +9765,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) water_clip = 1; } + bool materials_in_water = false; + +#if MATERIALS_IN_REFLECTIONS + materials_in_water = gSavedSettings.getS32("RenderWaterMaterials"); +#endif + if (!LLViewerCamera::getInstance()->cameraUnderWater()) { //generate planar reflection map @@ -8596,7 +9779,9 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLPipeline::sUseOcclusion = 0; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); glClearColor(0,0,0,0); + mWaterRef.bindTarget(); + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0; gGL.setColorMask(true, true); mWaterRef.clear(); @@ -8645,11 +9830,27 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) updateCull(camera, result); stateSort(camera, result); + if (LLPipeline::sRenderDeferred && materials_in_water) + { + mWaterRef.flush(); + + gPipeline.grabReferences(result); + gPipeline.mDeferredScreen.bindTarget(); + gGL.setColorMask(true, true); + glClearColor(0,0,0,0); + gPipeline.mDeferredScreen.clear(); + + renderGeomDeferred(camera); + } + else + { renderGeom(camera, TRUE); + } gPipeline.popRenderTypeMask(); } + gGL.setColorMask(true, false); gPipeline.pushRenderTypeMask(); clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER, @@ -8687,9 +9888,23 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) { gPipeline.grabReferences(ref_result); LLGLUserClipPlane clip_plane(plane, mat, projection); + + if (LLPipeline::sRenderDeferred && materials_in_water) + { + renderGeomDeferred(camera); + } + else + { renderGeom(camera); } } + } + + if (LLPipeline::sRenderDeferred && materials_in_water) + { + gPipeline.mDeferredScreen.flush(); + renderDeferredLightingToRT(&mWaterRef); + } gPipeline.popRenderTypeMask(); } @@ -8725,10 +9940,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLViewerCamera::updateFrustumPlanes(camera); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLColor4& col = LLDrawPoolWater::sWaterFogColor; glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f); mWaterDis.bindTarget(); LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1; + mWaterDis.getViewport(gGLViewport); if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate) @@ -8744,14 +9961,36 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gGL.setColorMask(true, true); mWaterDis.clear(); + + gGL.setColorMask(true, false); + + if (LLPipeline::sRenderDeferred && materials_in_water) + { + mWaterDis.flush(); + gPipeline.mDeferredScreen.bindTarget(); + gGL.setColorMask(true, true); + glClearColor(0,0,0,0); + gPipeline.mDeferredScreen.clear(); + gPipeline.grabReferences(result); + renderGeomDeferred(camera); + } + else + { renderGeom(camera); + } + if (LLPipeline::sRenderDeferred && materials_in_water) + { + gPipeline.mDeferredScreen.flush(); + renderDeferredLightingToRT(&mWaterDis); + } } - LLPipeline::sUnderWaterRender = FALSE; mWaterDis.flush(); + LLPipeline::sUnderWaterRender = FALSE; + } last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate; @@ -8846,13 +10085,13 @@ glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) return ret; } -static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows"); -static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow"); -static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_RENDER("Render Shadows"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA("Alpha Shadow"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_SIMPLE("Simple Shadow"); void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion, U32 target_width) { - LLFastTimer t(FTM_SHADOW_RENDER); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER); //clip out geometry on the same side of water as the camera S32 occlude = LLPipeline::sUseOcclusion; @@ -8867,19 +10106,36 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP, - LLRenderPass::PASS_FULLBRIGHT_SHINY + LLRenderPass::PASS_FULLBRIGHT_SHINY , + LLRenderPass::PASS_MATERIAL, + LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + LLRenderPass::PASS_SPECMAP, + LLRenderPass::PASS_SPECMAP_EMISSIVE, + LLRenderPass::PASS_NORMMAP, + LLRenderPass::PASS_NORMMAP_EMISSIVE, + LLRenderPass::PASS_NORMSPEC, + LLRenderPass::PASS_NORMSPEC_EMISSIVE, }; LLGLEnable cull(GL_CULL_FACE); + //enable depth clamping if available + LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0); + if (use_shader) { gDeferredShadowCubeProgram.bind(); } + LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID-1]; + + occlusion_target.bindTarget(); updateCull(shadow_cam, result); + occlusion_target.flush(); + stateSort(shadow_cam, result); + //generate shadow map gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); @@ -8910,7 +10166,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gGL.diffuseColor4f(1,1,1,1); gGL.setColorMask(false, false); - LLFastTimer ftm(FTM_SHADOW_SIMPLE); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE); gGL.getTexUnit(0)->disable(); for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) @@ -8936,9 +10192,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera } { - LLFastTimer ftm(FTM_SHADOW_ALPHA); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA); gDeferredShadowAlphaMaskProgram.bind(); - gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f); gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); U32 mask = LLVertexBuffer::MAP_VERTEX | @@ -8946,10 +10201,19 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; - renderObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE); - renderObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE); + renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE); + renderMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE); + gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f); renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE); + + mask = mask & ~LLVertexBuffer::MAP_TEXTURE_INDEX; + gDeferredTreeShadowProgram.bind(); + renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, mask); + renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, mask); + renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, mask); + renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, mask); + gDeferredTreeShadowProgram.setMinimumAlpha(0.598f); renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); } @@ -8959,7 +10223,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gDeferredShadowCubeProgram.bind(); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); - doOcclusion(shadow_cam); + + LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID-1]; + + doOcclusion(shadow_cam, occlusion_source, occlusion_target); if (use_shader) { @@ -8978,10 +10245,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLPipeline::sShadowRender = FALSE; } -static LLFastTimer::DeclareTimer FTM_VISIBLE_CLOUD("Visible Cloud"); +static LLTrace::BlockTimerStatHandle FTM_VISIBLE_CLOUD("Visible Cloud"); BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir) { - LLFastTimer t(FTM_VISIBLE_CLOUD); + LL_RECORD_BLOCK_TIME(FTM_VISIBLE_CLOUD); //get point cloud of intersection of frust and min, max if (getVisibleExtents(camera, min, max)) @@ -9012,7 +10279,7 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2])); //add corners of camera frustum - for (U32 i = 0; i < 8; i++) + for (U32 i = 0; i < LLCamera::AGENT_FRUSTRUM_NUM; i++) { pp.push_back(camera.mAgentFrustum[i]); } @@ -9039,7 +10306,7 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector for (U32 i = 0; i < 12; i++) { //for each line segment in bounding box - for (U32 j = 0; j < 6; j++) + for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; j++) { //for each plane in camera frustum const LLPlane& cp = camera.getAgentPlane(j); const LLVector3& v1 = pp[bs[i*2+0]]; @@ -9081,9 +10348,6 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector 3,7 }; - LLVector3 center = (max+min)*0.5f; - LLVector3 size = (max-min)*0.5f; - for (U32 i = 0; i < 12; i++) { for (U32 j = 0; j < 6; ++j) @@ -9128,19 +10392,19 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector } } - for (U32 j = 0; j < 6; ++j) + for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; ++j) { const LLPlane& cp = camera.getAgentPlane(j); F32 dist = cp.dist(pp[i]); if (dist > 0.05f) //point is above some plane, not contained - { + { found = false; break; - } - } + } + } - if (found) - { + if (found) + { fp.push_back(pp[i]); } } @@ -9187,7 +10451,7 @@ void LLPipeline::generateHighlight(LLCamera& camera) if (!mHighlightSet.empty()) { - F32 transition = gFrameIntervalSeconds/RenderHighlightFadeTime; + F32 transition = gFrameIntervalSeconds.value()/RenderHighlightFadeTime; LLGLDisable test(GL_ALPHA_TEST); LLGLDepthTest depth(GL_FALSE); @@ -9231,7 +10495,7 @@ void LLPipeline::generateHighlight(LLCamera& camera) } -static LLFastTimer::DeclareTimer FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); +static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); void LLPipeline::generateSunShadow(LLCamera& camera) { @@ -9240,7 +10504,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) return; } - LLFastTimer t(FTM_GEN_SUN_SHADOW); + LL_RECORD_BLOCK_TIME(FTM_GEN_SUN_SHADOW); BOOL skip_avatar_update = FALSE; if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson) @@ -9283,6 +10547,22 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, LLPipeline::RENDER_TYPE_PASS_SHINY, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_MATERIAL, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_SPECMAP, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_BLEND, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_MASK, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_NORMMAP, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_BLEND, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_MASK, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE, END_RENDER_TYPES); gGL.setColorMask(false, false); @@ -9309,7 +10589,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]); //currently used for amount to extrude frusta corners for constructing shadow frusta - LLVector3 n = RenderShadowNearDist; + //LLVector3 n = RenderShadowNearDist; //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; //put together a universal "near clip" plane for shadow frusta @@ -9445,7 +10725,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadowFrustPoints[j].clear(); } - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j; + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0+j); //restore render matrices glh_set_current_modelview(saved_view); @@ -9802,7 +11082,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera) { static LLCullResult result[4]; - //LLGLEnable enable(GL_DEPTH_CLAMP_NV); renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, TRUE, target_width); } @@ -9822,12 +11101,14 @@ void LLPipeline::generateSunShadow(LLCamera& camera) if (gen_shadow) { - F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f); + LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat(); + F32 fade_amt = gFrameIntervalSeconds.value() + * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0); //update shadow targets for (U32 i = 0; i < 2; i++) { //for each current shadow - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i; + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW4+i); if (mShadowSpotLight[i].notNull() && (mShadowSpotLight[i] == mTargetShadowSpotLight[0] || @@ -9946,7 +11227,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) static LLCullResult result[2]; - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4; + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4); renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width); @@ -9996,7 +11277,7 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu LLSpatialGroup* group = *i; if (!group->isDead() && (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && - gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) && + gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) && group->mDrawMap.find(type) != group->mDrawMap.end()) { pass->renderGroup(group,type,mask,texture); @@ -10004,11 +11285,11 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu } } -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_MARK_VISIBLE("Impostor Mark Visible"); -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_SETUP("Impostor Setup"); -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_BACKGROUND("Impostor Background"); -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_ALLOCATE("Impostor Allocate"); -static LLFastTimer::DeclareTimer FTM_IMPOSTOR_RESIZE("Impostor Resize"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_MARK_VISIBLE("Impostor Mark Visible"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_SETUP("Impostor Setup"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_BACKGROUND("Impostor Background"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_ALLOCATE("Impostor Allocate"); +static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_RESIZE("Impostor Resize"); void LLPipeline::generateImpostor(LLVOAvatar* avatar) { @@ -10027,46 +11308,54 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) assertInitialized(); - bool muted = avatar->isVisuallyMuted(); + bool visually_muted = avatar->isVisuallyMuted(); pushRenderTypeMask(); - if (muted) + if (visually_muted) { andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); } else { - andRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, - LLPipeline::RENDER_TYPE_AVATAR, + andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_GLOW, LLPipeline::RENDER_TYPE_BUMP, - LLPipeline::RENDER_TYPE_GRASS, - LLPipeline::RENDER_TYPE_SIMPLE, - LLPipeline::RENDER_TYPE_FULLBRIGHT, - LLPipeline::RENDER_TYPE_ALPHA, - LLPipeline::RENDER_TYPE_INVISIBLE, LLPipeline::RENDER_TYPE_PASS_SIMPLE, LLPipeline::RENDER_TYPE_PASS_ALPHA, LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_POST_BUMP, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_GLOW, + LLPipeline::RENDER_TYPE_PASS_GRASS, LLPipeline::RENDER_TYPE_PASS_SHINY, LLPipeline::RENDER_TYPE_PASS_INVISIBLE, LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_ALPHA_MASK, + LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_INVISIBLE, + LLPipeline::RENDER_TYPE_SIMPLE, END_RENDER_TYPES); } S32 occlusion = sUseOcclusion; sUseOcclusion = 0; + sReflectionRender = sRenderDeferred ? FALSE : TRUE; + sShadowRender = TRUE; sImpostorRender = TRUE; LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); { - LLFastTimer t(FTM_IMPOSTOR_MARK_VISIBLE); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_MARK_VISIBLE); markVisible(avatar->mDrawable, *viewer_camera); LLVOAvatar::sUseImpostors = FALSE; @@ -10096,7 +11385,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) U32 resX = 0; { - LLFastTimer t(FTM_IMPOSTOR_SETUP); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_SETUP); const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); @@ -10109,11 +11398,13 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLVector4a left; left.load3(camera.getLeftAxis().mV); left.mul(left); + llassert(left.dot3(left).getF32() > F_APPROXIMATELY_ZERO); left.normalize3fast(); LLVector4a up; up.load3(camera.getUpAxis().mV); up.mul(up); + llassert(up.dot3(up).getF32() > F_APPROXIMATELY_ZERO); up.normalize3fast(); tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); @@ -10151,33 +11442,60 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (!avatar->mImpostor.isComplete()) { - LLFastTimer t(FTM_IMPOSTOR_ALLOCATE); - avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_ALLOCATE); + if (LLPipeline::sRenderDeferred) { + avatar->mImpostor.allocate(resX,resY,GL_SRGB8_ALPHA8,TRUE,FALSE); addDeferredAttachments(avatar->mImpostor); } + else + { + avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + } gGL.getTexUnit(0)->bind(&avatar->mImpostor); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } - else if(resX != avatar->mImpostor.getWidth() || - resY != avatar->mImpostor.getHeight()) + else if(resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight()) { - LLFastTimer t(FTM_IMPOSTOR_RESIZE); - avatar->mImpostor.resize(resX,resY,GL_RGBA); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_RESIZE); + avatar->mImpostor.resize(resX,resY); } avatar->mImpostor.bindTarget(); } + F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; + + if (visually_muted) + { //disable alpha masking for muted avatars (get whole skin silhouette) + LLDrawPoolAvatar::sMinimumAlpha = 0.f; + } + if (LLPipeline::sRenderDeferred) { avatar->mImpostor.clear(); renderGeomDeferred(camera); + + renderGeomPostDeferred(camera); + + // Shameless hack time: render it all again, + // this time writing the depth + // values we need to generate the alpha mask below + // while preserving the alpha-sorted color rendering + // from the previous pass + // + sImpostorRenderAlphaDepthPass = true; + // depth-only here... + // + gGL.setColorMask(false,false); renderGeomPostDeferred(camera); + + sImpostorRenderAlphaDepthPass = false; + } else { @@ -10185,10 +11503,27 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) glScissor(0, 0, resX, resY); avatar->mImpostor.clear(); renderGeom(camera); + + // Shameless hack time: render it all again, + // this time writing the depth + // values we need to generate the alpha mask below + // while preserving the alpha-sorted color rendering + // from the previous pass + // + sImpostorRenderAlphaDepthPass = true; + + // depth-only here... + // + gGL.setColorMask(false,false); + renderGeom(camera); + + sImpostorRenderAlphaDepthPass = false; } - + + LLDrawPoolAvatar::sMinimumAlpha = old_alpha; + { //create alpha mask based on depth buffer (grey out if muted) - LLFastTimer t(FTM_IMPOSTOR_BACKGROUND); + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_BACKGROUND); if (LLPipeline::sRenderDeferred) { GLuint buff = GL_COLOR_ATTACHMENT0; @@ -10197,7 +11532,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLGLDisable blend(GL_BLEND); - if (muted) + if (visually_muted) { gGL.setColorMask(true, true); } @@ -10222,10 +11557,20 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (LLGLSLShader::sNoFixedFunction) { - gUIProgram.bind(); + gDebugProgram.bind(); + } + + + if (LLMuteList::getInstance()->isMuted(avatar->getID())) + { //grey muted avatar + gGL.diffuseColor4ub(64,64,64,255); + } + else + { // Visually muted avatar + gGL.diffuseColor4fv( avatar->getMutedAVColor().mV ); } - gGL.color4ub(64,64,64,255); + { gGL.begin(LLRender::QUADS); gGL.vertex3f(-1, -1, clip_plane); gGL.vertex3f(1, -1, clip_plane); @@ -10233,10 +11578,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) gGL.vertex3f(-1, 1, clip_plane); gGL.end(); gGL.flush(); + } if (LLGLSLShader::sNoFixedFunction) { - gUIProgram.unbind(); + gDebugProgram.unbind(); } gGL.popMatrix(); @@ -10316,7 +11662,7 @@ void LLPipeline::setRenderTypeMask(U32 type, ...) if (type > END_RENDER_TYPES) { - llerrs << "Invalid render type." << llendl; + LL_ERRS() << "Invalid render type." << LL_ENDL; } } @@ -10337,7 +11683,7 @@ BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const if (type > END_RENDER_TYPES) { - llerrs << "Invalid render type." << llendl; + LL_ERRS() << "Invalid render type." << LL_ENDL; } return FALSE; @@ -10354,7 +11700,7 @@ void LLPipeline::popRenderTypeMask() { if (mRenderTypeEnableStack.empty()) { - llerrs << "Depleted render type stack." << llendl; + LL_ERRS() << "Depleted render type stack." << LL_ENDL; } memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled)); @@ -10385,7 +11731,7 @@ void LLPipeline::andRenderTypeMask(U32 type, ...) if (type > END_RENDER_TYPES) { - llerrs << "Invalid render type." << llendl; + LL_ERRS() << "Invalid render type." << LL_ENDL; } for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i) @@ -10410,7 +11756,23 @@ void LLPipeline::clearRenderTypeMask(U32 type, ...) if (type > END_RENDER_TYPES) { - llerrs << "Invalid render type." << llendl; + LL_ERRS() << "Invalid render type." << LL_ENDL; + } +} + +void LLPipeline::setAllRenderTypes() +{ + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = TRUE; + } +} + +void LLPipeline::clearAllRenderTypes() +{ + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = FALSE; } } @@ -10557,6 +11919,3 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id ) } } - - - |