diff options
Diffstat (limited to 'indra/newview/pipeline.cpp')
-rw-r--r-- | indra/newview/pipeline.cpp | 133 |
1 files changed, 89 insertions, 44 deletions
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index a64655960f..dbcc7fba9f 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -811,6 +811,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (LLPipeline::sRenderDeferred) { + // Set this flag in case we crash while resizing window or allocating space for deferred rendering targets + gSavedSettings.setBOOL("RenderInitError", TRUE); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); + S32 shadow_detail = RenderShadowDetail; BOOL ssao = RenderDeferredSSAO; @@ -842,9 +846,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 0) { //allocate 4 sun shadow maps + U32 sun_shadow_map_width = ((U32(resX*scale)+1)&~1); // must be even to avoid a stripe in the horizontal shadow blur for (U32 i = 0; i < 4; i++) { - if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; + if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; } } else @@ -860,9 +865,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 1) { //allocate two spot shadow maps + U32 spot_shadow_map_width = width; for (U32 i = 4; i < 6; i++) { - if (!mShadow[i].allocate(width, height, 0, TRUE, FALSE)) return false; + if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false; } } else @@ -872,6 +878,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) mShadow[i].release(); } } + + // don't disable shaders on next session + gSavedSettings.setBOOL("RenderInitError", FALSE); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); } else { @@ -1027,11 +1037,7 @@ void LLPipeline::releaseGLBuffers() mTrueNoiseMap = 0; } - if (mLightFunc) - { - LLImageGL::deleteTextures(1, &mLightFunc); - mLightFunc = 0; - } + releaseLUTBuffers(); mWaterRef.release(); mWaterDis.release(); @@ -1047,6 +1053,15 @@ void LLPipeline::releaseGLBuffers() LLVOAvatar::resetImpostors(); } +void LLPipeline::releaseLUTBuffers() +{ + if (mLightFunc) + { + LLImageGL::deleteTextures(1, &mLightFunc); + mLightFunc = 0; + } +} + void LLPipeline::releaseScreenBuffers() { mUIScreen.release(); @@ -1076,10 +1091,11 @@ void LLPipeline::createGLBuffers() if (LLPipeline::sWaterReflections) { //water reflection texture - U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution"); + U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512); mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE); - mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE); + //always use FBO for mWaterDis so it can be used for avatar texture bakes + mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true); } mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); @@ -1141,50 +1157,69 @@ void LLPipeline::createGLBuffers() gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } + createLUTBuffers(); + } + + gBumpImageList.restoreGL(); +} + +void LLPipeline::createLUTBuffers() +{ + if (sRenderDeferred) + { if (!mLightFunc) { U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); - U8* lg = new U8[lightResX*lightResY]; - + U8* ls = new U8[lightResX*lightResY]; + F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); + // Calculate the (normalized) Blinn-Phong specular lookup texture. for (U32 y = 0; y < lightResY; ++y) { for (U32 x = 0; x < lightResX; ++x) { - //spec func + ls[y*lightResX+x] = 0; F32 sa = (F32) x/(lightResX-1); F32 spec = (F32) y/(lightResY-1); - //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255); - - //F32 sp = acosf(sa)/(1.f-spec); - - sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent")); - F32 a = acosf(sa*0.25f+0.75f); - F32 m = llmax(0.5f-spec*0.5f, 0.001f); - F32 t2 = tanf(a)/m; - t2 *= t2; - - F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f; - F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2); - - lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255); + F32 n = spec * spec * specExp; + + // Nothing special here. Just your typical blinn-phong term. + spec = powf(sa, n); + + // Apply our normalization function. + // Note: This is the full equation that applies the full normalization curve, not an approximation. + // This is fine, given we only need to create our LUT once per buffer initialization. + // The only trade off is we have a really low dynamic range. + // This means we have to account for things not being able to exceed 0 to 1 in our shaders. + spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); + + // Always sample at a 1.0/2.2 curve. + // This "Gamma corrects" our specular term, boosting our lower exponent reflections. + spec = powf(spec, 1.f/2.2f); + + // Easy fix for our dynamic range problem: divide by 6 here, multiply by 6 in our shaders. + // This allows for our specular term to exceed a value of 1 in our shaders. + // This is something that can be important for energy conserving specular models where higher exponents can result in highlights that exceed a range of 0 to 1. + // Technically, we could just use an R16F texture, but driver support for R16F textures can be somewhat spotty at times. + // This works remarkably well for higher specular exponents, though banding can sometimes be seen on lower exponents. + // Combined with a bit of noise and trilinear filtering, the banding is hardly noticable. + ls[y*lightResX+x] = (U8)(llclamp(spec * (1.f / 6), 0.f, 1.f) * 255); } } - + LLImageGL::generateTextures(1, &mLightFunc); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, lg); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - - delete [] lg; + + delete [] ls; } } - - gBumpImageList.restoreGL(); } -void LLPipeline::restoreGL() + +void LLPipeline::restoreGL() { LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL); assertInitialized(); @@ -6642,9 +6677,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) mDeferredLight.flush(); } + U32 dof_width = (U32) (mScreen.getWidth()*CameraDoFResScale); + U32 dof_height = (U32) (mScreen.getHeight()*CameraDoFResScale); + { //perform DoF sampling at half-res (preserve alpha channel) mScreen.bindTarget(); - glViewport(0,0,(GLsizei) (mScreen.getWidth()*CameraDoFResScale), (GLsizei) (mScreen.getHeight()*CameraDoFResScale)); + glViewport(0,0, dof_width, dof_height); gGL.setColorMask(true, false); shader = &gDeferredPostProgram; @@ -6657,7 +6695,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); gGL.vertex2f(-1,-1); @@ -6702,6 +6740,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width-1); + shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height-1); gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); @@ -8255,7 +8295,7 @@ static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows"); static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow"); static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow"); -void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion) +void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion, U32 target_width) { LLFastTimer t(FTM_SHADOW_RENDER); @@ -8346,7 +8386,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLFastTimer ftm(FTM_SHADOW_ALPHA); gDeferredShadowAlphaMaskProgram.bind(); gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f); - + gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | @@ -8811,16 +8852,16 @@ void LLPipeline::generateSunShadow(LLCamera& camera) da = powf(da, split_exp.mV[2]); - F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da; - - + for (U32 i = 0; i < 4; ++i) { F32 x = (F32)(i+1)/4.f; x = powf(x, sxp); mSunClipPlanes.mV[i] = near_clip+range*x; } + + mSunClipPlanes.mV[0] *= 1.25f; //bump back first split for transition padding } // convenience array of 4 near clip plane distances @@ -8877,8 +8918,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f; delta.normVec(); F32 dp = delta*pn; - frust[i] = eye + (delta*dist[j]*0.95f)/dp; - frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp; + frust[i] = eye + (delta*dist[j]*0.75f)/dp; + frust[i+4] = eye + (delta*dist[j+1]*1.25f)/dp; } shadow_cam.calcAgentFrustumPlanes(frust); @@ -9199,11 +9240,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadow[j].getViewport(gGLViewport); mShadow[j].clear(); + U32 target_width = mShadow[j].getWidth(); + { static LLCullResult result[4]; //LLGLEnable enable(GL_DEPTH_CLAMP_NV); - renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE); + renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, TRUE, target_width); } mShadow[j].flush(); @@ -9342,11 +9385,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadow[i+4].getViewport(gGLViewport); mShadow[i+4].clear(); + U32 target_width = mShadow[i+4].getWidth(); + static LLCullResult result[2]; 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, target_width); mShadow[i+4].flush(); } |