summaryrefslogtreecommitdiff
path: root/indra/newview/pipeline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/pipeline.cpp')
-rw-r--r--indra/newview/pipeline.cpp82
1 files changed, 53 insertions, 29 deletions
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index e2cb22e307..ab994c71cb 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1035,11 +1035,7 @@ void LLPipeline::releaseGLBuffers()
mTrueNoiseMap = 0;
}
- if (mLightFunc)
- {
- LLImageGL::deleteTextures(1, &mLightFunc);
- mLightFunc = 0;
- }
+ releaseLUTBuffers();
mWaterRef.release();
mWaterDis.release();
@@ -1055,6 +1051,15 @@ void LLPipeline::releaseGLBuffers()
LLVOAvatar::resetImpostors();
}
+void LLPipeline::releaseLUTBuffers()
+{
+ if (mLightFunc)
+ {
+ LLImageGL::deleteTextures(1, &mLightFunc);
+ mLightFunc = 0;
+ }
+}
+
void LLPipeline::releaseScreenBuffers()
{
mUIScreen.release();
@@ -1150,50 +1155,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();