diff options
| author | Graham Madarasz (Graham) <graham@lindenlab.com> | 2013-03-01 11:34:33 -0800 | 
|---|---|---|
| committer | Graham Madarasz (Graham) <graham@lindenlab.com> | 2013-03-01 11:34:33 -0800 | 
| commit | 59a0c687807e2a4293708f263f1c8eca2dd86b8f (patch) | |
| tree | 978fc68cace6a566c4595d32d1425df6d6430e7b | |
| parent | 7f66555ed6ce46ac85a10a349e9f40b73c136950 (diff) | |
Fix windoze line-endings from missing commit hook fiasco
| -rw-r--r-- | indra/llrender/llpostprocess.cpp | 1190 | 
1 files changed, 595 insertions, 595 deletions
| diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index c51f85ab71..4c36185b08 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -1,595 +1,595 @@ -/** 
 - * @file llpostprocess.cpp
 - * @brief LLPostProcess class implementation
 - *
 - * $LicenseInfo:firstyear=2007&license=viewerlgpl$
 - * Second Life Viewer Source Code
 - * Copyright (C) 2010, Linden Research, Inc.
 - * 
 - * This library is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU Lesser General Public
 - * License as published by the Free Software Foundation;
 - * version 2.1 of the License only.
 - * 
 - * This library is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - * Lesser General Public License for more details.
 - * 
 - * You should have received a copy of the GNU Lesser General Public
 - * License along with this library; if not, write to the Free Software
 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 - * 
 - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 - * $/LicenseInfo$
 - */
 -
 -#include "linden_common.h"
 -
 -#include "llpostprocess.h"
 -#include "llglslshader.h"
 -#include "llsdserialize.h"
 -#include "llrender.h"
 -
 -static LLStaticHashedString sRenderTexture("RenderTexture");
 -static LLStaticHashedString sBrightness("brightness");
 -static LLStaticHashedString sContrast("contrast");
 -static LLStaticHashedString sContrastBase("contrastBase");
 -static LLStaticHashedString sSaturation("saturation");
 -static LLStaticHashedString sLumWeights("lumWeights");
 -static LLStaticHashedString sNoiseTexture("NoiseTexture");
 -static LLStaticHashedString sBrightMult("brightMult");
 -static LLStaticHashedString sNoiseStrength("noiseStrength");
 -static LLStaticHashedString sExtractLow("extractLow");
 -static LLStaticHashedString sExtractHigh("extractHigh");
 -static LLStaticHashedString sBloomStrength("bloomStrength");
 -static LLStaticHashedString sTexelSize("texelSize");
 -static LLStaticHashedString sBlurDirection("blurDirection");
 -static LLStaticHashedString sBlurWidth("blurWidth");
 -
 -LLPostProcess * gPostProcess = NULL;
 -
 -
 -static const unsigned int NOISE_SIZE = 512;
 -
 -/// 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;
 -
 -static const char * const XML_FILENAME = "postprocesseffects.xml";
 -
 -LLPostProcess::LLPostProcess(void) : 
 -					initialized(false),  
 -					mAllEffects(LLSD::emptyMap()),
 -					screenW(1), screenH(1)
 -{
 -	mSceneRenderTexture = NULL ; 
 -	mNoiseTexture = NULL ;
 -	mTempBloomTexture = NULL ;
 -
 -	noiseTextureScale = 1.0f;
 -					
 -	/*  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;
 -
 -	llifstream effectsXML(pathName);
 -
 -	if (effectsXML)
 -	{
 -		LLPointer<LLSDParser> parser = new LLSDXMLParser();
 -
 -		parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED);
 -	}
 -
 -	if (!mAllEffects.has("default"))
 -	{
 -		LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap());
 -
 -		defaultEffect["enable_night_vision"] = LLSD::Boolean(false);
 -		defaultEffect["enable_bloom"] = LLSD::Boolean(false);
 -		defaultEffect["enable_color_filter"] = LLSD::Boolean(false);
 -
 -		/// NVG Defaults
 -		defaultEffect["brightness_multiplier"] = 3.0;
 -		defaultEffect["noise_size"] = 25.0;
 -		defaultEffect["noise_strength"] = 0.4;
 -
 -		// TODO BTest potentially add this to tweaks?
 -		noiseTextureScale = 1.0f;
 -		
 -		/// Bloom Defaults
 -		defaultEffect["extract_low"] = 0.95;
 -		defaultEffect["extract_high"] = 1.0;
 -		defaultEffect["bloom_width"] = 2.25;
 -		defaultEffect["bloom_strength"] = 1.5;
 -
 -		/// Color Filter Defaults
 -		defaultEffect["brightness"] = 1.0;
 -		defaultEffect["contrast"] = 1.0;
 -		defaultEffect["saturation"] = 1.0;
 -
 -		LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray());
 -		contrastBase.append(1.0);
 -		contrastBase.append(1.0);
 -		contrastBase.append(1.0);
 -		contrastBase.append(0.5);
 -	}
 -
 -	setSelectedEffect("default");
 -	*/
 -}
 -
 -LLPostProcess::~LLPostProcess(void)
 -{
 -	invalidate() ;
 -}
 -
 -// static
 -void LLPostProcess::initClass(void)
 -{
 -	//this will cause system to crash at second time login
 -	//if first time login fails due to network connection --- bao
 -	//***llassert_always(gPostProcess == NULL);
 -	//replaced by the following line:
 -	if(gPostProcess)
 -		return ;
 -	
 -	
 -	gPostProcess = new LLPostProcess();
 -}
 -
 -// static
 -void LLPostProcess::cleanupClass()
 -{
 -	delete gPostProcess;
 -	gPostProcess = NULL;
 -}
 -
 -void LLPostProcess::setSelectedEffect(std::string const & effectName)
 -{
 -	mSelectedEffectName = effectName;
 -	static_cast<LLSD &>(tweaks) = mAllEffects[effectName];
 -}
 -
 -void LLPostProcess::saveEffect(std::string const & effectName)
 -{
 -	/*  Do nothing.  Needs to be updated to use our current shader system, and to work with the move into llrender.
 -	mAllEffects[effectName] = tweaks;
 -
 -	std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
 -	//llinfos << "Saving PostProcess Effects settings to " << pathName << llendl;
 -
 -	llofstream effectsXML(pathName);
 -
 -	LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
 -
 -	formatter->format(mAllEffects, effectsXML);
 -	*/
 -}
 -void LLPostProcess::invalidate()
 -{
 -	mSceneRenderTexture = NULL ;
 -	mNoiseTexture = NULL ;
 -	mTempBloomTexture = NULL ;
 -	initialized = FALSE ;
 -}
 -
 -void LLPostProcess::apply(unsigned int width, unsigned int height)
 -{
 -	if (!initialized || width != screenW || height != screenH){
 -		initialize(width, height);
 -	}
 -	if (shadersEnabled()){
 -		doEffects();
 -	}
 -}
 -
 -void LLPostProcess::initialize(unsigned int width, unsigned int height)
 -{
 -	screenW = width;
 -	screenH = height;
 -	createTexture(mSceneRenderTexture, screenW, screenH);
 -	initialized = true;
 -
 -	checkError();
 -	createNightVisionShader();
 -	createBloomShader();
 -	createColorFilterShader();
 -	checkError();
 -}
 -
 -inline bool LLPostProcess::shadersEnabled(void)
 -{
 -	return (tweaks.useColorFilter().asBoolean() ||
 -			tweaks.useNightVisionShader().asBoolean() ||
 -			tweaks.useBloomShader().asBoolean() );
 -
 -}
 -
 -void LLPostProcess::applyShaders(void)
 -{
 -	if (tweaks.useColorFilter()){
 -		applyColorFilterShader();
 -		checkError();
 -	}	
 -	if (tweaks.useNightVisionShader()){
 -		/// If any of the above shaders have been called update the frame buffer;
 -		if (tweaks.useColorFilter())
 -		{
 -			U32 tex = mSceneRenderTexture->getTexName() ;
 -			copyFrameBuffer(tex, screenW, screenH);
 -		}
 -		applyNightVisionShader();
 -		checkError();
 -	}
 -	if (tweaks.useBloomShader()){
 -		/// If any of the above shaders have been called update the frame buffer;
 -		if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean())
 -		{
 -			U32 tex = mSceneRenderTexture->getTexName() ;
 -			copyFrameBuffer(tex, screenW, screenH);
 -		}
 -		applyBloomShader();
 -		checkError();
 -	}
 -}
 -
 -void LLPostProcess::applyColorFilterShader(void)
 -{	
 -	/*  Do nothing.  Needs to be updated to use our current shader system, and to work with the move into llrender.
 -	gPostColorFilterProgram.bind();
 -
 -	gGL.getTexUnit(0)->activate();
 -	gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
 -
 -	gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture);
 -
 -	getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject);
 -	glUniform1iARB(colorFilterUniforms["RenderTexture"], 0);
 -	glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness());
 -	glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast());
 -	float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f;
 -	baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI);
 -	float baseR = tweaks.getContrastBaseR() * baseI;
 -	float baseG = tweaks.getContrastBaseG() * baseI;
 -	float baseB = tweaks.getContrastBaseB() * baseI;
 -	glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB);
 -	glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation());
 -	glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
 -	
 -	LLGLEnable blend(GL_BLEND);
 -	gGL.setSceneBlendType(LLRender::BT_REPLACE);
 -	LLGLDepthTest depth(GL_FALSE);
 -		
 -	/// Draw a screen space quad
 -	drawOrthoQuad(screenW, screenH, QUAD_NORMAL);
 -	gPostColorFilterProgram.unbind();
 -	*/
 -}
 -
 -void LLPostProcess::createColorFilterShader(void)
 -{
 -	/// Define uniform names
 -	colorFilterUniforms[sRenderTexture] = 0;
 -	colorFilterUniforms[sBrightness] = 0;
 -	colorFilterUniforms[sContrast] = 0;
 -	colorFilterUniforms[sContrastBase] = 0;
 -	colorFilterUniforms[sSaturation] = 0;
 -	colorFilterUniforms[sLumWeights] = 0;
 -}
 -
 -void LLPostProcess::applyNightVisionShader(void)
 -{	
 -	/*  Do nothing.  Needs to be updated to use our current shader system, and to work with the move into llrender.
 -	gPostNightVisionProgram.bind();
 -
 -	gGL.getTexUnit(0)->activate();
 -	gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
 -
 -	getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject);
 -	gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture);
 -	glUniform1iARB(nightVisionUniforms["RenderTexture"], 0);
 -
 -	gGL.getTexUnit(1)->activate();
 -	gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);	
 -
 -	gGL.getTexUnit(1)->bindManual(LLTexUnit::TT_TEXTURE, noiseTexture);
 -	glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1);
 -
 -	
 -	glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult());
 -	glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength());
 -	noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f);
 -	noiseTextureScale *= (screenH / NOISE_SIZE);
 -
 -
 -	glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
 -	
 -	LLGLEnable blend(GL_BLEND);
 -	gGL.setSceneBlendType(LLRender::BT_REPLACE);
 -	LLGLDepthTest depth(GL_FALSE);
 -		
 -	/// Draw a screen space quad
 -	drawOrthoQuad(screenW, screenH, QUAD_NOISE);
 -	gPostNightVisionProgram.unbind();
 -	gGL.getTexUnit(0)->activate();
 -	*/
 -}
 -
 -void LLPostProcess::createNightVisionShader(void)
 -{
 -	/// Define uniform names
 -	nightVisionUniforms[sRenderTexture] = 0;
 -	nightVisionUniforms[sNoiseTexture] = 0;
 -	nightVisionUniforms[sBrightMult] = 0;	
 -	nightVisionUniforms[sNoiseStrength] = 0;
 -	nightVisionUniforms[sLumWeights] = 0;	
 -
 -	createNoiseTexture(mNoiseTexture);
 -}
 -
 -void LLPostProcess::applyBloomShader(void)
 -{
 -
 -}
 -
 -void LLPostProcess::createBloomShader(void)
 -{
 -	createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
 -
 -	/// Create Bloom Extract Shader
 -	bloomExtractUniforms[sRenderTexture] = 0;
 -	bloomExtractUniforms[sExtractLow] = 0;
 -	bloomExtractUniforms[sExtractHigh] = 0;	
 -	bloomExtractUniforms[sLumWeights] = 0;	
 -	
 -	/// Create Bloom Blur Shader
 -	bloomBlurUniforms[sRenderTexture] = 0;
 -	bloomBlurUniforms[sBloomStrength] = 0;	
 -	bloomBlurUniforms[sTexelSize] = 0;
 -	bloomBlurUniforms[sBlurDirection] = 0;
 -	bloomBlurUniforms[sBlurWidth] = 0;
 -}
 -
 -void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)
 -{
 -	/// Find uniform locations and insert into map	
 -	glslUniforms::iterator i;
 -	for (i  = uniforms.begin(); i != uniforms.end(); ++i){
 -		i->second = glGetUniformLocationARB(prog, i->first.String().c_str());
 -	}
 -}
 -
 -void LLPostProcess::doEffects(void)
 -{
 -	/// Save GL State
 -	glPushAttrib(GL_ALL_ATTRIB_BITS);
 -	glPushClientAttrib(GL_ALL_ATTRIB_BITS);
 -
 -	/// Copy the screen buffer to the render texture
 -	{
 -		U32 tex = mSceneRenderTexture->getTexName() ;
 -		copyFrameBuffer(tex, screenW, screenH);
 -	}
 -
 -	/// Clear the frame buffer.
 -	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 -	glClear(GL_COLOR_BUFFER_BIT);
 -	
 -	/// Change to an orthogonal view
 -	viewOrthogonal(screenW, screenH);
 -	
 -	checkError();
 -	applyShaders();
 -	
 -	LLGLSLShader::bindNoShader();
 -	checkError();
 -
 -	/// Change to a perspective view
 -	viewPerspective();	
 -
 -	/// Reset GL State
 -	glPopClientAttrib();
 -	glPopAttrib();
 -	checkError();
 -}
 -
 -void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height)
 -{
 -	gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture);
 -	glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0);
 -}
 -
 -void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type)
 -{
 -#if 0
 -	float noiseX = 0.f;
 -	float noiseY = 0.f;
 -	float screenRatio = 1.0f;
 -
 -	if (type == QUAD_NOISE){
 -		noiseX = ((float) rand() / (float) RAND_MAX);
 -		noiseY = ((float) rand() / (float) RAND_MAX);
 -		screenRatio = (float) width / (float) height;
 -	}
 -	
 -
 -	glBegin(GL_QUADS);
 -		if (type != QUAD_BLOOM_EXTRACT){
 -			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height);
 -		} else {
 -			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height * 2.0f);
 -		}
 -		if (type == QUAD_NOISE){
 -			glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
 -									noiseX,
 -									noiseTextureScale + noiseY);
 -		} else if (type == QUAD_BLOOM_COMBINE){
 -			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, (GLfloat) height * 0.5f);
 -		}
 -		glVertex2f(0.f, (GLfloat) screenH - height);
 -
 -		if (type != QUAD_BLOOM_EXTRACT){
 -			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
 -		} else {
 -			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
 -		}
 -		if (type == QUAD_NOISE){
 -			glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
 -									noiseX,
 -									noiseY);
 -		} else if (type == QUAD_BLOOM_COMBINE){
 -			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, 0.f);
 -		}
 -		glVertex2f(0.f, (GLfloat) height + (screenH - height));
 -
 -		
 -		if (type != QUAD_BLOOM_EXTRACT){
 -			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, 0.f);
 -		} else {
 -			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, 0.f);
 -		}
 -		if (type == QUAD_NOISE){
 -			glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
 -									screenRatio * noiseTextureScale + noiseX,
 -									noiseY);
 -		} else if (type == QUAD_BLOOM_COMBINE){
 -			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, 0.f);
 -		}
 -		glVertex2f((GLfloat) width, (GLfloat) height + (screenH - height));
 -
 -		
 -		if (type != QUAD_BLOOM_EXTRACT){
 -			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, (GLfloat) height);
 -		} else {
 -			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f);
 -		}
 -		if (type == QUAD_NOISE){
 -			glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
 -									screenRatio * noiseTextureScale + noiseX,
 -									noiseTextureScale + noiseY);
 -		} else if (type == QUAD_BLOOM_COMBINE){
 -			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f);
 -		}
 -		glVertex2f((GLfloat) width, (GLfloat) screenH - height);
 -	glEnd();
 -#endif
 -}
 -
 -void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height)
 -{
 -	gGL.matrixMode(LLRender::MM_PROJECTION);
 -	gGL.pushMatrix();
 -	gGL.loadIdentity();
 -	gGL.ortho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f );
 -	gGL.matrixMode(LLRender::MM_MODELVIEW);
 -	gGL.pushMatrix();
 -	gGL.loadIdentity();
 -}
 -
 -void LLPostProcess::viewPerspective(void)
 -{
 -	gGL.matrixMode(LLRender::MM_PROJECTION);
 -	gGL.popMatrix();
 -	gGL.matrixMode(LLRender::MM_MODELVIEW);
 -	gGL.popMatrix();
 -}
 -
 -void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height)
 -{
 -	viewPerspective();
 -	viewOrthogonal(width, height);
 -}
 -
 -void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height)
 -{
 -	std::vector<GLubyte> data(width * height * 4, 0) ;
 -
 -	texture = new LLImageGL(FALSE) ;	
 -	if(texture->createGLTexture())
 -	{
 -		gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName());
 -		glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0,
 -			GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
 -		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
 -		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
 -	}
 -}
 -
 -void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture)
 -{	
 -	std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE);
 -	for (unsigned int i = 0; i < NOISE_SIZE; i++){
 -		for (unsigned int k = 0; k < NOISE_SIZE; k++){
 -			buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f);
 -		}
 -	}
 -
 -	texture = new LLImageGL(FALSE) ;
 -	if(texture->createGLTexture())
 -	{
 -		gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
 -		LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]);
 -		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
 -		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
 -	}
 -}
 -
 -bool LLPostProcess::checkError(void)
 -{
 -	GLenum glErr;
 -    bool    retCode = false;
 -
 -    glErr = glGetError();
 -    while (glErr != GL_NO_ERROR)
 -    {
 -		// shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl;
 -		char const * err_str_raw = (const char *) gluErrorString(glErr);
 -
 -		if(err_str_raw == NULL)
 -		{
 -			std::ostringstream err_builder;
 -			err_builder << "unknown error number " << glErr;
 -			mShaderErrorString = err_builder.str();
 -		}
 -		else
 -		{
 -			mShaderErrorString = err_str_raw;
 -		}
 -
 -        retCode = true;
 -        glErr = glGetError();
 -    }
 -    return retCode;
 -}
 -
 -void LLPostProcess::checkShaderError(GLhandleARB shader)
 -{
 -    GLint infologLength = 0;
 -    GLint charsWritten  = 0;
 -    GLchar *infoLog;
 -
 -    checkError();  // Check for OpenGL errors
 -
 -    glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
 -
 -    checkError();  // Check for OpenGL errors
 -
 -    if (infologLength > 0)
 -    {
 -        infoLog = (GLchar *)malloc(infologLength);
 -        if (infoLog == NULL)
 -        {
 -            /// Could not allocate infolog buffer
 -            return;
 -        }
 -        glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog);
 -		// shaderErrorLog << (char *) infoLog << std::endl;
 -		mShaderErrorString = (char *) infoLog;
 -        free(infoLog);
 -    }
 -    checkError();  // Check for OpenGL errors
 -}
 +/**  + * @file llpostprocess.cpp + * @brief LLPostProcess class implementation + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llpostprocess.h" +#include "llglslshader.h" +#include "llsdserialize.h" +#include "llrender.h" + +static LLStaticHashedString sRenderTexture("RenderTexture"); +static LLStaticHashedString sBrightness("brightness"); +static LLStaticHashedString sContrast("contrast"); +static LLStaticHashedString sContrastBase("contrastBase"); +static LLStaticHashedString sSaturation("saturation"); +static LLStaticHashedString sLumWeights("lumWeights"); +static LLStaticHashedString sNoiseTexture("NoiseTexture"); +static LLStaticHashedString sBrightMult("brightMult"); +static LLStaticHashedString sNoiseStrength("noiseStrength"); +static LLStaticHashedString sExtractLow("extractLow"); +static LLStaticHashedString sExtractHigh("extractHigh"); +static LLStaticHashedString sBloomStrength("bloomStrength"); +static LLStaticHashedString sTexelSize("texelSize"); +static LLStaticHashedString sBlurDirection("blurDirection"); +static LLStaticHashedString sBlurWidth("blurWidth"); + +LLPostProcess * gPostProcess = NULL; + + +static const unsigned int NOISE_SIZE = 512; + +/// 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; + +static const char * const XML_FILENAME = "postprocesseffects.xml"; + +LLPostProcess::LLPostProcess(void) :  +					initialized(false),   +					mAllEffects(LLSD::emptyMap()), +					screenW(1), screenH(1) +{ +	mSceneRenderTexture = NULL ;  +	mNoiseTexture = NULL ; +	mTempBloomTexture = NULL ; + +	noiseTextureScale = 1.0f; +					 +	/*  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; + +	llifstream effectsXML(pathName); + +	if (effectsXML) +	{ +		LLPointer<LLSDParser> parser = new LLSDXMLParser(); + +		parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED); +	} + +	if (!mAllEffects.has("default")) +	{ +		LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap()); + +		defaultEffect["enable_night_vision"] = LLSD::Boolean(false); +		defaultEffect["enable_bloom"] = LLSD::Boolean(false); +		defaultEffect["enable_color_filter"] = LLSD::Boolean(false); + +		/// NVG Defaults +		defaultEffect["brightness_multiplier"] = 3.0; +		defaultEffect["noise_size"] = 25.0; +		defaultEffect["noise_strength"] = 0.4; + +		// TODO BTest potentially add this to tweaks? +		noiseTextureScale = 1.0f; +		 +		/// Bloom Defaults +		defaultEffect["extract_low"] = 0.95; +		defaultEffect["extract_high"] = 1.0; +		defaultEffect["bloom_width"] = 2.25; +		defaultEffect["bloom_strength"] = 1.5; + +		/// Color Filter Defaults +		defaultEffect["brightness"] = 1.0; +		defaultEffect["contrast"] = 1.0; +		defaultEffect["saturation"] = 1.0; + +		LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray()); +		contrastBase.append(1.0); +		contrastBase.append(1.0); +		contrastBase.append(1.0); +		contrastBase.append(0.5); +	} + +	setSelectedEffect("default"); +	*/ +} + +LLPostProcess::~LLPostProcess(void) +{ +	invalidate() ; +} + +// static +void LLPostProcess::initClass(void) +{ +	//this will cause system to crash at second time login +	//if first time login fails due to network connection --- bao +	//***llassert_always(gPostProcess == NULL); +	//replaced by the following line: +	if(gPostProcess) +		return ; +	 +	 +	gPostProcess = new LLPostProcess(); +} + +// static +void LLPostProcess::cleanupClass() +{ +	delete gPostProcess; +	gPostProcess = NULL; +} + +void LLPostProcess::setSelectedEffect(std::string const & effectName) +{ +	mSelectedEffectName = effectName; +	static_cast<LLSD &>(tweaks) = mAllEffects[effectName]; +} + +void LLPostProcess::saveEffect(std::string const & effectName) +{ +	/*  Do nothing.  Needs to be updated to use our current shader system, and to work with the move into llrender. +	mAllEffects[effectName] = tweaks; + +	std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); +	//llinfos << "Saving PostProcess Effects settings to " << pathName << llendl; + +	llofstream effectsXML(pathName); + +	LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); + +	formatter->format(mAllEffects, effectsXML); +	*/ +} +void LLPostProcess::invalidate() +{ +	mSceneRenderTexture = NULL ; +	mNoiseTexture = NULL ; +	mTempBloomTexture = NULL ; +	initialized = FALSE ; +} + +void LLPostProcess::apply(unsigned int width, unsigned int height) +{ +	if (!initialized || width != screenW || height != screenH){ +		initialize(width, height); +	} +	if (shadersEnabled()){ +		doEffects(); +	} +} + +void LLPostProcess::initialize(unsigned int width, unsigned int height) +{ +	screenW = width; +	screenH = height; +	createTexture(mSceneRenderTexture, screenW, screenH); +	initialized = true; + +	checkError(); +	createNightVisionShader(); +	createBloomShader(); +	createColorFilterShader(); +	checkError(); +} + +inline bool LLPostProcess::shadersEnabled(void) +{ +	return (tweaks.useColorFilter().asBoolean() || +			tweaks.useNightVisionShader().asBoolean() || +			tweaks.useBloomShader().asBoolean() ); + +} + +void LLPostProcess::applyShaders(void) +{ +	if (tweaks.useColorFilter()){ +		applyColorFilterShader(); +		checkError(); +	}	 +	if (tweaks.useNightVisionShader()){ +		/// If any of the above shaders have been called update the frame buffer; +		if (tweaks.useColorFilter()) +		{ +			U32 tex = mSceneRenderTexture->getTexName() ; +			copyFrameBuffer(tex, screenW, screenH); +		} +		applyNightVisionShader(); +		checkError(); +	} +	if (tweaks.useBloomShader()){ +		/// If any of the above shaders have been called update the frame buffer; +		if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()) +		{ +			U32 tex = mSceneRenderTexture->getTexName() ; +			copyFrameBuffer(tex, screenW, screenH); +		} +		applyBloomShader(); +		checkError(); +	} +} + +void LLPostProcess::applyColorFilterShader(void) +{	 +	/*  Do nothing.  Needs to be updated to use our current shader system, and to work with the move into llrender. +	gPostColorFilterProgram.bind(); + +	gGL.getTexUnit(0)->activate(); +	gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE); + +	gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture); + +	getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject); +	glUniform1iARB(colorFilterUniforms["RenderTexture"], 0); +	glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness()); +	glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast()); +	float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f; +	baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI); +	float baseR = tweaks.getContrastBaseR() * baseI; +	float baseG = tweaks.getContrastBaseG() * baseI; +	float baseB = tweaks.getContrastBaseB() * baseI; +	glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB); +	glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation()); +	glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B); +	 +	LLGLEnable blend(GL_BLEND); +	gGL.setSceneBlendType(LLRender::BT_REPLACE); +	LLGLDepthTest depth(GL_FALSE); +		 +	/// Draw a screen space quad +	drawOrthoQuad(screenW, screenH, QUAD_NORMAL); +	gPostColorFilterProgram.unbind(); +	*/ +} + +void LLPostProcess::createColorFilterShader(void) +{ +	/// Define uniform names +	colorFilterUniforms[sRenderTexture] = 0; +	colorFilterUniforms[sBrightness] = 0; +	colorFilterUniforms[sContrast] = 0; +	colorFilterUniforms[sContrastBase] = 0; +	colorFilterUniforms[sSaturation] = 0; +	colorFilterUniforms[sLumWeights] = 0; +} + +void LLPostProcess::applyNightVisionShader(void) +{	 +	/*  Do nothing.  Needs to be updated to use our current shader system, and to work with the move into llrender. +	gPostNightVisionProgram.bind(); + +	gGL.getTexUnit(0)->activate(); +	gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE); + +	getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject); +	gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture); +	glUniform1iARB(nightVisionUniforms["RenderTexture"], 0); + +	gGL.getTexUnit(1)->activate(); +	gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);	 + +	gGL.getTexUnit(1)->bindManual(LLTexUnit::TT_TEXTURE, noiseTexture); +	glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1); + +	 +	glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult()); +	glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength()); +	noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f); +	noiseTextureScale *= (screenH / NOISE_SIZE); + + +	glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B); +	 +	LLGLEnable blend(GL_BLEND); +	gGL.setSceneBlendType(LLRender::BT_REPLACE); +	LLGLDepthTest depth(GL_FALSE); +		 +	/// Draw a screen space quad +	drawOrthoQuad(screenW, screenH, QUAD_NOISE); +	gPostNightVisionProgram.unbind(); +	gGL.getTexUnit(0)->activate(); +	*/ +} + +void LLPostProcess::createNightVisionShader(void) +{ +	/// Define uniform names +	nightVisionUniforms[sRenderTexture] = 0; +	nightVisionUniforms[sNoiseTexture] = 0; +	nightVisionUniforms[sBrightMult] = 0;	 +	nightVisionUniforms[sNoiseStrength] = 0; +	nightVisionUniforms[sLumWeights] = 0;	 + +	createNoiseTexture(mNoiseTexture); +} + +void LLPostProcess::applyBloomShader(void) +{ + +} + +void LLPostProcess::createBloomShader(void) +{ +	createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5)); + +	/// Create Bloom Extract Shader +	bloomExtractUniforms[sRenderTexture] = 0; +	bloomExtractUniforms[sExtractLow] = 0; +	bloomExtractUniforms[sExtractHigh] = 0;	 +	bloomExtractUniforms[sLumWeights] = 0;	 +	 +	/// Create Bloom Blur Shader +	bloomBlurUniforms[sRenderTexture] = 0; +	bloomBlurUniforms[sBloomStrength] = 0;	 +	bloomBlurUniforms[sTexelSize] = 0; +	bloomBlurUniforms[sBlurDirection] = 0; +	bloomBlurUniforms[sBlurWidth] = 0; +} + +void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog) +{ +	/// Find uniform locations and insert into map	 +	glslUniforms::iterator i; +	for (i  = uniforms.begin(); i != uniforms.end(); ++i){ +		i->second = glGetUniformLocationARB(prog, i->first.String().c_str()); +	} +} + +void LLPostProcess::doEffects(void) +{ +	/// Save GL State +	glPushAttrib(GL_ALL_ATTRIB_BITS); +	glPushClientAttrib(GL_ALL_ATTRIB_BITS); + +	/// Copy the screen buffer to the render texture +	{ +		U32 tex = mSceneRenderTexture->getTexName() ; +		copyFrameBuffer(tex, screenW, screenH); +	} + +	/// Clear the frame buffer. +	glClearColor(0.0f, 0.0f, 0.0f, 1.0f); +	glClear(GL_COLOR_BUFFER_BIT); +	 +	/// Change to an orthogonal view +	viewOrthogonal(screenW, screenH); +	 +	checkError(); +	applyShaders(); +	 +	LLGLSLShader::bindNoShader(); +	checkError(); + +	/// Change to a perspective view +	viewPerspective();	 + +	/// Reset GL State +	glPopClientAttrib(); +	glPopAttrib(); +	checkError(); +} + +void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height) +{ +	gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture); +	glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0); +} + +void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type) +{ +#if 0 +	float noiseX = 0.f; +	float noiseY = 0.f; +	float screenRatio = 1.0f; + +	if (type == QUAD_NOISE){ +		noiseX = ((float) rand() / (float) RAND_MAX); +		noiseY = ((float) rand() / (float) RAND_MAX); +		screenRatio = (float) width / (float) height; +	} +	 + +	glBegin(GL_QUADS); +		if (type != QUAD_BLOOM_EXTRACT){ +			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height); +		} else { +			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height * 2.0f); +		} +		if (type == QUAD_NOISE){ +			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, +									noiseX, +									noiseTextureScale + noiseY); +		} else if (type == QUAD_BLOOM_COMBINE){ +			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, (GLfloat) height * 0.5f); +		} +		glVertex2f(0.f, (GLfloat) screenH - height); + +		if (type != QUAD_BLOOM_EXTRACT){ +			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f); +		} else { +			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f); +		} +		if (type == QUAD_NOISE){ +			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, +									noiseX, +									noiseY); +		} else if (type == QUAD_BLOOM_COMBINE){ +			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, 0.f); +		} +		glVertex2f(0.f, (GLfloat) height + (screenH - height)); + +		 +		if (type != QUAD_BLOOM_EXTRACT){ +			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, 0.f); +		} else { +			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, 0.f); +		} +		if (type == QUAD_NOISE){ +			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, +									screenRatio * noiseTextureScale + noiseX, +									noiseY); +		} else if (type == QUAD_BLOOM_COMBINE){ +			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, 0.f); +		} +		glVertex2f((GLfloat) width, (GLfloat) height + (screenH - height)); + +		 +		if (type != QUAD_BLOOM_EXTRACT){ +			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, (GLfloat) height); +		} else { +			glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f); +		} +		if (type == QUAD_NOISE){ +			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, +									screenRatio * noiseTextureScale + noiseX, +									noiseTextureScale + noiseY); +		} else if (type == QUAD_BLOOM_COMBINE){ +			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f); +		} +		glVertex2f((GLfloat) width, (GLfloat) screenH - height); +	glEnd(); +#endif +} + +void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height) +{ +	gGL.matrixMode(LLRender::MM_PROJECTION); +	gGL.pushMatrix(); +	gGL.loadIdentity(); +	gGL.ortho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f ); +	gGL.matrixMode(LLRender::MM_MODELVIEW); +	gGL.pushMatrix(); +	gGL.loadIdentity(); +} + +void LLPostProcess::viewPerspective(void) +{ +	gGL.matrixMode(LLRender::MM_PROJECTION); +	gGL.popMatrix(); +	gGL.matrixMode(LLRender::MM_MODELVIEW); +	gGL.popMatrix(); +} + +void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height) +{ +	viewPerspective(); +	viewOrthogonal(width, height); +} + +void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height) +{ +	std::vector<GLubyte> data(width * height * 4, 0) ; + +	texture = new LLImageGL(FALSE) ;	 +	if(texture->createGLTexture()) +	{ +		gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName()); +		glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, +			GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); +		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); +		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); +	} +} + +void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture) +{	 +	std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE); +	for (unsigned int i = 0; i < NOISE_SIZE; i++){ +		for (unsigned int k = 0; k < NOISE_SIZE; k++){ +			buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f); +		} +	} + +	texture = new LLImageGL(FALSE) ; +	if(texture->createGLTexture()) +	{ +		gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName()); +		LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); +		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); +		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); +	} +} + +bool LLPostProcess::checkError(void) +{ +	GLenum glErr; +    bool    retCode = false; + +    glErr = glGetError(); +    while (glErr != GL_NO_ERROR) +    { +		// shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl; +		char const * err_str_raw = (const char *) gluErrorString(glErr); + +		if(err_str_raw == NULL) +		{ +			std::ostringstream err_builder; +			err_builder << "unknown error number " << glErr; +			mShaderErrorString = err_builder.str(); +		} +		else +		{ +			mShaderErrorString = err_str_raw; +		} + +        retCode = true; +        glErr = glGetError(); +    } +    return retCode; +} + +void LLPostProcess::checkShaderError(GLhandleARB shader) +{ +    GLint infologLength = 0; +    GLint charsWritten  = 0; +    GLchar *infoLog; + +    checkError();  // Check for OpenGL errors + +    glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength); + +    checkError();  // Check for OpenGL errors + +    if (infologLength > 0) +    { +        infoLog = (GLchar *)malloc(infologLength); +        if (infoLog == NULL) +        { +            /// Could not allocate infolog buffer +            return; +        } +        glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog); +		// shaderErrorLog << (char *) infoLog << std::endl; +		mShaderErrorString = (char *) infoLog; +        free(infoLog); +    } +    checkError();  // Check for OpenGL errors +} | 
