Pull and merge from ssh://hg@bitbucket.org/lindenlab/viewer-development-materials.
commit
9b05e5f35b
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -150,7 +150,7 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
|
|||
vector< pair<string,GLenum> >::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,17 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -471,6 +481,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())
|
||||
|
|
|
|||
|
|
@ -123,12 +123,22 @@ public:
|
|||
GLint getAttribLocation(U32 attrib);
|
||||
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,
|
||||
//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();
|
||||
|
|
@ -153,6 +163,7 @@ public:
|
|||
LLShaderFeatures mFeatures;
|
||||
std::vector< std::pair< std::string, GLenum > > mShaderFiles;
|
||||
std::string mName;
|
||||
boost::unordered_map<std::string, std::string> mDefines;
|
||||
};
|
||||
|
||||
//UI shader (declared here so llui_libtest will link properly)
|
||||
|
|
|
|||
|
|
@ -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, boost::unordered_map<std::string, std::string> defines, S32 texture_index_channels)
|
||||
{
|
||||
GLenum error = GL_NO_ERROR;
|
||||
if (gDebugGL)
|
||||
|
|
@ -657,6 +657,12 @@ 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 (boost::unordered_map<std::string,std::string>::iterator iter = defines.begin(); iter != defines.end(); ++iter)
|
||||
{
|
||||
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 +860,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, boost::unordered_map<std::string, std::string> 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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -826,12 +826,14 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
|
|||
shaders.push_back( make_pair( "objects/indexedTextureV.glsl", 1 ) );
|
||||
}
|
||||
shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) );
|
||||
|
||||
|
||||
boost::unordered_map<std::string, std::string> 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++)
|
||||
{
|
||||
// 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 +881,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue