aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llpostprocess.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llpostprocess.cpp')
-rw-r--r--linden/indra/newview/llpostprocess.cpp641
1 files changed, 641 insertions, 0 deletions
diff --git a/linden/indra/newview/llpostprocess.cpp b/linden/indra/newview/llpostprocess.cpp
new file mode 100644
index 0000000..11a211a
--- /dev/null
+++ b/linden/indra/newview/llpostprocess.cpp
@@ -0,0 +1,641 @@
1/**
2 * @file llpostprocess.cpp
3 * @brief LLPostProcess class implementation
4 *
5 * $LicenseInfo:firstyear=2007&license=viewergpl$
6 *
7 * Copyright (c) 2007-2008, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32#include "llviewerprecompiledheaders.h"
33
34#include "pipeline.h"
35#include "llpostprocess.h"
36#include "llglslshader.h"
37#include "llsdserialize.h"
38#include "llglimmediate.h"
39
40
41LLPostProcess * gPostProcess = NULL;
42
43
44static const unsigned int NOISE_SIZE = 512;
45
46/// CALCULATING LUMINANCE (Using NTSC lum weights)
47/// http://en.wikipedia.org/wiki/Luma_%28video%29
48static const float LUMINANCE_R = 0.299f;
49static const float LUMINANCE_G = 0.587f;
50static const float LUMINANCE_B = 0.114f;
51
52static const char * const XML_FILENAME = "postprocesseffects.xml";
53
54LLPostProcess::LLPostProcess(void) :
55 sceneRenderTexture(0), noiseTexture(0),
56 tempBloomTexture(0),
57 initialized(false),
58 mAllEffects(LLSD::emptyMap()),
59 screenW(1), screenH(1)
60{
61 LLString pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
62 llinfos << "Loading PostProcess Effects settings from " << pathName << llendl;
63
64 llifstream effectsXML(pathName.c_str());
65
66 if (effectsXML)
67 {
68 LLPointer<LLSDParser> parser = new LLSDXMLParser();
69
70 parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED);
71 }
72
73 if (!mAllEffects.has("default"))
74 {
75 LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap());
76
77 defaultEffect["enable_night_vision"] = LLSD::Boolean(false);
78 defaultEffect["enable_bloom"] = LLSD::Boolean(false);
79 defaultEffect["enable_color_filter"] = LLSD::Boolean(false);
80
81 /// NVG Defaults
82 defaultEffect["brightness_multiplier"] = 3.0;
83 defaultEffect["noise_size"] = 25.0;
84 defaultEffect["noise_strength"] = 0.4;
85
86 // TODO BTest potentially add this to tweaks?
87 noiseTextureScale = 1.0f;
88
89 /// Bloom Defaults
90 defaultEffect["extract_low"] = 0.95;
91 defaultEffect["extract_high"] = 1.0;
92 defaultEffect["bloom_width"] = 2.25;
93 defaultEffect["bloom_strength"] = 1.5;
94
95 /// Color Filter Defaults
96 defaultEffect["brightness"] = 1.0;
97 defaultEffect["contrast"] = 1.0;
98 defaultEffect["saturation"] = 1.0;
99
100 LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray());
101 contrastBase.append(1.0);
102 contrastBase.append(1.0);
103 contrastBase.append(1.0);
104 contrastBase.append(0.5);
105 }
106
107 setSelectedEffect("default");
108}
109
110LLPostProcess::~LLPostProcess(void)
111{
112 glDeleteTextures(1, &sceneRenderTexture);
113 glDeleteTextures(1, &noiseTexture);
114 glDeleteTextures(1, &tempBloomTexture);
115}
116
117// static
118void LLPostProcess::initClass(void)
119{
120 //this will cause system to crash at second time login
121 //if first time login fails due to network connection --- bao
122 //***llassert_always(gPostProcess == NULL);
123 //replaced by the following line:
124 if(gPostProcess)
125 return ;
126
127
128 gPostProcess = new LLPostProcess();
129}
130
131// static
132void LLPostProcess::cleanupClass()
133{
134 delete gPostProcess;
135 gPostProcess = NULL;
136}
137
138void LLPostProcess::setSelectedEffect(std::string const & effectName)
139{
140 mSelectedEffectName = effectName;
141 static_cast<LLSD &>(tweaks) = mAllEffects[effectName];
142}
143
144void LLPostProcess::saveEffect(std::string const & effectName)
145{
146 mAllEffects[effectName] = tweaks;
147
148 LLString pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
149 //llinfos << "Saving PostProcess Effects settings to " << pathName << llendl;
150
151 llofstream effectsXML(pathName.c_str());
152
153 LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
154
155 formatter->format(mAllEffects, effectsXML);
156}
157
158void LLPostProcess::apply(unsigned int width, unsigned int height)
159{
160 if (!initialized || width != screenW || height != screenH){
161 initialize(width, height);
162 }
163 if (shadersEnabled()){
164 doEffects();
165 }
166}
167
168void LLPostProcess::initialize(unsigned int width, unsigned int height)
169{
170 screenW = width;
171 screenH = height;
172 createTexture(sceneRenderTexture, screenW, screenH);
173 initialized = true;
174
175 checkError();
176 createNightVisionShader();
177 createBloomShader();
178 createColorFilterShader();
179 checkError();
180}
181
182inline bool LLPostProcess::shadersEnabled(void)
183{
184 return (tweaks.useColorFilter().asBoolean() ||
185 tweaks.useNightVisionShader().asBoolean() ||
186 tweaks.useBloomShader().asBoolean() );
187
188}
189
190void LLPostProcess::applyShaders(void)
191{
192 if (tweaks.useColorFilter()){
193 applyColorFilterShader();
194 checkError();
195 }
196 if (tweaks.useNightVisionShader()){
197 /// If any of the above shaders have been called update the frame buffer;
198 if (tweaks.useColorFilter()){
199 copyFrameBuffer(sceneRenderTexture, screenW, screenH);
200 }
201 applyNightVisionShader();
202 checkError();
203 }
204 if (tweaks.useBloomShader()){
205 /// If any of the above shaders have been called update the frame buffer;
206 if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()){
207 copyFrameBuffer(sceneRenderTexture, screenW, screenH);
208 }
209 applyBloomShader();
210 checkError();
211 }
212}
213
214void LLPostProcess::applyColorFilterShader(void)
215{
216 gPostColorFilterProgram.bind();
217
218 glClientActiveTextureARB(GL_TEXTURE0_ARB);
219 glActiveTextureARB(GL_TEXTURE0_ARB);
220 glEnable(GL_TEXTURE_RECTANGLE_ARB);
221
222 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sceneRenderTexture);
223
224 getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject);
225 glUniform1iARB(colorFilterUniforms["RenderTexture"], 0);
226 glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness());
227 glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast());
228 float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f;
229 baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI);
230 float baseR = tweaks.getContrastBaseR() * baseI;
231 float baseG = tweaks.getContrastBaseG() * baseI;
232 float baseB = tweaks.getContrastBaseB() * baseI;
233 glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB);
234 glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation());
235 glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
236
237 LLGLEnable blend(GL_BLEND);
238 gGL.blendFunc(GL_ONE,GL_ZERO);
239 LLGLDepthTest depth(GL_FALSE);
240
241 /// Draw a screen space quad
242 drawOrthoQuad(screenW, screenH, QUAD_NORMAL);
243 gPostColorFilterProgram.unbind();
244}
245
246void LLPostProcess::createColorFilterShader(void)
247{
248 /// Define uniform names
249 colorFilterUniforms["RenderTexture"] = 0;
250 colorFilterUniforms["brightness"] = 0;
251 colorFilterUniforms["contrast"] = 0;
252 colorFilterUniforms["contrastBase"] = 0;
253 colorFilterUniforms["saturation"] = 0;
254 colorFilterUniforms["lumWeights"] = 0;
255}
256
257void LLPostProcess::applyNightVisionShader(void)
258{
259 gPostNightVisionProgram.bind();
260
261 glClientActiveTextureARB(GL_TEXTURE0_ARB);
262 glActiveTextureARB(GL_TEXTURE0_ARB);
263 glEnable(GL_TEXTURE_RECTANGLE_ARB);
264
265 getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject);
266 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sceneRenderTexture);
267 glUniform1iARB(nightVisionUniforms["RenderTexture"], 0);
268
269 glClientActiveTextureARB(GL_TEXTURE1_ARB);
270 glActiveTextureARB(GL_TEXTURE1_ARB);
271 glEnable(GL_TEXTURE_2D);
272
273 glBindTexture(GL_TEXTURE_2D, noiseTexture);
274 glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1);
275
276
277 glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult());
278 glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength());
279 noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f);
280 noiseTextureScale *= (screenH / NOISE_SIZE);
281
282
283 glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
284
285 LLGLEnable blend(GL_BLEND);
286 gGL.blendFunc(GL_ONE,GL_ZERO);
287 LLGLDepthTest depth(GL_FALSE);
288
289 /// Draw a screen space quad
290 drawOrthoQuad(screenW, screenH, QUAD_NOISE);
291 gPostNightVisionProgram.unbind();
292 glActiveTextureARB(GL_TEXTURE0_ARB);
293}
294
295void LLPostProcess::createNightVisionShader(void)
296{
297 /// Define uniform names
298 nightVisionUniforms["RenderTexture"] = 0;
299 nightVisionUniforms["NoiseTexture"] = 0;
300 nightVisionUniforms["brightMult"] = 0;
301 nightVisionUniforms["noiseStrength"] = 0;
302 nightVisionUniforms["lumWeights"] = 0;
303
304 createNoiseTexture(noiseTexture);
305}
306
307void LLPostProcess::applyBloomShader(void)
308{
309
310}
311
312void LLPostProcess::createBloomShader(void)
313{
314 createTexture(tempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
315
316 /// Create Bloom Extract Shader
317 bloomExtractUniforms["RenderTexture"] = 0;
318 bloomExtractUniforms["extractLow"] = 0;
319 bloomExtractUniforms["extractHigh"] = 0;
320 bloomExtractUniforms["lumWeights"] = 0;
321
322 /// Create Bloom Blur Shader
323 bloomBlurUniforms["RenderTexture"] = 0;
324 bloomBlurUniforms["bloomStrength"] = 0;
325 bloomBlurUniforms["texelSize"] = 0;
326 bloomBlurUniforms["blurDirection"] = 0;
327 bloomBlurUniforms["blurWidth"] = 0;
328}
329
330void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)
331{
332 /// Find uniform locations and insert into map
333 std::map<const char *, GLuint>::iterator i;
334 for (i = uniforms.begin(); i != uniforms.end(); ++i){
335 i->second = glGetUniformLocationARB(prog, i->first);
336 }
337}
338
339void LLPostProcess::doEffects(void)
340{
341 /// Save GL State
342 glPushAttrib(GL_ALL_ATTRIB_BITS);
343 glPushClientAttrib(GL_ALL_ATTRIB_BITS);
344
345 /// Copy the screen buffer to the render texture
346 copyFrameBuffer(sceneRenderTexture, screenW, screenH);
347
348 /// Clear the frame buffer.
349 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
350 glClear(GL_COLOR_BUFFER_BIT);
351
352 /// Change to an orthogonal view
353 viewOrthogonal(screenW, screenH);
354
355 checkError();
356 applyShaders();
357
358 glUseProgramObjectARB(0);
359 checkError();
360
361 /// Change to a perspective view
362 viewPerspective();
363
364 /// Reset GL State
365 glPopClientAttrib();
366 glPopAttrib();
367 checkError();
368}
369
370void LLPostProcess::copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height)
371{
372 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
373 glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0);
374}
375
376void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type)
377{
378#if 0
379 float noiseX = 0.f;
380 float noiseY = 0.f;
381 float screenRatio = 1.0f;
382
383 if (type == QUAD_NOISE){
384 noiseX = ((float) rand() / (float) RAND_MAX);
385 noiseY = ((float) rand() / (float) RAND_MAX);
386 screenRatio = (float) width / (float) height;
387 }
388
389
390 glBegin(GL_QUADS);
391 if (type != QUAD_BLOOM_EXTRACT){
392 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height);
393 } else {
394 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height * 2.0f);
395 }
396 if (type == QUAD_NOISE){
397 glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
398 noiseX,
399 noiseTextureScale + noiseY);
400 } else if (type == QUAD_BLOOM_COMBINE){
401 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, (GLfloat) height * 0.5f);
402 }
403 glVertex2f(0.f, (GLfloat) screenH - height);
404
405 if (type != QUAD_BLOOM_EXTRACT){
406 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
407 } else {
408 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
409 }
410 if (type == QUAD_NOISE){
411 glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
412 noiseX,
413 noiseY);
414 } else if (type == QUAD_BLOOM_COMBINE){
415 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, 0.f);
416 }
417 glVertex2f(0.f, (GLfloat) height + (screenH - height));
418
419
420 if (type != QUAD_BLOOM_EXTRACT){
421 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, 0.f);
422 } else {
423 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, 0.f);
424 }
425 if (type == QUAD_NOISE){
426 glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
427 screenRatio * noiseTextureScale + noiseX,
428 noiseY);
429 } else if (type == QUAD_BLOOM_COMBINE){
430 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, 0.f);
431 }
432 glVertex2f((GLfloat) width, (GLfloat) height + (screenH - height));
433
434
435 if (type != QUAD_BLOOM_EXTRACT){
436 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, (GLfloat) height);
437 } else {
438 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f);
439 }
440 if (type == QUAD_NOISE){
441 glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
442 screenRatio * noiseTextureScale + noiseX,
443 noiseTextureScale + noiseY);
444 } else if (type == QUAD_BLOOM_COMBINE){
445 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f);
446 }
447 glVertex2f((GLfloat) width, (GLfloat) screenH - height);
448 glEnd();
449#endif
450}
451
452void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height)
453{
454 glMatrixMode(GL_PROJECTION);
455 glPushMatrix();
456 glLoadIdentity();
457 glOrtho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f );
458 glMatrixMode(GL_MODELVIEW);
459 glPushMatrix();
460 glLoadIdentity();
461}
462
463void LLPostProcess::viewPerspective(void)
464{
465 glMatrixMode( GL_PROJECTION );
466 glPopMatrix();
467 glMatrixMode( GL_MODELVIEW );
468 glPopMatrix();
469}
470
471void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height)
472{
473 viewPerspective();
474 viewOrthogonal(width, height);
475}
476
477void LLPostProcess::createTexture(GLuint & texture, unsigned int width, unsigned int height)
478{
479 if (texture != 0){
480 glDeleteTextures(1, &texture);
481 }
482
483 std::vector<GLubyte> data(width * height * 4, 0);
484
485 glGenTextures(1, &texture);
486 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
487 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0,
488 GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
489 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
490 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
491 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
492 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
493}
494
495void LLPostProcess::createNoiseTexture(GLuint & texture)
496{
497 if (texture != 0){
498 glDeleteTextures(1, &texture);
499 }
500 glGenTextures(1, &texture);
501
502 std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE);
503 for (unsigned int i = 0; i < NOISE_SIZE; i++){
504 for (unsigned int k = 0; k < NOISE_SIZE; k++){
505 buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f);
506 }
507 }
508 glBindTexture(GL_TEXTURE_2D, texture);
509 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]);
510 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
511 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
512 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
513 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
514}
515
516bool LLPostProcess::checkError(void)
517{
518 GLenum glErr;
519 bool retCode = false;
520
521 glErr = glGetError();
522 while (glErr != GL_NO_ERROR)
523 {
524 // shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl;
525 char const * err_str_raw = (const char *) gluErrorString(glErr);
526
527 if(err_str_raw == NULL)
528 {
529 std::ostringstream err_builder;
530 err_builder << "unknown error number " << glErr;
531 mShaderErrorString = err_builder.str();
532 }
533 else
534 {
535 mShaderErrorString = err_str_raw;
536 }
537
538 retCode = true;
539 glErr = glGetError();
540 }
541 return retCode;
542}
543
544void LLPostProcess::checkShaderError(GLhandleARB shader)
545{
546 GLint infologLength = 0;
547 GLint charsWritten = 0;
548 GLchar *infoLog;
549
550 checkError(); // Check for OpenGL errors
551
552 glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
553
554 checkError(); // Check for OpenGL errors
555
556 if (infologLength > 0)
557 {
558 infoLog = (GLchar *)malloc(infologLength);
559 if (infoLog == NULL)
560 {
561 /// Could not allocate infolog buffer
562 return;
563 }
564 glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog);
565 // shaderErrorLog << (char *) infoLog << std::endl;
566 mShaderErrorString = (char *) infoLog;
567 free(infoLog);
568 }
569 checkError(); // Check for OpenGL errors
570}
571
572void LLPostProcess::textureBlendReplace(void)
573{
574 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
575 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE );
576 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE );
577 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
578}
579
580void LLPostProcess::textureBlendAdd(void)
581{
582 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
583 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD );
584 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
585 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
586 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
587 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
588}
589
590void LLPostProcess::textureBlendAddSigned(void)
591{
592 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
593 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD_SIGNED );
594 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
595 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
596 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
597 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
598}
599
600void LLPostProcess::textureBlendSubtract(void)
601{
602 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
603 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT );
604 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
605 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
606 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
607 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
608}
609
610void LLPostProcess::textureBlendAlpha(void)
611{
612 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
613 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE );
614 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
615 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
616 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS );
617 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
618 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
619 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA );
620}
621
622void LLPostProcess::textureBlendMultiply(void)
623{
624 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
625 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE );
626 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
627 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
628 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
629 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
630}
631
632void LLPostProcess::textureBlendMultiplyX2(void)
633{
634 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
635 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE );
636 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
637 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
638 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
639 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
640 glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, 2 );
641}