diff options
Diffstat (limited to 'indra')
98 files changed, 3067 insertions, 1950 deletions
diff --git a/indra/llcommon/lldarray.h b/indra/llcommon/lldarray.h index 0e56a11d53..af647c7e7a 100644 --- a/indra/llcommon/lldarray.h +++ b/indra/llcommon/lldarray.h @@ -202,7 +202,7 @@ public: { U32 n = mVector.size(); mIndexMap[k] = n; - mVector.resize(n+1); + mVector.push_back(Type()); llassert(mVector.size() == mIndexMap.size()); return mVector[n]; } diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index 369b06b48a..44ea80a36b 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -51,7 +51,7 @@ public: void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} void skip(const U32 index) { mBytep += mSkip*index;} - + U32 getSkip() const { return mSkip; } Object* get() { return mObjectp; } Object* operator->() { return mObjectp; } Object& operator *() { return *mObjectp; } diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index c1022c1195..4bda00ed86 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -370,6 +370,8 @@ void LLCrashLogger::updateApplication(const std::string& message) bool LLCrashLogger::init() { + LLCurl::initClass(); + // We assume that all the logs we're looking for reside on the current drive gDirUtilp->initAppDirs("SecondLife"); diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 34348230b6..3c3356f41d 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -86,6 +86,8 @@ const F32 SKEW_MAX = 0.95f; const F32 SCULPT_MIN_AREA = 0.002f; const S32 SCULPT_MIN_AREA_DETAIL = 1; +#define GEN_TRI_STRIP 0 + BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) { LLVector3 test = (pt2-pt1)%(pt3-pt2); @@ -1688,7 +1690,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; generate(); - if (mParams.getSculptID().isNull()) + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { createVolumeFaces(); } @@ -1864,6 +1866,11 @@ void LLVolume::createVolumeFaces() LLProfile::Face& face = mProfilep->mFaces[i]; vf.mBeginS = face.mIndex; vf.mNumS = face.mCount; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } + vf.mBeginT = 0; vf.mNumT= getPath().mPath.size(); vf.mID = i; @@ -1907,6 +1914,10 @@ void LLVolume::createVolumeFaces() if (face.mFlat && vf.mNumS > 2) { //flat inner faces have to copy vert normals vf.mNumS = vf.mNumS*2; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } } } else @@ -4521,7 +4532,9 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) if (!partial_build) { +#if GEN_TRI_STRIP mTriStrip.clear(); +#endif S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; for(S32 gx = 0;gx<grid_size;gx++) { @@ -4535,6 +4548,7 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); } +#if GEN_TRI_STRIP if (gy == 0) { mTriStrip.push_back((gx+1)*(grid_size+1)); @@ -4550,6 +4564,7 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) { mTriStrip.push_back(gy+1+gx*(grid_size+1)); } +#endif } else { @@ -4558,6 +4573,7 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); } +#if GEN_TRI_STRIP if (gy == 0) { mTriStrip.push_back(gx*(grid_size+1)); @@ -4572,15 +4588,18 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) { mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1)); } +#endif } } } +#if GEN_TRI_STRIP if (mTriStrip.size()%2 == 1) { mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); } +#endif } return TRUE; @@ -4950,6 +4969,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) mIndices[3*i+v2] = i + 1; } +#if GEN_TRI_STRIP //make tri strip if (mTypeMask & OPEN_MASK) { @@ -4992,6 +5012,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); } } +#endif } return TRUE; @@ -4999,6 +5020,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) void LLVolumeFace::makeTriStrip() { +#if GEN_TRI_STRIP for (U32 i = 0; i < mIndices.size(); i+=3) { U16 i0 = mIndices[i]; @@ -5027,6 +5049,7 @@ void LLVolumeFace::makeTriStrip() { mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); } +#endif } void LLVolumeFace::createBinormals() @@ -5112,12 +5135,6 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) mHasBinormals = FALSE; } - - LLVector3& face_min = mExtents[0]; - LLVector3& face_max = mExtents[1]; - - mCenter.clearVec(); - S32 begin_stex = llfloor( profile[mBeginS].mV[2] ); S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS; @@ -5173,15 +5190,6 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) mVertices[cur_vertex].mNormal = LLVector3(0,0,0); mVertices[cur_vertex].mBinormal = LLVector3(0,0,0); - - if (cur_vertex == 0) - { - face_min = face_max = mesh[i].mPos; - } - else - { - update_min_max(face_min, face_max, mesh[i].mPos); - } cur_vertex++; @@ -5215,12 +5223,22 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) mVertices[cur_vertex].mNormal = LLVector3(0,0,0); mVertices[cur_vertex].mBinormal = LLVector3(0,0,0); - update_min_max(face_min,face_max,mesh[i].mPos); - cur_vertex++; } } + + //get bounding box for this side + LLVector3& face_min = mExtents[0]; + LLVector3& face_max = mExtents[1]; + mCenter.clearVec(); + + face_min = face_max = mVertices[0].mPosition; + for (U32 i = 1; i < mVertices.size(); ++i) + { + update_min_max(face_min, face_max, mVertices[i].mPosition); + } + mCenter = (face_min + face_max) * 0.5f; S32 cur_index = 0; @@ -5229,13 +5247,17 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) if (!partial_build) { +#if GEN_TRI_STRIP mTriStrip.clear(); +#endif // Now we generate the indices. for (t = 0; t < (mNumT-1); t++) { +#if GEN_TRI_STRIP //prepend terminating index to strip mTriStrip.push_back(mNumS*t); +#endif for (s = 0; s < (mNumS-1); s++) { @@ -5246,6 +5268,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) mIndices[cur_index++] = s+1 + mNumS*t; //bottom right mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right +#if GEN_TRI_STRIP if (s == 0) { mTriStrip.push_back(s+mNumS*t); @@ -5253,6 +5276,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) } mTriStrip.push_back(s+1+mNumS*t); mTriStrip.push_back(s+1+mNumS*(t+1)); +#endif mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face if (t < mNumT-2) { //top right/top left neighbor face @@ -5294,44 +5318,37 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) } mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face } +#if GEN_TRI_STRIP //append terminating vertex to strip mTriStrip.push_back(mNumS-1+mNumS*(t+1)); +#endif } +#if GEN_TRI_STRIP if (mTriStrip.size()%2 == 1) { mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); } +#endif } //generate normals for (U32 i = 0; i < mIndices.size()/3; i++) //for each triangle { - const S32 i0 = mIndices[i*3+0]; - const S32 i1 = mIndices[i*3+1]; - const S32 i2 = mIndices[i*3+2]; - const VertexData& v0 = mVertices[i0]; - const VertexData& v1 = mVertices[i1]; - const VertexData& v2 = mVertices[i2]; + const U16* idx = &(mIndices[i*3]); + + VertexData* v[] = + { &mVertices[idx[0]], &mVertices[idx[1]], &mVertices[idx[2]] }; //calculate triangle normal - LLVector3 norm = (v0.mPosition-v1.mPosition) % (v0.mPosition-v2.mPosition); + LLVector3 norm = (v[0]->mPosition-v[1]->mPosition) % (v[0]->mPosition-v[2]->mPosition); - for (U32 j = 0; j < 3; j++) - { //add triangle normal to vertices - const S32 idx = mIndices[i*3+j]; - mVertices[idx].mNormal += norm; // * (weight_sum - d[j])/weight_sum; - } + v[0]->mNormal += norm; + v[1]->mNormal += norm; + v[2]->mNormal += norm; //even out quad contributions - if ((i & 1) == 0) - { - mVertices[i2].mNormal += norm; - } - else - { - mVertices[i1].mNormal += norm; - } + v[i%2+1]->mNormal += norm; } // adjust normals based on wrapping and stitching diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index 5e9dfd81fa..e3ce2c5ad3 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -444,13 +444,13 @@ void LLPumpIO::pump() pump(DEFAULT_POLL_TIMEOUT); } -static LLFastTimer::DeclareTimer FTM_PUMP("Pump"); +static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO"); //timeout is in microseconds void LLPumpIO::pump(const S32& poll_timeout) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); - LLFastTimer t1(FTM_PUMP); + LLFastTimer t1(FTM_PUMP_IO); //llinfos << "LLPumpIO::pump()" << llendl; // Run any pending runners. @@ -778,6 +778,8 @@ bool LLPumpIO::respond( return true; } +static LLFastTimer::DeclareTimer FTM_PUMP_CALLBACK_CHAIN("Chain"); + void LLPumpIO::callback() { LLMemType m1(LLMemType::MTYPE_IO_PUMP); @@ -799,6 +801,7 @@ void LLPumpIO::callback() callbacks_t::iterator end = mCallbacks.end(); for(; it != end; ++it) { + LLFastTimer t(FTM_PUMP_CALLBACK_CHAIN); // it's always the first and last time for respone chains (*it).mHead = (*it).mChainLinks.begin(); (*it).mInit = true; diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 4f828186cb..e67d436887 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -286,6 +286,7 @@ public: void setLightTexture(const LLUUID& id) { mLightTexture = id; } LLUUID getLightTexture() const { return mLightTexture; } + bool isLightSpotlight() const { return mLightTexture.notNull(); } void setParams(const LLVector3& params) { mParams = params; } LLVector3 getParams() const { return mParams; } diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index a3f7a946ec..7ff68fe34b 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -185,6 +185,9 @@ PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = // GL_EXT_framebuffer_blit PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL; +// GL_EXT_blend_func_separate +PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL; + // GL_ARB_draw_buffers PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL; @@ -324,6 +327,7 @@ LLGLManager::LLGLManager() : mHasCompressedTextures(FALSE), mHasFramebufferObject(FALSE), mHasFramebufferMultisample(FALSE), + mHasBlendFuncSeparate(FALSE), mHasVertexBufferObject(FALSE), mHasPBuffer(FALSE), @@ -633,6 +637,11 @@ void LLGLManager::initExtensions() #else mHasDrawBuffers = FALSE; # endif +# if GL_EXT_blend_func_separate + mHasBlendFuncSeparate = TRUE; +#else + mHasBlendFuncSeparate = FALSE; +# endif mHasMipMapGeneration = FALSE; mHasSeparateSpecularColor = FALSE; mHasAnisotropic = FALSE; @@ -659,6 +668,7 @@ void LLGLManager::initExtensions() && ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts); mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); + mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts); #if !LL_DARWIN mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); @@ -682,6 +692,7 @@ void LLGLManager::initExtensions() mHasFramebufferObject = FALSE; mHasFramebufferMultisample = FALSE; mHasDrawBuffers = FALSE; + mHasBlendFuncSeparate = FALSE; mHasMipMapGeneration = FALSE; mHasSeparateSpecularColor = FALSE; mHasAnisotropic = FALSE; @@ -706,6 +717,7 @@ void LLGLManager::initExtensions() mHasShaderObjects = FALSE; mHasVertexShader = FALSE; mHasFragmentShader = FALSE; + mHasBlendFuncSeparate = FALSE; LL_WARNS("RenderInit") << "GL extension support forced to SIMPLE level via LL_GL_BASICEXT" << LL_ENDL; } if (getenv("LL_GL_BLACKLIST")) /* Flawfinder: ignore */ @@ -734,7 +746,8 @@ void LLGLManager::initExtensions() if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE; if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE; - + if (strchr(blacklist,'u')) mHasBlendFuncSeparate = FALSE;//S + } #endif // LL_LINUX || LL_SOLARIS @@ -782,6 +795,14 @@ void LLGLManager::initExtensions() { LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_fragment_shader" << LL_ENDL; } + if (!mHasBlendFuncSeparate) + { + LL_INFOS("RenderInit") << "Couldn't initialize GL_EXT_blend_func_separate" << LL_ENDL; + } + if (!mHasDrawBuffers) + { + LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_draw_buffers" << LL_ENDL; + } // Disable certain things due to known bugs if (mIsIntel && mHasMipMapGeneration) @@ -852,6 +873,10 @@ void LLGLManager::initExtensions() { glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDrawBuffersARB"); } + if (mHasBlendFuncSeparate) + { + glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT"); + } #if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS // This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); @@ -1014,24 +1039,9 @@ void flush_glerror() glGetError(); } -void assert_glerror() +void do_assert_glerror() { - if (!gGLActive) - { - //llwarns << "GL used while not active!" << llendl; - - if (gDebugSession) - { - //ll_fail("GL used while not active"); - } - } - - if (gNoRender || !gDebugGL) - { - return; - } - - if (!gGLManager.mInited) + if (LL_UNLIKELY(!gGLManager.mInited)) { LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL; } @@ -1039,10 +1049,9 @@ void assert_glerror() GLenum error; error = glGetError(); BOOL quit = FALSE; - while (error) + while (LL_UNLIKELY(error)) { quit = TRUE; -#ifndef LL_LINUX // *FIX: ! This should be an error for linux as well. GLubyte const * gl_error_msg = gluErrorString(error); if (NULL != gl_error_msg) { @@ -1066,7 +1075,6 @@ void assert_glerror() } } error = glGetError(); -#endif } if (quit) @@ -1082,6 +1090,25 @@ void assert_glerror() } } +void assert_glerror() +{ + if (!gGLActive) + { + //llwarns << "GL used while not active!" << llendl; + + if (gDebugSession) + { + //ll_fail("GL used while not active"); + } + } + + if (!gNoRender && gDebugGL) + { + do_assert_glerror(); + } +} + + void clear_glerror() { // Create or update texture to be used with this data diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 91421f3c95..0c2da7dd08 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -87,6 +87,7 @@ public: BOOL mHasCompressedTextures; BOOL mHasFramebufferObject; BOOL mHasFramebufferMultisample; + BOOL mHasBlendFuncSeparate; // ARB Extensions BOOL mHasVertexBufferObject; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index f33ae7d8f0..f6d35bc766 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -216,6 +216,9 @@ extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; +//GL_EXT_blend_func_separate +extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; + //GL_EXT_framebuffer_object extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; @@ -249,7 +252,10 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; # include "GL/glh_extensions.h" # undef __APPLE__ -#elif LL_LINUX +#elif LL_LINUX +//---------------------------------------------------------------------------- +// LL_LINUX + //---------------------------------------------------------------------------- // Linux, MESA headers, but not necessarily assuming MESA runtime. // quotes so we get libraries/.../GL/ version @@ -285,6 +291,7 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; # define LL_LINUX_NV_GL_HEADERS 0 #endif // LL_LINUX && defined(WINGDIAPI) + #if LL_LINUX_NV_GL_HEADERS // Missing functions when using nvidia headers: extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; @@ -445,6 +452,9 @@ extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB; extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; +//GL_EXT_blend_func_separate +extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; + //GL_EXT_framebuffer_object extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; @@ -473,7 +483,10 @@ extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; + #elif LL_WINDOWS +//---------------------------------------------------------------------------- +// LL_WINDOWS // windows gl headers depend on things like APIENTRY, so include windows. #define WIN32_LEAN_AND_MEAN @@ -641,6 +654,9 @@ extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB; extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB; extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; +//GL_EXT_blend_func_separate +extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; + //GL_EXT_framebuffer_object extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; @@ -669,6 +685,7 @@ extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; + #elif LL_DARWIN //---------------------------------------------------------------------------- // LL_DARWIN @@ -685,6 +702,9 @@ extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; // Note that they also must not be called on 10.3.9. This should be taken care of by a runtime check for the existence of the GL extension. #include <AvailabilityMacros.h> +//GL_EXT_blend_func_separate +extern void glBlendFuncSeparateEXT(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; + // GL_EXT_framebuffer_object extern GLboolean glIsRenderbufferEXT(GLuint renderbuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; extern void glBindRenderbufferEXT(GLenum target, GLuint renderbuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index ff47c57c70..2f02ccf30b 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1645,7 +1645,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() } } -void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) +void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) { if(!mNeedsAlphaAndPickMask) { @@ -1653,26 +1653,91 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) } U32 length = w * h; - const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset ; + U32 alphatotal = 0; - S32 sample[16]; - memset(sample, 0, sizeof(S32)*16); - - for (U32 i = 0; i < length; i++) + U32 sample[16]; + memset(sample, 0, sizeof(U32)*16); + + // generate histogram of quantized alpha. + // also add-in the histogram of a 2x2 box-sampled version. The idea is + // this will mid-skew the data (and thus increase the chances of not + // being used as a mask) from high-frequency alpha maps which + // suffer the worst from aliasing when used as alpha masks. + if (w >= 2 && h >= 2) + { + llassert(w%2 == 0); + llassert(h%2 == 0); + const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset; + for (U32 y = 0; y < h; y+=2) + { + const GLubyte* current = rowstart; + for (U32 x = 0; x < w; x+=2) + { + const U32 s1 = current[0]; + alphatotal += s1; + const U32 s2 = current[w * mAlphaStride]; + alphatotal += s2; + current += mAlphaStride; + const U32 s3 = current[0]; + alphatotal += s3; + const U32 s4 = current[w * mAlphaStride]; + alphatotal += s4; + current += mAlphaStride; + + ++sample[s1/16]; + ++sample[s2/16]; + ++sample[s3/16]; + ++sample[s4/16]; + + const U32 asum = (s1+s2+s3+s4); + alphatotal += asum; + sample[asum/(16*4)] += 4; + } + + rowstart += 2 * w * mAlphaStride; + } + length *= 2; // we sampled everything twice, essentially + } + else { - ++sample[*current/16]; - current += mAlphaStride ; + const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset; + for (U32 i = 0; i < length; i++) + { + const U32 s1 = *current; + alphatotal += s1; + ++sample[s1/16]; + current += mAlphaStride; + } } + + // if more than 1/16th of alpha samples are mid-range, this + // shouldn't be treated as a 1-bit mask - U32 total = 0; + // also, if all of the alpha samples are clumped on one half + // of the range (but not at an absolute extreme), then consider + // this to be an intentional effect and don't treat as a mask. + + U32 midrangetotal = 0; for (U32 i = 4; i < 11; i++) { - total += sample[i]; + midrangetotal += sample[i]; + } + U32 lowerhalftotal = 0; + for (U32 i = 0; i < 8; i++) + { + lowerhalftotal += sample[i]; + } + U32 upperhalftotal = 0; + for (U32 i = 8; i < 16; i++) + { + upperhalftotal += sample[i]; } - if (total > length/16) + if (midrangetotal > length/16 || // lots of midrange, or + (lowerhalftotal == length && alphatotal != 0) || // all close to transparent but not all totally transparent, or + (upperhalftotal == length && alphatotal != 255*length)) // all close to opaque but not all totally opaque { - mIsMask = FALSE; + mIsMask = FALSE; // not suitable for masking } else { diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 41239d24c8..03939888a5 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -91,7 +91,7 @@ public: protected: virtual ~LLImageGL(); - void analyzeAlpha(const void* data_in, S32 w, S32 h); + void analyzeAlpha(const void* data_in, U32 w, U32 h); void calcAlphaChannelOffsetAndStride(); public: diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index c3540a717c..5597b23c69 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -778,8 +778,10 @@ LLRender::LLRender() mCurrAlphaFunc = CF_DEFAULT; mCurrAlphaFuncVal = 0.01f; - mCurrBlendSFactor = BF_UNDEF; - mCurrBlendDFactor = BF_UNDEF; + mCurrBlendColorSFactor = BF_UNDEF; + mCurrBlendAlphaSFactor = BF_UNDEF; + mCurrBlendColorDFactor = BF_UNDEF; + mCurrBlendAlphaDFactor = BF_UNDEF; } LLRender::~LLRender() @@ -995,15 +997,44 @@ void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor) { llassert(sfactor < BF_UNDEF); llassert(dfactor < BF_UNDEF); - if (mCurrBlendSFactor != sfactor || mCurrBlendDFactor != dfactor) + if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor || + mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor) { - mCurrBlendSFactor = sfactor; - mCurrBlendDFactor = dfactor; + mCurrBlendColorSFactor = sfactor; + mCurrBlendAlphaSFactor = sfactor; + mCurrBlendColorDFactor = dfactor; + mCurrBlendAlphaDFactor = dfactor; flush(); glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]); } } +void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, + eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor) +{ + llassert(color_sfactor < BF_UNDEF); + llassert(color_dfactor < BF_UNDEF); + llassert(alpha_sfactor < BF_UNDEF); + llassert(alpha_dfactor < BF_UNDEF); + if (!gGLManager.mHasBlendFuncSeparate) + { + LL_WARNS_ONCE("render") << "no glBlendFuncSeparateEXT(), using color-only blend func" << llendl; + blendFunc(color_sfactor, color_dfactor); + return; + } + if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor || + mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor) + { + mCurrBlendColorSFactor = color_sfactor; + mCurrBlendAlphaSFactor = alpha_sfactor; + mCurrBlendColorDFactor = color_dfactor; + mCurrBlendAlphaDFactor = alpha_dfactor; + flush(); + glBlendFuncSeparateEXT(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor], + sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]); + } +} + LLTexUnit* LLRender::getTexUnit(U32 index) { if (index < mTexUnits.size()) diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index a90fbd4a5c..f6c87aa1db 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -323,7 +323,11 @@ public: void setAlphaRejectSettings(eCompareFunc func, F32 value = 0.01f); + // applies blend func to both color and alpha void blendFunc(eBlendFactor sfactor, eBlendFactor dfactor); + // applies separate blend functions to color and alpha + void blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, + eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor); LLTexUnit* getTexUnit(U32 index); @@ -362,8 +366,10 @@ private: std::vector<LLTexUnit*> mTexUnits; LLTexUnit* mDummyTexUnit; - eBlendFactor mCurrBlendSFactor; - eBlendFactor mCurrBlendDFactor; + eBlendFactor mCurrBlendColorSFactor; + eBlendFactor mCurrBlendColorDFactor; + eBlendFactor mCurrBlendAlphaSFactor; + eBlendFactor mCurrBlendAlphaDFactor; F32 mMaxAnisotropy; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index bf5eda21eb..ae43915a9d 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -61,6 +61,7 @@ BOOL LLVertexBuffer::sVBOActive = FALSE; BOOL LLVertexBuffer::sIBOActive = FALSE; U32 LLVertexBuffer::sAllocatedBytes = 0; BOOL LLVertexBuffer::sMapped = FALSE; +BOOL LLVertexBuffer::sUseStreamDraw = TRUE; std::vector<U32> LLVertexBuffer::sDeleteList; @@ -381,6 +382,11 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : { mUsage = 0 ; } + + if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw) + { + mUsage = 0; + } S32 stride = calcStride(typemask, mOffsets); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index b785a22976..e2fecdffef 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -83,6 +83,8 @@ public: static LLVBOPool sDynamicVBOPool; static LLVBOPool sStreamIBOPool; static LLVBOPool sDynamicIBOPool; + + static BOOL sUseStreamDraw; static void initClass(bool use_vbo); static void cleanupClass(); diff --git a/indra/newview/app_settings/high_graphics.xml b/indra/newview/app_settings/high_graphics.xml index 6368f7099e..587b2f2a89 100644 --- a/indra/newview/app_settings/high_graphics.xml +++ b/indra/newview/app_settings/high_graphics.xml @@ -12,8 +12,6 @@ <RenderFlexTimeFactor value="1"/> <!--256... but they don't use this--> <RenderGlowResolutionPow value="9"/> - <!--Sun/Moon only--> - <RenderLightingDetail value="1"/> <!--Low number--> <RenderMaxPartCount value="4096"/> <!--bump okay--> @@ -31,9 +29,14 @@ <!--Default for now--> <RenderVolumeLODFactor value="1.125"/> <!--NO SHADERS--> - <RenderWaterReflections value="FALSE"/> - <!--NO SHADERS--> <VertexShaderEnable value="TRUE"/> <!--NO SHADERS--> <WindLightUseAtmosShaders value="TRUE"/> + <!--Deferred Shading--> + <RenderDeferred value="FALSE"/> + <!--SSAO Disabled--> + <RenderDeferredSSAO value="FALSE"/> + <!--Sun Shadows--> + <RenderShadowDetail value="0"/> + </settings> diff --git a/indra/newview/app_settings/low_graphics.xml b/indra/newview/app_settings/low_graphics.xml index 3f67a70d7a..a300c8646c 100644 --- a/indra/newview/app_settings/low_graphics.xml +++ b/indra/newview/app_settings/low_graphics.xml @@ -12,8 +12,6 @@ <RenderFlexTimeFactor value="0.5"/> <!--256... but they don't use this--> <RenderGlowResolutionPow value="8"/> - <!--Sun/Moon only--> - <RenderLightingDetail value="0"/> <!--Low number--> <RenderMaxPartCount value="1024"/> <!--bump okay--> @@ -31,9 +29,14 @@ <!--Default for now--> <RenderVolumeLODFactor value="1.125"/> <!--NO SHADERS--> - <RenderWaterReflections value="FALSE"/> - <!--NO SHADERS--> <VertexShaderEnable value="FALSE"/> <!--NO SHADERS--> <WindLightUseAtmosShaders value="FALSE"/> + <!--No Deferred Shading--> + <RenderDeferred value="FALSE"/> + <!--SSAO Disabled--> + <RenderDeferredSSAO value="FALSE"/> + <!--No Shadows--> + <RenderShadowDetail value="0"/> + </settings> diff --git a/indra/newview/app_settings/mid_graphics.xml b/indra/newview/app_settings/mid_graphics.xml index 12da77da40..a1430a58f9 100644 --- a/indra/newview/app_settings/mid_graphics.xml +++ b/indra/newview/app_settings/mid_graphics.xml @@ -12,8 +12,6 @@ <RenderFlexTimeFactor value="1"/> <!--256... but they don't use this--> <RenderGlowResolutionPow value="8"/> - <!--Sun/Moon only--> - <RenderLightingDetail value="1"/> <!--Low number--> <RenderMaxPartCount value="2048"/> <!--bump okay--> @@ -31,9 +29,14 @@ <!--Default for now--> <RenderVolumeLODFactor value="1.125"/> <!--NO SHADERS--> - <RenderWaterReflections value="FALSE"/> - <!--NO SHADERS--> <VertexShaderEnable value="TRUE"/> <!--NO SHADERS--> <WindLightUseAtmosShaders value="FALSE"/> + <!--No Deferred Shading--> + <RenderDeferred value="FALSE"/> + <!--SSAO Disabled--> + <RenderDeferredSSAO value="FALSE"/> + <!--No Shadows--> + <RenderShadowDetail value="0"/> + </settings> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4e4c0274e7..56d8719e46 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6241,7 +6241,7 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <integer>60</integer> + <integer>200</integer> </map> <key>RenderSSAOFactor</key> <map> @@ -6616,6 +6616,52 @@ <real>0.01</real> </map> + <key>RenderShadowBiasError</key> + <map> + <key>Comment</key> + <string>Error scale for shadow bias (based on altitude).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0</real> + </map> + <key>RenderShadowOffsetError</key> + <map> + <key>Comment</key> + <string>Error scale for shadow offset (based on altitude).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0</real> + </map> + + <key>RenderSpotShadowBias</key> + <map> + <key>Comment</key> + <string>Bias value for shadows (prevent shadow acne).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.0</real> + </map> + <key>RenderSpotShadowOffset</key> + <map> + <key>Comment</key> + <string>Offset value for shadows (prevent shadow acne).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.04</real> + </map> + <key>RenderShadowResolutionScale</key> <map> <key>Comment</key> @@ -6628,8 +6674,6 @@ <real>1.0</real> </map> - - <key>RenderDeferredTreeShadowBias</key> <map> <key>Comment</key> @@ -6751,7 +6795,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>1</real> + <real>8</real> </map> <key>RenderDeferred</key> @@ -6765,19 +6809,7 @@ <key>Value</key> <integer>0</integer> </map> - - <key>RenderDeferredShadow</key> - <map> - <key>Comment</key> - <string>Enable shadows in deferred renderer.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - + <key>RenderDeferredGI</key> <map> <key>Comment</key> @@ -6790,10 +6822,10 @@ <integer>0</integer> </map> - <key>RenderDeferredSunShadow</key> + <key>RenderDeferredSun</key> <map> <key>Comment</key> - <string>Generate shadows from the sun.</string> + <string>Execute sunlight shader in deferred renderer.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6802,10 +6834,10 @@ <integer>1</integer> </map> - <key>RenderDeferredSun</key> + <key>RenderDeferredAtmospheric</key> <map> <key>Comment</key> - <string>Execute sunlight shader in deferred renderer.</string> + <string>Execute atmospheric shader in deferred renderer.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6814,10 +6846,10 @@ <integer>1</integer> </map> - <key>RenderDeferredAtmospheric</key> + <key>RenderDeferredSSAO</key> <map> <key>Comment</key> - <string>Execute atmospheric shader in deferred renderer.</string> + <string>Execute screen space ambient occlusion shader in deferred renderer.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7076,10 +7108,10 @@ <key>Value</key> <real>256.0</real> </map> - <key>RenderFastAlpha</key> + <key>RenderAutoMaskAlphaNonDeferred</key> <map> <key>Comment</key> - <string>Use lossy alpha rendering optimization (opaque/nonexistent small alpha faces).</string> + <string>Use alpha masks where appropriate, in the non-deferred (non-'Lighting and Shadows') graphics mode</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7087,6 +7119,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>RenderAutoMaskAlphaDeferred</key> + <map> + <key>Comment</key> + <string>Use alpha masks where appropriate, in the deferred ('Lighting and Shadows') graphics mode</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>RenderFastUI</key> <map> <key>Comment</key> @@ -7348,17 +7391,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderLightingDetail</key> - <map> - <key>Comment</key> - <string>Amount of detail for lighting objects/avatars/terrain (0=sun/moon only, 1=enable local lights)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>1</integer> - </map> <key>RenderMaxPartCount</key> <map> <key>Comment</key> @@ -7458,7 +7490,19 @@ <key>Value</key> <integer>2</integer> </map> - <key>RenderReflectionRes</key> + <key>RenderShadowDetail</key> + <map> + <key>Comment</key> + <string>Detail of shadows.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>2</integer> + </map> + + <key>RenderReflectionRes</key> <map> <key>Comment</key> <string>Reflection map resolution.</string> @@ -7588,7 +7632,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>RenderUIBuffer</key> <map> @@ -7689,6 +7733,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderUseStreamVBO</key> + <map> + <key>Comment</key> + <string>Use VBO's for stream buffers</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>RenderVolumeLODFactor</key> <map> <key>Comment</key> @@ -7733,17 +7788,6 @@ <key>Value</key> <integer>512</integer> </map> - <key>RenderWaterReflections</key> - <map> - <key>Comment</key> - <string>Reflect the environment in the water.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>RotateRight</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index 4fb109d687..fea2e16090 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -24,8 +24,6 @@ varying vec3 vary_fragcoord; varying vec3 vary_position; varying vec3 vary_light; -uniform float alpha_soften; - uniform mat4 inv_proj; vec4 getPosition(vec2 pos_screen) @@ -57,15 +55,6 @@ void main() color.rgb = scaleSoftClip(color.rgb); - if (samp_pos.z != 0.0 && gl_Color.a < 1.0) - { - float dist_factor = alpha_soften; - float a = gl_Color.a; - a *= a; - dist_factor *= 1.0/(1.0-a); - color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); - } - //gl_FragColor = gl_Color; gl_FragColor = color; //gl_FragColor = vec4(1,0,1,1); diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 1a7d58b07b..04e556c11a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -9,7 +9,7 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -41,23 +41,22 @@ void main() calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col; - col.a = gl_Color.a; - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - col.rgb = scaleUpLight(col.rgb); + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + vary_light = gl_LightSource[0].position.xyz; vary_ambient = col.rgb*gl_Color.rgb; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index c1988d3c78..650fbcc3f5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -10,7 +10,7 @@ mat4 getSkinnedTransform(); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -47,23 +47,22 @@ void main() calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col; - col.a = gl_Color.a; - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - col.rgb = scaleUpLight(col.rgb); + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + vary_ambient = col.rgb*gl_Color.rgb; vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 75df388941..afbe08a579 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -20,6 +20,7 @@ void main() gl_FragData[0] = vec4(diff.rgb, 0.0); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl index 00083eb6b3..085ffddeec 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -10,7 +10,7 @@ uniform sampler2D diffuseMap; void main() { - gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a); - //gl_FragColor = vec4(1,1,1,1); + //gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a); + gl_FragColor = vec4(1,1,1,1); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index bd5e9dd758..d1c5d7cb19 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -10,13 +10,11 @@ uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; uniform sampler2DRect lightMap; -uniform sampler2DRect giLightMap; uniform float dist_factor; uniform float blur_size; uniform vec2 delta; -uniform vec3 kern[32]; -uniform int kern_length; +uniform vec3 kern[4]; uniform float kern_scale; varying vec2 vary_fragcoord; @@ -39,7 +37,8 @@ vec4 getPosition(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm vec3 pos = getPosition(vary_fragcoord.xy).xyz; vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; @@ -50,7 +49,7 @@ void main() vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' vec4 col = defined_weight.xyxx * ccol; - for (int i = 1; i < kern_length; i++) + for (int i = 1; i < 4; i++) { vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; vec3 samppos = getPosition(tc).xyz; @@ -61,12 +60,22 @@ void main() defined_weight += kern[i].xy; } } + for (int i = 1; i < 4; i++) + { + vec2 tc = vary_fragcoord.xy - kern[i].z*dlt; + vec3 samppos = getPosition(tc).xyz; + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + if (d*d <= 0.003) + { + col += texture2DRect(lightMap, tc)*kern[i].xyxx; + defined_weight += kern[i].xy; + } + } col /= defined_weight.xyxx; gl_FragColor = col; - - //gl_FragColor = ccol; } + diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 1c29dae5f7..2197744a37 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -14,14 +14,16 @@ varying vec3 vary_mat2; void main() { - vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + vec3 col = gl_Color.rgb * texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; vec3 norm = texture2D(bumpMap, gl_TexCoord[0].xy).rgb * 2.0 - 1.0; vec3 tnorm = vec3(dot(norm,vary_mat0), - dot(norm,vary_mat1), - dot(norm,vary_mat2)); + dot(norm,vary_mat1), + dot(norm,vary_mat2)); - gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); - gl_FragData[1] = vec4(col*gl_Color.a, gl_Color.a); - gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0); + gl_FragData[0] = vec4(col, 0.0); + gl_FragData[1] = gl_Color.aaaa; // spec + //gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested + vec3 nvn = normalize(tnorm); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 5895ebda84..3803119cda 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -11,8 +11,10 @@ varying vec3 vary_normal; void main() { - vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; - gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); - gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 col = gl_Color.rgb * texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + gl_FragData[0] = vec4(col, 0.0); + gl_FragData[1] = gl_Color.aaaa; // spec + //gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index e518bddb98..0db9586a88 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -23,8 +23,6 @@ varying vec4 vary_position; varying vec3 vary_normal; varying vec3 vary_fragcoord; -uniform float alpha_soften; - uniform mat4 inv_proj; vec4 getPosition(vec2 pos_screen) @@ -56,15 +54,6 @@ void main() color.rgb = fullbrightScaleSoftClip(color.rgb); - if (samp_pos.z != 0.0 && color.a < 1.0) - { - float dist_factor = alpha_soften; - float a = color.a; - a *= a; - dist_factor *= 1.0/(1.0-a); - color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); - } - //gl_FragColor = gl_Color; gl_FragColor = color; //gl_FragColor = vec4(1,0,1,1); diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl index b351eec6e5..d4b153c4af 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl @@ -159,7 +159,8 @@ void main() { vec2 pos_screen = vary_fragcoord.xy; vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm gl_FragData[0].xyz = giAmbient(pos, norm); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index 8c140a7b4f..508bbf415e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -11,7 +11,8 @@ uniform sampler2D specularMap; void main() { - gl_FragData[0] = texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[0] = vec4(col.rgb, col.a <= 0.5 ? 0.0 : 0.005); gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy); gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 797b9e9f3b..b494b521ca 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -53,7 +53,9 @@ void main() discard; } - vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz*2.0-1.0); + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + norm = normalize(norm); vec4 spec = texture2DRect(specularRect, frag.xy); vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; float noise = texture2D(noiseMap, frag.xy/128.0).b; diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 28bcd720c0..82e9450e68 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -5,9 +5,10 @@ * $License$ */ - #version 120 +//class 1 -- no shadows + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect diffuseRect; @@ -26,12 +27,15 @@ uniform vec3 proj_n; uniform float proj_focus; //distance from plane to begin blurring uniform float proj_lod; //(number of mips in proj map) uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; uniform float proj_ambiance; uniform float near_clip; uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; +uniform int proj_shadow_idx; +uniform float shadow_fade; varying vec4 vary_light; @@ -40,6 +44,52 @@ uniform vec2 screen_res; uniform mat4 inv_proj; +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + + float det = min(lod/(proj_lod*0.5), 1.0); + + float d = min(dist.x, dist.y); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).a; @@ -68,7 +118,7 @@ void main() { discard; } - + vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; norm = normalize(norm); @@ -83,7 +133,11 @@ void main() proj_tc.xyz /= proj_tc.w; float fa = gl_Color.a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + if (dist_atten <= 0.0) + { + discard; + } lv = proj_origin-pos.xyz; lv = normalize(lv); @@ -101,32 +155,32 @@ void main() proj_tc.y > 0.0) { float lit = 0.0; + float amb_da = proj_ambiance; + if (da > 0.0) { float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; lit = da * dist_atten * noise; col = lcol*lit*diff_tex; + amb_da += (da*0.5)*proj_ambiance; } - float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); - float amb_da = proj_ambiance; - + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; } @@ -144,35 +198,28 @@ void main() { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); if (stc.z > 0.0) { - stc.xy /= stc.z+proj_near; - + stc.xy /= stc.w; + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb; } } } } - /*if (spec.a > 0.0) - { - //vec3 ref = reflect(normalize(pos), norm); - float sa = dot(normalize(lv-normalize(pos)),norm);; - //sa = max(sa, 0.0); - //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*lcol*spec.rgb; - }*/ - gl_FragColor.rgb = col; gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 78256e20cc..3aecbc5f23 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -55,7 +55,8 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm float da = dot(norm, lv); if (da < 0.0) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl index 9612aee405..bd554c2d84 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl @@ -38,10 +38,10 @@ vec4 getPosition(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm vec3 pos = getPosition(vary_fragcoord.xy).xyz; - vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; vec2 dlt = kern_scale * delta/(1.0+norm.xy*norm.xy); dlt /= max(-pos.z*dist_factor, 1.0); @@ -51,9 +51,10 @@ void main() for (int i = 0; i < kern_length; i++) { vec2 tc = vary_fragcoord.xy + kern[i].y*dlt; - vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0; + vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz; + sampNorm = vec3((sampNorm.xy-0.5)*2.0,sampNorm.z); // unpack norm - float d = dot(norm.xyz, sampNorm); + float d = dot(norm.xyz, sampNorm); if (d > 0.8) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index b4b0d0ce9d..bef91e735d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -11,6 +11,7 @@ uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; uniform sampler2DRect depthMap; uniform sampler2D noiseMap; uniform samplerCube environmentMap; @@ -40,7 +41,7 @@ uniform float scene_light_strength; uniform vec3 env_mat[3]; //uniform mat4 shadow_matrix[3]; //uniform vec4 shadow_clip; -//uniform mat3 ssao_effect_mat; +uniform mat3 ssao_effect_mat; varying vec4 vary_light; varying vec2 vary_fragcoord; @@ -55,9 +56,8 @@ vec3 vary_AtmosAttenuation; uniform mat4 inv_proj; uniform vec2 screen_res; -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; +vec4 getPosition_d(vec2 pos_screen, float depth) +{ vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -68,6 +68,12 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + return getPosition_d(pos_screen, depth); +} + vec3 getPositionEye() { return vary_PositionEye; @@ -178,7 +184,17 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { temp2.x += .25; //increase ambient when there are more clouds - vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; + + /* decrease value and saturation (that in HSV, not HSL) for occluded areas + * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); //haze color setAdditiveColor( @@ -241,8 +257,10 @@ vec3 scaleSoftClip(vec3 light) void main() { vec2 tc = vary_fragcoord.xy; - vec3 pos = getPosition(tc).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; + float depth = texture2DRect(depthMap, tc.xy).a; + vec3 pos = getPosition_d(tc, depth).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; float da = max(dot(norm.xyz, vary_light.xyz), 0.0); @@ -250,23 +268,76 @@ void main() vec4 diffuse = texture2DRect(diffuseRect, tc); vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - calcAtmospherics(pos.xyz, 0.0); + vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + float scol = max(scol_ambocc.r, diffuse.a); + float ambocc = scol_ambocc.g; + + calcAtmospherics(pos.xyz, ambocc); vec3 col = atmosAmbient(vec3(0)); - col += atmosAffectDirectionalLight(clamp(da, diffuse.a, 1.0)); + col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); col *= diffuse.rgb; - if (spec.a > 0.0) + if (spec.a > 0.0) // specular reflection { - vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + // the old infinite-sky shiny reflection + // + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + + /* + // screen-space cheap fakey reflection map + // + vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); + depth -= 0.5; // unbias depth + // first figure out where we'll make our 2D guess from + vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. + float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 + float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); + ref2d += vec2(checkoffset, checkoffset); + ref2d += tc.xy; // use as offset from destination + // Get attributes from the 2D guess point. + // We average two samples of diffuse (not of anything else) per + // pixel to try to reduce aliasing some more. + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + + texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); + float refdepth = texture2DRect(depthMap, ref2d).a; + vec3 refpos = getPosition_d(ref2d, refdepth).xyz; + vec3 refn = texture2DRect(normalMap, ref2d).rgb; + refn = normalize(vec3((refn.xy-0.5)*2.0,refn.z)); // unpack norm + // figure out how appropriate our guess actually was + float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); + // darken reflections from points which face away from the reflected ray - our guess was a back-face + //refapprop *= step(dot(refnorm, refn), 0.0); + refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant + // get appropriate light strength for guess-point. + // reflect light direction to increase the illusion that + // these are reflections. + vec3 reflight = reflect(lightnorm.xyz, norm.xyz); + float reflit = max(dot(refn, reflight.xyz), 0.0); + // apply sun color to guess-point, dampen according to inappropriateness of guess + float refmod = min(refapprop, reflit); + vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; + vec3 ssshiny = (refprod * spec.a); + ssshiny *= 0.3; // dampen it even more + */ + vec3 ssshiny = vec3(0,0,0); + + // add the two types of shiny together + col += (ssshiny + dumbshiny) * spec.rgb; } col = atmosLighting(col); col = scaleSoftClip(col); - + gl_FragColor.rgb = col; gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 2a7234fd83..1b95b253c3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -68,7 +68,8 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm norm = normalize(norm); float l_dist = -dot(lv, proj_n); @@ -161,17 +162,6 @@ void main() } } - /*if (spec.a > 0.0) - { - //vec3 ref = reflect(normalize(pos), norm); - float sa = dot(normalize(lv-normalize(pos)),norm);; - //sa = max(sa, 0.0); - //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*lcol*spec.rgb; - }*/ - gl_FragColor.rgb = col; gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index 22bdd2c7f3..56e4055c02 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -5,196 +5,11 @@ * $License$ */ -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2DRectShadow shadowMap4; -uniform sampler2DRectShadow shadowMap5; -uniform sampler2D noiseMap; - -uniform sampler2D lightFunc; - - -// Inputs -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; -uniform float ssao_radius; -uniform float ssao_max_radius; -uniform float ssao_factor; -uniform float ssao_factor_inv; - -varying vec2 vary_fragcoord; -varying vec4 vary_light; - -uniform mat4 inv_proj; -uniform vec2 screen_res; - -uniform float shadow_bias; -uniform float shadow_offset; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +//class 1, no shadow, no SSAO, should never be called -//calculate decreases in ambient lighting when crowded out (SSAO) -float calcAmbientOcclusion(vec4 pos, vec3 norm) -{ - vec2 kern[8]; - // exponentially (^2) distant occlusion samples spread around origin - kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; - kern[1] = vec2(1.0, 0.0) * 0.250*0.250; - kern[2] = vec2(0.0, 1.0) * 0.375*0.375; - kern[3] = vec2(0.0, -1.0) * 0.500*0.500; - kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; - kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; - kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; - kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - - vec2 pos_screen = vary_fragcoord.xy; - vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; - - float angle_hidden = 0.0; - int points = 0; - - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - - // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) - for (int i = 0; i < 8; i++) - { - vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; - - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); - - // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area - // --> solid angle shrinking by the square of distance - //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 - //(k should vary inversely with # of samples, but this is taken care of later) - - //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces - // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor) - angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); - - // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" - points = points + int(diff.z > -1.0); - } - - angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - - return (1.0 - (float(points != 0) * angle_hidden)); -} +#extension GL_ARB_texture_rectangle : enable void main() { - vec2 pos_screen = vary_fragcoord.xy; - - //try doing an unproject here - - vec4 pos = getPosition(pos_screen); - - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; - - /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL - { - gl_FragColor = vec4(0.0); // doesn't matter - return; - }*/ - - float shadow = 1.0; - float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); - - vec4 spos = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0); - - //vec3 debug = vec3(0,0,0); - - if (dp_directional_light == 0.0) - { - // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup - shadow = 0.0; - } - else if (spos.z > -shadow_clip.w) - { - vec4 lpos; - - if (spos.z < -shadow_clip.z) - { - lpos = shadow_matrix[3]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap3, lpos).x; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - else if (spos.z < -shadow_clip.y) - { - lpos = shadow_matrix[2]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap2, lpos).x; - } - else if (spos.z < -shadow_clip.x) - { - lpos = shadow_matrix[1]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap1, lpos).x; - } - else - { - lpos = shadow_matrix[0]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap0, lpos).x; - } - - // take the most-shadowed value out of these two: - // * the blurred sun shadow in the light (shadow) map - // * an unblurred dot product between the sun and this norm - // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting - shadow = min(shadow, dp_directional_light); - - /*debug.r = lpos.y / (lpos.w*screen_res.y); - - lpos.xy /= lpos.w*32.0; - if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) - { - debug.gb = vec2(0.5, 0.5); - } - - debug += (1.0-shadow)*0.5;*/ - - } - else - { - // more distant than the shadow map covers - just use directional shading as shadow - shadow = dp_directional_light; - } - - gl_FragColor[0] = shadow; - gl_FragColor[1] = calcAmbientOcclusion(pos, norm); - - //spotlight shadow 1 - vec4 lpos = shadow_matrix[4]*spos; - lpos.xy *= screen_res; - gl_FragColor[2] = shadow2DRectProj(shadowMap4, lpos).x; - - //spotlight shadow 2 - lpos = shadow_matrix[5]*spos; - lpos.xy *= screen_res; - gl_FragColor[3] = shadow2DRectProj(shadowMap5, lpos).x; - - //gl_FragColor.rgb = pos.xyz; - //gl_FragColor.b = shadow; - //gl_FragColor.rgb = debug; + gl_FragColor = vec4(0,0,0,0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl new file mode 100644 index 0000000000..cdbed4b791 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -0,0 +1,124 @@ +/** + * @file sunLightSSAOF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +//class 1 -- no shadow, SSAO only + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2D noiseMap; + +uniform sampler2D lightFunc; + + +// Inputs +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform float ssao_radius; +uniform float ssao_max_radius; +uniform float ssao_factor; +uniform float ssao_factor_inv; + +varying vec2 vary_fragcoord; +varying vec4 vary_light; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +uniform float shadow_bias; +uniform float shadow_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +//calculate decreases in ambient lighting when crowded out (SSAO) +float calcAmbientOcclusion(vec4 pos, vec3 norm) +{ + float ret = 1.0; + + float dist = dot(pos.xyz,pos.xyz); + + if (dist < 64.0*64.0) + { + vec2 kern[8]; + // exponentially (^2) distant occlusion samples spread around origin + kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; + kern[1] = vec2(1.0, 0.0) * 0.250*0.250; + kern[2] = vec2(0.0, 1.0) * 0.375*0.375; + kern[3] = vec2(0.0, -1.0) * 0.500*0.500; + kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; + kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; + kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; + kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; + + vec2 pos_screen = vary_fragcoord.xy; + vec3 pos_world = pos.xyz; + vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; + + float angle_hidden = 0.0; + int points = 0; + + float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; + + vec3 diff = pos_world - samppos_world; + float dist2 = dot(diff, diff); + + // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area + // --> solid angle shrinking by the square of distance + //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 + //(k should vary inversely with # of samples, but this is taken care of later) + + //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces + // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor) + angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); + + // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" + points = points + int(diff.z > -1.0); + } + + angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); + + ret = (1.0 - (float(points != 0) * angle_hidden)); + ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); + } + + return min(ret, 1.0); +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + + //try doing an unproject here + + vec4 pos = getPosition(pos_screen); + + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + + gl_FragColor[0] = 1.0; + gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + gl_FragColor[2] = 1.0; + gl_FragColor[3] = 1.0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 3cccfb7202..fa0a60c98d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -29,6 +29,7 @@ void main() gl_FragData[0] = vec4(outColor.rgb, 0.0); gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 258acee08c..5b33ea5bfe 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -14,5 +14,6 @@ void main() vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index d21575119d..361ae8dc84 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -115,7 +115,7 @@ void main() vec4 fb = texture2D(screenTex, distort2); //mix with reflection - // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug + // Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999); float shadow = 1.0; @@ -131,11 +131,11 @@ void main() //color.rgb = scaleSoftClip(color.rgb); //color.a = spec * sunAngle2; - //wavef.z = -0.25f; - wavef = normalize(wavef); - wavef = (norm_mat*vec4(wavef, 1.0)).xyz; + //wavef.z *= 0.1f; + //wavef = normalize(wavef); + vec3 screenspacewavef = (norm_mat*vec4(wavef, 1.0)).xyz; - gl_FragData[0] = vec4(color.rgb, 0.75); - gl_FragData[1] = vec4(1,1,1, 0.8); - gl_FragData[2] = vec4(wavef*0.5+0.5, 0.0); + gl_FragData[0] = vec4(color.rgb, 0.5); // diffuse + gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec + gl_FragData[2] = vec4(screenspacewavef.xy*0.5+0.5, screenspacewavef.z, screenspacewavef.z*0.5); // normalxyz, displace } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index 3e8fdfb3e4..da49e59b89 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -12,7 +12,8 @@ float calcDirectionalLight(vec3 n, vec3 l) return a; } -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la) + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight) { //get light vector vec3 lv = lp.xyz-v; @@ -26,9 +27,13 @@ float calcPointLight(vec3 v, vec3 n, vec4 lp, float la) //distance attenuation float da = clamp(1.0/(la * d), 0.0, 1.0); + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + //angular attenuation da *= calcDirectionalLight(n, lv); - + return da; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index ad16de6d81..665fe16b43 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -29,8 +29,6 @@ varying vec3 vary_fragcoord; varying vec3 vary_position; varying vec3 vary_light; -uniform float alpha_soften; - uniform float shadow_bias; uniform mat4 inv_proj; @@ -115,15 +113,6 @@ void main() color.rgb = scaleSoftClip(color.rgb); - if (samp_pos.z != 0.0 && gl_Color.a < 1.0) - { - float dist_factor = alpha_soften; - float a = gl_Color.a; - a *= a; - dist_factor *= 1.0/(1.0-a); - color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); - } - //gl_FragColor = gl_Color; gl_FragColor = color; //gl_FragColor = vec4(1,0,1,1)*shadow; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 5991e1f3b5..1fae8c4da3 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -9,7 +9,7 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -42,23 +42,21 @@ void main() calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col; - col.a = gl_Color.a; - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - col.rgb = scaleUpLight(col.rgb); + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + vary_light = gl_LightSource[0].position.xyz; vary_ambient = col.rgb*gl_Color.rgb; diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index a939499b17..f8dd1b7431 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -10,7 +10,7 @@ mat4 getSkinnedTransform(); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -53,23 +53,22 @@ void main() calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col; - col.a = gl_Color.a; - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - col.rgb = scaleUpLight(col.rgb); + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + vary_ambient = col.rgb*gl_Color.rgb; vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl index 0fad5b4b50..d1c5d7cb19 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl @@ -37,7 +37,8 @@ vec4 getPosition(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm vec3 pos = getPosition(vary_fragcoord.xy).xyz; vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl index 02beddd43b..e32e9f4b32 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl @@ -31,7 +31,8 @@ float getDepth(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm float depth = getDepth(vary_fragcoord.xy); vec2 tc = vary_fragcoord.xy; @@ -46,8 +47,12 @@ void main() de = step(depth_cutoff, de); vec2 ne; - ne.x = dot(texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb*2.0-1.0, norm); - ne.y = dot(texture2DRect(normalMap, tc+vec2(sc,sc)).rgb*2.0-1.0, norm); + vec3 nexnorm = texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb; + nexnorm = vec3((nexnorm.xy-0.5)*2.0,nexnorm.z); // unpack norm + ne.x = dot(nexnorm, norm); + vec3 neynorm = texture2DRect(normalMap, tc+vec2(sc,sc)).rgb; + neynorm = vec3((neynorm.xy-0.5)*2.0,neynorm.z); // unpack norm + ne.y = dot(neynorm, norm); ne = 1.0-ne; diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 651959413c..22ffb58c63 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -43,6 +43,52 @@ uniform vec2 screen_res; uniform mat4 inv_proj; +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + + float det = min(lod/(proj_lod*0.5), 1.0); + + float d = min(dist.x, dist.y); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).a; @@ -83,7 +129,8 @@ void main() shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm norm = normalize(norm); float l_dist = -dot(lv, proj_n); @@ -126,7 +173,7 @@ void main() float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; @@ -137,7 +184,7 @@ void main() } //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); amb_da += (da*da*0.5+0.5)*proj_ambiance; @@ -167,22 +214,23 @@ void main() if (stc.z > 0.0) { stc.xy /= stc.w; - + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; } } } } - //attenuate point light contribution by SSAO component - col *= texture2DRect(lightMap, frag.xy).g; - gl_FragColor.rgb = col; gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 531f7376a3..fd6ae2b960 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -11,6 +11,7 @@ uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect normalMap; uniform sampler2DRect lightMap; +uniform sampler2DRect depthMap; uniform sampler2D noiseMap; uniform samplerCube environmentMap; uniform sampler2D lightFunc; @@ -41,7 +42,6 @@ uniform vec3 env_mat[3]; uniform vec4 shadow_clip; uniform mat3 ssao_effect_mat; -uniform sampler2DRect depthMap; uniform mat4 inv_proj; uniform vec2 screen_res; @@ -55,9 +55,8 @@ vec3 vary_AmblitColor; vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; +vec4 getPosition_d(vec2 pos_screen, float depth) +{ vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -68,6 +67,12 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + return getPosition_d(pos_screen, depth); +} + vec3 getPositionEye() { return vary_PositionEye; @@ -251,8 +256,10 @@ vec3 scaleSoftClip(vec3 light) void main() { vec2 tc = vary_fragcoord.xy; - vec3 pos = getPosition(tc).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; + float depth = texture2DRect(depthMap, tc.xy).a; + vec3 pos = getPosition_d(tc, depth).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; float da = max(dot(norm.xyz, vary_light.xyz), 0.0); @@ -271,24 +278,67 @@ void main() col *= diffuse.rgb; - if (spec.a > 0.0) + if (spec.a > 0.0) // specular reflection { - vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + // the old infinite-sky shiny reflection + // + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + + /* + // screen-space cheap fakey reflection map + // + vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); + depth -= 0.5; // unbias depth + // first figure out where we'll make our 2D guess from + vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. + float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 + float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); + ref2d += vec2(checkoffset, checkoffset); + ref2d += tc.xy; // use as offset from destination + // Get attributes from the 2D guess point. + // We average two samples of diffuse (not of anything else) per + // pixel to try to reduce aliasing some more. + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + + texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); + float refdepth = texture2DRect(depthMap, ref2d).a; + vec3 refpos = getPosition_d(ref2d, refdepth).xyz; + float refshad = texture2DRect(lightMap, ref2d).r; + vec3 refn = texture2DRect(normalMap, ref2d).rgb; + refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm + refn = normalize(refn); + // figure out how appropriate our guess actually was + float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); + // darken reflections from points which face away from the reflected ray - our guess was a back-face + //refapprop *= step(dot(refnorm, refn), 0.0); + refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant + // get appropriate light strength for guess-point + // reflect light direction to increase the illusion that + // these are reflections. + vec3 reflight = reflect(lightnorm.xyz, norm.xyz); + float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad); + // apply sun color to guess-point, dampen according to inappropriateness of guess + float refmod = min(refapprop, reflit); + vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; + vec3 ssshiny = (refprod * spec.a); + ssshiny *= 0.3; // dampen it even more + */ + vec3 ssshiny = vec3(0,0,0); + + // add the two types of shiny together + col += (ssshiny + dumbshiny) * spec.rgb; } col = atmosLighting(col); col = scaleSoftClip(col); gl_FragColor.rgb = col; - - //gl_FragColor.rgb = gi_col.rgb; gl_FragColor.a = 0.0; - - //gl_FragColor.rg = scol_ambocc.rg; - //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; - //gl_FragColor.rgb = norm.rgb*0.5+0.5; - //gl_FragColor.rgb = vec3(ambocc); - //gl_FragColor.rgb = vec3(scol); } diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index d6534083cf..8a90199b7c 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -82,7 +82,8 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm norm = normalize(norm); float l_dist = -dot(lv, proj_n); @@ -179,21 +180,6 @@ void main() } } - /*if (spec.a > 0.0) - { - //vec3 ref = reflect(normalize(pos), norm); - float sa = dot(normalize(lv-normalize(pos)),norm);; - //sa = max(sa, 0.0); - //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*lcol*spec.rgb; - }*/ - - //attenuate point light contribution by SSAO component - col *= texture2DRect(lightMap, frag.xy).g; - - gl_FragColor.rgb = col; gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index a0026edcd2..7423347346 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -7,6 +7,8 @@ #extension GL_ARB_texture_rectangle : enable +//class 2, shadows, no SSAO + uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; uniform sampler2DRectShadow shadowMap0; @@ -39,6 +41,9 @@ uniform vec2 proj_shadow_res; uniform float shadow_bias; uniform float shadow_offset; +uniform float spot_shadow_bias; +uniform float spot_shadow_offset; + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).a; @@ -52,56 +57,6 @@ vec4 getPosition(vec2 pos_screen) return pos; } -//calculate decreases in ambient lighting when crowded out (SSAO) -float calcAmbientOcclusion(vec4 pos, vec3 norm) -{ - vec2 kern[8]; - // exponentially (^2) distant occlusion samples spread around origin - kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; - kern[1] = vec2(1.0, 0.0) * 0.250*0.250; - kern[2] = vec2(0.0, 1.0) * 0.375*0.375; - kern[3] = vec2(0.0, -1.0) * 0.500*0.500; - kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; - kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; - kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; - kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - - vec2 pos_screen = vary_fragcoord.xy; - vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; - - float angle_hidden = 0.0; - int points = 0; - - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - - // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) - for (int i = 0; i < 8; i++) - { - vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; - - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); - - // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area - // --> solid angle shrinking by the square of distance - //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 - //(k should vary inversely with # of samples, but this is taken care of later) - - //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces - // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor) - angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); - - // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" - points = points + int(diff.z > -1.0); - } - - angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - - return (1.0 - (float(points != 0) * angle_hidden)); -} - float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; @@ -123,7 +78,7 @@ float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; - stc.z += shadow_bias*scl; + stc.z += spot_shadow_bias*scl; float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; @@ -134,8 +89,7 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); - - + return shadow/5.0; //return shadow; @@ -149,7 +103,10 @@ void main() vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + vec4 nmap4 = texture2DRect(normalMap, pos_screen); + nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm + float displace = nmap4.w; + vec3 norm = nmap4.xyz; /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { @@ -158,9 +115,12 @@ void main() }*/ float shadow = 1.0; - float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); - vec4 spos = vec4(pos.xyz + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0); + vec3 shadow_pos = pos.xyz + displace*norm; + vec3 offset = vary_light.xyz * (1.0-dp_directional_light); + + vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0); if (spos.z > -shadow_clip.w) { @@ -220,15 +180,17 @@ void main() } gl_FragColor[0] = shadow; - gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + gl_FragColor[1] = 1.0; + + spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0); //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.1).x; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.1).x; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); //gl_FragColor.rgb = pos.xyz; //gl_FragColor.b = shadow; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl new file mode 100644 index 0000000000..4e33a1af45 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -0,0 +1,257 @@ +/** + * @file sunLightSSAOF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +//class 2 -- shadows and SSAO + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap4; +uniform sampler2DShadow shadowMap5; +uniform sampler2D noiseMap; + +uniform sampler2D lightFunc; + +// Inputs +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform float ssao_radius; +uniform float ssao_max_radius; +uniform float ssao_factor; +uniform float ssao_factor_inv; + +varying vec2 vary_fragcoord; +varying vec4 vary_light; + +uniform mat4 inv_proj; +uniform vec2 screen_res; +uniform vec2 shadow_res; +uniform vec2 proj_shadow_res; + +uniform float shadow_bias; +uniform float shadow_offset; + +uniform float spot_shadow_bias; +uniform float spot_shadow_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +//calculate decreases in ambient lighting when crowded out (SSAO) +float calcAmbientOcclusion(vec4 pos, vec3 norm) +{ + float ret = 1.0; + + float dist = dot(pos.xyz,pos.xyz); + + if (dist < 64.0*64.0) + { + vec2 kern[8]; + // exponentially (^2) distant occlusion samples spread around origin + kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; + kern[1] = vec2(1.0, 0.0) * 0.250*0.250; + kern[2] = vec2(0.0, 1.0) * 0.375*0.375; + kern[3] = vec2(0.0, -1.0) * 0.500*0.500; + kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; + kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; + kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; + kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; + + vec2 pos_screen = vary_fragcoord.xy; + vec3 pos_world = pos.xyz; + vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; + + float angle_hidden = 0.0; + int points = 0; + + float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; + + vec3 diff = pos_world - samppos_world; + float dist2 = dot(diff, diff); + + // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area + // --> solid angle shrinking by the square of distance + //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 + //(k should vary inversely with # of samples, but this is taken care of later) + + //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces + // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor) + angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); + + // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" + points = points + int(diff.z > -1.0); + } + + angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); + + ret = (1.0 - (float(points != 0) * angle_hidden)); + ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); + } + + return min(ret, 1.0); +} + +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias*scl; + + float cs = shadow2DRect(shadowMap, stc.xyz).x; + float shadow = cs; + + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); + + return shadow/5.0; + + //return shadow; +} + +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += spot_shadow_bias*scl; + + float cs = shadow2D(shadowMap, stc.xyz).x; + float shadow = cs; + + vec2 off = 1.5/proj_shadow_res; + + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); + + + return shadow/5.0; + + //return shadow; +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + + //try doing an unproject here + + vec4 pos = getPosition(pos_screen); + + vec4 nmap4 = texture2DRect(normalMap, pos_screen); + nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm + float displace = nmap4.w; + vec3 norm = nmap4.xyz; + + /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL + { + gl_FragColor = vec4(0.0); // doesn't matter + return; + }*/ + + float shadow = 1.0; + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + + vec3 shadow_pos = pos.xyz + displace*norm; + vec3 offset = vary_light.xyz * (1.0-dp_directional_light); + + vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0); + + if (spos.z > -shadow_clip.w) + { + if (dp_directional_light == 0.0) + { + // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup + shadow = 0.0; + } + else + { + vec4 lpos; + + if (spos.z < -shadow_clip.z) + { + lpos = shadow_matrix[3]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap3, lpos, 0.25); + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (spos.z < -shadow_clip.y) + { + lpos = shadow_matrix[2]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap2, lpos, 0.5); + } + else if (spos.z < -shadow_clip.x) + { + lpos = shadow_matrix[1]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap1, lpos, 0.75); + } + else + { + lpos = shadow_matrix[0]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap0, lpos, 1.0); + } + + // take the most-shadowed value out of these two: + // * the blurred sun shadow in the light (shadow) map + // * an unblurred dot product between the sun and this norm + // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting + shadow = min(shadow, dp_directional_light); + + //lpos.xy /= lpos.w*32.0; + //if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) + //{ + // shadow = 0.0; + //} + + } + } + else + { + // more distant than the shadow map covers + shadow = 1.0; + } + + gl_FragColor[0] = shadow; + gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + + spos.xyz = shadow_pos+offset*spot_shadow_offset; + + //spotlight shadow 1 + vec4 lpos = shadow_matrix[4]*spos; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); + + //spotlight shadow 2 + lpos = shadow_matrix[5]*spos; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); + + //gl_FragColor.rgb = pos.xyz; + //gl_FragColor.b = shadow; +} diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl index f4c59734a4..19800d96dc 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl @@ -6,7 +6,7 @@ */ float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -18,9 +18,10 @@ vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[1].diffuse.rgb * calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); + + col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); col.rgb = scaleDownLight(col.rgb); // Add windlight lights diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl index 7325825d6d..66606233cd 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl @@ -44,7 +44,8 @@ float getDepth(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm float depth = getDepth(vary_fragcoord.xy); vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; @@ -56,9 +57,10 @@ void main() for (int i = 0; i < kern_length; i++) { vec2 tc = vary_fragcoord.xy + kern[i].y*dlt; - vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0; - - float d = dot(norm.xyz, sampNorm); + vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz; + sampNorm = vec3((sampNorm.xy-0.5)*2.0,sampNorm.z); // unpack norm + + float d = dot(norm.xyz, sampNorm); if (d > 0.5) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl index 939710cb56..1b8354dbd1 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl @@ -178,7 +178,8 @@ void main() float rad = gi_range*0.5; - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm float dist = max(length(pos.xyz)-rad, 0.0); float da = clamp(1.0-dist/rad, 0.0, 1.0); diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 96a083b522..c88edd0a60 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -56,9 +56,8 @@ vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; uniform float gi_ambiance; -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; +vec4 getPosition_d(vec2 pos_screen, float depth) +{ vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -69,6 +68,12 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + return getPosition_d(pos_screen, depth); +} + vec3 getPositionEye() { return vary_PositionEye; @@ -252,8 +257,10 @@ vec3 scaleSoftClip(vec3 light) void main() { vec2 tc = vary_fragcoord.xy; - vec3 pos = getPosition(tc).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; + float depth = texture2DRect(depthMap, tc.xy).a; + vec3 pos = getPosition_d(tc, depth).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; float da = max(dot(norm.xyz, vary_light.xyz), 0.0); @@ -274,11 +281,63 @@ void main() col *= diffuse.rgb; - if (spec.a > 0.0) + if (spec.a > 0.0) // specular reflection { - vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + // the old infinite-sky shiny reflection + // + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a; + + /* + // screen-space cheap fakey reflection map + // + vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); + depth -= 0.5; // unbias depth + // first figure out where we'll make our 2D guess from + vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. + float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 + float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); + + ref2d += vec2(checkoffset, checkoffset); + ref2d += tc.xy; // use as offset from destination + // Get attributes from the 2D guess point. + // We average two samples of diffuse (not of anything else) per + // pixel to try to reduce aliasing some more. + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + + texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); + float refdepth = texture2DRect(depthMap, ref2d).a; + vec3 refpos = getPosition_d(ref2d, refdepth).xyz; + float refshad = texture2DRect(lightMap, ref2d).r; + vec3 refn = texture2DRect(normalMap, ref2d).rgb; + refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm + refn = normalize(refn); + // figure out how appropriate our guess actually was + float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); + // darken reflections from points which face away from the reflected ray - our guess was a back-face + //refapprop *= step(dot(refnorm, refn), 0.0); + refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant + // get appropriate light strength for guess-point. + // reflect light direction to increase the illusion that + // these are reflections. + vec3 reflight = reflect(lightnorm.xyz, norm.xyz); + float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad); + // apply sun color to guess-point, dampen according to inappropriateness of guess + float refmod = min(refapprop, reflit); + vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; + vec3 ssshiny = (refprod * spec.a); + ssshiny *= 0.3; // dampen it even more + */ + vec3 ssshiny = vec3(0,0,0); + + // add the two types of shiny together + col += (ssshiny + dumbshiny) * spec.rgb; } col = atmosLighting(col); diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl index 258acee08c..5b33ea5bfe 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl @@ -14,5 +14,6 @@ void main() vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl index 1c5234c450..f129a1517b 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl @@ -6,7 +6,7 @@ */ float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -15,24 +15,21 @@ vec3 scaleUpLight(vec3 light); vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) { - vec4 col; - col.a = color.a; + vec4 col = vec4(0.0, 0.0, 0.0, color.a); - // Add windlight lights - col.rgb = atmosAffectDirectionalLight(calcDirectionalLight(norm, gl_LightSource[0].position.xyz)); - col.rgb += atmosAmbient(baseLight.rgb); - col.rgb = scaleUpLight(col.rgb); - // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); - + + // Add windlight lights + col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, gl_LightSource[0].position.xyz)); + col.rgb += atmosAmbient(baseLight.rgb); col.rgb = min(col.rgb*color.rgb, 1.0); diff --git a/indra/newview/app_settings/ultra_graphics.xml b/indra/newview/app_settings/ultra_graphics.xml index f16ec6c30f..f741089ca2 100644 --- a/indra/newview/app_settings/ultra_graphics.xml +++ b/indra/newview/app_settings/ultra_graphics.xml @@ -12,14 +12,12 @@ <RenderFlexTimeFactor value="1"/> <!--256... but they don't use this--> <RenderGlowResolutionPow value="9"/> - <!--Sun/Moon only--> - <RenderLightingDetail value="1"/> <!--Low number--> <RenderMaxPartCount value="4096"/> <!--bump okay--> <RenderObjectBump value="TRUE"/> <!--NO SHADERS--> - <RenderReflectionDetail value="3"/> + <RenderReflectionDetail value="4"/> <!--Simple--> <RenderTerrainDetail value="1"/> <!--Default for now--> @@ -31,9 +29,14 @@ <!--Default for now--> <RenderVolumeLODFactor value="2.0"/> <!--NO SHADERS--> - <RenderWaterReflections value="TRUE"/> - <!--NO SHADERS--> <VertexShaderEnable value="TRUE"/> <!--NO SHADERS--> <WindLightUseAtmosShaders value="TRUE"/> + <!--Deferred Shading--> + <RenderDeferred value="TRUE"/> + <!--SSAO Enabled--> + <RenderDeferredSSAO value="TRUE"/> + <!--Full Shadows--> + <RenderShadowDetail value="2"/> + </settings> diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 5f31ccbb19..d2c13a43be 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -23,7 +23,7 @@ version 21 // NOTE: All settings are set to the MIN of applied values, including 'all'! // list all -RenderAnisotropic 1 0 +RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarVP 1 1 @@ -35,18 +35,16 @@ RenderFogRatio 1 4.0 RenderGamma 1 0 RenderGlowResolutionPow 1 9 RenderGround 1 1 -RenderLightingDetail 1 1 RenderMaxPartCount 1 8192 RenderNightBrightness 1 1.0 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVBOEnable 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 UseStartScreen 1 1 UseOcclusion 1 1 VertexShaderEnable 1 1 @@ -56,6 +54,9 @@ Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 RenderShaderLightingMaxLevel 1 3 +RenderDeferred 1 1 +RenderDeferredSSAO 1 1 +RenderShadowDetail 1 2 // @@ -69,7 +70,6 @@ RenderAvatarVP 1 0 RenderFarClip 1 64 RenderFlexTimeFactor 1 0.5 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 0 RenderMaxPartCount 1 1024 RenderObjectBump 1 0 RenderReflectionDetail 1 0 @@ -78,10 +78,13 @@ RenderTerrainLODFactor 1 1 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 0 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + // // Mid Graphics Settings @@ -94,7 +97,6 @@ RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 1 RenderMaxPartCount 1 2048 RenderObjectBump 1 1 RenderReflectionDetail 1 0 @@ -103,10 +105,13 @@ RenderTerrainLODFactor 1 1.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + // // High Graphics Settings (purty) @@ -119,7 +124,6 @@ RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 RenderMaxPartCount 1 4096 RenderObjectBump 1 1 RenderReflectionDetail 1 2 @@ -128,10 +132,13 @@ RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + // // Ultra graphics (REALLY PURTY!) @@ -144,19 +151,21 @@ RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 RenderMaxPartCount 1 8192 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 +RenderDeferred 1 1 +RenderDeferredSSAO 1 1 +RenderShadowDetail 1 2 + // // Class Unknown Hardware (unknown) @@ -194,9 +203,12 @@ RenderVBOEnable 1 1 list NoPixelShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 // // No Vertex Shaders available @@ -204,9 +216,13 @@ WindLightUseAtmosShaders 0 0 list NoVertexShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + // "Default" setups for safe, low, medium, high // @@ -214,14 +230,17 @@ list safe RenderAnisotropic 1 0 RenderAvatarCloth 0 0 RenderAvatarVP 0 0 -RenderLightingDetail 1 0 RenderObjectBump 0 0 RenderMaxPartCount 1 1024 RenderTerrainDetail 1 0 RenderUseImpostors 0 0 RenderVBOEnable 1 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + // // CPU based feature masks @@ -245,11 +264,9 @@ RenderVBOEnable 1 0 list Intel RenderAnisotropic 1 0 -RenderLightingDetail 1 0 list GeForce2 RenderAnisotropic 1 0 -RenderLightingDetail 1 0 RenderMaxPartCount 1 2048 RenderTerrainDetail 1 0 RenderVBOEnable 1 1 diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index 61a8e51c50..254b9c4ce4 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -23,7 +23,7 @@ version 21 // NOTE: All settings are set to the MIN of applied values, including 'all'! // list all -RenderAnisotropic 1 0 +RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarVP 1 1 @@ -35,18 +35,16 @@ RenderFogRatio 1 4.0 RenderGamma 1 0 RenderGlowResolutionPow 1 9 RenderGround 1 1 -RenderLightingDetail 1 1 RenderMaxPartCount 1 8192 RenderNightBrightness 1 1.0 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVBOEnable 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 UseStartScreen 1 1 UseOcclusion 1 1 VertexShaderEnable 1 1 @@ -55,6 +53,10 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 +RenderShaderLightingMaxLevel 1 3 +RenderDeferred 1 1 +RenderDeferredSSAO 1 1 +RenderShadowDetail 1 2 // // Low Graphics Settings @@ -67,7 +69,6 @@ RenderAvatarVP 1 0 RenderFarClip 1 64 RenderFlexTimeFactor 1 0.5 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 0 RenderMaxPartCount 1 1024 RenderObjectBump 1 0 RenderReflectionDetail 1 0 @@ -76,10 +77,13 @@ RenderTerrainLODFactor 1 1 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 0 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + // // Mid Graphics Settings @@ -92,7 +96,6 @@ RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 1 RenderMaxPartCount 1 2048 RenderObjectBump 1 1 RenderReflectionDetail 1 0 @@ -101,10 +104,13 @@ RenderTerrainLODFactor 1 1.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 + // // High Graphics Settings (purty) @@ -117,7 +123,6 @@ RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 RenderMaxPartCount 1 4096 RenderObjectBump 1 1 RenderReflectionDetail 1 2 @@ -126,10 +131,13 @@ RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 48 +RenderDeferred 1 1 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 1 + // // Ultra graphics (REALLY PURTY!) @@ -142,19 +150,21 @@ RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 RenderMaxPartCount 1 8192 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 +RenderDeferred 1 1 +RenderDeferredSSAO 1 1 +RenderShadowDetail 1 2 + // // Class Unknown Hardware (unknown) @@ -192,9 +202,12 @@ RenderVBOEnable 1 1 list NoPixelShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 // // No Vertex Shaders available @@ -202,9 +215,13 @@ WindLightUseAtmosShaders 0 0 list NoVertexShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + // "Default" setups for safe, low, medium, high // @@ -212,14 +229,17 @@ list safe RenderAnisotropic 1 0 RenderAvatarCloth 0 0 RenderAvatarVP 0 0 -RenderLightingDetail 1 0 RenderObjectBump 0 0 RenderMaxPartCount 1 1024 RenderTerrainDetail 1 0 RenderUseImpostors 0 0 RenderVBOEnable 1 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 + // // CPU based feature masks @@ -243,13 +263,11 @@ RenderVBOEnable 1 0 list Intel RenderAnisotropic 1 0 -RenderLightingDetail 1 0 // Avoid some Intel crashes on Linux RenderCubeMap 0 0 list GeForce2 RenderAnisotropic 1 0 -RenderLightingDetail 1 0 RenderMaxPartCount 1 2048 RenderTerrainDetail 1 0 RenderVBOEnable 1 1 @@ -461,17 +479,47 @@ list NVIDIA_GeForce_Go_6 RenderVBOEnable 1 0 Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_7000 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7100 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7200 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7300 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7400 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7500 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7900 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7200 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7300 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7300_LE +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7400 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7900 +RenderShaderLightingMaxLevel 1 2 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 12d47a904c..db0252d2e7 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -366,6 +366,7 @@ list ATI_Radeon_X1500 Disregard128DefaultDrawDistance 1 0 list ATI_Radeon_X1600 Disregard128DefaultDrawDistance 1 0 +RenderUseFBO 0 0 list ATI_Radeon_X1700 Disregard128DefaultDrawDistance 1 0 list ATI_Mobility_Radeon_X1xxx diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f7f7cb599e..fd78bc62c8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -903,6 +903,11 @@ static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread"); static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads"); static LLFastTimer::DeclareTimer FTM_IDLE("Idle"); static LLFastTimer::DeclareTimer FTM_PUMP("Pump"); +static LLFastTimer::DeclareTimer FTM_PUMP_ARES("Ares"); +static LLFastTimer::DeclareTimer FTM_PUMP_SERVICE("Service"); +static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback"); +static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot"); +static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update"); bool LLAppViewer::mainLoop() { @@ -1012,10 +1017,20 @@ bool LLAppViewer::mainLoop() LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP); pingMainloopTimeout("Main:ServicePump"); LLFastTimer t4(FTM_PUMP); - gAres->process(); - // this pump is necessary to make the login screen show up - gServicePump->pump(); - gServicePump->callback(); + { + LLFastTimer t(FTM_PUMP_ARES); + gAres->process(); + } + { + LLFastTimer t(FTM_PUMP_SERVICE); + // this pump is necessary to make the login screen show up + gServicePump->pump(); + + { + LLFastTimer t(FTM_SERVICE_CALLBACK); + gServicePump->callback(); + } + } } resumeMainloopTimeout(); @@ -3474,9 +3489,12 @@ void LLAppViewer::idle() gAgent.moveYaw(-1.f); } - // Handle automatic walking towards points - gAgentPilot.updateTarget(); - gAgent.autoPilot(&yaw); + { + LLFastTimer t(FTM_AGENT_AUTOPILOT); + // Handle automatic walking towards points + gAgentPilot.updateTarget(); + gAgent.autoPilot(&yaw); + } static LLFrameTimer agent_update_timer; static U32 last_control_flags; @@ -3487,6 +3505,7 @@ void LLAppViewer::idle() if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND))) { + LLFastTimer t(FTM_AGENT_UPDATE); // Send avatar and camera info last_control_flags = gAgent.getControlFlags(); send_agent_update(TRUE); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 38eda5bd2e..ed6a791e7f 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -523,7 +523,7 @@ F32 LLDrawable::updateXform(BOOL undamped) { // snap to final position dist_squared = 0.0f; - if (!isRoot()) + if (getVOVolume() && !isRoot()) { //child prim snapping to some position, needs a rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index e3e66fa00d..ae30af3647 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -474,6 +474,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) { if (params.mTexture.notNull()) { + params.mTexture->addTextureStats(params.mVSize); gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; if (params.mTextureMatrix) { diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 67870c10e9..f85b46cfba 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -133,6 +133,7 @@ public: PASS_FULLBRIGHT_SHINY, PASS_SHINY, PASS_BUMP, + PASS_POST_BUMP, PASS_GLOW, PASS_ALPHA, PASS_ALPHA_MASK, diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 875c9ac6a9..def463cb41 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -60,7 +60,9 @@ static BOOL deferred_render = FALSE; LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : LLRenderPass(type), current_shader(NULL), target_shader(NULL), - simple_shader(NULL), fullbright_shader(NULL) + simple_shader(NULL), fullbright_shader(NULL), + mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF), + mAlphaSFactor(LLRender::BF_UNDEF), mAlphaDFactor(LLRender::BF_UNDEF) { } @@ -178,9 +180,16 @@ void LLDrawPoolAlpha::render(S32 pass) LLGLSPipelineAlpha gls_pipeline_alpha; - if (LLPipeline::sFastAlpha && !deferred_render) + gGL.setColorMask(true, true); + + if (LLPipeline::sAutoMaskAlphaNonDeferred && !deferred_render) { - LLGLDisable blend_disable(GL_BLEND); + mColorSFactor = LLRender::BF_ONE; // } + mColorDFactor = LLRender::BF_ZERO; // } these are like disabling blend on the color channels, but we're still blending on the alpha channel so that we can suppress glow + mAlphaSFactor = LLRender::BF_ZERO; + mAlphaDFactor = LLRender::BF_ZERO; // block (zero-out) glow where the alpha test succeeds + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); if (mVertexShaderLevel > 0) { @@ -204,8 +213,17 @@ void LLDrawPoolAlpha::render(S32 pass) } LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy ? GL_TRUE : GL_FALSE); + + mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend + mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression + mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + renderAlpha(getVertexDataMask()); + gGL.setColorMask(true, false); + if (deferred_render && current_shader != NULL) { gPipeline.unbindDeferredShader(*current_shader); @@ -283,9 +301,18 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; + llassert(group); + llassert(group->mSpatialPartition); + if (group->mSpatialPartition->mRenderByGroup && - !group->isDead()) + !group->isDead()) { + bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow. + // All particle systems seem to come off the wire with texture entries which claim that they glow. This is probably a bug in the data. Suppress. + group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE && + group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_CLOUD && + group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE; + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) @@ -294,96 +321,118 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) LLRenderPass::applyModelMatrix(params); - if (params.mFullbright) { - // Turn off lighting if it hasn't already been so. - if (light_enabled || !initialized_lighting) + if (params.mFullbright) + { + // Turn off lighting if it hasn't already been so. + if (light_enabled || !initialized_lighting) + { + initialized_lighting = TRUE; + if (use_shaders) + { + target_shader = fullbright_shader; + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + } + light_enabled = FALSE; + } + } + // Turn on lighting if it isn't already. + else if (!light_enabled || !initialized_lighting) { initialized_lighting = TRUE; if (use_shaders) { - target_shader = fullbright_shader; + target_shader = simple_shader; } else { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + gPipeline.enableLightsDynamic(); } - light_enabled = FALSE; + light_enabled = TRUE; } - } - // Turn on lighting if it isn't already. - else if (!light_enabled || !initialized_lighting) - { - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = simple_shader; - } - else - { - gPipeline.enableLightsDynamic(); - } - light_enabled = TRUE; - } - // If we need shaders, and we're not ALREADY using the proper shader, then bind it - // (this way we won't rebind shaders unnecessarily). - if(use_shaders && (current_shader != target_shader)) - { - llassert(target_shader != NULL); - if (deferred_render && current_shader != NULL) + // If we need shaders, and we're not ALREADY using the proper shader, then bind it + // (this way we won't rebind shaders unnecessarily). + if(use_shaders && (current_shader != target_shader)) { - gPipeline.unbindDeferredShader(*current_shader); - diffuse_channel = 0; - } - current_shader = target_shader; - if (deferred_render) - { - gPipeline.bindDeferredShader(*current_shader); - diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - } - else - { - current_shader->bind(); + llassert(target_shader != NULL); + if (deferred_render && current_shader != NULL) + { + gPipeline.unbindDeferredShader(*current_shader); + diffuse_channel = 0; + } + current_shader = target_shader; + if (deferred_render) + { + gPipeline.bindDeferredShader(*current_shader); + diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + } + else + { + current_shader->bind(); + } } - } - else if (!use_shaders && current_shader != NULL) - { - if (deferred_render) + else if (!use_shaders && current_shader != NULL) { - gPipeline.unbindDeferredShader(*current_shader); - diffuse_channel = 0; + if (deferred_render) + { + gPipeline.unbindDeferredShader(*current_shader); + diffuse_channel = 0; + } + LLGLSLShader::bindNoShader(); + current_shader = NULL; } - LLGLSLShader::bindNoShader(); - current_shader = NULL; - } - - if (params.mGroup) - { - params.mGroup->rebuildMesh(); - } - - if (params.mTexture.notNull()) - { - gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get()); - if(params.mTexture.notNull()) + if (params.mGroup) { - params.mTexture->addTextureStats(params.mVSize); + params.mGroup->rebuildMesh(); } - if (params.mTextureMatrix) + + + if (params.mTexture.notNull()) { - gGL.getTexUnit(0)->activate(); - glMatrixMode(GL_TEXTURE); - glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; + gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get()); + if(params.mTexture.notNull()) + { + params.mTexture->addTextureStats(params.mVSize); + } + if (params.mTextureMatrix) + { + gGL.getTexUnit(0)->activate(); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } } } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + + // If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha. + if (draw_glow_for_this_partition && + params.mGlowColor.mV[3] > 0) + { + // install glow-accumulating blend mode + gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color + LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) + // glow doesn't use vertex colors from the mesh data + params.mVertexBuffer->setBuffer(mask & ~LLVertexBuffer::MAP_COLOR); + glColor4ubv(params.mGlowColor.mV); + + // do the actual drawing, again + params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + + // restore our alpha blend mode + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + } + if (params.mTextureMatrix && params.mTexture.notNull()) { gGL.getTexUnit(0)->activate(); diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h index 3aa752f72c..61f73d0b31 100644 --- a/indra/newview/lldrawpoolalpha.h +++ b/indra/newview/lldrawpoolalpha.h @@ -34,6 +34,7 @@ #define LL_LLDRAWPOOLALPHA_H #include "lldrawpool.h" +#include "llrender.h" #include "llframetimer.h" class LLFace; @@ -83,6 +84,12 @@ private: LLGLSLShader* target_shader; LLGLSLShader* simple_shader; LLGLSLShader* fullbright_shader; + + // our 'normal' alpha blend function for this pass + LLRender::eBlendFactor mColorSFactor; + LLRender::eBlendFactor mColorDFactor; + LLRender::eBlendFactor mAlphaSFactor; + LLRender::eBlendFactor mAlphaDFactor; }; class LLDrawPoolAlphaPostWater : public LLDrawPoolAlpha diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 546b60f286..c58fbbdcd0 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -123,7 +123,7 @@ void LLDrawPoolAvatar::prerender() if (sShaderLevel > 0) { - sBufferUsage = GL_STATIC_DRAW_ARB; + sBufferUsage = GL_DYNAMIC_DRAW_ARB; } else { @@ -157,6 +157,8 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) { LLFastTimer t(FTM_RENDER_CHARACTERS); + sSkipTransparent = TRUE; + if (LLPipeline::sImpostorRender) { beginDeferredSkinned(); @@ -181,6 +183,8 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) { LLFastTimer t(FTM_RENDER_CHARACTERS); + sSkipTransparent = FALSE; + if (LLPipeline::sImpostorRender) { endDeferredSkinned(); @@ -250,7 +254,6 @@ S32 LLDrawPoolAvatar::getNumShadowPasses() void LLDrawPoolAvatar::beginShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_AVATAR); - sVertexProgram = &gDeferredAvatarShadowProgram; if (sShaderLevel > 0) { @@ -272,7 +275,6 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) void LLDrawPoolAvatar::endShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_AVATAR); - if (sShaderLevel > 0) { sRenderingSkinned = FALSE; @@ -310,6 +312,11 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) return; } + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } + avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); } @@ -346,7 +353,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) switch (pass) { case 0: - beginFootShadow(); + beginImpostor(); break; case 1: beginRigid(); @@ -370,7 +377,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) switch (pass) { case 0: - endFootShadow(); + endImpostor(); break; case 1: endRigid(); @@ -380,7 +387,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) } } -void LLDrawPoolAvatar::beginFootShadow() +void LLDrawPoolAvatar::beginImpostor() { if (!LLPipeline::sReflectionRender) { @@ -392,7 +399,7 @@ void LLDrawPoolAvatar::beginFootShadow() diffuse_channel = 0; } -void LLDrawPoolAvatar::endFootShadow() +void LLDrawPoolAvatar::endImpostor() { gPipeline.enableLightsDynamic(); } @@ -564,7 +571,6 @@ void LLDrawPoolAvatar::endSkinned() void LLDrawPoolAvatar::beginDeferredSkinned() { - sSkipTransparent = TRUE; sShaderLevel = mVertexShaderLevel; sVertexProgram = &gDeferredAvatarProgram; @@ -579,7 +585,6 @@ void LLDrawPoolAvatar::beginDeferredSkinned() void LLDrawPoolAvatar::endDeferredSkinned() { - sSkipTransparent = FALSE; // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done sRenderingSkinned = FALSE; disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); @@ -691,10 +696,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel); } - else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred) - { - avatarp->renderFootShadows(); - } return; } @@ -848,9 +849,7 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const LLVertexBufferAvatar::LLVertexBufferAvatar() : LLVertexBuffer(sDataMask, - LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 ? - GL_DYNAMIC_DRAW_ARB : - GL_STREAM_DRAW_ARB) + GL_STREAM_DRAW_ARB) //avatars are always stream draw due to morph targets { } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index b947943619..d247260527 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -88,11 +88,11 @@ public: /*virtual*/ void renderShadow(S32 pass); void beginRigid(); - void beginFootShadow(); + void beginImpostor(); void beginSkinned(); void endRigid(); - void endFootShadow(); + void endImpostor(); void endSkinned(); void beginDeferredImpostor(); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 19cdccb630..a3b236fcb9 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -618,9 +618,9 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) } //static -void LLDrawPoolBump::beginBump() +void LLDrawPoolBump::beginBump(U32 pass) { - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + if (!gPipeline.hasRenderBatches(pass)) { return; } @@ -663,9 +663,9 @@ void LLDrawPoolBump::beginBump() } //static -void LLDrawPoolBump::renderBump() +void LLDrawPoolBump::renderBump(U32 pass) { - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + if (!gPipeline.hasRenderBatches(pass)) { return; } @@ -678,13 +678,13 @@ void LLDrawPoolBump::renderBump() /// Get rid of z-fighting with non-bump pass. LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -1.0f); - renderBump(LLRenderPass::PASS_BUMP, sVertexMask); + renderBump(pass, sVertexMask); } //static -void LLDrawPoolBump::endBump() +void LLDrawPoolBump::endBump(U32 pass) { - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + if (!gPipeline.hasRenderBatches(pass)) { return; } @@ -701,6 +701,18 @@ void LLDrawPoolBump::endBump() gGL.setSceneBlendType(LLRender::BT_ALPHA); } +S32 LLDrawPoolBump::getNumDeferredPasses() +{ + if (gSavedSettings.getBOOL("RenderObjectBump")) + { + return 1; + } + else + { + return 0; + } +} + void LLDrawPoolBump::beginDeferredPass(S32 pass) { if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) @@ -755,17 +767,41 @@ void LLDrawPoolBump::renderDeferred(S32 pass) void LLDrawPoolBump::beginPostDeferredPass(S32 pass) { - beginFullbrightShiny(); + switch (pass) + { + case 0: + beginFullbrightShiny(); + break; + case 1: + beginBump(LLRenderPass::PASS_POST_BUMP); + break; + } } void LLDrawPoolBump::endPostDeferredPass(S32 pass) { - endFullbrightShiny(); + switch (pass) + { + case 0: + endFullbrightShiny(); + break; + case 1: + endBump(LLRenderPass::PASS_POST_BUMP); + break; + } } void LLDrawPoolBump::renderPostDeferred(S32 pass) { - renderFullbrightShiny(); + switch (pass) + { + case 0: + renderFullbrightShiny(); + break; + case 1: + renderBump(LLRenderPass::PASS_POST_BUMP); + break; + } } //////////////////////////////////////////////////////////////// @@ -782,17 +818,22 @@ void LLBumpImageList::init() LLStandardBumpmap::init(); } -void LLBumpImageList::shutdown() +void LLBumpImageList::clear() { + // these will be re-populated on-demand mBrightnessEntries.clear(); mDarknessEntries.clear(); +} + +void LLBumpImageList::shutdown() +{ + clear(); LLStandardBumpmap::shutdown(); } void LLBumpImageList::destroyGL() { - mBrightnessEntries.clear(); - mDarknessEntries.clear(); + clear(); LLStandardBumpmap::destroyGL(); } @@ -851,6 +892,7 @@ void LLBumpImageList::updateImages() } } } + for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); ) { bump_image_map_t::iterator curiter = iter++; @@ -1028,7 +1070,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI { bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries ); bump_image_map_t::iterator iter = entries_list.find(source_asset_id); - if (iter != entries_list.end()) + if (iter != entries_list.end()) // bump not cached yet { LLPointer<LLImageRaw> dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1); U8* dst_data = dst_image->getData(); @@ -1113,8 +1155,11 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI F32 twice_one_over_range = 2.f / (maximum - minimum); S32 i; - const F32 ARTIFICIAL_SCALE = 2.f; // Advantage: exagerates the effect in midrange. Disadvantage: clamps at the extremes. - if( BE_DARKNESS == bump_code ) + bool bump_polarity_negative = LLPipeline::sRenderDeferred ? + (BE_BRIGHTNESS == bump_code) : (BE_DARKNESS == bump_code); // deferred mode likes its normal map values inverted + + const F32 ARTIFICIAL_SCALE = 2.f; // Advantage: exaggerates the effect in midrange. Disadvantage: clamps at the extremes. + if (bump_polarity_negative) { for( i = minimum; i <= maximum; i++ ) { @@ -1124,7 +1169,6 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI } else { - // BE_LIGHTNESS for( i = minimum; i <= maximum; i++ ) { F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f; @@ -1139,9 +1183,9 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI } //--------------------------------------------------- - //immediately assign bump to a global smart pointer in case some local smart pointer - //accidently releases it. - LLPointer<LLViewerTexture> bump = LLViewerTextureManager::getLocalTexture( TRUE); + // immediately assign bump to a global smart pointer in case some local smart pointer + // accidentally releases it. + LLPointer<LLViewerTexture> bump = LLViewerTextureManager::getLocalTexture( TRUE ); if (!LLPipeline::sRenderDeferred) { @@ -1150,8 +1194,8 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI } else { - LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); - generateNormalMapFromAlpha(src, nrm_image); + LLPointer<LLImageRaw> nrm_image = new LLImageRaw(dst_image->getWidth(), dst_image->getHeight(), 4); + generateNormalMapFromAlpha(dst_image, nrm_image); bump->setExplicitFormat(GL_RGBA, GL_RGBA); bump->createGLTexture(0, nrm_image); } diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index bf940cf1e4..219e2aac54 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -75,16 +75,16 @@ public: void renderFullbrightShiny(); void endFullbrightShiny(); - void beginBump(); - void renderBump(); - void endBump(); + void beginBump(U32 pass = LLRenderPass::PASS_BUMP); + void renderBump(U32 pass = LLRenderPass::PASS_BUMP); + void endBump(U32 pass = LLRenderPass::PASS_BUMP); - virtual S32 getNumDeferredPasses() { return 1; } + virtual S32 getNumDeferredPasses(); /*virtual*/ void beginDeferredPass(S32 pass); /*virtual*/ void endDeferredPass(S32 pass); /*virtual*/ void renderDeferred(S32 pass); - virtual S32 getNumPostDeferredPasses() { return 1; } + virtual S32 getNumPostDeferredPasses() { return 2; } /*virtual*/ void beginPostDeferredPass(S32 pass); /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass); @@ -136,6 +136,7 @@ public: void init(); void shutdown(); + void clear(); void destroyGL(); void restoreGL(); void updateImages(); diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index ca7a1b47c2..91191287cd 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -55,6 +55,10 @@ void LLDrawPoolGlow::render(S32 pass) LLFastTimer t(FTM_RENDER_GLOW); LLGLEnable blend(GL_BLEND); LLGLDisable test(GL_ALPHA_TEST); + gGL.flush(); + /// Get rid of z-fighting with non-glow pass. + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); gGL.setSceneBlendType(LLRender::BT_ADD); U32 shader_level = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); @@ -147,7 +151,8 @@ void LLDrawPoolSimple::render(S32 pass) renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); if (LLPipeline::sRenderDeferred) - { + { //if deferred rendering is enabled, bump faces aren't reigstered as simple + //render bump faces here as simple so bump faces will appear under water renderTexture(LLRenderPass::PASS_BUMP, getVertexDataMask()); } } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index a1336815f7..f6932b0e68 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -862,11 +862,34 @@ void LLFace::updateRebuildFlags() } } + +bool LLFace::canRenderAsMask() +{ + const LLTextureEntry* te = getTextureEntry(); + return ( + ( + (LLPipeline::sRenderDeferred && LLPipeline::sAutoMaskAlphaDeferred) || + + (!LLPipeline::sRenderDeferred && LLPipeline::sAutoMaskAlphaNonDeferred) + ) // do we want masks at all? + && + (te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha + !(LLPipeline::sRenderDeferred && te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible in deferred rendering mode, need to figure out why - for now, avoid + (te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask + + getTexture()->getIsAlphaMask() // texture actually qualifies for masking (lazily recalculated but expensive) + ); +} + + +static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom"); + BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, const U16 &index_offset) { + LLFastTimer t(FTM_FACE_GET_GEOM); const LLVolumeFace &vf = volume.getVolumeFace(f); S32 num_vertices = (S32)vf.mVertices.size(); S32 num_indices = LLPipeline::sUseTriStrips ? (S32)vf.mTriStrip.size() : (S32) vf.mIndices.size(); diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 67dd97e6f7..02cc2af433 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -138,10 +138,10 @@ public: void unsetFaceColor(); // switch back to material color const LLColor4& getFaceColor() const { return mFaceColor; } const LLColor4& getRenderColor() const; - //for volumes void updateRebuildFlags(); + bool canRenderAsMask(); // logic helper BOOL getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 0eeef0039c..f29f7160e8 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -799,7 +799,7 @@ void LLFloaterPreference::buildPopupLists() void LLFloaterPreference::refreshEnabledState() { - LLCheckBoxCtrl* ctrl_reflections = getChild<LLCheckBoxCtrl>("Reflections"); + LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections"); LLRadioGroup* radio_reflection_detail = getChild<LLRadioGroup>("ReflectionDetailRadio"); // Reflections @@ -812,7 +812,7 @@ void LLFloaterPreference::refreshEnabledState() bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump"); getChild<LLCheckBoxCtrl>("BumpShiny")->setEnabled(bumpshiny ? TRUE : FALSE); - radio_reflection_detail->setEnabled(ctrl_reflections->get() && reflections); + radio_reflection_detail->setEnabled(reflections); // Avatar Mode // Enable Avatar Shaders @@ -858,6 +858,30 @@ void LLFloaterPreference::refreshEnabledState() // *HACK just checks to see if we can use shaders... // maybe some cards that use shaders, but don't support windlight ctrl_wind_light->setEnabled(ctrl_shader_enable->getEnabled() && shaders); + + //Deferred/SSAO/Shadows + LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); + if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseFBO") && + LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + shaders) + { + BOOL enabled = (ctrl_wind_light->get()) ? TRUE : FALSE; + + ctrl_deferred->setEnabled(enabled); + + LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO"); + LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail"); + + enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE); + + ctrl_ssao->setEnabled(enabled); + + enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"); + + ctrl_shadow->setEnabled(enabled); + } + + // now turn off any features that are unavailable disableUnavailableSettings(); @@ -866,12 +890,15 @@ void LLFloaterPreference::refreshEnabledState() void LLFloaterPreference::disableUnavailableSettings() { - LLCheckBoxCtrl* ctrl_reflections = getChild<LLCheckBoxCtrl>("Reflections"); + LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections"); LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram"); LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth"); LLCheckBoxCtrl* ctrl_shader_enable = getChild<LLCheckBoxCtrl>("BasicShaders"); LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders"); LLCheckBoxCtrl* ctrl_avatar_impostors = getChild<LLCheckBoxCtrl>("AvatarImpostors"); + LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); + LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail"); + LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO"); // if vertex shaders off, disable all shader related products if(!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")) @@ -883,13 +910,22 @@ void LLFloaterPreference::disableUnavailableSettings() ctrl_wind_light->setValue(FALSE); ctrl_reflections->setEnabled(FALSE); - ctrl_reflections->setValue(FALSE); + ctrl_reflections->setValue(0); ctrl_avatar_vp->setEnabled(FALSE); ctrl_avatar_vp->setValue(FALSE); ctrl_avatar_cloth->setEnabled(FALSE); ctrl_avatar_cloth->setValue(FALSE); + + ctrl_shadows->setEnabled(FALSE); + ctrl_shadows->setValue(0); + + ctrl_ssao->setEnabled(FALSE); + ctrl_ssao->setValue(FALSE); + + ctrl_deferred->setEnabled(FALSE); + ctrl_deferred->setValue(FALSE); } // disabled windlight @@ -897,10 +933,47 @@ void LLFloaterPreference::disableUnavailableSettings() { ctrl_wind_light->setEnabled(FALSE); ctrl_wind_light->setValue(FALSE); + + //deferred needs windlight, disable deferred + ctrl_shadows->setEnabled(FALSE); + ctrl_shadows->setValue(0); + + ctrl_ssao->setEnabled(FALSE); + ctrl_ssao->setValue(FALSE); + + ctrl_deferred->setEnabled(FALSE); + ctrl_deferred->setValue(FALSE); + } + + // disabled deferred + if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred")) + { + ctrl_shadows->setEnabled(FALSE); + ctrl_shadows->setValue(0); + + ctrl_ssao->setEnabled(FALSE); + ctrl_ssao->setValue(FALSE); + + ctrl_deferred->setEnabled(FALSE); + ctrl_deferred->setValue(FALSE); + } + + // disabled deferred SSAO + if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO")) + { + ctrl_ssao->setEnabled(FALSE); + ctrl_ssao->setValue(FALSE); } + // disabled deferred shadows + if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail")) + { + ctrl_shadows->setEnabled(FALSE); + ctrl_shadows->setValue(0); + } + // disabled reflections - if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderWaterReflections")) + if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail")) { ctrl_reflections->setEnabled(FALSE); ctrl_reflections->setValue(FALSE); @@ -914,13 +987,25 @@ void LLFloaterPreference::disableUnavailableSettings() ctrl_avatar_cloth->setEnabled(FALSE); ctrl_avatar_cloth->setValue(FALSE); + + //deferred needs AvatarVP, disable deferred + ctrl_shadows->setEnabled(FALSE); + ctrl_shadows->setValue(0); + + ctrl_ssao->setEnabled(FALSE); + ctrl_ssao->setValue(FALSE); + + ctrl_deferred->setEnabled(FALSE); + ctrl_deferred->setValue(FALSE); } + // disabled cloth if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth")) { ctrl_avatar_cloth->setEnabled(FALSE); ctrl_avatar_cloth->setValue(FALSE); } + // disabled impostors if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors")) { diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index fbe68b4d92..8b01637239 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -574,7 +574,7 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) LLUUID id = LightTextureCtrl->getImageAssetID(); if (id.notNull()) { - if (volobjp->getLightTextureID().isNull()) + if (!volobjp->isLightSpotlight()) { //this commit is making this a spot light, set UI to default params volobjp->setLightTextureID(id); LLVector3 spot_params = volobjp->getSpotLightParams(); @@ -591,7 +591,7 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) volobjp->setSpotLightParams(spot_params); } } - else if (volobjp->getLightTextureID().notNull()) + else if (volobjp->isLightSpotlight()) { //no longer a spot light volobjp->setLightTextureID(id); //self->childDisable("Light FOV"); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index d6e9256fee..c229657ded 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1513,6 +1513,7 @@ void LLSpatialGroup::checkOcclusion() { if (LLPipeline::sUseOcclusion > 1) { + LLFastTimer t(FTM_OCCLUSION_READBACK); LLSpatialGroup* parent = getParent(); if (parent && parent->isOcclusionState(LLSpatialGroup::OCCLUDED)) { //if the parent has been marked as occluded, the child is implicitly occluded @@ -1520,7 +1521,6 @@ void LLSpatialGroup::checkOcclusion() } else if (isOcclusionState(QUERY_PENDING)) { //otherwise, if a query is pending, read it back - LLFastTimer t(FTM_OCCLUSION_READBACK); GLuint res = 1; if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) { @@ -1924,11 +1924,8 @@ public: return; } - if (mRes == 2) - { - //fully in, don't traverse further (won't effect extents - } - else if (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) + if ((mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || + mRes == 2) { //don't need to do frustum check LLSpatialGroup::OctreeTraveler::traverse(n); } @@ -3423,11 +3420,23 @@ LLCullResult::LLCullResult() void LLCullResult::clear() { mVisibleGroupsSize = 0; + mVisibleGroupsEnd = mVisibleGroups.begin(); + mAlphaGroupsSize = 0; + mAlphaGroupsEnd = mAlphaGroups.begin(); + mOcclusionGroupsSize = 0; + mOcclusionGroupsEnd = mOcclusionGroups.begin(); + mDrawableGroupsSize = 0; + mDrawableGroupsEnd = mDrawableGroups.begin(); + mVisibleListSize = 0; + mVisibleListEnd = mVisibleList.begin(); + mVisibleBridgeSize = 0; + mVisibleBridgeEnd = mVisibleBridge.begin(); + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) { @@ -3436,6 +3445,7 @@ void LLCullResult::clear() mRenderMap[i][j] = 0; } mRenderMapSize[i] = 0; + mRenderMapEnd[i] = mRenderMap[i].begin(); } } @@ -3446,7 +3456,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups() LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups() { - return mVisibleGroups.begin() + mVisibleGroupsSize; + return mVisibleGroupsEnd; } LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups() @@ -3456,7 +3466,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups() LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups() { - return mAlphaGroups.begin() + mAlphaGroupsSize; + return mAlphaGroupsEnd; } LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups() @@ -3466,7 +3476,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups() LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups() { - return mOcclusionGroups.begin() + mOcclusionGroupsSize; + return mOcclusionGroupsEnd; } LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups() @@ -3476,7 +3486,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups() LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups() { - return mDrawableGroups.begin() + mDrawableGroupsSize; + return mDrawableGroupsEnd; } LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList() @@ -3486,7 +3496,7 @@ LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList() LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList() { - return mVisibleList.begin() + mVisibleListSize; + return mVisibleListEnd; } LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge() @@ -3496,7 +3506,7 @@ LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge() LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge() { - return mVisibleBridge.begin() + mVisibleBridgeSize; + return mVisibleBridgeEnd; } LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type) @@ -3506,7 +3516,7 @@ LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type) LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type) { - return mRenderMap[type].begin() + mRenderMapSize[type]; + return mRenderMapEnd[type]; } void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) @@ -3520,6 +3530,7 @@ void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) mVisibleGroups.push_back(group); } ++mVisibleGroupsSize; + mVisibleGroupsEnd = mVisibleGroups.begin()+mVisibleGroupsSize; } void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) @@ -3533,6 +3544,7 @@ void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) mAlphaGroups.push_back(group); } ++mAlphaGroupsSize; + mAlphaGroupsEnd = mAlphaGroups.begin()+mAlphaGroupsSize; } void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) @@ -3546,6 +3558,7 @@ void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) mOcclusionGroups.push_back(group); } ++mOcclusionGroupsSize; + mOcclusionGroupsEnd = mOcclusionGroups.begin()+mOcclusionGroupsSize; } void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) @@ -3559,6 +3572,7 @@ void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) mDrawableGroups.push_back(group); } ++mDrawableGroupsSize; + mDrawableGroupsEnd = mDrawableGroups.begin()+mDrawableGroupsSize; } void LLCullResult::pushDrawable(LLDrawable* drawable) @@ -3572,6 +3586,7 @@ void LLCullResult::pushDrawable(LLDrawable* drawable) mVisibleList.push_back(drawable); } ++mVisibleListSize; + mVisibleListEnd = mVisibleList.begin()+mVisibleListSize; } void LLCullResult::pushBridge(LLSpatialBridge* bridge) @@ -3585,6 +3600,7 @@ void LLCullResult::pushBridge(LLSpatialBridge* bridge) mVisibleBridge.push_back(bridge); } ++mVisibleBridgeSize; + mVisibleBridgeEnd = mVisibleBridge.begin()+mVisibleBridgeSize; } void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) @@ -3598,6 +3614,7 @@ void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) mRenderMap[type].push_back(draw_info); } ++mRenderMapSize[type]; + mRenderMapEnd[type] = mRenderMap[type].begin() + mRenderMapSize[type]; } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 7896488379..19af6a0c38 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -346,11 +346,11 @@ public: F32 mBuilt; OctreeNode* mOctreeNode; LLSpatialPartition* mSpatialPartition; - LLVector3 mBounds[2]; - LLVector3 mExtents[2]; + LLVector3 mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) + LLVector3 mExtents[2]; // extents (min, max) of this node and all its children - LLVector3 mObjectExtents[2]; - LLVector3 mObjectBounds[2]; + LLVector3 mObjectExtents[2]; // extents (min, max) of objects in this node + LLVector3 mObjectBounds[2]; // bounding box (center, size) of objects in this node LLPointer<LLVertexBuffer> mVertexBuffer; F32* mOcclusionVerts; @@ -534,12 +534,19 @@ private: U32 mRenderMapSize[LLRenderPass::NUM_RENDER_TYPES]; sg_list_t mVisibleGroups; + sg_list_t::iterator mVisibleGroupsEnd; sg_list_t mAlphaGroups; + sg_list_t::iterator mAlphaGroupsEnd; sg_list_t mOcclusionGroups; + sg_list_t::iterator mOcclusionGroupsEnd; sg_list_t mDrawableGroups; + sg_list_t::iterator mDrawableGroupsEnd; drawable_list_t mVisibleList; + drawable_list_t::iterator mVisibleListEnd; bridge_list_t mVisibleBridge; + bridge_list_t::iterator mVisibleBridgeEnd; drawinfo_list_t mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; + drawinfo_list_t::iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; }; @@ -606,14 +613,13 @@ public: //class for wrangling geometry out of volumes (implemented in LLVOVolume.cpp) class LLVolumeGeometryManager: public LLGeometryManager { -public: + public: virtual ~LLVolumeGeometryManager() { } virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); - }; //spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp) diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 514f72c334..e856c18d70 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -43,6 +43,7 @@ #include "llagent.h" #include "llagentcamera.h" #include "llconsole.h" +#include "lldrawpoolbump.h" #include "lldrawpoolterrain.h" #include "llflexibleobject.h" #include "llfeaturemanager.h" @@ -118,6 +119,9 @@ static bool handleTerrainDetailChanged(const LLSD& newvalue) static bool handleSetShaderChanged(const LLSD& newvalue) { + // changing shader level may invalidate existing cached ad-hoc bump maps, as the shader type determines the format of the bump map it expectes - clear the bump cache + gBumpImageList.clear(); + LLViewerShaderMgr::instance()->setShaders(); return true; } @@ -299,15 +303,6 @@ static bool handleWLSkyDetailChanged(const LLSD&) return true; } -static bool handleRenderLightingDetailChanged(const LLSD& newvalue) -{ - if (gPipeline.isInit()) - { - gPipeline.setLightingDetail(newvalue.asInteger()); - } - return true; -} - static bool handleResetVertexBuffersChanged(const LLSD&) { if (gPipeline.isInit()) @@ -514,6 +509,10 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); + gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); + gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); + gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); + gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); @@ -534,7 +533,8 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderMaxPartCount")->getSignal()->connect(boost::bind(&handleMaxPartCountChanged, _2)); gSavedSettings.getControl("RenderDynamicLOD")->getSignal()->connect(boost::bind(&handleRenderDynamicLODChanged, _2)); gSavedSettings.getControl("RenderDebugTextureBind")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderFastAlpha")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); + gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); + gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderUseFBO")->getSignal()->connect(boost::bind(&handleRenderUseFBOChanged, _2)); @@ -544,7 +544,8 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _2)); gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _2)); gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); - gSavedSettings.getControl("RenderDeferredShadow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); + gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); + gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderDeferredGI")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2)); gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _2)); @@ -569,8 +570,8 @@ void settings_setup_listeners() gSavedSettings.getControl("MuteAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); gSavedSettings.getControl("MuteUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); gSavedSettings.getControl("RenderVBOEnable")->getSignal()->connect(boost::bind(&handleRenderUseVBOChanged, _2)); + gSavedSettings.getControl("RenderUseStreamVBO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _2)); - gSavedSettings.getControl("RenderLightingDetail")->getSignal()->connect(boost::bind(&handleRenderLightingDetailChanged, _2)); gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _2)); gSavedSettings.getControl("JoystickAxis0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); gSavedSettings.getControl("JoystickAxis1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index f0800e82e7..570dd1a105 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -595,7 +595,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLPipeline::sUseOcclusion = 3; } - LLPipeline::sFastAlpha = gSavedSettings.getBOOL("RenderFastAlpha"); + LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred"); + LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred"); LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible"); LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate"); @@ -868,12 +869,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } } - /// We copy the frame buffer straight into a texture here, - /// and then display it again with compositor effects. - /// Using render to texture would be faster/better, but I don't have a - /// grasp of their full display stack just yet. - // gPostProcess->apply(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); - if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.renderDeferredLighting(); @@ -935,9 +930,10 @@ void render_hud_attachments() bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles"); //only render hud objects - U32 mask = gPipeline.getRenderTypeMask(); + gPipeline.pushRenderTypeMask(); + // turn off everything - gPipeline.setRenderTypeMask(0); + gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES); // turn on HUD gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); // turn on HUD particles @@ -991,7 +987,8 @@ void render_hud_attachments() render_hud_elements(); //restore type mask - gPipeline.setRenderTypeMask(mask); + gPipeline.popRenderTypeMask(); + if (has_ui) { gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); @@ -1116,7 +1113,7 @@ void render_ui(F32 zoom_factor, int subfield) { gPipeline.renderBloom(gSnapshot, zoom_factor, subfield); } - + render_hud_elements(); render_hud_attachments(); } diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index 95f05b5f5f..8f2006b431 100644 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -440,13 +440,13 @@ void LLViewerJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pix } } -void LLViewerJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind) +void LLViewerJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) { for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); ++iter) { LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->updateFaceData(face, pixel_area, damp_wind); + joint->updateFaceData(face, pixel_area, damp_wind, terse_update); } } diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h index 0d3092a044..67bd7786c3 100644 --- a/indra/newview/llviewerjoint.h +++ b/indra/newview/llviewerjoint.h @@ -126,7 +126,7 @@ public: PickName getPickName() { return mPickName; } virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); - virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE); + virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); virtual BOOL updateLOD(F32 pixel_area, BOOL activate); virtual void updateJointGeometry(); virtual void dump(); diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 7225aa1523..6be7c442ef 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -667,7 +667,9 @@ void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 //----------------------------------------------------------------------------- // updateFaceData() //----------------------------------------------------------------------------- -void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind) +static LLFastTimer::DeclareTimer FTM_AVATAR_FACE("Avatar Face"); + +void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) { mFace = face; @@ -676,6 +678,8 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w return; } + LLFastTimer t(FTM_AVATAR_FACE); + LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> tex_coordsp; @@ -694,29 +698,98 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w face->mVertexBuffer->getIndexStrider(indicesp); stop_glerror(); - for (U16 i = 0; i < mMesh->getNumVertices(); i++) + verticesp += mMesh->mFaceVertexOffset; + tex_coordsp += mMesh->mFaceVertexOffset; + normalsp += mMesh->mFaceVertexOffset; + vertex_weightsp += mMesh->mFaceVertexOffset; + clothing_weightsp += mMesh->mFaceVertexOffset; + + const U32* __restrict coords = (U32*) mMesh->getCoords(); + const U32* __restrict tex_coords = (U32*) mMesh->getTexCoords(); + const U32* __restrict normals = (U32*) mMesh->getNormals(); + const U32* __restrict weights = (U32*) mMesh->getWeights(); + const U32* __restrict cloth_weights = (U32*) mMesh->getClothingWeights(); + + const U32 num_verts = mMesh->getNumVertices(); + + U32 i = 0; + + const U32 skip = verticesp.getSkip()/sizeof(U32); + + U32* __restrict v = (U32*) verticesp.get(); + U32* __restrict n = (U32*) normalsp.get(); + + if (terse_update) { - verticesp[mMesh->mFaceVertexOffset + i] = *(mMesh->getCoords() + i); - tex_coordsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getTexCoords() + i); - normalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getNormals() + i); - vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i); - if (damp_wind) + for (S32 i = num_verts; i > 0; --i) { - clothing_weightsp[mMesh->mFaceVertexOffset + i] = LLVector4(0,0,0,0); + //morph target application only, only update positions and normals + v[0] = coords[0]; + v[1] = coords[1]; + v[2] = coords[2]; + coords += 3; + v += skip; } - else + + for (S32 i = num_verts; i > 0; --i) { - clothing_weightsp[mMesh->mFaceVertexOffset + i] = (*(mMesh->getClothingWeights() + i)); + n[0] = normals[0]; + n[1] = normals[1]; + n[2] = normals[2]; + normals += 3; + n += skip; } } + else + { - for (S32 i = 0; i < mMesh->getNumFaces(); i++) - { - for (U32 j = 0; j < 3; j++) + U32* __restrict tc = (U32*) tex_coordsp.get(); + U32* __restrict vw = (U32*) vertex_weightsp.get(); + U32* __restrict cw = (U32*) clothing_weightsp.get(); + + do + { + v[0] = *(coords++); + v[1] = *(coords++); + v[2] = *(coords++); + v += skip; + + tc[0] = *(tex_coords++); + tc[1] = *(tex_coords++); + tc += skip; + + n[0] = *(normals++); + n[1] = *(normals++); + n[2] = *(normals++); + n += skip; + + vw[0] = *(weights++); + vw += skip; + + cw[0] = *(cloth_weights++); + cw[1] = *(cloth_weights++); + cw[2] = *(cloth_weights++); + cw[3] = *(cloth_weights++); + cw += skip; + } + while (++i < num_verts); + + const U32 idx_count = mMesh->getNumFaces()*3; + + indicesp += mMesh->mFaceIndexOffset; + + U16* __restrict idx = indicesp.get(); + S32* __restrict src_idx = (S32*) mMesh->getFaces(); + + i = 0; + + const S32 offset = (S32) mMesh->mFaceVertexOffset; + + do { - U32 k = i*3+j+mMesh->mFaceIndexOffset; - indicesp[k] = mMesh->getFaces()[i][j] + mMesh->mFaceVertexOffset; + *(idx++) = *(src_idx++)+offset; } + while (++i < idx_count); } } } diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index d62b0ada85..3b8d9c82b8 100644 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -140,7 +140,7 @@ public: /*virtual*/ U32 drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy ); /*virtual*/ void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); - /*virtual*/ void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE); + /*virtual*/ void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); /*virtual*/ BOOL updateLOD(F32 pixel_area, BOOL activate); /*virtual*/ void updateJointGeometry(); /*virtual*/ void dump(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 28c1a1ad3a..bb2378e489 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3608,6 +3608,7 @@ const F32 THRESHOLD_HEAD_ROT_QDOT = 0.9997f; // ~= 2.5 degrees -- if its less th const F32 MAX_HEAD_ROT_QDOT = 0.99999f; // ~= 0.5 degrees -- if its greater than this then no need to update head_rot // between these values we delay the updates (but no more than one second) +static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE_SEND("Send Message"); void send_agent_update(BOOL force_send, BOOL send_reliable) { @@ -3766,6 +3767,7 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) if (duplicate_count < DUP_MSGS && !gDisconnected) { + LLFastTimer t(FTM_AGENT_UPDATE_SEND); // Build the message msg->newMessageFast(_PREHASH_AgentUpdate); msg->nextBlockFast(_PREHASH_AgentData); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 86b1a8c910..0e29851778 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -317,10 +317,16 @@ S32 LLViewerShaderMgr::getVertexShaderLevel(S32 type) void LLViewerShaderMgr::setShaders() { - if (!gPipeline.mInitialized || !sInitialized) + //setShaders might be called redundantly by gSavedSettings, so return on reentrance + static bool reentrance = false; + + if (!gPipeline.mInitialized || !sInitialized || reentrance) { return; } + + reentrance = true; + // Make sure the compiled shader map is cleared before we recompile shaders. mShaderObjects.clear(); @@ -368,17 +374,11 @@ void LLViewerShaderMgr::setShaders() S32 wl_class = 2; S32 water_class = 2; S32 deferred_class = 0; - if (!(LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders") - && gSavedSettings.getBOOL("WindLightUseAtmosShaders"))) - { - // user has disabled WindLight in their settings, downgrade - // windlight shaders to stub versions. - wl_class = 1; - } - - if (LLPipeline::sRenderDeferred) + + if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + gSavedSettings.getBOOL("RenderDeferred")) { - if (gSavedSettings.getBOOL("RenderDeferredShadow")) + if (gSavedSettings.getS32("RenderShadowDetail") > 0) { if (gSavedSettings.getBOOL("RenderDeferredGI")) { //shadows + gi @@ -393,6 +393,24 @@ void LLViewerShaderMgr::setShaders() { //no shadows deferred_class = 1; } + + //make sure framebuffer objects are enabled + gSavedSettings.setBOOL("RenderUseFBO", TRUE); + + //make sure hardware skinning is enabled + gSavedSettings.setBOOL("RenderAvatarVP", TRUE); + + //make sure atmospheric shaders are enabled + gSavedSettings.setBOOL("WindLightUseAtmosShaders", TRUE); + } + + + if (!(LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders") + && gSavedSettings.getBOOL("WindLightUseAtmosShaders"))) + { + // user has disabled WindLight in their settings, downgrade + // windlight shaders to stub versions. + wl_class = 1; } if(!gSavedSettings.getBOOL("EnableRippleWater")) @@ -517,6 +535,8 @@ void LLViewerShaderMgr::setShaders() gViewerWindow->setCursor(UI_CURSOR_ARROW); } gPipeline.createGLBuffers(); + + reentrance = false; } void LLViewerShaderMgr::unloadShaders() @@ -973,10 +993,21 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + std::string fragment; + + if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + { + fragment = "deferred/sunLightSSAOF.glsl"; + } + else + { + fragment = "deferred/sunLightF.glsl"; + } + gDeferredSunProgram.mName = "Deferred Sun Shader"; gDeferredSunProgram.mShaderFiles.clear(); gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB)); gDeferredSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredSunProgram.createShader(NULL, NULL); } diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index bdc34d0f18..6ada122662 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -592,7 +592,7 @@ void update_statistics(U32 frame_count) } } LLViewerStats::getInstance()->setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gSavedSettings.getS32("RenderLightingDetail")); + LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail()); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); #if 0 // 1.9.2 diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 56d22a0608..3ee912e00f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1372,7 +1372,7 @@ LLViewerWindow::LLViewerWindow( gSavedSettings.getBOOL("DisableVerticalSync"), !gNoRender, ignore_pixel_depth, - gSavedSettings.getU32("RenderFSAASamples")); + 0); //gSavedSettings.getU32("RenderFSAASamples")); if (!LLAppViewer::instance()->restoreErrorTrap()) { @@ -3829,140 +3829,6 @@ void LLViewerWindow::playSnapshotAnimAndSound() BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) { return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type); - - // *TODO below code was broken in deferred pipeline - /* - if ((!raw) || preview_width < 10 || preview_height < 10) - { - return FALSE; - } - - if(gResizeScreenTexture) //the window is resizing - { - return FALSE ; - } - - setCursor(UI_CURSOR_WAIT); - - // Hide all the UI widgets first and draw a frame - BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); - - if ( prev_draw_ui != show_ui) - { - LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments; - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = FALSE; - } - - S32 render_name = gSavedSettings.getS32("RenderName"); - gSavedSettings.setS32("RenderName", 0); - LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame - - S32 w = preview_width ; - S32 h = preview_height ; - LLVector2 display_scale = mDisplayScale ; - mDisplayScale.setVec((F32)w / mWindowRectRaw.getWidth(), (F32)h / mWindowRectRaw.getHeight()) ; - LLRect window_rect = mWindowRectRaw; - mWindowRectRaw.set(0, h, w, 0); - - gDisplaySwapBuffers = FALSE; - gDepthDirty = TRUE; - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - setup3DRender(); - - LLFontGL::setFontDisplay(FALSE) ; - LLHUDText::setDisplayText(FALSE) ; - if (type == SNAPSHOT_TYPE_OBJECT_ID) - { - gObjectList.renderPickList(gViewerWindow->getWindowRectScaled(), FALSE, FALSE); - } - else - { - display(do_rebuild, 1.0f, 0, TRUE); - render_ui(); - } - - S32 glformat, gltype, glpixel_length ; - if(SNAPSHOT_TYPE_DEPTH == type) - { - glpixel_length = 4 ; - glformat = GL_DEPTH_COMPONENT ; - gltype = GL_FLOAT ; - } - else - { - glpixel_length = 3 ; - glformat = GL_RGB ; - gltype = GL_UNSIGNED_BYTE ; - } - - raw->resize(w, h, glpixel_length); - glReadPixels(0, 0, w, h, glformat, gltype, raw->getData()); - - if(SNAPSHOT_TYPE_DEPTH == type) - { - LLViewerCamera* camerap = LLViewerCamera::getInstance(); - F32 depth_conversion_factor_1 = (camerap->getFar() + camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear()); - F32 depth_conversion_factor_2 = (camerap->getFar() - camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear()); - - //calculate the depth - for (S32 y = 0 ; y < h ; y++) - { - for(S32 x = 0 ; x < w ; x++) - { - S32 i = (w * y + x) << 2 ; - - F32 depth_float_i = *(F32*)(raw->getData() + i); - - F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float_i * depth_conversion_factor_2)); - U8 depth_byte = F32_to_U8(linear_depth_float, camerap->getNear(), camerap->getFar()); - *(raw->getData() + i + 0) = depth_byte; - *(raw->getData() + i + 1) = depth_byte; - *(raw->getData() + i + 2) = depth_byte; - *(raw->getData() + i + 3) = 255; - } - } - } - - LLFontGL::setFontDisplay(TRUE) ; - LLHUDText::setDisplayText(TRUE) ; - mDisplayScale.setVec(display_scale) ; - mWindowRectRaw = window_rect; - setup3DRender(); - gDisplaySwapBuffers = FALSE; - gDepthDirty = TRUE; - - // POST SNAPSHOT - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = TRUE; - } - - setCursor(UI_CURSOR_ARROW); - - if (do_rebuild) - { - // If we had to do a rebuild, that means that the lists of drawables to be rendered - // was empty before we started. - // Need to reset these, otherwise we call state sort on it again when render gets called the next time - // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of - // objects on them. - gPipeline.resetDrawOrders(); - } - - gSavedSettings.setS32("RenderName", render_name); - - return TRUE;*/ } // Saves the image from the screen to the specified filename and path. @@ -4722,8 +4588,9 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, return TRUE; } - U32 fsaa = gSavedSettings.getU32("RenderFSAASamples"); - U32 old_fsaa = mWindow->getFSAASamples(); + //U32 fsaa = gSavedSettings.getU32("RenderFSAASamples"); + //U32 old_fsaa = mWindow->getFSAASamples(); + // going from windowed to windowed if (!old_fullscreen && !fullscreen) { @@ -4733,7 +4600,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, mWindow->setSize(size); } - if (fsaa == old_fsaa) + //if (fsaa == old_fsaa) { return TRUE; } @@ -4762,13 +4629,13 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, gSavedSettings.setS32("WindowY", old_pos.mY); } - mWindow->setFSAASamples(fsaa); + //mWindow->setFSAASamples(fsaa); result_first_try = mWindow->switchContext(fullscreen, size, disable_vsync); if (!result_first_try) { // try to switch back - mWindow->setFSAASamples(old_fsaa); + //mWindow->setFSAASamples(old_fsaa); result_second_try = mWindow->switchContext(old_fullscreen, old_size, disable_vsync); if (!result_second_try) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 2ec8ced543..a6cb22a111 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -692,10 +692,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mBakedTextureDatas[i].mTextureIndex = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i); } - mDirtyMesh = TRUE; // Dirty geometry, need to regenerate. + mDirtyMesh = 2; // Dirty geometry, need to regenerate. mMeshTexturesDirty = FALSE; - mShadow0Facep = NULL; - mShadow1Facep = NULL; mHeadp = NULL; mIsBuilt = FALSE; @@ -731,12 +729,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRippleTimeLast = 0.f; - mShadowImagep = LLViewerTextureManager::getFetchedTextureFromFile("foot_shadow.j2c"); - - // GL NOT ACTIVE HERE - //gGL.getTexUnit(0)->bind(mShadowImagep.get()); - //mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP); - mInAir = FALSE; mStepOnLand = TRUE; @@ -1922,7 +1914,7 @@ void LLVOAvatar::updateMeshData() } if(num_vertices < 1)//skip empty meshes { - break ; + continue ; } if(last_v_num > 0)//put the last inserted part into next vertex buffer. { @@ -1944,6 +1936,8 @@ void LLVOAvatar::updateMeshData() // resize immediately facep->setSize(num_vertices, num_indices); + bool terse_update = false; + if(facep->mVertexBuffer.isNull()) { facep->mVertexBuffer = new LLVertexBufferAvatar(); @@ -1951,7 +1945,15 @@ void LLVOAvatar::updateMeshData() } else { - facep->mVertexBuffer->resizeBuffer(num_vertices, num_indices) ; + if (facep->mVertexBuffer->getRequestedIndices() == num_indices && + facep->mVertexBuffer->getRequestedVerts() == num_vertices) + { + terse_update = true; + } + else + { + facep->mVertexBuffer->resizeBuffer(num_vertices, num_indices) ; + } } facep->setGeomIndex(0); @@ -1966,7 +1968,7 @@ void LLVOAvatar::updateMeshData() for(S32 k = j ; k < part_index ; k++) { - mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR); + mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update); } stop_glerror(); @@ -2319,12 +2321,6 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) LLJoint::sNumUpdates = 0; LLJoint::sNumTouches = 0; - // *NOTE: this is necessary for the floating name text above your head. - if (mDrawable.notNull()) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_SHADOW, TRUE); - } - BOOL visible = isVisible() || mNeedsAnimUpdate; // update attachments positions @@ -3652,12 +3648,19 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) return num_indices; } - if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) + LLFace* face = mDrawable->getFace(0); + + bool needs_rebuild = !face || face->mVertexBuffer.isNull() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY); + + if (needs_rebuild || mDirtyMesh) { //LOD changed or new mesh created, allocate new vertex buffer if needed - updateMeshData(); - mDirtyMesh = FALSE; - mNeedsSkin = TRUE; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) + { + updateMeshData(); + mDirtyMesh = 0; + mNeedsSkin = TRUE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } } if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -3905,54 +3908,6 @@ U32 LLVOAvatar::renderRigid() return num_indices; } -U32 LLVOAvatar::renderFootShadows() -{ - U32 num_indices = 0; - - if (!mIsBuilt) - { - return 0; - } - - if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead())) - { - return 0; - } - - if (!mIsBuilt) - { - return 0; - } - - // Don't render foot shadows if your lower body is completely invisible. - // (non-humanoid avatars rule!) - if (!isTextureVisible(TEX_LOWER_BAKED)) - { - return 0; - } - - // Update the shadow, tractor, and text label geometry. - if (mDrawable->isState(LLDrawable::REBUILD_SHADOW) && !isImpostor()) - { - updateShadowFaces(); - mDrawable->clearState(LLDrawable::REBUILD_SHADOW); - } - - U32 foot_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0; - - LLGLDepthTest test(GL_TRUE, GL_FALSE); - //render foot shadows - LLGLEnable blend(GL_BLEND); - gGL.getTexUnit(0)->bind(mShadowImagep, TRUE); - glColor4fv(mShadow0Facep->getRenderColor().mV); - mShadow0Facep->renderIndexed(foot_mask); - glColor4fv(mShadow1Facep->getRenderColor().mV); - mShadow1Facep->renderIndexed(foot_mask); - - return num_indices; -} - U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) { if (!mImpostor.isComplete()) @@ -4073,11 +4028,6 @@ void LLVOAvatar::updateTextures() { setDebugText(llformat("%4.0f:%4.0f", fsqrtf(mMinPixelArea),fsqrtf(mMaxPixelArea))); } - - if( render_avatar ) - { - mShadowImagep->addTextureStats(mPixelArea); - } } @@ -5223,7 +5173,7 @@ BOOL LLVOAvatar::updateJointLODs() if (res) { sNumLODChangesThisFrame++; - dirtyMesh(); + dirtyMesh(2); return TRUE; } } @@ -5247,18 +5197,9 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) mDrawable->addFace(poolp, NULL); mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR); - LLFace *facep; - - // Add faces for the foot shadows - facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep); - mShadow0Facep = facep; - - facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep); - mShadow1Facep = facep; - mNumInitFaces = mDrawable->getNumFaces() ; - dirtyMesh(); + dirtyMesh(2); return mDrawable; } @@ -5298,107 +5239,6 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) } //----------------------------------------------------------------------------- -// updateShadowFaces() -//----------------------------------------------------------------------------- -void LLVOAvatar::updateShadowFaces() -{ - LLFace *face0p = mShadow0Facep; - LLFace *face1p = mShadow1Facep; - - // - // render avatar shadows - // - if (mInAir || mUpdatePeriod >= IMPOSTOR_PERIOD) - { - face0p->setSize(0, 0); - face1p->setSize(0, 0); - return; - } - - LLSprite sprite(mShadowImagep.notNull() ? mShadowImagep->getID() : LLUUID::null); - sprite.setFollow(FALSE); - const F32 cos_angle = gSky.getSunDirection().mV[2]; - F32 cos_elev = sqrt(1 - cos_angle * cos_angle); - if (cos_angle < 0) cos_elev = -cos_elev; - sprite.setSize(0.4f + cos_elev * 0.8f, 0.3f); - LLVector3 sun_vec = gSky.mVOSkyp ? gSky.mVOSkyp->getToSun() : LLVector3(0.f, 0.f, 0.f); - - if (mShadowImagep->hasGLTexture()) - { - LLVector3 normal; - LLVector3d shadow_pos; - LLVector3 shadow_pos_agent; - F32 foot_height; - - if (mFootLeftp) - { - LLVector3 joint_world_pos = mFootLeftp->getWorldPosition(); - // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now - // but we make an explicit ray trace call in expectation of future improvements - resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos), - gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal); - shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos); - foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ]; - - // Pull sprite in direction of surface normal - shadow_pos_agent += normal * SHADOW_OFFSET_AMT; - - // Render sprite - sprite.setNormal(normal); - if (isSelf() && gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) - { - sprite.setColor(0.f, 0.f, 0.f, 0.f); - } - else - { - sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f)); - } - sprite.setPosition(shadow_pos_agent); - - LLVector3 foot_to_knee = mKneeLeftp->getWorldPosition() - joint_world_pos; - //foot_to_knee.normalize(); - foot_to_knee -= projected_vec(foot_to_knee, sun_vec); - sprite.setYaw(azimuth(sun_vec - foot_to_knee)); - - sprite.updateFace(*face0p); - } - - if (mFootRightp) - { - LLVector3 joint_world_pos = mFootRightp->getWorldPosition(); - // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now - // but we make an explicit ray trace call in expectation of future improvements - resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos), - gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal); - shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos); - foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ]; - - // Pull sprite in direction of surface normal - shadow_pos_agent += normal * SHADOW_OFFSET_AMT; - - // Render sprite - sprite.setNormal(normal); - if (isSelf() && gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) - { - sprite.setColor(0.f, 0.f, 0.f, 0.f); - } - else - { - sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f)); - } - sprite.setPosition(shadow_pos_agent); - - LLVector3 foot_to_knee = mKneeRightp->getWorldPosition() - joint_world_pos; - //foot_to_knee.normalize(); - foot_to_knee -= projected_vec(foot_to_knee, sun_vec); - sprite.setYaw(azimuth(sun_vec - foot_to_knee)); - - sprite.updateFace(*face1p); - } - } -} - -//----------------------------------------------------------------------------- // updateSexDependentLayerSets() //----------------------------------------------------------------------------- void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake ) @@ -5413,9 +5253,12 @@ void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake ) //----------------------------------------------------------------------------- void LLVOAvatar::dirtyMesh() { - mDirtyMesh = TRUE; + dirtyMesh(1); +} +void LLVOAvatar::dirtyMesh(S32 priority) +{ + mDirtyMesh = llmax(mDirtyMesh, priority); } - //----------------------------------------------------------------------------- // hideSkirt() //----------------------------------------------------------------------------- @@ -7593,18 +7436,15 @@ BOOL LLVOAvatar::updateLOD() BOOL res = updateJointLODs(); LLFace* facep = mDrawable->getFace(0); - if (facep->mVertexBuffer.isNull() || - (LLVertexBuffer::sEnableVBOs && - ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) != - (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE)))) + if (facep->mVertexBuffer.isNull()) { - mDirtyMesh = TRUE; + dirtyMesh(2); } - if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) + if (mDirtyMesh >= 2 || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) { //LOD changed or new mesh created, allocate new vertex buffer if needed updateMeshData(); - mDirtyMesh = FALSE; + mDirtyMesh = 0; mNeedsSkin = TRUE; mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 24bd2739f7..9a1e6dee15 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -338,7 +338,6 @@ private: **/ public: - U32 renderFootShadows(); U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); @@ -572,7 +571,8 @@ protected: void releaseMeshData(); virtual void restoreMeshData(); private: - BOOL mDirtyMesh; + void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority + S32 mDirtyMesh; // 0 -- not dirty, 1 -- morphed, 2 -- LOD BOOL mMeshTexturesDirty; typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 594435475f..15b04fa746 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2451,6 +2451,17 @@ void LLVOVolume::updateSpotLightPriority() } +bool LLVOVolume::isLightSpotlight() const +{ + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (params) + { + return params->isLightSpotlight(); + } + return false; +} + + LLViewerTexture* LLVOVolume::getLightTexture() { LLUUID id = getLightTextureID(); @@ -2910,9 +2921,7 @@ F32 LLVOVolume::getBinRadius() { LLFace* face = mDrawable->getFace(i); if (face->getPoolType() == LLDrawPool::POOL_ALPHA && - (!LLPipeline::sFastAlpha || - face->getFaceColor().mV[3] != 1.f || - !face->getTexture()->getIsAlphaMask())) + !face->canRenderAsMask()) { alpha_wrap = TRUE; break; @@ -3188,11 +3197,10 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, S32 idx = draw_vec.size()-1; - BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || - (type == LLRenderPass::PASS_INVISIBLE) || - (type == LLRenderPass::PASS_ALPHA ? facep->isState(LLFace::FULLBRIGHT) : FALSE); - + (type == LLRenderPass::PASS_INVISIBLE) || + (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)); + if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) { llwarns << "Non fullbright face has no normals!" << llendl; @@ -3217,16 +3225,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, model_mat = &(drawable->getRegion()->mRenderMatrix); } - U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0); + + U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; LLViewerTexture* tex = facep->getTexture(); - U8 glow = 0; - - if (type == LLRenderPass::PASS_GLOW) - { - glow = (U8) (facep->getTextureEntry()->getGlow() * 255); - } + U8 glow = (U8) (facep->getTextureEntry()->getGlow() * 255); if (facep->mVertexBuffer.isNull()) { @@ -3291,6 +3295,7 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); + void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (group->changeLOD()) @@ -3416,10 +3421,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (type == LLDrawPool::POOL_ALPHA) { - if (LLPipeline::sFastAlpha && - (te->getColor().mV[VW] == 1.0f) && - (!te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible, need to figure out why - for now, avoid - facep->getTexture()->getIsAlphaMask()) + if (facep->canRenderAsMask()) { //can be treated as alpha mask simple_faces.push_back(facep); } @@ -3521,6 +3523,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry"); +static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM_PARTIAL("Terse Rebuild"); + void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { llassert(group); @@ -3533,6 +3537,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { + LLFastTimer t(FTM_VOLUME_GEOM_PARTIAL); LLDrawable* drawablep = *drawable_iter; if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) @@ -3760,15 +3765,12 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: const LLTextureEntry* te = facep->getTextureEntry(); - BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE; + BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; if (is_alpha) { // can we safely treat this as an alpha mask? - if (LLPipeline::sFastAlpha && - (te->getColor().mV[VW] == 1.0f) && - (!te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible, need to figure out why - for now, avoid - facep->getTexture()->getIsAlphaMask()) + if (facep->canRenderAsMask()) { if (te->getFullbright()) { @@ -3793,66 +3795,76 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD && LLPipeline::sRenderBump && te->getShiny()) - { + { //shiny if (tex->getPrimaryFormat() == GL_ALPHA) - { + { //invisiprim+shiny registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); } else if (LLPipeline::sRenderDeferred) - { - if (te->getBumpmap()) - { - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else if (te->getFullbright()) - { + { //deferred rendering + if (te->getFullbright()) + { //register in post deferred fullbright shiny pass registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + if (te->getBumpmap()) + { //register in post deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } + } + else if (te->getBumpmap()) + { //register in deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_BUMP); } else - { + { //register in deferred simple pass (deferred simple includes shiny) llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } else if (fullbright) - { + { //not deferred, register in standard fullbright shiny pass registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); } else - { + { //not deferred or fullbright, register in standard shiny pass registerFace(group, facep, LLRenderPass::PASS_SHINY); } } else - { + { //not alpha and not shiny if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) - { + { //invisiprim registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); } else if (fullbright) - { + { //fullbright registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) + { //if this is the deferred render and a bump map is present, register in post deferred bump + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } } else { - if (LLPipeline::sRenderDeferred && te->getBumpmap()) - { + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) + { //non-shiny or fullbright deferred bump registerFace(group, facep, LLRenderPass::PASS_BUMP); } else - { + { //all around simple llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } + //not sure why this is here -- shiny HUD attachments maybe? -- davep 5/11/2010 if (!is_alpha && te->getShiny() && LLPipeline::sRenderBump) { registerFace(group, facep, LLRenderPass::PASS_SHINY); } } + //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 if (!is_alpha && !LLPipeline::sRenderDeferred) { llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); @@ -3864,7 +3876,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } } - if (LLPipeline::sRenderGlow && te->getGlow() > 0.f) + if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) { registerFace(group, facep, LLRenderPass::PASS_GLOW); } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index a8bb597f93..fbae011ffc 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -215,6 +215,7 @@ public: LLColor3 getLightBaseColor() const; // not scaled by intensity LLColor3 getLightColor() const; // scaled by intensity LLUUID getLightTextureID() const; + bool isLightSpotlight() const; LLVector3 getSpotLightParams() const; void updateSpotLightPriority(); F32 getSpotLightPriority() const; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 58b9f5ce18..71809e3972 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1029,9 +1029,11 @@ void LLWorld::disconnectRegions() } } +static LLFastTimer::DeclareTimer FTM_ENABLE_SIMULATOR("Enable Sim"); void process_enable_simulator(LLMessageSystem *msg, void **user_data) { + LLFastTimer t(FTM_ENABLE_SIMULATOR); // enable the appropriate circuit for this simulator and // add its values into the gSimulator structure U64 handle; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 2d2fc38573..b027fae033 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -191,6 +191,7 @@ std::string gPoolNames[] = }; void drawBox(const LLVector3& c, const LLVector3& r); +void drawBoxOutline(const LLVector3& pos, const LLVector3& size); U32 nhpo2(U32 v) { @@ -268,7 +269,8 @@ BOOL LLPipeline::sRenderHighlight = TRUE; BOOL LLPipeline::sForceOldBakedUpload = FALSE; S32 LLPipeline::sUseOcclusion = 0; BOOL LLPipeline::sDelayVBUpdate = TRUE; -BOOL LLPipeline::sFastAlpha = TRUE; +BOOL LLPipeline::sAutoMaskAlphaDeferred = TRUE; +BOOL LLPipeline::sAutoMaskAlphaNonDeferred = FALSE; BOOL LLPipeline::sDisableShaders = FALSE; BOOL LLPipeline::sRenderBump = TRUE; BOOL LLPipeline::sUseTriStrips = TRUE; @@ -327,7 +329,6 @@ LLPipeline::LLPipeline() : mInitialized(FALSE), mVertexShadersEnabled(FALSE), mVertexShadersLoaded(0), - mRenderTypeMask(0), mRenderDebugFeatureMask(0), mRenderDebugMask(0), mOldRenderDebugMask(0), @@ -361,6 +362,7 @@ void LLPipeline::init() sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); + LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO"); sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); @@ -380,7 +382,11 @@ void LLPipeline::init() LLViewerStats::getInstance()->mTrianglesDrawnStat.reset(); resetFrameStats(); - mRenderTypeMask = 0xffffffff; // All render types start on + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled + } + mRenderDebugFeatureMask = 0xffffffff; // All debugging features on mRenderDebugMask = 0; // All debug starts off @@ -407,6 +413,8 @@ void LLPipeline::init() { mSpotLightFade[i] = 1.f; } + + setLightingDetail(-1); } LLPipeline::~LLPipeline() @@ -509,6 +517,7 @@ void LLPipeline::destroyGL() } static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); + void LLPipeline::resizeScreenTexture() { LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE); @@ -565,9 +574,12 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale"); + //HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug) + U32 shadow_fmt = gGLManager.mIsATI ? GL_ALPHA : 0; + for (U32 i = 0; i < 4; i++) { - mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + mShadow[i].allocate(U32(resX*scale),U32(resY*scale), shadow_fmt, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE); } @@ -576,11 +588,9 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) for (U32 i = 4; i < 6; i++) { - mShadow[i].allocate(width, height, 0, TRUE, FALSE); + mShadow[i].allocate(width, height, shadow_fmt, TRUE, FALSE); } - - width = nhpo2(resX)/2; height = nhpo2(resY)/2; mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE); @@ -624,10 +634,12 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) void LLPipeline::updateRenderDeferred() { BOOL deferred = (gSavedSettings.getBOOL("RenderDeferred") && - LLRenderTarget::sUseFBO && - gSavedSettings.getBOOL("VertexShaderEnable") && - gSavedSettings.getBOOL("RenderAvatarVP") && - gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE; + LLRenderTarget::sUseFBO && + LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + gSavedSettings.getBOOL("VertexShaderEnable") && + gSavedSettings.getBOOL("RenderAvatarVP") && + (gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE) && + !gUseWireframe; sRenderDeferred = deferred; } @@ -902,13 +914,18 @@ S32 LLPipeline::setLightingDetail(S32 level) if (level < 0) { - level = gSavedSettings.getS32("RenderLightingDetail"); + if (gSavedSettings.getBOOL("VertexShaderEnable")) + { + level = 1; + } + else + { + level = 0; + } } level = llclamp(level, 0, getMaxLightingDetail()); if (level != mLightingDetail) { - gSavedSettings.setS32("RenderLightingDetail", level); - mLightingDetail = level; if (mVertexShadersLoaded == 1) @@ -1512,8 +1529,10 @@ BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera) BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max) { - min = LLVector3(F32_MAX, F32_MAX, F32_MAX); - max = LLVector3(-F32_MAX, -F32_MAX, -F32_MAX); + const F32 X = 65536.f; + + min = LLVector3(X,X,X); + max = LLVector3(-X,-X,-X); U32 saved_camera_id = LLViewerCamera::sCurCameraID; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; @@ -1946,31 +1965,40 @@ void LLPipeline::updateGeom(F32 max_dtime) void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) { LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_VISIBLE); - if(!drawablep || drawablep->isDead()) - { - return; - } - - if (drawablep->isSpatialBridge()) - { - LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; - if (root && root->getParent() && root->getVObj() && root->getVObj()->isAttachment()) + if(drawablep && !drawablep->isDead()) + { + if (drawablep->isSpatialBridge()) { - LLVOAvatar* av = root->getParent()->getVObj()->asAvatar(); - if (av && av->isImpostor()) + const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; + llassert(root); // trying to catch a bad assumption + if (root && // // this test may not be needed, see above + root->getVObj()->isAttachment()) { - return; + LLDrawable* rootparent = root->getParent(); + if (rootparent) // this IS sometimes NULL + { + LLViewerObject *vobj = rootparent->getVObj(); + llassert(vobj); // trying to catch a bad assumption + if (vobj) // this test may not be needed, see above + { + const LLVOAvatar* av = vobj->asAvatar(); + if (av && av->isImpostor()) + { + return; + } + } + } } + sCull->pushBridge((LLSpatialBridge*) drawablep); + } + else + { + sCull->pushDrawable(drawablep); } - sCull->pushBridge((LLSpatialBridge*) drawablep); - } - else - { - sCull->pushDrawable(drawablep); - } - drawablep->setVisible(camera); + drawablep->setVisible(camera); + } } void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) @@ -2180,14 +2208,13 @@ static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order"); void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { - const U32 face_mask = (1 << LLPipeline::RENDER_TYPE_AVATAR) | - (1 << LLPipeline::RENDER_TYPE_GROUND) | - (1 << LLPipeline::RENDER_TYPE_TERRAIN) | - (1 << LLPipeline::RENDER_TYPE_TREE) | - (1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_WATER); - - if (mRenderTypeMask & face_mask) + if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_GROUND, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::END_RENDER_TYPES)) { //clear faces from face pools LLFastTimer t(FTM_RESET_DRAWORDER); @@ -3410,26 +3437,14 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); - renderHighlights(); - mHighlightFaces.clear(); - - renderDebug(); - - LLVertexBuffer::unbind(); - - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - // Render debugging beacons. - gObjectList.renderObjectBeacons(); - gObjectList.resetObjectBeacons(); - } - if (occlude) { occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); doOcclusion(camera); + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); } } @@ -3592,12 +3607,17 @@ void LLPipeline::renderDebug() for (U32 i = 0; i < 8; i++) { + LLVector3* frust = mShadowCamera[i].mAgentFrustum; + if (i > 3) - { + { //render shadow frusta as volumes + if (mShadowFrustPoints[i-4].empty()) + { + continue; + } + gGL.color4fv(col+(i-4)*4); - LLVector3* frust = mShadowCamera[i].mAgentFrustum; - gGL.begin(LLRender::TRIANGLE_STRIP); gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); @@ -3625,31 +3645,49 @@ void LLPipeline::renderDebug() if (i < 4) { - gGL.begin(LLRender::LINES); - - F32* c = col+i*4; - for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j) + + if (i == 0 || !mShadowFrustPoints[i].empty()) { - - gGL.color3fv(c); + //render visible point cloud + gGL.flush(); + glPointSize(8.f); + gGL.begin(LLRender::POINTS); - for (U32 k = 0; k < mShadowFrustPoints[i].size(); ++k) - { - if (j != k) - { - gGL.vertex3fv(mShadowFrustPoints[i][j].mV); - gGL.vertex3fv(mShadowFrustPoints[i][k].mV); - } - } + F32* c = col+i*4; + gGL.color3fv(c); - if (!mShadowFrustOrigin[i].isExactlyZero()) - { + for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j) + { gGL.vertex3fv(mShadowFrustPoints[i][j].mV); - gGL.color4f(1,1,1,1); - gGL.vertex3fv(mShadowFrustOrigin[i].mV); + } + gGL.end(); + + gGL.flush(); + glPointSize(1.f); + + LLVector3* ext = mShadowExtents[i]; + LLVector3 pos = (ext[0]+ext[1])*0.5f; + LLVector3 size = (ext[1]-ext[0])*0.5f; + drawBoxOutline(pos, size); + + //render camera frustum splits as outlines + gGL.begin(LLRender::LINES); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV); + gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); + gGL.end(); } - gGL.end(); + } /*for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -4273,7 +4311,7 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.0f); glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f); glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 0.0f); - glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 180.0f); + glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 180.0f); } else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini) { @@ -4561,32 +4599,41 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) LLVector4 light_pos_gl(light_pos, 1.0f); F32 light_radius = llmax(light->getLightRadius(), 0.001f); - F32 atten, quad; -#if 0 //1.9.1 - if (pool->getVertexShaderLevel() > 0) - { - atten = light_radius; - quad = llmax(light->getLightFalloff(), 0.0001f); - } - else -#endif - { - F32 x = (3.f * (1.f + light->getLightFalloff())); - atten = x / (light_radius); // % of brightness at radius - quad = 0.0f; - } + F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic? probably trying to match a historic behavior. + float linatten = x / (light_radius); // % of brightness at radius + mHWLightColors[cur_light] = light_color; S32 gllight = GL_LIGHT0+cur_light; glLightfv(gllight, GL_POSITION, light_pos_gl.mV); glLightfv(gllight, GL_DIFFUSE, light_color.mV); glLightfv(gllight, GL_AMBIENT, LLColor4::black.mV); - glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV); glLightf (gllight, GL_CONSTANT_ATTENUATION, 0.0f); - glLightf (gllight, GL_LINEAR_ATTENUATION, atten); - glLightf (gllight, GL_QUADRATIC_ATTENUATION, quad); - glLightf (gllight, GL_SPOT_EXPONENT, 0.0f); - glLightf (gllight, GL_SPOT_CUTOFF, 180.0f); + glLightf (gllight, GL_LINEAR_ATTENUATION, linatten); + glLightf (gllight, GL_QUADRATIC_ATTENUATION, 0.0f); + if (light->isLightSpotlight()) // directional (spot-)light + { + 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; + //llinfos << "SPOT!!!!!!! fov: " << spotparams.mV[0] << " focus: " << spotparams.mV[1] << " dir: " << at_axis << llendl; + glLightfv(gllight, GL_SPOT_DIRECTION, at_axis.mV); + glLightf (gllight, GL_SPOT_EXPONENT, 2.0f); // 2.0 = good old dot product ^ 2 + glLightf (gllight, GL_SPOT_CUTOFF, 90.0f); // hemisphere + const float specular[] = {0.f, 0.f, 0.f, 0.f}; + glLightfv(gllight, GL_SPECULAR, specular); + } + else // omnidirectional (point) light + { + glLightf (gllight, GL_SPOT_EXPONENT, 0.0f); + glLightf (gllight, GL_SPOT_CUTOFF, 180.0f); + + // we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight + const float specular[] = {0.f, 0.f, 0.f, 1.f}; + glLightfv(gllight, GL_SPECULAR, specular); + //llinfos << "boring light" << llendl; + } cur_light++; if (cur_light >= 8) { @@ -4613,13 +4660,10 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) LLVector4 light_pos_gl(light_pos, 1.0f); F32 light_radius = 16.f; - F32 atten, quad; - { - F32 x = 3.f; - atten = x / (light_radius); // % of brightness at radius - quad = 0.0f; - } + F32 x = 3.f; + float linatten = x / (light_radius); // % of brightness at radius + mHWLightColors[2] = light_color; S32 gllight = GL_LIGHT2; glLightfv(gllight, GL_POSITION, light_pos_gl.mV); @@ -4627,8 +4671,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) glLightfv(gllight, GL_AMBIENT, LLColor4::black.mV); glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV); glLightf (gllight, GL_CONSTANT_ATTENUATION, 0.0f); - glLightf (gllight, GL_LINEAR_ATTENUATION, atten); - glLightf (gllight, GL_QUADRATIC_ATTENUATION, quad); + glLightf (gllight, GL_LINEAR_ATTENUATION, linatten); + glLightf (gllight, GL_QUADRATIC_ATTENUATION, 0.0f); glLightf (gllight, GL_SPOT_EXPONENT, 0.0f); glLightf (gllight, GL_SPOT_CUTOFF, 180.0f); } @@ -4749,16 +4793,16 @@ void LLPipeline::enableLightsFullbright(const LLColor4& color) enableLights(mask); glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV); - if (mLightingDetail >= 2) + /*if (mLightingDetail >= 2) { glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default - } + }*/ } void LLPipeline::disableLights() { enableLights(0); // no lighting (full bright) - glColor4f(1.f, 1.f, 1.f, 1.f); // lighting color = white by default + //glColor4f(1.f, 1.f, 1.f, 1.f); // lighting color = white by default } //============================================================================ @@ -4948,8 +4992,7 @@ void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light) //static void LLPipeline::toggleRenderType(U32 type) { - U32 bit = (1<<type); - gPipeline.mRenderTypeMask ^= bit; + gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type]; } //static @@ -5361,6 +5404,7 @@ void LLPipeline::resetVertexBuffers() { sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); + LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO"); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -5496,6 +5540,7 @@ void LLPipeline::bindScreenToTexture() } static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom"); + void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM); @@ -5818,6 +5863,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + + if (LLRenderTarget::sUseFBO) + { //copy depth buffer from mScreen to framebuffer + LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), + 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } } @@ -5834,8 +5885,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) } +static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred"); + void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post, U32 noise_map) { + LLFastTimer t(FTM_BIND_DEFERRED); + if (noise_map == 0xFFFFFFFF) { noise_map = mNoiseMap; @@ -6173,11 +6228,16 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen matrix_nondiag, matrix_nondiag, matrix_diag}; shader.uniformMatrix3fv("ssao_effect_mat", 1, GL_FALSE, ssao_effect_mat); + F32 shadow_offset_error = 1.f + gSavedSettings.getF32("RenderShadowOffsetError") * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + F32 shadow_bias_error = 1.f + gSavedSettings.getF32("RenderShadowBiasError") * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f); - shader.uniform1f("alpha_soften", gSavedSettings.getF32("RenderDeferredAlphaSoften")); - shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset")); - shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias")); + shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset")*shadow_offset_error); + shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias")*shadow_bias_error); + shader.uniform1f ("spot_shadow_offset", gSavedSettings.getF32("RenderSpotShadowOffset")); + shader.uniform1f("spot_shadow_bias", gSavedSettings.getF32("RenderSpotShadowBias")); + shader.uniform1f("lum_scale", gSavedSettings.getF32("RenderLuminanceScale")); shader.uniform1f("sun_lum_scale", gSavedSettings.getF32("RenderSunLuminanceScale")); shader.uniform1f("sun_lum_offset", gSavedSettings.getF32("RenderSunLuminanceOffset")); @@ -6271,16 +6331,16 @@ void LLPipeline::renderDeferredLighting() glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); } - if (gSavedSettings.getBOOL("RenderDeferredShadow")) - { - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); - mDeferredLight[0].bindTarget(); - if (gSavedSettings.getBOOL("RenderDeferredSun")) + mDeferredLight[0].bindTarget(); + + if (gSavedSettings.getBOOL("RenderDeferredSSAO") || gSavedSettings.getS32("RenderShadowDetail") > 0) + { { //paint shadow/SSAO light map (direct lighting lightmap) LLFastTimer ftm(FTM_SUN_SHADOW); bindDeferredShader(gDeferredSunProgram, 0); @@ -6321,18 +6381,22 @@ void LLPipeline::renderDeferredLighting() unbindDeferredShader(gDeferredSunProgram); } - else - { - mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT); - } + } + else + { + glClearColor(1,1,1,1); + mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); + } - mDeferredLight[0].flush(); + mDeferredLight[0].flush(); + { //global illumination specific block (still experimental) if (gSavedSettings.getBOOL("RenderDeferredBlurLight") && - gSavedSettings.getBOOL("RenderDeferredGI")) - { + gSavedSettings.getBOOL("RenderDeferredGI")) + { LLFastTimer ftm(FTM_EDGE_DETECTION); - //get edge map + //generate edge map LLGLDisable blend(GL_BLEND); LLGLDisable test(GL_ALPHA_TEST); LLGLDepthTest depth(GL_FALSE); @@ -6429,79 +6493,79 @@ void LLPipeline::renderDeferredLighting() unbindDeferredShader(gDeferredPostGIProgram); } } + } - if (gSavedSettings.getBOOL("RenderDeferredBlurLight")) - { //soften direct lighting lightmap - LLFastTimer ftm(FTM_SOFTEN_SHADOW); - //blur lightmap - mDeferredLight[1].bindTarget(); + if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + { //soften direct lighting lightmap + LLFastTimer ftm(FTM_SOFTEN_SHADOW); + //blur lightmap + mDeferredLight[1].bindTarget(); - glClearColor(1,1,1,1); - mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); - glClearColor(0,0,0,0); - - bindDeferredShader(gDeferredBlurLightProgram); + glClearColor(1,1,1,1); + mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); + + bindDeferredShader(gDeferredBlurLightProgram); - LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); - const U32 kern_length = 4; - F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); - F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); + LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); + const U32 kern_length = 4; + F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); + F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); - // sample symmetrically with the middle sample falling exactly on 0.0 - F32 x = 0.f; + // sample symmetrically with the middle sample falling exactly on 0.0 + F32 x = 0.f; - LLVector3 gauss[32]; // xweight, yweight, offset + LLVector3 gauss[32]; // xweight, yweight, offset - for (U32 i = 0; i < kern_length; i++) - { - gauss[i].mV[0] = llgaussian(x, go.mV[0]); - gauss[i].mV[1] = llgaussian(x, go.mV[1]); - gauss[i].mV[2] = x; - x += 1.f; - } + for (U32 i = 0; i < kern_length; i++) + { + gauss[i].mV[0] = llgaussian(x, go.mV[0]); + gauss[i].mV[1] = llgaussian(x, go.mV[1]); + gauss[i].mV[2] = x; + x += 1.f; + } - gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); - gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); - gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); + gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - - mDeferredLight[1].flush(); - unbindDeferredShader(gDeferredBlurLightProgram); + mDeferredLight[1].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); - bindDeferredShader(gDeferredBlurLightProgram, 1); - mDeferredLight[0].bindTarget(); + bindDeferredShader(gDeferredBlurLightProgram, 1); + mDeferredLight[0].bindTarget(); - gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); + gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - mDeferredLight[0].flush(); - unbindDeferredShader(gDeferredBlurLightProgram); + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); } - - stop_glerror(); - glPopMatrix(); - stop_glerror(); - glMatrixMode(GL_MODELVIEW); - stop_glerror(); - glPopMatrix(); - stop_glerror(); + mDeferredLight[0].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); } + stop_glerror(); + glPopMatrix(); + stop_glerror(); + glMatrixMode(GL_MODELVIEW); + stop_glerror(); + glPopMatrix(); + stop_glerror(); + //copy depth and stencil from deferred screen //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); @@ -6509,11 +6573,15 @@ void LLPipeline::renderDeferredLighting() if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2) { mDeferredLight[1].bindTarget(); - mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); + // clear color buffer here (GI) - zeroing alpha (glow) is important or it will accumulate against sky + glClearColor(0,0,0,0); + mScreen.clear(GL_COLOR_BUFFER_BIT); } else { mScreen.bindTarget(); + // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky + glClearColor(0,0,0,0); mScreen.clear(GL_COLOR_BUFFER_BIT); } @@ -6550,15 +6618,16 @@ void LLPipeline::renderDeferredLighting() LLGLDisable stencil(GL_STENCIL_TEST); gGL.setSceneBlendType(LLRender::BT_ALPHA); - U32 render_mask = mRenderTypeMask; - mRenderTypeMask = mRenderTypeMask & - ((1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_CLOUDS) | - (1 << LLPipeline::RENDER_TYPE_WL_SKY)); + gPipeline.pushRenderTypeMask(); + + gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_CLOUDS, + LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::END_RENDER_TYPES); renderGeomPostDeferred(*LLViewerCamera::getInstance()); - mRenderTypeMask = render_mask; + gPipeline.popRenderTypeMask(); } BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights"); @@ -6603,6 +6672,15 @@ void LLPipeline::renderDeferredLighting() continue; } + if (volume->isAttachment()) + { + if (!sRenderAttachedLights) + { + continue; + } + } + + LLVector3 center = drawablep->getPositionAgent(); F32* c = center.mV; F32 s = volume->getLightRadius()*1.5f; @@ -6653,7 +6731,7 @@ void LLPipeline::renderDeferredLighting() { //draw box if camera is outside box if (render_local) { - if (volume->getLightTexture()) + if (volume->isLightSpotlight()) { drawablep->getVOVolume()->updateSpotLightPriority(); spot_lights.push_back(drawablep); @@ -6670,7 +6748,7 @@ void LLPipeline::renderDeferredLighting() } else if (render_fullscreen) { - if (volume->getLightTexture()) + if (volume->isLightSpotlight()) { drawablep->getVOVolume()->updateSpotLightPriority(); fullscreen_spot_lights.push_back(drawablep); @@ -6871,29 +6949,48 @@ void LLPipeline::renderDeferredLighting() LLGLDisable blend(GL_BLEND); LLGLDisable stencil(GL_STENCIL_TEST); - U32 render_mask = mRenderTypeMask; - mRenderTypeMask = mRenderTypeMask & - ((1 << LLPipeline::RENDER_TYPE_ALPHA) | - (1 << LLPipeline::RENDER_TYPE_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_VOLUME) | - (1 << LLPipeline::RENDER_TYPE_GLOW) | - (1 << LLPipeline::RENDER_TYPE_BUMP) | - (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) | - (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) | - (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) | - (1 << LLPipeline::RENDER_TYPE_PASS_GLOW) | - (1 << LLPipeline::RENDER_TYPE_PASS_GRASS) | - (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) | - (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY) | - (1 << LLPipeline::RENDER_TYPE_AVATAR)); + 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, + END_RENDER_TYPES); renderGeomPostDeferred(*LLViewerCamera::getInstance()); - mRenderTypeMask = render_mask; + popRenderTypeMask(); + } + + { + //render highlights, etc. + renderHighlights(); + mHighlightFaces.clear(); + + renderDebug(); + + LLVertexBuffer::unbind(); + + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + // Render debugging beacons. + gObjectList.renderObjectBeacons(); + LLHUDObject::renderAll(); + gObjectList.resetObjectBeacons(); + } } mScreen.flush(); @@ -7130,8 +7227,8 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLPipeline::sUseOcclusion = llmin(occlusion, 1); - U32 type_mask = gPipeline.mRenderTypeMask; - + gPipeline.pushRenderTypeMask(); + glh::matrix4f projection = glh_get_current_projection(); glh::matrix4f mat; @@ -7199,44 +7296,48 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) glCullFace(GL_FRONT); static LLCullResult ref_result; - U32 ref_mask = 0; + if (LLDrawPoolWater::sNeedsDistortionUpdate) { //initial sky pass (no user clip plane) { //mask out everything but the sky - U32 tmp = mRenderTypeMask; - mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_WL_SKY)); + gPipeline.pushRenderTypeMask(); + gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::END_RENDER_TYPES); static LLCullResult result; updateCull(camera, result); llpushcallstacks ; stateSort(camera, result); - mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_CLOUDS) | - (1 << LLPipeline::RENDER_TYPE_WL_SKY)); + andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_CLOUDS, + LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::END_RENDER_TYPES); + renderGeom(camera, TRUE); - mRenderTypeMask = tmp; + gPipeline.popRenderTypeMask(); } - U32 mask = mRenderTypeMask; - mRenderTypeMask &= ~((1<<LLPipeline::RENDER_TYPE_WATER) | - (1<<LLPipeline::RENDER_TYPE_GROUND) | - (1<<LLPipeline::RENDER_TYPE_SKY) | - (1<<LLPipeline::RENDER_TYPE_CLOUDS)); - - if (gSavedSettings.getBOOL("RenderWaterReflections")) + gPipeline.pushRenderTypeMask(); + + clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_GROUND, + LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_CLOUDS, + LLPipeline::END_RENDER_TYPES); + + S32 detail = gSavedSettings.getS32("RenderReflectionDetail"); + if (detail > 0) { //mask out selected geometry based on reflection detail - - S32 detail = gSavedSettings.getS32("RenderReflectionDetail"); - if (detail < 3) + if (detail < 4) { - mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_PARTICLES); - if (detail < 2) + clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES); + if (detail < 3) { - mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_AVATAR); - if (detail < 1) + clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); + if (detail < 2) { - mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_VOLUME); + clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES); } } } @@ -7248,18 +7349,17 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) stateSort(camera, ref_result); } - ref_mask = mRenderTypeMask; - mRenderTypeMask = mask; - } - if (LLDrawPoolWater::sNeedsDistortionUpdate) - { - mRenderTypeMask = ref_mask; - if (gSavedSettings.getBOOL("RenderWaterReflections")) + if (LLDrawPoolWater::sNeedsDistortionUpdate) { - gPipeline.grabReferences(ref_result); - LLGLUserClipPlane clip_plane(plane, mat, projection); - renderGeom(camera); + if (gSavedSettings.getS32("RenderReflectionDetail") > 0) + { + gPipeline.grabReferences(ref_result); + LLGLUserClipPlane clip_plane(plane, mat, projection); + renderGeom(camera); + } } + + gPipeline.popRenderTypeMask(); } glCullFace(GL_BACK); glPopMatrix(); @@ -7273,18 +7373,20 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) if (last_update) { camera.setFar(camera_in.getFar()); - mRenderTypeMask = type_mask & (~(1<<LLPipeline::RENDER_TYPE_WATER) | - (1<<LLPipeline::RENDER_TYPE_GROUND)); + clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_GROUND, + END_RENDER_TYPES); stop_glerror(); LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? FALSE : TRUE; if (LLPipeline::sUnderWaterRender) { - mRenderTypeMask &= ~((1<<LLPipeline::RENDER_TYPE_GROUND) | - (1<<LLPipeline::RENDER_TYPE_SKY) | - (1<<LLPipeline::RENDER_TYPE_CLOUDS) | - (1<<LLPipeline::RENDER_TYPE_WL_SKY)); + clearRenderTypeMask(LLPipeline::RENDER_TYPE_GROUND, + LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_CLOUDS, + LLPipeline::RENDER_TYPE_WL_SKY, + END_RENDER_TYPES); } LLViewerCamera::updateFrustumPlanes(camera); @@ -7326,7 +7428,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } glClearColor(0.f, 0.f, 0.f, 0.f); gViewerWindow->setup3DViewport(); - mRenderTypeMask = type_mask; + gPipeline.popRenderTypeMask(); LLDrawPoolWater::sNeedsReflectionUpdate = FALSE; LLDrawPoolWater::sNeedsDistortionUpdate = FALSE; LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd)); @@ -7518,115 +7620,172 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLPipeline::sShadowRender = FALSE; } - +static LLFastTimer::DeclareTimer 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); //get point cloud of intersection of frust and min, max - //get set of planes - std::vector<LLPlane> ps; - if (getVisibleExtents(camera, min, max)) { return FALSE; } - ps.push_back(LLPlane(min, LLVector3(-1,0,0))); - ps.push_back(LLPlane(min, LLVector3(0,-1,0))); - ps.push_back(LLPlane(min, LLVector3(0,0,-1))); - ps.push_back(LLPlane(max, LLVector3(1,0,0))); - ps.push_back(LLPlane(max, LLVector3(0,1,0))); - ps.push_back(LLPlane(max, LLVector3(0,0,1))); + //get set of planes on bounding box + std::vector<LLPlane> bp; + + bp.push_back(LLPlane(min, LLVector3(-1,0,0))); + bp.push_back(LLPlane(min, LLVector3(0,-1,0))); + bp.push_back(LLPlane(min, LLVector3(0,0,-1))); + bp.push_back(LLPlane(max, LLVector3(1,0,0))); + bp.push_back(LLPlane(max, LLVector3(0,1,0))); + bp.push_back(LLPlane(max, LLVector3(0,0,1))); + + //potential points + std::vector<LLVector3> pp; + + //add corners of AABB + pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2])); + pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2])); + pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2])); + pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2])); + pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2])); + pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2])); + pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2])); + pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2])); - /*if (!light_dir.isExactlyZero()) + //add corners of camera frustum + for (U32 i = 0; i < 8; i++) { - LLPlane ucp; - LLPlane mcp; + pp.push_back(camera.mAgentFrustum[i]); + } - F32 maxd = -1.f; - F32 mind = 1.f; - for (U32 i = 0; i < ps.size(); ++i) - { //pick the plane most aligned to lightDir for user clip plane - LLVector3 n(ps[i].mV); - F32 da = n*light_dir; - if (da > maxd) - { - maxd = da; - ucp = ps[i]; - } + //bounding box line segments + U32 bs[] = + { + 0,1, + 1,3, + 3,2, + 2,0, + + 4,5, + 5,7, + 7,6, + 6,4, + + 0,4, + 1,5, + 3,7, + 2,6 + }; + + for (U32 i = 0; i < 12; i++) + { //for each line segment in bounding box + for (U32 j = 0; j < 6; j++) + { //for each plane in camera frustum + const LLPlane& cp = camera.getAgentPlane(j); + const LLVector3& v1 = pp[bs[i*2+0]]; + const LLVector3& v2 = pp[bs[i*2+1]]; + const LLVector3 n(cp.mV); + + LLVector3 line = v1-v2; + + F32 d1 = line*n; + F32 d2 = -cp.dist(v2); + + F32 t = d2/d1; - if (da < mind) + if (t > 0.f && t < 1.f) { - mind = da; - mcp = ps[i]; + LLVector3 intersect = v2+line*t; + pp.push_back(intersect); } } - - camera.setUserClipPlane(ucp); + } - ps.clear(); - ps.push_back(ucp); - ps.push_back(mcp); - }*/ - - for (U32 i = 0; i < 6; i++) + //camera frustum line segments + const U32 fs[] = { - ps.push_back(camera.getAgentPlane(i)); - } + 0,1, + 1,2, + 2,3, + 3,1, - //get set of points where planes intersect and points are not above any plane - fp.clear(); - - for (U32 i = 0; i < ps.size(); ++i) + 4,5, + 5,6, + 6,7, + 7,4, + + 0,4, + 1,5, + 2,6, + 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 < ps.size(); ++j) + for (U32 j = 0; j < 6; ++j) { - for (U32 k = 0; k < ps.size(); ++k) - { - if (i == j || - i == k || - k == j) - { - continue; - } + const LLVector3& v1 = pp[fs[i*2+0]+8]; + const LLVector3& v2 = pp[fs[i*2+1]+8]; + const LLPlane& cp = bp[j]; + const LLVector3 n(cp.mV); - LLVector3 n1,n2,n3; - F32 d1,d2,d3; + LLVector3 line = v1-v2; - n1.setVec(ps[i].mV); - n2.setVec(ps[j].mV); - n3.setVec(ps[k].mV); + F32 d1 = line*n; + F32 d2 = -cp.dist(v2); - d1 = ps[i].mV[3]; - d2 = ps[j].mV[3]; - d3 = ps[k].mV[3]; - - //get point of intersection of 3 planes "p" - LLVector3 p = (-d1*(n2%n3)-d2*(n3%n1)-d3*(n1%n2))/(n1*(n2%n3)); - - if (llround(p*n1+d1, 0.0001f) == 0.f && - llround(p*n2+d2, 0.0001f) == 0.f && - llround(p*n3+d3, 0.0001f) == 0.f) - { //point is on all three planes - BOOL found = TRUE; - for (U32 l = 0; l < ps.size() && found; ++l) - { - if (llround(ps[l].dist(p), 0.0001f) > 0.0f) - { //point is above some plane, not contained - found = FALSE; - } - } + F32 t = d2/d1; - if (found) - { - fp.push_back(p); - } - } - } + if (t > 0.f && t < 1.f) + { + LLVector3 intersect = v2+line*t; + pp.push_back(intersect); + } } } + LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f), + max+LLVector3(0.05f,0.05f,0.05f) }; + + for (U32 i = 0; i < pp.size(); ++i) + { + bool found = true; + + const F32* p = pp[i].mV; + + for (U32 j = 0; j < 3; ++j) + { + if (p[j] < ext[0].mV[j] || + p[j] > ext[1].mV[j]) + { + found = false; + break; + } + } + + for (U32 j = 0; j < 6; ++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) + { + fp.push_back(pp[i]); + } + } + if (fp.empty()) { return FALSE; @@ -7724,21 +7883,22 @@ void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<L sun_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); static LLCullResult result; - U32 type_mask = mRenderTypeMask; + pushRenderTypeMask(); - mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | - (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | - (1<<LLPipeline::RENDER_TYPE_BUMP) | - (1<<LLPipeline::RENDER_TYPE_VOLUME) | - (1<<LLPipeline::RENDER_TYPE_TREE) | - (1<<LLPipeline::RENDER_TYPE_TERRAIN) | - (1<<LLPipeline::RENDER_TYPE_WATER) | - (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) | - (1<<LLPipeline::RENDER_TYPE_AVATAR) | - (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_PASS_SHINY)); + andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_BUMP, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW, + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_PASS_SIMPLE, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_SHINY, + END_RENDER_TYPES); @@ -7807,7 +7967,7 @@ void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<L LLPipeline::sShadowRender = FALSE; sMinRenderSize = 0.f; - mRenderTypeMask = type_mask; + popRenderTypeMask(); } @@ -7891,30 +8051,11 @@ void LLPipeline::generateHighlight(LLCamera& camera) void LLPipeline::generateSunShadow(LLCamera& camera) { - if (!sRenderDeferred || !gSavedSettings.getBOOL("RenderDeferredShadow")) + if (!sRenderDeferred || gSavedSettings.getS32("RenderShadowDetail") <= 0) { return; } - //temporary hack to disable shadows but keep local lights - static BOOL clear = TRUE; - BOOL gen_shadow = gSavedSettings.getBOOL("RenderDeferredSunShadow"); - if (!gen_shadow) - { - if (clear) - { - clear = FALSE; - for (U32 i = 0; i < 6; i++) - { - mShadow[i].bindTarget(); - mShadow[i].clear(); - mShadow[i].flush(); - } - } - return; - } - clear = TRUE; - F64 last_modelview[16]; F64 last_projection[16]; for (U32 i = 0; i < 16; i++) @@ -7923,23 +8064,24 @@ void LLPipeline::generateSunShadow(LLCamera& camera) last_projection[i] = gGLLastProjection[i]; } - U32 type_mask = mRenderTypeMask; - mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | - (1<<LLPipeline::RENDER_TYPE_ALPHA) | - (1<<LLPipeline::RENDER_TYPE_GRASS) | - (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | - (1<<LLPipeline::RENDER_TYPE_BUMP) | - (1<<LLPipeline::RENDER_TYPE_VOLUME) | - (1<<LLPipeline::RENDER_TYPE_AVATAR) | - (1<<LLPipeline::RENDER_TYPE_TREE) | - (1<<LLPipeline::RENDER_TYPE_TERRAIN) | - (1<<LLPipeline::RENDER_TYPE_WATER) | - (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) | - (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY)); + pushRenderTypeMask(); + andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE, + LLPipeline::RENDER_TYPE_ALPHA, + LLPipeline::RENDER_TYPE_GRASS, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_BUMP, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW, + LLPipeline::RENDER_TYPE_PASS_SIMPLE, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_SHINY, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + END_RENDER_TYPES); gGL.setColorMask(false, false); @@ -7991,17 +8133,32 @@ void LLPipeline::generateSunShadow(LLCamera& camera) at.normVec(); + LLCamera main_camera = camera; + F32 near_clip = 0.f; { //get visible point cloud std::vector<LLVector3> fp; + main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum); + LLVector3 min,max; - getVisiblePointCloud(camera,min,max,fp); + getVisiblePointCloud(main_camera,min,max,fp); if (fp.empty()) { - mRenderTypeMask = type_mask; + if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowCamera[0] = main_camera; + mShadowExtents[0][0] = min; + mShadowExtents[0][1] = max; + + mShadowFrustPoints[0].clear(); + mShadowFrustPoints[1].clear(); + mShadowFrustPoints[2].clear(); + mShadowFrustPoints[3].clear(); + } + popRenderTypeMask(); return; } @@ -8075,7 +8232,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) shadow_cam = camera; shadow_cam.setFar(16.f); - LLViewerCamera::updateFrustumPlanes(shadow_cam); + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); LLVector3* frust = shadow_cam.mAgentFrustum; @@ -8087,10 +8244,11 @@ void LLPipeline::generateSunShadow(LLCamera& camera) for (U32 i = 0; i < 4; i++) { LLVector3 delta = frust[i+4]-eye; + delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f; delta.normVec(); F32 dp = delta*pn; - frust[i] = eye + (delta*dist[j])/dp; - frust[i+4] = eye + (delta*dist[j+1])/dp; + frust[i] = eye + (delta*dist[j]*0.95f)/dp; + frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp; } shadow_cam.calcAgentFrustumPlanes(frust); @@ -8430,135 +8588,155 @@ void LLPipeline::generateSunShadow(LLCamera& camera) } } - - - F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f); - //update shadow targets - for (U32 i = 0; i < 2; i++) - { //for each current shadow - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i; + //hack to disable projector shadows + static bool clear = true; + bool gen_shadow = gSavedSettings.getS32("RenderShadowDetail") > 1; + + if (gen_shadow) + { + clear = true; + F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f); - if (mShadowSpotLight[i].notNull() && - (mShadowSpotLight[i] == mTargetShadowSpotLight[0] || - mShadowSpotLight[i] == mTargetShadowSpotLight[1])) - { //keep this spotlight - mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f); - } - else - { //fade out this light - mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f); - - if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull()) - { //faded out, grab one of the pending spots (whichever one isn't already taken) - if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2]) - { - mShadowSpotLight[i] = mTargetShadowSpotLight[0]; - } - else - { - mShadowSpotLight[i] = mTargetShadowSpotLight[1]; + //update shadow targets + for (U32 i = 0; i < 2; i++) + { //for each current shadow + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i; + + if (mShadowSpotLight[i].notNull() && + (mShadowSpotLight[i] == mTargetShadowSpotLight[0] || + mShadowSpotLight[i] == mTargetShadowSpotLight[1])) + { //keep this spotlight + mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f); + } + else + { //fade out this light + mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f); + + if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull()) + { //faded out, grab one of the pending spots (whichever one isn't already taken) + if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2]) + { + mShadowSpotLight[i] = mTargetShadowSpotLight[0]; + } + else + { + mShadowSpotLight[i] = mTargetShadowSpotLight[1]; + } } } } - } - - for (S32 i = 0; i < 2; i++) - { - glh_set_current_modelview(saved_view); - glh_set_current_projection(saved_proj); - - if (mShadowSpotLight[i].isNull()) + + for (S32 i = 0; i < 2; i++) { - continue; - } + glh_set_current_modelview(saved_view); + glh_set_current_projection(saved_proj); - LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume(); + if (mShadowSpotLight[i].isNull()) + { + continue; + } - if (!volume) - { - mShadowSpotLight[i] = NULL; - continue; - } + LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume(); - LLDrawable* drawable = mShadowSpotLight[i]; + if (!volume) + { + mShadowSpotLight[i] = NULL; + continue; + } - LLVector3 params = volume->getSpotLightParams(); - F32 fov = params.mV[0]; + LLDrawable* drawable = mShadowSpotLight[i]; - //get agent->light space matrix (modelview) - LLVector3 center = drawable->getPositionAgent(); - LLQuaternion quat = volume->getRenderRotation(); + LLVector3 params = volume->getSpotLightParams(); + F32 fov = params.mV[0]; - //get near clip plane - LLVector3 scale = volume->getScale(); - LLVector3 at_axis(0,0,-scale.mV[2]*0.5f); - at_axis *= quat; + //get agent->light space matrix (modelview) + LLVector3 center = drawable->getPositionAgent(); + LLQuaternion quat = volume->getRenderRotation(); - LLVector3 np = center+at_axis; - at_axis.normVec(); + //get near clip plane + LLVector3 scale = volume->getScale(); + LLVector3 at_axis(0,0,-scale.mV[2]*0.5f); + at_axis *= quat; - //get origin that has given fov for plane np, at_axis, and given scale - F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f); + LLVector3 np = center+at_axis; + at_axis.normVec(); - LLVector3 origin = np - at_axis*dist; + //get origin that has given fov for plane np, at_axis, and given scale + F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f); - LLMatrix4 mat(quat, LLVector4(origin, 1.f)); + LLVector3 origin = np - at_axis*dist; - view[i+4] = glh::matrix4f((F32*) mat.mMatrix); + LLMatrix4 mat(quat, LLVector4(origin, 1.f)); - view[i+4] = view[i+4].inverse(); + view[i+4] = glh::matrix4f((F32*) mat.mMatrix); - //get perspective matrix - F32 near_clip = dist+0.01f; - F32 width = scale.mV[VX]; - F32 height = scale.mV[VY]; - F32 far_clip = dist+volume->getLightRadius()*1.5f; + view[i+4] = view[i+4].inverse(); - F32 fovy = fov * RAD_TO_DEG; - F32 aspect = width/height; - - proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip); + //get perspective matrix + F32 near_clip = dist+0.01f; + F32 width = scale.mV[VX]; + F32 height = scale.mV[VY]; + F32 far_clip = dist+volume->getLightRadius()*1.5f; - //translate and scale to from [-1, 1] to [0, 1] - glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, - 0.f, 0.5f, 0.f, 0.5f, - 0.f, 0.f, 0.5f, 0.5f, - 0.f, 0.f, 0.f, 1.f); + F32 fovy = fov * RAD_TO_DEG; + F32 aspect = width/height; + + proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip); - glh_set_current_modelview(view[i+4]); - glh_set_current_projection(proj[i+4]); + //translate and scale to from [-1, 1] to [0, 1] + glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, + 0.f, 0.5f, 0.f, 0.5f, + 0.f, 0.f, 0.5f, 0.5f, + 0.f, 0.f, 0.f, 1.f); - mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view; - - for (U32 j = 0; j < 16; j++) - { - gGLLastModelView[j] = mShadowModelview[i+4].m[j]; - gGLLastProjection[j] = mShadowProjection[i+4].m[j]; - } + glh_set_current_modelview(view[i+4]); + glh_set_current_projection(proj[i+4]); - mShadowModelview[i+4] = view[i+4]; - mShadowProjection[i+4] = proj[i+4]; + mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view; + + for (U32 j = 0; j < 16; j++) + { + gGLLastModelView[j] = mShadowModelview[i+4].m[j]; + gGLLastProjection[j] = mShadowProjection[i+4].m[j]; + } - LLCamera shadow_cam = camera; - shadow_cam.setFar(far_clip); - shadow_cam.setOrigin(origin); + mShadowModelview[i+4] = view[i+4]; + mShadowProjection[i+4] = proj[i+4]; - LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); + LLCamera shadow_cam = camera; + shadow_cam.setFar(far_clip); + shadow_cam.setOrigin(origin); - stop_glerror(); + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); + + stop_glerror(); - mShadow[i+4].bindTarget(); - mShadow[i+4].getViewport(gGLViewport); + mShadow[i+4].bindTarget(); + mShadow[i+4].getViewport(gGLViewport); - static LLCullResult result[2]; + static LLCullResult result[2]; - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4; - renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE); + renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE); - mShadow[i+4].flush(); - } + mShadow[i+4].flush(); + } + } + else + { + if (clear) + { + clear = false; + for (U32 i = 4; i < 6; i++) + { + mShadow[i].bindTarget(); + mShadow[i].clear(); + mShadow[i].flush(); + } + } + } if (!gSavedSettings.getBOOL("CameraOffset")) { @@ -8582,7 +8760,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) gGLLastProjection[i] = last_projection[i]; } - mRenderTypeMask = type_mask; + popRenderTypeMask(); } void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture) @@ -8618,38 +8796,36 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) assertInitialized(); - U32 mask; BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID()); + pushRenderTypeMask(); + if (muted) { - mask = 1 << LLPipeline::RENDER_TYPE_AVATAR; + andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); } else { - mask = (1<<LLPipeline::RENDER_TYPE_VOLUME) | - (1<<LLPipeline::RENDER_TYPE_AVATAR) | - (1<<LLPipeline::RENDER_TYPE_BUMP) | - (1<<LLPipeline::RENDER_TYPE_GRASS) | - (1<<LLPipeline::RENDER_TYPE_SIMPLE) | - (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | - (1<<LLPipeline::RENDER_TYPE_ALPHA) | - (1<<LLPipeline::RENDER_TYPE_INVISIBLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) | - (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) | - (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) | - (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY); + andRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_AVATAR, + 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_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_SHINY, + LLPipeline::RENDER_TYPE_PASS_INVISIBLE, + LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, + END_RENDER_TYPES); } - mask = mask & gPipeline.getRenderTypeMask(); - U32 saved_mask = gPipeline.mRenderTypeMask; - gPipeline.mRenderTypeMask = mask; - S32 occlusion = sUseOcclusion; sUseOcclusion = 0; sReflectionRender = sRenderDeferred ? FALSE : TRUE; @@ -8823,7 +8999,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) sReflectionRender = FALSE; sImpostorRender = FALSE; sShadowRender = FALSE; - gPipeline.mRenderTypeMask = saved_mask; + popRenderTypeMask(); glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -8864,4 +9040,121 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() return sCull->endAlphaGroups(); } +BOOL LLPipeline::hasRenderType(const U32 type) const +{ + return mRenderTypeEnabled[type]; +} + +void LLPipeline::setRenderTypeMask(U32 type, ...) +{ + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = TRUE; + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } +} + +BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const +{ + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + return TRUE; + } + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } + + return FALSE; +} + +void LLPipeline::pushRenderTypeMask() +{ + std::string cur_mask; + cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.push(cur_mask); +} + +void LLPipeline::popRenderTypeMask() +{ + if (mRenderTypeEnableStack.empty()) + { + llerrs << "Depleted render type stack." << llendl; + } + + memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.pop(); +} + +void LLPipeline::andRenderTypeMask(U32 type, ...) +{ + va_list args; + + BOOL tmp[NUM_RENDER_TYPES]; + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + tmp[i] = FALSE; + } + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + tmp[type] = TRUE; + } + + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } + + for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = tmp[i]; + } + +} + +void LLPipeline::clearRenderTypeMask(U32 type, ...) +{ + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = FALSE; + + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } +} + diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 60e0b0ae8c..9d25e6d189 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -46,6 +46,8 @@ #include "lldrawable.h" #include "llrendertarget.h" +#include <stack> + class LLViewerTexture; class LLEdge; class LLFace; @@ -277,12 +279,25 @@ public: LLCullResult::sg_list_t::iterator beginAlphaGroups(); LLCullResult::sg_list_t::iterator endAlphaGroups(); + void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); - BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1<<type))) ? TRUE : FALSE; } + BOOL hasRenderDebugFeatureMask(const U32 mask) const { return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; } BOOL hasRenderDebugMask(const U32 mask) const { return (mRenderDebugMask & mask) ? TRUE : FALSE; } - void setRenderTypeMask(const U32 mask) { mRenderTypeMask = mask; } - U32 getRenderTypeMask() const { return mRenderTypeMask; } + + + + BOOL hasRenderType(const U32 type) const; + BOOL hasAnyRenderType(const U32 type, ...) const; + + void setRenderTypeMask(U32 type, ...); + void orRenderTypeMask(U32 type, ...); + void andRenderTypeMask(U32 type, ...); + void clearRenderTypeMask(U32 type, ...); + + void pushRenderTypeMask(); + void popRenderTypeMask(); + static void toggleRenderType(U32 type); // For UI control of render features @@ -360,6 +375,7 @@ public: RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY, RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY, RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP, + RENDER_TYPE_PASS_POST_BUMP = LLRenderPass::PASS_POST_BUMP, RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW, RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA, RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK, @@ -370,7 +386,9 @@ public: RENDER_TYPE_VOLUME, RENDER_TYPE_PARTICLES, RENDER_TYPE_CLOUDS, - RENDER_TYPE_HUD_PARTICLES + RENDER_TYPE_HUD_PARTICLES, + NUM_RENDER_TYPES, + END_RENDER_TYPES = NUM_RENDER_TYPES }; enum LLRenderDebugFeatureMask @@ -444,7 +462,8 @@ public: static BOOL sForceOldBakedUpload; // If true will not use capabilities to upload baked textures. static S32 sUseOcclusion; // 0 = no occlusion, 1 = read only, 2 = read/write static BOOL sDelayVBUpdate; - static BOOL sFastAlpha; + static BOOL sAutoMaskAlphaDeferred; + static BOOL sAutoMaskAlphaNonDeferred; static BOOL sDisableShaders; // if TRUE, rendering will be done without shaders static BOOL sRenderBump; static BOOL sUseTriStrips; @@ -532,7 +551,9 @@ public: S32 mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed protected: - U32 mRenderTypeMask; + BOOL mRenderTypeEnabled[NUM_RENDER_TYPES]; + std::stack<std::string> mRenderTypeEnableStack; + U32 mRenderDebugFeatureMask; U32 mRenderDebugMask; diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index c9ebeb60fb..66a6696a2c 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2137,14 +2137,24 @@ parameter="RenderDebugPipeline" /> </menu_item_check> <menu_item_check - label="Fast Alpha" - name="Fast Alpha"> + label="Automatic Alpha Masks (deferred)" + name="Automatic Alpha Masks (deferred)"> <menu_item_check.on_check function="CheckControl" - parameter="RenderFastAlpha" /> + parameter="RenderAutoMaskAlphaDeferred" /> <menu_item_check.on_click function="ToggleControl" - parameter="RenderFastAlpha" /> + parameter="RenderAutoMaskAlphaDeferred" /> + </menu_item_check> + <menu_item_check + label="Automatic Alpha Masks (non-deferred)" + name="Automatic Alpha Masks (non-deferred)"> + <menu_item_check.on_check + function="CheckControl" + parameter="RenderAutoMaskAlphaNonDeferred" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="RenderAutoMaskAlphaNonDeferred" /> </menu_item_check> <menu_item_check label="Animation Textures" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 0a56f711dd..68a0db3b89 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -155,12 +155,12 @@ visiblity_control="ShowAdvancedGraphicsSettings" border="false" follows="top|left" - height="260" + height="283" label="CustomGraphics" layout="topleft" left="5" name="CustomGraphics Panel" - top="124" + top="101" width="485"> <text type="string" @@ -211,119 +211,111 @@ <check_box.commit_callback function="Pref.VertexShaderEnable" /> </check_box> - <check_box - control_name="RenderWaterReflections" + <check_box + control_name="RenderDeferred" height="16" initial_value="true" - label="Water reflections" + label="Lighting and Shadows" layout="topleft" left_delta="0" - name="Reflections" + name="UseLightShaders" top_pad="1" width="256"> - <check_box.commit_callback + <check_box.commit_callback function="Pref.VertexShaderEnable" /> - </check_box> - <text - type="string" - length="1" - follows="left|top" - height="12" - layout="topleft" - left_delta="0" - name="ReflectionDetailText" - top_pad="7" - width="128"> - Reflection detail: - </text> - <radio_group - control_name="RenderReflectionDetail" - draw_border="false" - height="70" - layout="topleft" - left_delta="-2" - name="ReflectionDetailRadio" - top_pad="3" - width="321"> - <radio_item - height="16" - label="Terrain and trees" - layout="topleft" - left="3" - name="0" - top="3" - width="315" /> - <radio_item - height="16" - label="All static objects" - layout="topleft" - left_delta="0" - name="1" - top_delta="16" - width="315" /> - <radio_item - height="16" - label="All avatars and objects" - layout="topleft" - left_delta="0" - name="2" - top_delta="16" - width="315" /> - <radio_item - height="16" - label="Everything" - layout="topleft" - left_delta="0" - name="3" - top_delta="16" - width="315" /> - </radio_group> - <text - type="string" - length="1" - follows="left|top" - height="12" - layout="topleft" - left_delta="2" - name="AvatarRenderingText" - top_pad="5" - width="158"> - Avatar rendering: - </text> - <check_box - control_name="RenderUseImpostors" + </check_box> + <check_box + control_name="RenderDeferredSSAO" height="16" initial_value="true" - label="Avatar impostors" + label="Ambient Occlusion" layout="topleft" left_delta="0" - name="AvatarImpostors" - top_pad="7" - width="256" /> - <check_box - control_name="RenderAvatarVP" - height="16" - initial_value="true" - label="Hardware skinning" - layout="topleft" - left_delta="0" - name="AvatarVertexProgram" + name="UseSSAO" top_pad="1" width="256"> - <check_box.commit_callback + <check_box.commit_callback function="Pref.VertexShaderEnable" /> - </check_box> - <check_box - control_name="RenderAvatarCloth" - height="16" - initial_value="true" - label="Avatar cloth" - layout="topleft" - left_delta="0" - name="AvatarCloth" - top_pad="1" - width="256" /> + </check_box> + <text + type="string" + length="1" + top_pad="8" + follows="top|left" + height="23" + width="110" + word_wrap="true" + layout="topleft" + left="10" + name="shadows_label"> + Shadows: + </text> + <combo_box + control_name="RenderShadowDetail" + height="23" + layout="topleft" + left="10" + top_pad="0" + name="ShadowDetail" + width="150"> + <combo_box.item + label="None" + name="0" + value="0"/> + <combo_box.item + label="Sun/Moon" + name="1" + value="1"/> + <combo_box.item + label="Sun/Moon + Projectors" + name="2" + value="2"/> + </combo_box> + + <text + type="string" + length="1" + top_pad="8" + follows="top|left" + height="23" + width="110" + word_wrap="true" + layout="topleft" + left="10" + name="reflection_label"> + Water Reflections: + </text> + <combo_box + control_name="RenderReflectionDetail" + height="23" + layout="topleft" + left_="10" + top_pad ="0" + name="Reflections" + width="150"> + <combo_box.item + label="Minimal" + name="0" + value="0"/> + <combo_box.item + label="Terrain and trees" + name="1" + value="1"/> + <combo_box.item + label="All static objects" + name="2" + value="2"/> + <combo_box.item + label="All avatars and objects" + name="3" + value="3"/> + <combo_box.item + label="Everything" + name="4" + value="4"/> + </combo_box> + <slider control_name="RenderFarClip" decimal_digits="0" @@ -522,7 +514,7 @@ layout="topleft" left="469" name="PostProcessText" - top="305" + top="328" width="128"> Low </text> @@ -599,52 +591,61 @@ width="128"> Low </text> + <text + type="string" + length="1" + follows="left|top" + height="12" + layout="topleft" + left_delta="-260" + name="AvatarRenderingText" + top_pad="8" + width="128"> + Avatar rendering: + </text> + <check_box + control_name="RenderUseImpostors" + height="16" + initial_value="true" + label="Avatar impostors" + layout="topleft" + left_delta="0" + name="AvatarImpostors" + top_pad="7" + width="256" /> + <check_box + control_name="RenderAvatarVP" + height="16" + initial_value="true" + label="Hardware skinning" + layout="topleft" + left_delta="0" + name="AvatarVertexProgram" + top_pad="1" + width="256"> + <check_box.commit_callback + function="Pref.VertexShaderEnable" /> + </check_box> + <check_box + control_name="RenderAvatarCloth" + height="16" + initial_value="true" + label="Avatar cloth" + layout="topleft" + left_delta="0" + name="AvatarCloth" + top_pad="1" + width="256" /> <text type="string" length="1" follows="left|top" height="12" layout="topleft" - left="200" - name="LightingDetailText" - top_pad="8" - width="140"> - Lighting detail: - </text> - <radio_group - control_name="RenderLightingDetail" - draw_border="false" - height="38" - layout="topleft" - name="LightingDetailRadio" - top_pad="5" - width="200"> - <radio_item - height="16" - label="Sun and moon only" - layout="topleft" - name="SunMoon" - value="0" - top="3" - width="156" /> - <radio_item - height="16" - label="Nearby local lights" - layout="topleft" - name="LocalLights" - value="1" - top_delta="16" - width="156" /> - </radio_group> - <text - type="string" - length="1" - follows="left|top" - height="12" - layout="topleft" + left="358" left_pad="-30" name="TerrainDetailText" - top="465" + top="488" width="155"> Terrain detail: </text> @@ -671,7 +672,7 @@ name="2" top_delta="16" width="50" /> - </radio_group> + </radio_group> --> </panel> <button |