A little bit of postprocess shader tinkering.

This commit is contained in:
Shyotl
2012-12-12 03:10:05 -06:00
parent c641cc6394
commit 2424d2a082
7 changed files with 340 additions and 185 deletions

View File

@@ -49,12 +49,63 @@ extern LLGLSLShader gPostNightVisionProgram;
extern LLGLSLShader gPostGaussianBlurProgram;
extern LLGLSLShader gPostPosterizeProgram;
extern LLGLSLShader gPostMotionBlurProgram;
extern LLGLSLShader gPostVignetteProgram;
static const unsigned int NOISE_SIZE = 512;
static const char * const XML_FILENAME = "postprocesseffects.xml";
template<> LLSD LLPostProcessShader::LLShaderSetting<LLVector4>::getDefaultValue()
class LLPostProcessShader : public IPostProcessShader, public LLRefCount
{
public:
LLPostProcessShader(const std::string& enable_name, LLGLSLShader& shader, bool enabled = false) :
mShader(shader), mEnabled(enable_name,enabled)
{
addSetting(mEnabled);
}
/*virtual*/ bool isEnabled() const {return mShader.mProgramObject && mEnabled;}
/*virtual*/ void bindShader() {mShader.bind();}
/*virtual*/ void unbindShader() {mShader.unbind();}
/*virtual*/ LLGLSLShader& getShader() {return mShader;}
/*virtual*/ LLSD getDefaults(); //See IPostProcessShader::getDefaults
/*virtual*/ void loadSettings(const LLSD& settings); //See IPostProcessShader::loadSettings
/*virtual*/ void addSetting(IShaderSettingBase& setting) { mSettings.push_back(&setting); }
protected:
template<typename T>
struct LLShaderSetting : public IShaderSettingBase
{
LLShaderSetting(const std::string& name, T def) :
mValue(def), mDefault(def), mSettingName(name) {}
operator T() const { return mValue; }
T get() const { return mValue; }
/*virtual*/ const std::string& getName() const { return mSettingName; } //See LLShaderSettingBase::getName
/*virtual*/ LLSD getDefaultValue() const { return mDefault; } //See LLShaderSettingBase::getDefaultValue
/*virtual*/ void setValue(const LLSD& value) { mValue = value; } //See LLShaderSettingBase::setValue
private:
const std::string mSettingName; //LLSD key names as found in postprocesseffects.xml. eg 'contrast_base'
T mValue; //The member variable mentioned above.
T mDefault; //Set via ctor. Value is inserted into the defaults LLSD list if absent from postprocesseffects.xml
};
private:
std::vector<IShaderSettingBase*> mSettings; //Contains a list of all the 'settings' this shader uses. Manually add via push_back in ctor.
LLGLSLShader& mShader;
LLShaderSetting<bool> mEnabled;
};
//helpers
class LLPostProcessSinglePassColorShader : public LLPostProcessShader
{
public:
LLPostProcessSinglePassColorShader(const std::string& enable_name, LLGLSLShader& shader, bool enabled = false) :
LLPostProcessShader(enable_name, shader, enabled) {}
/*virtual*/ S32 getColorChannel() const {return 0;}
/*virtual*/ S32 getDepthChannel() const {return -1;}
/*virtual*/ bool draw(U32 pass) {return pass == 1;}
/*virtual*/ void postDraw() {}
};
template<> LLSD LLPostProcessShader::LLShaderSetting<LLVector4>::getDefaultValue() const
{
return mDefault.getValue();
}
@@ -66,223 +117,181 @@ template<> void LLPostProcessShader::LLShaderSetting<LLVector4>::setValue(const
LLSD LLPostProcessShader::getDefaults()
{
LLSD defaults;
for(std::vector<LLShaderSettingBase*>::iterator it=mSettings.begin();it!=mSettings.end();++it)
for(std::vector<IShaderSettingBase*>::iterator it=mSettings.begin();it!=mSettings.end();++it)
{
defaults[(*it)->mSettingName]=(*it)->getDefaultValue();
defaults[(*it)->getName()]=(*it)->getDefaultValue();
}
return defaults;
}
void LLPostProcessShader::loadSettings(const LLSD& settings)
{
for(std::vector<LLShaderSettingBase*>::iterator it=mSettings.begin();it!=mSettings.end();++it)
for(std::vector<IShaderSettingBase*>::iterator it=mSettings.begin();it!=mSettings.end();++it)
{
LLSD value = settings[(*it)->mSettingName];
LLSD value = settings[(*it)->getName()];
(*it)->setValue(value);
}
}
class LLColorFilterShader : public LLPostProcessShader
class LLColorFilterShader : public LLPostProcessSinglePassColorShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<F32> mGamma, mBrightness, mContrast, mSaturation;
LLShaderSetting<LLVector4> mContrastBase;
public:
LLColorFilterShader() :
mEnabled("enable_color_filter",false),
LLColorFilterShader() :
LLPostProcessSinglePassColorShader("enable_color_filter",gPostColorFilterProgram),
mGamma("gamma",1.f),
mBrightness("brightness",1.f),
mContrast("contrast",1.f),
mSaturation("saturation",1.f),
mContrastBase("contrast_base",LLVector4(1.f,1.f,1.f,0.5f))
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mGamma);
mSettings.push_back(&mBrightness);
mSettings.push_back(&mContrast);
mSettings.push_back(&mSaturation);
mSettings.push_back(&mContrastBase);
addSetting(mGamma);
addSetting(mBrightness);
addSetting(mContrast);
addSetting(mSaturation);
addSetting(mContrastBase);
}
bool isEnabled() { return mEnabled && gPostColorFilterProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return -1; }
QuadType bind()
/*virtual*/ QuadType preDraw()
{
if(!isEnabled())
return QUAD_NONE;
/// CALCULATING LUMINANCE (Using NTSC lum weights)
/// http://en.wikipedia.org/wiki/Luma_%28video%29
static const float LUMINANCE_R = 0.299f;
static const float LUMINANCE_G = 0.587f;
static const float LUMINANCE_B = 0.114f;
gPostColorFilterProgram.bind();
getShader().uniform1f("gamma", mGamma);
getShader().uniform1f("brightness", mBrightness);
getShader().uniform1f("contrast", mContrast);
float baseI = (mContrastBase.get()[VX] + mContrastBase.get()[VY] + mContrastBase.get()[VZ]) / 3.0f;
baseI = mContrastBase.get()[VW] / llmax(baseI,0.001f);
float baseR = mContrastBase.get()[VX] * baseI;
float baseG = mContrastBase.get()[VY] * baseI;
float baseB = mContrastBase.get()[VZ] * baseI;
getShader().uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV);
getShader().uniform1f("saturation", mSaturation);
gPostColorFilterProgram.uniform1f("gamma", mGamma);
gPostColorFilterProgram.uniform1f("brightness", mBrightness);
gPostColorFilterProgram.uniform1f("contrast", mContrast);
float baseI = (mContrastBase.mValue[VX] + mContrastBase.mValue[VY] + mContrastBase.mValue[VZ]) / 3.0f;
baseI = mContrastBase.mValue[VW] / ((baseI < 0.001f) ? 0.001f : baseI);
float baseR = mContrastBase.mValue[VX] * baseI;
float baseG = mContrastBase.mValue[VY] * baseI;
float baseB = mContrastBase.mValue[VZ] * baseI;
gPostColorFilterProgram.uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV);
gPostColorFilterProgram.uniform1f("saturation", mSaturation);
gPostColorFilterProgram.uniform3fv("lumWeights", 1, LLVector3(LUMINANCE_R, LUMINANCE_G, LUMINANCE_B).mV);
return QUAD_NORMAL;
}
bool draw(U32 pass) {return pass == 1;}
void unbind()
{
gPostColorFilterProgram.unbind();
}
};
class LLNightVisionShader : public LLPostProcessShader
class LLNightVisionShader : public LLPostProcessSinglePassColorShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<F32> mBrightnessMult, mNoiseStrength;
public:
LLNightVisionShader() :
mEnabled("enable_night_vision",false),
LLPostProcessSinglePassColorShader("enable_night_vision",gPostNightVisionProgram),
mBrightnessMult("brightness_multiplier",3.f),
mNoiseStrength("noise_strength",.4f)
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mBrightnessMult);
mSettings.push_back(&mNoiseStrength);
addSetting(mBrightnessMult);
addSetting(mNoiseStrength);
}
bool isEnabled() { return mEnabled && gPostNightVisionProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return -1; }
QuadType bind()
/*virtual*/ QuadType preDraw()
{
if(!isEnabled())
return QUAD_NONE;
gPostNightVisionProgram.bind();
LLPostProcess::getInstance()->bindNoise(1);
gPostNightVisionProgram.uniform1f("brightMult", mBrightnessMult);
gPostNightVisionProgram.uniform1f("noiseStrength", mNoiseStrength);
getShader().uniform1f("brightMult", mBrightnessMult);
getShader().uniform1f("noiseStrength", mNoiseStrength);
return QUAD_NOISE;
}
bool draw(U32 pass) {return pass == 1;}
void unbind()
};
class LLPosterizeShader : public LLPostProcessSinglePassColorShader
{
private:
LLShaderSetting<S32> mNumLayers;
public:
LLPosterizeShader() : LLPostProcessSinglePassColorShader("enable_posterize",gPostPosterizeProgram),
mNumLayers("posterize_layers",2)
{
gPostNightVisionProgram.unbind();
addSetting(mNumLayers);
}
/*virtual*/ QuadType preDraw()
{
getShader().uniform1i("layerCount", mNumLayers);
return QUAD_NORMAL;
}
};
class LLVignetteShader : public LLPostProcessSinglePassColorShader
{
private:
LLShaderSetting<F32> mStrength, mRadius, mDarkness, mDesaturation, mChromaticAberration;
public:
LLVignetteShader() : LLPostProcessSinglePassColorShader("enable_vignette",gPostVignetteProgram),
mStrength("vignette_strength",.85f),
mRadius("vignette_radius",.7f),
mDarkness("vignette_darkness",1.f),
mDesaturation("vignette_desaturation",1.5f),
mChromaticAberration("vignette_chromatic_aberration",.05f)
{
addSetting(mStrength);
addSetting(mRadius);
addSetting(mDarkness);
addSetting(mDesaturation);
addSetting(mChromaticAberration);
}
/*virtual*/ QuadType preDraw()
{
LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions();
getShader().uniform1f("vignette_strength", mStrength);
getShader().uniform1f("vignette_radius", mRadius);
getShader().uniform1f("vignette_darkness", mDarkness);
getShader().uniform1f("vignette_desaturation", mDesaturation);
getShader().uniform1f("vignette_chromatic_aberration", mChromaticAberration);
getShader().uniform2fv("screen_res", 1, screen_rect.mV);
return QUAD_NORMAL;
}
};
class LLGaussBlurShader : public LLPostProcessShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<S32> mNumPasses;
GLint mPassLoc;
public:
LLGaussBlurShader() :
mEnabled("enable_gauss_blur",false),
LLGaussBlurShader() : LLPostProcessShader("enable_gauss_blur",gPostGaussianBlurProgram),
mNumPasses("gauss_blur_passes",2),
mPassLoc(0)
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mNumPasses);
addSetting(mNumPasses);
}
bool isEnabled() { return mEnabled && mNumPasses && gPostGaussianBlurProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return -1; }
QuadType bind()
/*virtual*/ bool isEnabled() const { return LLPostProcessShader::isEnabled() && mNumPasses.get(); }
/*virtual*/ S32 getColorChannel() const { return 0; }
/*virtual*/ S32 getDepthChannel() const { return -1; }
/*virtual*/ QuadType preDraw()
{
if(!isEnabled())
return QUAD_NONE;
gPostGaussianBlurProgram.bind();
mPassLoc = gPostGaussianBlurProgram.getUniformLocation("horizontalPass");
mPassLoc = getShader().getUniformLocation("horizontalPass");
return QUAD_NORMAL;
}
bool draw(U32 pass)
/*virtual*/ bool draw(U32 pass)
{
if((S32)pass > mNumPasses*2)
return false;
glUniform1iARB(mPassLoc, (pass-1) % 2);
return true;
}
void unbind()
{
gPostGaussianBlurProgram.unbind();
}
};
class LLPosterizeShader : public LLPostProcessShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<S32> mNumLayers;
public:
LLPosterizeShader() :
mEnabled("enable_posterize",false),
mNumLayers("posterize_layers",2)
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mNumLayers);
}
bool isEnabled() { return mEnabled && gPostPosterizeProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return -1; }
QuadType bind()
{
if(!isEnabled())
return QUAD_NONE;
gPostPosterizeProgram.bind();
gPostPosterizeProgram.uniform1i("layerCount", mNumLayers);
return QUAD_NORMAL;
}
bool draw(U32 pass)
{
return pass == 1;
}
void unbind()
{
gPostPosterizeProgram.unbind();
}
/*virtual*/ void postDraw() {}
};
class LLMotionShader : public LLPostProcessShader
{
private:
LLShaderSetting<bool> mEnabled;
LLShaderSetting<S32> mStrength;
public:
LLMotionShader() :
mEnabled("enable_motionblur",false),
mStrength("blur_strength",false)
LLMotionShader() : LLPostProcessShader("enable_motionblur",gPostMotionBlurProgram),
mStrength("blur_strength",1)
{
mSettings.push_back(&mEnabled);
mSettings.push_back(&mStrength);
addSetting(mStrength);
}
bool isEnabled() { return mEnabled && gPostMotionBlurProgram.mProgramObject; }
S32 getColorChannel() { return 0; }
S32 getDepthChannel() { return 1; }
QuadType bind()
/*virtual*/ S32 getColorChannel() const { return 0; }
/*virtual*/ S32 getDepthChannel() const { return 1; }
/*virtual*/ QuadType preDraw()
{
if(!isEnabled())
{
return QUAD_NONE;
}
glh::matrix4f inv_proj(gGLModelView);
inv_proj.mult_left(gGLProjection);
inv_proj = inv_proj.inverse();
@@ -291,22 +300,18 @@ public:
LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions();
gPostMotionBlurProgram.bind();
gPostMotionBlurProgram.uniformMatrix4fv("prev_proj", 1, GL_FALSE, prev_proj.m);
gPostMotionBlurProgram.uniformMatrix4fv("inv_proj", 1, GL_FALSE, inv_proj.m);
gPostMotionBlurProgram.uniform2fv("screen_res", 1, screen_rect.mV);
gPostMotionBlurProgram.uniform1i("blur_strength", mStrength);
getShader().uniformMatrix4fv("prev_proj", 1, GL_FALSE, prev_proj.m);
getShader().uniformMatrix4fv("inv_proj", 1, GL_FALSE, inv_proj.m);
getShader().uniform2fv("screen_res", 1, screen_rect.mV);
getShader().uniform1i("blur_strength", mStrength);
return QUAD_NORMAL;
}
bool draw(U32 pass)
/*virtual*/ bool draw(U32 pass)
{
return pass == 1;
}
void unbind()
{
gPostMotionBlurProgram.unbind();
}
/*virtual*/ void postDraw() {}
};
LLPostProcess::LLPostProcess(void) :
@@ -320,12 +325,12 @@ LLPostProcess::LLPostProcess(void) :
mAllEffectInfo(LLSD::emptyMap())
{
mShaders.push_back(new LLMotionShader());
mShaders.push_back(new LLVignetteShader());
mShaders.push_back(new LLColorFilterShader());
mShaders.push_back(new LLNightVisionShader());
mShaders.push_back(new LLGaussBlurShader());
mShaders.push_back(new LLPosterizeShader());
/* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.*/
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
LL_DEBUGS2("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL;
@@ -547,20 +552,19 @@ void LLPostProcess::doEffects(void)
void LLPostProcess::applyShaders(void)
{
QuadType quad;
bool primary_rendertarget = 1;
for(std::list<LLPointer<LLPostProcessShader> >::iterator it=mShaders.begin();it!=mShaders.end();++it)
{
if((quad = (*it)->bind()) != QUAD_NONE)
if((*it)->isEnabled())
{
S32 color_channel = (*it)->getColorChannel();
S32 depth_channel = (*it)->getDepthChannel();
if(depth_channel >= 0)
gGL.getTexUnit(depth_channel)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mDepthTexture);
U32 pass = 1;
(*it)->bindShader();
QuadType quad = (*it)->preDraw();
while((*it)->draw(pass++))
{
mRenderTarget[!primary_rendertarget].bindTarget();
@@ -573,7 +577,8 @@ void LLPostProcess::applyShaders(void)
if(mRenderTarget[0].getFBO())
primary_rendertarget = !primary_rendertarget;
}
(*it)->unbind();
(*it)->postDraw();
(*it)->unbindShader();
}
}
//Only need to copy to framebuffer if FBOs are supported, else we've already been drawing to the framebuffer to begin with.

View File

@@ -38,57 +38,48 @@
#include "llrendertarget.h"
class LLSD;
class LLGLSLShader;
typedef enum _QuadType {
QUAD_NONE,
QUAD_NORMAL,
QUAD_NOISE
} QuadType;
//LLPostProcessShader is an attempt to encapsulate the shaders a little better.
class LLPostProcessShader : public LLRefCount //Abstract. PostProcess shaders derive off of this common base.
class IPostProcessShader //Abstract. PostProcess shaders derive off of this common base.
{
protected:
//LLShaderSetting is used to associate key names to member variables to avoid LLSD lookups when drawing.
//It also facilitates automating the assigning of defaults to, as well as parsing from, the effects LLSD list.
//This replaces the entire old PostProcessTweaks structure. More will be done in the future to move into a more
//xml-driven configuration.
struct LLShaderSettingBase
struct IShaderSettingBase
{
LLShaderSettingBase(const char* name) : mSettingName(name) {}
const char* mSettingName; //LLSD key names as found in postprocesseffects.xml. eg 'contrast_base'
virtual LLSD getDefaultValue() = 0; //Converts the member variable as an LLSD. Used to set defaults absent in postprocesseffects.xml
virtual ~IShaderSettingBase() {} //virtual dtor.
virtual const std::string& getName() const = 0; //Returns the name of this setting
virtual LLSD getDefaultValue() const = 0; //Converts the member variable as an LLSD. Used to set defaults absent in postprocesseffects.xml
virtual void setValue(const LLSD& value) = 0; //Connects the LLSD element to the member variable. Used when loading effects (such as default)
};
template<typename T>
struct LLShaderSetting : public LLShaderSettingBase
{
LLShaderSetting(const char* setting_name, T def) : LLShaderSettingBase(setting_name), mValue(def), mDefault(def) {}
T mValue; //The member variable mentioned above.
T mDefault; //Set via ctor. Value is inserted into the defaults LLSD list if absent from postprocesseffects.xml
LLSD getDefaultValue() { return mDefault; } //See LLShaderSettingBase::getDefaultValue
void setValue(const LLSD& value) { mValue = value; } //See LLShaderSettingBase::setValue
operator T() { return mValue; } //Typecast operator overload so this object can be handled as if it was whatever T represents.
};
std::vector<LLShaderSettingBase*> mSettings; //Contains a list of all the 'settings' this shader uses. Manually add via push_back in ctor.
public:
virtual ~LLPostProcessShader() {};
virtual bool isEnabled() = 0; //Returning false avoids bind/draw/unbind calls. If no shaders are enabled, framebuffer copying is skipped.
virtual S32 getColorChannel() = 0; //If color buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer.
virtual S32 getDepthChannel() = 0; //If depth buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer.
virtual QuadType bind() = 0; //Bind shader and textures, set up attribs. Returns the 'type' of quad to be drawn.
virtual ~IPostProcessShader() {} //virtual dtor.
virtual bool isEnabled() const = 0; //Returning false avoids bind/draw/unbind calls. If no shaders are enabled, framebuffer copying is skipped.
virtual S32 getColorChannel() const = 0; //If color buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer.
virtual S32 getDepthChannel() const = 0; //If depth buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer.
virtual void bindShader() = 0;
virtual void unbindShader() = 0;
virtual LLGLSLShader& getShader() = 0;
virtual QuadType preDraw() = 0; //Bind shader and textures, set up attribs. Returns the 'type' of quad to be drawn.
virtual bool draw(U32 pass) = 0; //returning false means finished. Used to update per-pass attributes and such. LLPostProcess will call
//drawOrthoQuad when this returns true, increment pass, then call this again, and keep repeating this until false is returned.
virtual void unbind() = 0; //Unbind shader and textures.
virtual void postDraw() = 0; //Done drawing..
LLSD getDefaults(); //Returns a full LLSD kvp list filled with default values.
void loadSettings(const LLSD& settings); //Parses the effects LLSD list and sets the member variables linked to them (via LLShaderSetting::setValue())
virtual LLSD getDefaults() = 0; //Returns a full LLSD kvp list filled with default values.
virtual void loadSettings(const LLSD& settings) = 0; //Parses the effects LLSD list and sets the member variables linked to them (via LLShaderSetting::setValue())
virtual void addSetting(IShaderSettingBase& setting) = 0;
};
//LLVector4 does not implicitly convert to and from LLSD, so template specilizations are necessary.
template<> LLSD LLPostProcessShader::LLShaderSetting<LLVector4>::getDefaultValue();
template<> void LLPostProcessShader::LLShaderSetting<LLVector4>::setValue(const LLSD& value);
class LLPostProcessShader;
class LLPostProcess : public LLSingleton<LLPostProcess>
{
private:

View File

@@ -0,0 +1,54 @@
/**
* @file colorFilterF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#extension GL_ARB_texture_rectangle : enable
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
uniform sampler2DRect tex0;
uniform float vignette_strength; //0 - 1
uniform float vignette_radius; //0 - 8
uniform float vignette_darkness; //0 - 1
uniform float vignette_desaturation; //0 - 10
uniform float vignette_chromatic_aberration; //0 - .1
uniform vec2 screen_res;
VARYING vec2 vary_texcoord0;
float luminance(vec3 color)
{
/// CALCULATING LUMINANCE (Using NTSC lum weights)
/// http://en.wikipedia.org/wiki/Luma_%28video%29
return dot(color, vec3(0.299, 0.587, 0.114));
}
void main(void)
{
vec3 color = texture2DRect(tex0, vary_texcoord0).rgb;
vec2 norm_texcood = (vary_texcoord0/screen_res);
vec2 offset = norm_texcood-vec2(.5);
float vignette = clamp(pow(1 - dot(offset,offset),vignette_radius) + 1-vignette_strength, 0.0, 1.0);
float inv_vignette = 1-vignette;
//vignette chromatic aberration (g
vec2 shift = screen_res * offset * vignette_chromatic_aberration * inv_vignette;
float g = texture2DRect(tex0,vary_texcoord0-shift).g;
float b = texture2DRect(tex0,vary_texcoord0-2*shift).b;
color.gb = vec2(g,b);
//vignette 'black' overlay.
color = mix(color * vignette, color, 1-vignette_darkness);
//vignette desaturation
color = mix(vec3(luminance(color)), color, clamp(1-inv_vignette*vignette_desaturation,0,1));
frag_color = vec4(color,1.0);
}

View File

@@ -25,6 +25,13 @@ uniform float gamma;
VARYING vec2 vary_texcoord0;
float luminance(vec3 color)
{
/// CALCULATING LUMINANCE (Using NTSC lum weights)
/// http://en.wikipedia.org/wiki/Luma_%28video%29
return dot(color, vec3(0.299, 0.587, 0.114));
}
void main(void)
{
vec3 color = vec3(texture2DRect(tex0, vary_texcoord0.st));
@@ -39,7 +46,7 @@ void main(void)
color = mix(contrastBase, color, contrast);
/// Modulate saturation
color = mix(vec3(dot(color, lumWeights)), color, saturation);
color = mix(vec3(luminance(color)), color, saturation);
frag_color = vec4(color, 1.0);
}

View File

@@ -177,6 +177,8 @@
<key>enable_posterize</key>
<boolean>0</boolean>
<key>enable_motionblur</key>
<boolean>0</boolean>
<key>enable_vignette</key>
<boolean>0</boolean>
<key>gauss_blur_passes</key>
<integer>2</integer>
@@ -194,6 +196,16 @@
<real>10</real>
<key>blur_strength</key>
<real>10</real>
<key>vignette_strength</key>
<real>0.85</real>
<key>vignette_radius</key>
<real>0.7</real>
<key>vignette_darkness</key>
<real>1.0</real>
<key>vignette_desaturation</key>
<real>1.0</real>
<key>vignette_chromatic_aberration</key>
<real>0.01</real>
</map>
</map>
</llsd>

View File

@@ -172,7 +172,8 @@ LLGLSLShader gPostNightVisionProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not
LLGLSLShader gPostGaussianBlurProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList
LLGLSLShader gPostPosterizeProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList
LLGLSLShader gPostMotionBlurProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList
LLGLSLShader gPostVignetteProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList
// Deferred rendering shaders
LLGLSLShader gDeferredImpostorProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics
@@ -908,7 +909,6 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
shaderUniforms.push_back("contrast");
shaderUniforms.push_back("contrastBase");
shaderUniforms.push_back("saturation");
shaderUniforms.push_back("lumWeights");
gPostColorFilterProgram.mName = "Color Filter Shader (Post)";
gPostColorFilterProgram.mShaderFiles.clear();
@@ -929,7 +929,6 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
shaderUniforms.reserve(3);
shaderUniforms.push_back("brightMult");
shaderUniforms.push_back("noiseStrength");
shaderUniforms.push_back("lumWeights");
gPostNightVisionProgram.mName = "Night Vision Shader (Post)";
gPostNightVisionProgram.mShaderFiles.clear();
@@ -998,6 +997,26 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
gPostMotionBlurProgram.uniform1i("tex1", 1);
}
}
{
vector<string> shaderUniforms;
shaderUniforms.reserve(3);
shaderUniforms.push_back("vignette_darkness");
shaderUniforms.push_back("vignette_radius");
shaderUniforms.push_back("screen_res");
gPostVignetteProgram.mName = "Vignette Shader (Post)";
gPostVignetteProgram.mShaderFiles.clear();
gPostVignetteProgram.mShaderFiles.push_back(make_pair("effects/VignetteF.glsl", GL_FRAGMENT_SHADER_ARB));
gPostVignetteProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB));
gPostVignetteProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
if(gPostVignetteProgram.createShader(NULL, &shaderUniforms))
{
gPostVignetteProgram.bind();
gPostVignetteProgram.uniform1i("tex0", 0);
}
}
#endif
return success;

View File

@@ -184,6 +184,73 @@
max_val="30" min_val="1" mouse_opaque="true"
name="blur_strength" show_text="true" value="0.7" width="200" />
</panel>
<panel border="true" bottom="-180" follows="left|top|right|bottom" height="400"
label="Vignette" left="1" mouse_opaque="false"
name="VignettePanel" width="398">
<check_box follows="left|top"
font="SansSerifSmall" height="16" initial_value="false" label="Enable"
left="4" mouse_opaque="true" name="enable_vignette" width="200" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom_delta="-21" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16"
left="10" mouse_opaque="true" name="VignetteStrengthText" v_pad="0"
width="355">
Strength
</text>
<slider bottom_delta="-35" can_edit_text="true"
decimal_digits="3" follows="left"
height="18" increment=".005" initial_val=".85" label="" left="14"
max_val="1" min_val="0" mouse_opaque="true"
name="vignette_strength" show_text="true" value="0" width="200" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom_delta="-21" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16"
left="10" mouse_opaque="true" name="VignetteRadiusText" v_pad="0"
width="355">
Radius
</text>
<slider bottom_delta="-35" can_edit_text="true"
decimal_digits="3" follows="left"
height="18" increment=".01" initial_val=".7" label="" left="14"
max_val="8" min_val=".1" mouse_opaque="true"
name="vignette_radius" show_text="true" value="0" width="200" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom_delta="-21" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16"
left="10" mouse_opaque="true" name="VignetteDarknessText" v_pad="0"
width="355">
Darkness
</text>
<slider bottom_delta="-35" can_edit_text="true"
decimal_digits="3" follows="left"
height="18" increment=".005" initial_val=".85" label="" left="14"
max_val="1" min_val="0" mouse_opaque="true"
name="vignette_darkness" show_text="true" value="0" width="200" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom_delta="-21" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16"
left="10" mouse_opaque="true" name="VignetteDesaturateText" v_pad="0"
width="355">
Desaturation Strength
</text>
<slider bottom_delta="-35" can_edit_text="true"
decimal_digits="3" follows="left"
height="18" increment=".05" initial_val="1" label="" left="14"
max_val="10" min_val="0" mouse_opaque="true"
name="vignette_desaturation" show_text="true" value="0" width="200" />
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom_delta="-21" drop_shadow_visible="true" follows="left|top|right"
font="SansSerif" h_pad="0" halign="left" height="16"
left="10" mouse_opaque="true" name="VignetteChormaticAberrationText" v_pad="0"
width="355">
Chromatic Aberration
</text>
<slider bottom_delta="-35" can_edit_text="true"
decimal_digits="3" follows="left"
height="18" increment="0.0005" initial_val=".01" label="" left="14"
max_val=".1" min_val="0" mouse_opaque="true"
name="vignette_chromatic_aberration" show_text="true" value="0" width="200" />
</panel>
<!--<panel border="true" bottom="-180" follows="left|top|right|bottom" height="400"
label="Bloom" left="1" mouse_opaque="true"
name="BloomPanel" width="398">