From ed1b78e32235680c3978b9830e5ba81115a0ab7d Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Tue, 28 Aug 2012 10:33:32 -0400 Subject: Added support for adding custom preprocessor definitions (for shader permutations) --- indra/llrender/llglslshader.cpp | 9 +++++++-- indra/llrender/llglslshader.h | 3 +++ indra/llrender/llshadermgr.cpp | 13 +++++++++++-- indra/llrender/llshadermgr.h | 2 +- indra/newview/llviewershadermgr.cpp | 11 +++++++---- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 7cbf39096e..d345b6593e 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -150,7 +150,7 @@ BOOL LLGLSLShader::createShader(vector * attributes, vector< pair >::iterator fileIter = mShaderFiles.begin(); for ( ; fileIter != mShaderFiles.end(); fileIter++ ) { - GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels); + GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mDefines, mFeatures.mIndexedTextureChannels); LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; if (shaderhandle > 0) { @@ -372,7 +372,12 @@ void LLGLSLShader::mapUniform(GLint index, const vector * uniforms) } } } - } +} + +void LLGLSLShader::addPermutation(std::string name, std::string value) +{ + mDefines[name] = value; +} GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 5c68cb46eb..bee5d9adda 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -123,6 +123,8 @@ public: GLint getAttribLocation(U32 attrib); GLint mapUniformTextureChannel(GLint location, GLenum type); + void addPermutation(std::string name, std::string value); + //enable/disable texture channel for specified uniform //if given texture uniform is active in the shader, //the corresponding channel will be active upon return @@ -153,6 +155,7 @@ public: LLShaderFeatures mFeatures; std::vector< std::pair< std::string, GLenum > > mShaderFiles; std::string mName; + std::map mDefines; }; //UI shader (declared here so llui_libtest will link properly) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index b6a9a6b653..d15584d2e1 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -521,7 +521,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) } } -GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels) +GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map defines, S32 texture_index_channels) { GLenum error = GL_NO_ERROR; if (gDebugGL) @@ -657,6 +657,15 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade std::string define = "#define " + iter->first + " " + iter->second + "\n"; text[count++] = (GLcharARB *) strdup(define.c_str()); } + + for (std::map::iterator iter = defines.begin(); iter != defines.end(); ++iter) + { + if (iter->first != "NULL") + { + std::string define = "#define " + iter->first + " " + iter->second + "\n"; + text[count++] = (GLcharARB *) strdup(define.c_str()); + } + } if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB) { @@ -854,7 +863,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (shader_level > 1) { shader_level--; - return loadShaderFile(filename,shader_level,type,texture_index_channels); + return loadShaderFile(filename,shader_level,type, defines, texture_index_channels); } LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL; } diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 7a16b7c20f..88c60b2144 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -176,7 +176,7 @@ public: void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE); BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE); BOOL validateProgramObject(GLhandleARB obj); - GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1); + GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map defines, S32 texture_index_channels = -1); // Implemented in the application to actually point to the shader directory. virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 4b0e0598f6..8c0ec4e275 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -826,12 +826,15 @@ BOOL LLViewerShaderMgr::loadBasicShaders() shaders.push_back( make_pair( "objects/indexedTextureV.glsl", 1 ) ); } shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); - + + std::map attribs; + attribs["NULL"] = "0"; + // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) { // Note usage of GL_VERTEX_SHADER_ARB - if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB) == 0) + if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB, attribs) == 0) { return FALSE; } @@ -879,11 +882,11 @@ BOOL LLViewerShaderMgr::loadBasicShaders() index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - + for (U32 i = 0; i < shaders.size(); i++) { // Note usage of GL_FRAGMENT_SHADER_ARB - if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, index_channels[i]) == 0) + if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, attribs, index_channels[i]) == 0) { return FALSE; } -- cgit v1.2.3 From 99371f892e7b35739be01e63036b4355e0e4dfe7 Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Tue, 28 Aug 2012 14:44:28 -0400 Subject: Added new bindTexture and unbindTexture API to LLGLSLShader. Reviewed by davep. --- indra/llrender/llglslshader.cpp | 52 +++++++++++++++++++++++++++++++++++++++++ indra/llrender/llglslshader.h | 9 ++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index d345b6593e..04878cabe2 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -476,6 +476,58 @@ void LLGLSLShader::bindNoShader(void) } } +S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode) +{ + S32 channel = 0; + channel = getUniformLocation(uniform); + + return bindTexture(channel, texture, mode); +} + +S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode) +{ + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + + uniform = mTexture[uniform]; + + if (uniform > -1) + { + gGL.getTexUnit(uniform)->bind(texture, mode); + } + + return uniform; +} + +S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode) +{ + S32 channel = 0; + channel = getUniformLocation(uniform); + + return unbindTexture(channel); +} + +S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) +{ + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + + uniform = mTexture[uniform]; + + if (uniform > -1) + { + gGL.getTexUnit(uniform)->unbind(mode); + } + + return uniform; +} + S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode) { if (uniform < 0 || uniform >= (S32)mTexture.size()) diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index bee5d9adda..185e6e7aeb 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -130,7 +130,14 @@ public: //the corresponding channel will be active upon return //returns channel texture is enabled in from [0-MAX) S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); - S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + + // bindTexture returns the texture unit we've bound the texture to. + // You can reuse the return value to unbind a texture when required. + S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); BOOL link(BOOL suppress_errors = FALSE); void bind(); -- cgit v1.2.3 From c911efb953a600092a6213c088d5b94fcf7779d3 Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Wed, 29 Aug 2012 03:41:26 -0400 Subject: Just pass in an empty preprocessor definition map from now on. The shader compiler won't add new #defines if it's empty. --- indra/llrender/llshadermgr.cpp | 7 ++----- indra/newview/llviewershadermgr.cpp | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index d15584d2e1..4f7f845c70 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -660,11 +660,8 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade for (std::map::iterator iter = defines.begin(); iter != defines.end(); ++iter) { - if (iter->first != "NULL") - { - std::string define = "#define " + iter->first + " " + iter->second + "\n"; - text[count++] = (GLcharARB *) strdup(define.c_str()); - } + std::string define = "#define " + iter->first + " " + iter->second + "\n"; + text[count++] = (GLcharARB *) strdup(define.c_str()); } if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 8c0ec4e275..e70bf013e7 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -828,7 +828,6 @@ BOOL LLViewerShaderMgr::loadBasicShaders() shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); std::map attribs; - attribs["NULL"] = "0"; // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) -- cgit v1.2.3 From e606677ed885c4e9189b0768b5e6f999fa2cf885 Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Wed, 29 Aug 2012 04:56:54 -0400 Subject: Added the ability to remove a preprocessor define. --- indra/edit-me-to-trigger-new-build.txt | 1 + indra/llrender/llglslshader.cpp | 5 +++++ indra/llrender/llglslshader.h | 1 + 3 files changed, 7 insertions(+) diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt index e69de29bb2..0519ecba6e 100644 --- a/indra/edit-me-to-trigger-new-build.txt +++ b/indra/edit-me-to-trigger-new-build.txt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 04878cabe2..39e81c4bfc 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -379,6 +379,11 @@ void LLGLSLShader::addPermutation(std::string name, std::string value) mDefines[name] = value; } +void LLGLSLShader::removePermutation(std::string name) +{ + mDefines[name].erase(); +} + GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) { if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB || diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 185e6e7aeb..f511c39484 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -124,6 +124,7 @@ public: GLint mapUniformTextureChannel(GLint location, GLenum type); void addPermutation(std::string name, std::string value); + void removePermutation(std::string name); //enable/disable texture channel for specified uniform //if given texture uniform is active in the shader, -- cgit v1.2.3 From d5b45b0b636557333c3408e7a60d5ef587ea99ad Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Wed, 29 Aug 2012 08:02:46 -0400 Subject: Use an unordered map for custom #defines instead of a map. Lookups are faster, and we don't really care about any particular order anyways for these. --- indra/llrender/llglslshader.h | 2 +- indra/llrender/llshadermgr.cpp | 4 ++-- indra/llrender/llshadermgr.h | 2 +- indra/newview/llviewershadermgr.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index f511c39484..2af74c20ff 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -163,7 +163,7 @@ public: LLShaderFeatures mFeatures; std::vector< std::pair< std::string, GLenum > > mShaderFiles; std::string mName; - std::map mDefines; + boost::unordered_map mDefines; }; //UI shader (declared here so llui_libtest will link properly) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 4f7f845c70..3b1ec281c9 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -521,7 +521,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) } } -GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map defines, S32 texture_index_channels) +GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map defines, S32 texture_index_channels) { GLenum error = GL_NO_ERROR; if (gDebugGL) @@ -658,7 +658,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade text[count++] = (GLcharARB *) strdup(define.c_str()); } - for (std::map::iterator iter = defines.begin(); iter != defines.end(); ++iter) + for (boost::unordered_map::iterator iter = defines.begin(); iter != defines.end(); ++iter) { std::string define = "#define " + iter->first + " " + iter->second + "\n"; text[count++] = (GLcharARB *) strdup(define.c_str()); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 88c60b2144..4b93aae735 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -176,7 +176,7 @@ public: void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE); BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE); BOOL validateProgramObject(GLhandleARB obj); - GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map defines, S32 texture_index_channels = -1); + GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map defines, S32 texture_index_channels = -1); // Implemented in the application to actually point to the shader directory. virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index e70bf013e7..43de7450c8 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -827,7 +827,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders() } shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); - std::map attribs; + boost::unordered_map attribs; // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) -- cgit v1.2.3 From 9593e85e144e2141c92abe597653851852501060 Mon Sep 17 00:00:00 2001 From: Jonathan Goodman Date: Sun, 9 Sep 2012 21:01:24 -0400 Subject: Use a customized normalized gaussian specular term. --- .../shaders/class1/deferred/multiPointLightF.glsl | 3 +- .../shaders/class1/deferred/pointLightF.glsl | 3 +- .../shaders/class1/deferred/softenLightF.glsl | 2 +- .../shaders/class2/deferred/softenLightF.glsl | 2 +- indra/newview/pipeline.cpp | 52 +++++++++++----------- 5 files changed, 30 insertions(+), 32 deletions(-) diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 7e79317543..9e194cdcd1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -128,8 +128,7 @@ void main() if (sa > 0.0) { - sa = 6 * texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); - sa *= noise; + sa = texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); col += da*sa*light_col[i].rgb*spec.rgb; } } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 75757b26c8..6e5ac8317b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -110,8 +110,7 @@ void main() float sa = dot(normalize(lv-normalize(pos)),norm); if (sa > 0.0) { - sa = 6 * texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); - sa *= noise; + sa = texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); col += da*sa*color.rgb*spec.rgb; } } diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 89448e2167..14eaafeb68 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -301,7 +301,7 @@ void main() // vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, sun_dir.xyz); - vec3 dumbshiny = vary_SunlitColor*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r); + vec3 dumbshiny = vary_SunlitColor*(texture2D(lightFunc, vec2(sa, spec.a)).r); // add the two types of shiny together vec3 spec_contrib = dumbshiny * spec.rgb; diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 9df9d75905..457189b48e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -309,7 +309,7 @@ void main() // vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, sun_dir.xyz); - vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r); + vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(texture2D(lightFunc, vec2(sa, spec.a)).r); // add the two types of shiny together vec3 spec_contrib = dumbshiny * spec.rgb; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 920bac93a2..28fc70e38a 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -397,7 +397,7 @@ void validate_framebuffer_object(); bool addDeferredAttachments(LLRenderTarget& target) { return target.addColorAttachment(GL_RGBA) && //specular - target.addColorAttachment(GL_RGBA); //normal+z + target.addColorAttachment(GL_RGB10_A2); //normal+z } LLPipeline::LLPipeline() : @@ -863,7 +863,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; if (!addDeferredAttachments(mDeferredScreen)) return false; - + if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; if (samples > 0) { @@ -1206,6 +1206,11 @@ void LLPipeline::createGLBuffers() gBumpImageList.restoreGL(); } +F32 lerpf(F32 a, F32 b, F32 w) +{ + return a + w * (b - a); +} + void LLPipeline::createLUTBuffers() { if (sRenderDeferred) @@ -1214,45 +1219,40 @@ void LLPipeline::createLUTBuffers() { U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); - U8* ls = new U8[lightResX*lightResY]; - F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); - // Calculate the (normalized) Blinn-Phong specular lookup texture. + F32* ls = new F32[lightResX*lightResY]; + //F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); // Note: only use this when creating new specular lighting functions. + // Calculate the (normalized) Gaussian specular lookup texture. (with a few tweaks) for (U32 y = 0; y < lightResY; ++y) { for (U32 x = 0; x < lightResX; ++x) { ls[y*lightResX+x] = 0; F32 sa = (F32) x/(lightResX-1); - F32 spec = (F32) y/(lightResY-1); - F32 n = spec * spec * specExp; + F32 spec = (F32) y/(lightResY); + F32 n = spec; - // Nothing special here. Just your typical blinn-phong term. - spec = powf(sa, n); + float angleNormalHalf = acosf(sa); + float exponent = angleNormalHalf / ((1 - n)); + exponent = -(exponent * exponent); + spec = expf(exponent); // 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))); + // This is based around the phong normalization function, trading n+2 for n+1 instead. + // Since we're using a gaussian model here, we actually don't really need as large of an exponent as blinn-phong shading. + // Instead, we assume that the correct exponent is 8 here. + // This was achieved through much tweaking to find a decent "middleground" with our specular highlights with the gaussian term. + // Bigger highlights don't look too soft, smaller highlights don't look too bright, and everything in the middle seems to have a well maintained highlight curvature. + // There isn't really much theory behind this one. This was done purely to produce a nice and mostly customizable BRDF. - // 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); + spec = lerpf(spec, spec * (n * 8 + 1) / 4.5, n); - // 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); + ls[y*lightResX+x] = spec; } } - LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R8, 1, &mLightFunc); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R16F, 1, &mLightFunc); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R16F, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); -- cgit v1.2.3 From 72af85ffbd1c4d4dd44acf7bf65fe55b4851d01b Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 18 Sep 2012 16:16:56 -0400 Subject: add EOL to trigger file to avoid coding policy check --- indra/edit-me-to-trigger-new-build.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt index 0519ecba6e..8d1c8b69c3 100644 --- a/indra/edit-me-to-trigger-new-build.txt +++ b/indra/edit-me-to-trigger-new-build.txt @@ -1 +1 @@ - \ No newline at end of file + -- cgit v1.2.3