00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "pipeline.h"
00035 #include "llpostprocess.h"
00036 #include "llglslshader.h"
00037 #include "llsdserialize.h"
00038 #include "llglimmediate.h"
00039
00040
00041 LLPostProcess * gPostProcess = NULL;
00042
00043
00044 static const unsigned int NOISE_SIZE = 512;
00045
00048 static const float LUMINANCE_R = 0.299f;
00049 static const float LUMINANCE_G = 0.587f;
00050 static const float LUMINANCE_B = 0.114f;
00051
00052 static const char * const XML_FILENAME = "postprocesseffects.xml";
00053
00054 LLPostProcess::LLPostProcess(void) :
00055 sceneRenderTexture(0), noiseTexture(0),
00056 tempBloomTexture(0),
00057 initialized(false),
00058 mAllEffects(LLSD::emptyMap()),
00059 screenW(1), screenH(1)
00060 {
00061 LLString pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
00062 LL_DEBUGS2("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL;
00063
00064 llifstream effectsXML(pathName.c_str());
00065
00066 if (effectsXML)
00067 {
00068 LLPointer<LLSDParser> parser = new LLSDXMLParser();
00069
00070 parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED);
00071 }
00072
00073 if (!mAllEffects.has("default"))
00074 {
00075 LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap());
00076
00077 defaultEffect["enable_night_vision"] = LLSD::Boolean(false);
00078 defaultEffect["enable_bloom"] = LLSD::Boolean(false);
00079 defaultEffect["enable_color_filter"] = LLSD::Boolean(false);
00080
00082 defaultEffect["brightness_multiplier"] = 3.0;
00083 defaultEffect["noise_size"] = 25.0;
00084 defaultEffect["noise_strength"] = 0.4;
00085
00086
00087 noiseTextureScale = 1.0f;
00088
00090 defaultEffect["extract_low"] = 0.95;
00091 defaultEffect["extract_high"] = 1.0;
00092 defaultEffect["bloom_width"] = 2.25;
00093 defaultEffect["bloom_strength"] = 1.5;
00094
00096 defaultEffect["brightness"] = 1.0;
00097 defaultEffect["contrast"] = 1.0;
00098 defaultEffect["saturation"] = 1.0;
00099
00100 LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray());
00101 contrastBase.append(1.0);
00102 contrastBase.append(1.0);
00103 contrastBase.append(1.0);
00104 contrastBase.append(0.5);
00105 }
00106
00107 setSelectedEffect("default");
00108 }
00109
00110 LLPostProcess::~LLPostProcess(void)
00111 {
00112 glDeleteTextures(1, &sceneRenderTexture);
00113 glDeleteTextures(1, &noiseTexture);
00114 glDeleteTextures(1, &tempBloomTexture);
00115 }
00116
00117
00118 void LLPostProcess::initClass(void)
00119 {
00120
00121
00122
00123
00124 if(gPostProcess)
00125 return ;
00126
00127
00128 gPostProcess = new LLPostProcess();
00129 }
00130
00131
00132 void LLPostProcess::cleanupClass()
00133 {
00134 delete gPostProcess;
00135 gPostProcess = NULL;
00136 }
00137
00138 void LLPostProcess::setSelectedEffect(std::string const & effectName)
00139 {
00140 mSelectedEffectName = effectName;
00141 static_cast<LLSD &>(tweaks) = mAllEffects[effectName];
00142 }
00143
00144 void LLPostProcess::saveEffect(std::string const & effectName)
00145 {
00146 mAllEffects[effectName] = tweaks;
00147
00148 LLString pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
00149
00150
00151 llofstream effectsXML(pathName.c_str());
00152
00153 LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
00154
00155 formatter->format(mAllEffects, effectsXML);
00156 }
00157
00158 void LLPostProcess::apply(unsigned int width, unsigned int height)
00159 {
00160 if (!initialized || width != screenW || height != screenH){
00161 initialize(width, height);
00162 }
00163 if (shadersEnabled()){
00164 doEffects();
00165 }
00166 }
00167
00168 void LLPostProcess::initialize(unsigned int width, unsigned int height)
00169 {
00170 screenW = width;
00171 screenH = height;
00172 createTexture(sceneRenderTexture, screenW, screenH);
00173 initialized = true;
00174
00175 checkError();
00176 createNightVisionShader();
00177 createBloomShader();
00178 createColorFilterShader();
00179 checkError();
00180 }
00181
00182 inline bool LLPostProcess::shadersEnabled(void)
00183 {
00184 return (tweaks.useColorFilter().asBoolean() ||
00185 tweaks.useNightVisionShader().asBoolean() ||
00186 tweaks.useBloomShader().asBoolean() );
00187
00188 }
00189
00190 void LLPostProcess::applyShaders(void)
00191 {
00192 if (tweaks.useColorFilter()){
00193 applyColorFilterShader();
00194 checkError();
00195 }
00196 if (tweaks.useNightVisionShader()){
00198 if (tweaks.useColorFilter()){
00199 copyFrameBuffer(sceneRenderTexture, screenW, screenH);
00200 }
00201 applyNightVisionShader();
00202 checkError();
00203 }
00204 if (tweaks.useBloomShader()){
00206 if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()){
00207 copyFrameBuffer(sceneRenderTexture, screenW, screenH);
00208 }
00209 applyBloomShader();
00210 checkError();
00211 }
00212 }
00213
00214 void LLPostProcess::applyColorFilterShader(void)
00215 {
00216 gPostColorFilterProgram.bind();
00217
00218 glActiveTextureARB(GL_TEXTURE0_ARB);
00219 glEnable(GL_TEXTURE_RECTANGLE_ARB);
00220
00221 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sceneRenderTexture);
00222
00223 getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject);
00224 glUniform1iARB(colorFilterUniforms["RenderTexture"], 0);
00225 glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness());
00226 glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast());
00227 float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f;
00228 baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI);
00229 float baseR = tweaks.getContrastBaseR() * baseI;
00230 float baseG = tweaks.getContrastBaseG() * baseI;
00231 float baseB = tweaks.getContrastBaseB() * baseI;
00232 glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB);
00233 glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation());
00234 glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
00235
00236 LLGLEnable blend(GL_BLEND);
00237 gGL.blendFunc(GL_ONE,GL_ZERO);
00238 LLGLDepthTest depth(GL_FALSE);
00239
00241 drawOrthoQuad(screenW, screenH, QUAD_NORMAL);
00242 gPostColorFilterProgram.unbind();
00243 }
00244
00245 void LLPostProcess::createColorFilterShader(void)
00246 {
00248 colorFilterUniforms["RenderTexture"] = 0;
00249 colorFilterUniforms["brightness"] = 0;
00250 colorFilterUniforms["contrast"] = 0;
00251 colorFilterUniforms["contrastBase"] = 0;
00252 colorFilterUniforms["saturation"] = 0;
00253 colorFilterUniforms["lumWeights"] = 0;
00254 }
00255
00256 void LLPostProcess::applyNightVisionShader(void)
00257 {
00258 gPostNightVisionProgram.bind();
00259
00260 glActiveTextureARB(GL_TEXTURE0_ARB);
00261 glEnable(GL_TEXTURE_RECTANGLE_ARB);
00262
00263 getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject);
00264 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sceneRenderTexture);
00265 glUniform1iARB(nightVisionUniforms["RenderTexture"], 0);
00266
00267 glActiveTextureARB(GL_TEXTURE1_ARB);
00268 glEnable(GL_TEXTURE_2D);
00269
00270 glBindTexture(GL_TEXTURE_2D, noiseTexture);
00271 glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1);
00272
00273
00274 glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult());
00275 glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength());
00276 noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f);
00277 noiseTextureScale *= (screenH / NOISE_SIZE);
00278
00279
00280 glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
00281
00282 LLGLEnable blend(GL_BLEND);
00283 gGL.blendFunc(GL_ONE,GL_ZERO);
00284 LLGLDepthTest depth(GL_FALSE);
00285
00287 drawOrthoQuad(screenW, screenH, QUAD_NOISE);
00288 gPostNightVisionProgram.unbind();
00289 glActiveTextureARB(GL_TEXTURE0_ARB);
00290 }
00291
00292 void LLPostProcess::createNightVisionShader(void)
00293 {
00295 nightVisionUniforms["RenderTexture"] = 0;
00296 nightVisionUniforms["NoiseTexture"] = 0;
00297 nightVisionUniforms["brightMult"] = 0;
00298 nightVisionUniforms["noiseStrength"] = 0;
00299 nightVisionUniforms["lumWeights"] = 0;
00300
00301 createNoiseTexture(noiseTexture);
00302 }
00303
00304 void LLPostProcess::applyBloomShader(void)
00305 {
00306
00307 }
00308
00309 void LLPostProcess::createBloomShader(void)
00310 {
00311 createTexture(tempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
00312
00314 bloomExtractUniforms["RenderTexture"] = 0;
00315 bloomExtractUniforms["extractLow"] = 0;
00316 bloomExtractUniforms["extractHigh"] = 0;
00317 bloomExtractUniforms["lumWeights"] = 0;
00318
00320 bloomBlurUniforms["RenderTexture"] = 0;
00321 bloomBlurUniforms["bloomStrength"] = 0;
00322 bloomBlurUniforms["texelSize"] = 0;
00323 bloomBlurUniforms["blurDirection"] = 0;
00324 bloomBlurUniforms["blurWidth"] = 0;
00325 }
00326
00327 void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)
00328 {
00330 std::map<const char *, GLuint>::iterator i;
00331 for (i = uniforms.begin(); i != uniforms.end(); ++i){
00332 i->second = glGetUniformLocationARB(prog, i->first);
00333 }
00334 }
00335
00336 void LLPostProcess::doEffects(void)
00337 {
00339 glPushAttrib(GL_ALL_ATTRIB_BITS);
00340 glPushClientAttrib(GL_ALL_ATTRIB_BITS);
00341
00343 copyFrameBuffer(sceneRenderTexture, screenW, screenH);
00344
00346 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
00347 glClear(GL_COLOR_BUFFER_BIT);
00348
00350 viewOrthogonal(screenW, screenH);
00351
00352 checkError();
00353 applyShaders();
00354
00355 glUseProgramObjectARB(0);
00356 checkError();
00357
00359 viewPerspective();
00360
00362 glPopClientAttrib();
00363 glPopAttrib();
00364 checkError();
00365 }
00366
00367 void LLPostProcess::copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height)
00368 {
00369 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
00370 glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0);
00371 }
00372
00373 void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type)
00374 {
00375 #if 0
00376 float noiseX = 0.f;
00377 float noiseY = 0.f;
00378 float screenRatio = 1.0f;
00379
00380 if (type == QUAD_NOISE){
00381 noiseX = ((float) rand() / (float) RAND_MAX);
00382 noiseY = ((float) rand() / (float) RAND_MAX);
00383 screenRatio = (float) width / (float) height;
00384 }
00385
00386
00387 glBegin(GL_QUADS);
00388 if (type != QUAD_BLOOM_EXTRACT){
00389 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height);
00390 } else {
00391 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height * 2.0f);
00392 }
00393 if (type == QUAD_NOISE){
00394 glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
00395 noiseX,
00396 noiseTextureScale + noiseY);
00397 } else if (type == QUAD_BLOOM_COMBINE){
00398 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, (GLfloat) height * 0.5f);
00399 }
00400 glVertex2f(0.f, (GLfloat) screenH - height);
00401
00402 if (type != QUAD_BLOOM_EXTRACT){
00403 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
00404 } else {
00405 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
00406 }
00407 if (type == QUAD_NOISE){
00408 glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
00409 noiseX,
00410 noiseY);
00411 } else if (type == QUAD_BLOOM_COMBINE){
00412 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, 0.f);
00413 }
00414 glVertex2f(0.f, (GLfloat) height + (screenH - height));
00415
00416
00417 if (type != QUAD_BLOOM_EXTRACT){
00418 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, 0.f);
00419 } else {
00420 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, 0.f);
00421 }
00422 if (type == QUAD_NOISE){
00423 glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
00424 screenRatio * noiseTextureScale + noiseX,
00425 noiseY);
00426 } else if (type == QUAD_BLOOM_COMBINE){
00427 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, 0.f);
00428 }
00429 glVertex2f((GLfloat) width, (GLfloat) height + (screenH - height));
00430
00431
00432 if (type != QUAD_BLOOM_EXTRACT){
00433 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, (GLfloat) height);
00434 } else {
00435 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f);
00436 }
00437 if (type == QUAD_NOISE){
00438 glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
00439 screenRatio * noiseTextureScale + noiseX,
00440 noiseTextureScale + noiseY);
00441 } else if (type == QUAD_BLOOM_COMBINE){
00442 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f);
00443 }
00444 glVertex2f((GLfloat) width, (GLfloat) screenH - height);
00445 glEnd();
00446 #endif
00447 }
00448
00449 void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height)
00450 {
00451 glMatrixMode(GL_PROJECTION);
00452 glPushMatrix();
00453 glLoadIdentity();
00454 glOrtho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f );
00455 glMatrixMode(GL_MODELVIEW);
00456 glPushMatrix();
00457 glLoadIdentity();
00458 }
00459
00460 void LLPostProcess::viewPerspective(void)
00461 {
00462 glMatrixMode( GL_PROJECTION );
00463 glPopMatrix();
00464 glMatrixMode( GL_MODELVIEW );
00465 glPopMatrix();
00466 }
00467
00468 void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height)
00469 {
00470 viewPerspective();
00471 viewOrthogonal(width, height);
00472 }
00473
00474 void LLPostProcess::createTexture(GLuint & texture, unsigned int width, unsigned int height)
00475 {
00476 if (texture != 0){
00477 glDeleteTextures(1, &texture);
00478 }
00479
00480 std::vector<GLubyte> data(width * height * 4, 0);
00481
00482 glGenTextures(1, &texture);
00483 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
00484 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0,
00485 GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
00486 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00487 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00488 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00489 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00490 }
00491
00492 void LLPostProcess::createNoiseTexture(GLuint & texture)
00493 {
00494 if (texture != 0){
00495 glDeleteTextures(1, &texture);
00496 }
00497 glGenTextures(1, &texture);
00498
00499 std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE);
00500 for (unsigned int i = 0; i < NOISE_SIZE; i++){
00501 for (unsigned int k = 0; k < NOISE_SIZE; k++){
00502 buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f);
00503 }
00504 }
00505 glBindTexture(GL_TEXTURE_2D, texture);
00506 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]);
00507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00508 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00509 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00510 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00511 }
00512
00513 bool LLPostProcess::checkError(void)
00514 {
00515 GLenum glErr;
00516 bool retCode = false;
00517
00518 glErr = glGetError();
00519 while (glErr != GL_NO_ERROR)
00520 {
00521
00522 char const * err_str_raw = (const char *) gluErrorString(glErr);
00523
00524 if(err_str_raw == NULL)
00525 {
00526 std::ostringstream err_builder;
00527 err_builder << "unknown error number " << glErr;
00528 mShaderErrorString = err_builder.str();
00529 }
00530 else
00531 {
00532 mShaderErrorString = err_str_raw;
00533 }
00534
00535 retCode = true;
00536 glErr = glGetError();
00537 }
00538 return retCode;
00539 }
00540
00541 void LLPostProcess::checkShaderError(GLhandleARB shader)
00542 {
00543 GLint infologLength = 0;
00544 GLint charsWritten = 0;
00545 GLchar *infoLog;
00546
00547 checkError();
00548
00549 glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
00550
00551 checkError();
00552
00553 if (infologLength > 0)
00554 {
00555 infoLog = (GLchar *)malloc(infologLength);
00556 if (infoLog == NULL)
00557 {
00559 return;
00560 }
00561 glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog);
00562
00563 mShaderErrorString = (char *) infoLog;
00564 free(infoLog);
00565 }
00566 checkError();
00567 }
00568
00569 void LLPostProcess::textureBlendReplace(void)
00570 {
00571 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
00572 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE );
00573 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE );
00574 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
00575 }
00576
00577 void LLPostProcess::textureBlendAdd(void)
00578 {
00579 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
00580 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD );
00581 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
00582 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
00583 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
00584 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
00585 }
00586
00587 void LLPostProcess::textureBlendAddSigned(void)
00588 {
00589 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
00590 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD_SIGNED );
00591 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
00592 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
00593 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
00594 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
00595 }
00596
00597 void LLPostProcess::textureBlendSubtract(void)
00598 {
00599 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
00600 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT );
00601 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
00602 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
00603 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
00604 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
00605 }
00606
00607 void LLPostProcess::textureBlendAlpha(void)
00608 {
00609 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
00610 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE );
00611 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
00612 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
00613 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS );
00614 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
00615 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
00616 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA );
00617 }
00618
00619 void LLPostProcess::textureBlendMultiply(void)
00620 {
00621 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
00622 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE );
00623 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
00624 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
00625 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
00626 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
00627 }
00628
00629 void LLPostProcess::textureBlendMultiplyX2(void)
00630 {
00631 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
00632 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE );
00633 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
00634 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
00635 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
00636 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
00637 glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, 2 );
00638 }