X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Fmupen64plus-video-arachnoid%2Fsrc%2FCombiner%2FAdvancedTexEnvCombiner.cpp;fp=source%2Fmupen64plus-video-arachnoid%2Fsrc%2FCombiner%2FAdvancedTexEnvCombiner.cpp;h=5d32a5d4f4560a2a0b0986e1f53dc464eca8e3c9;hb=22726e4d55be26faa48b57b22689cbedde27ae44;hp=0000000000000000000000000000000000000000;hpb=fc5d46b49a19d41f9f2da5a9336daec452900475;p=mupen64plus-pandora.git diff --git a/source/mupen64plus-video-arachnoid/src/Combiner/AdvancedTexEnvCombiner.cpp b/source/mupen64plus-video-arachnoid/src/Combiner/AdvancedTexEnvCombiner.cpp new file mode 100755 index 0000000..5d32a5d --- /dev/null +++ b/source/mupen64plus-video-arachnoid/src/Combiner/AdvancedTexEnvCombiner.cpp @@ -0,0 +1,590 @@ +/****************************************************************************** + * Arachnoid Graphics Plugin for Mupen64Plus + * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/ + * + * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *****************************************************************************/ + +#include +using std::max; +#include "AdvancedTexEnvCombiner.h" +#include "CombinerStructs.h" +#include "MultiTexturingExt.h" //glActiveTextureARB +#include "ExtensionChecker.h" + +#ifndef GL_ATI_texture_env_combine3 +#define GL_ATI_texture_env_combine3 + #define GL_ATI_texture_env_combine3 + #define GL_MODULATE_ADD_ATI 0x8744 + #define GL_MODULATE_SIGNED_ADD_ATI 0x8745 + #define GL_MODULATE_SUBTRACT_ATI 0x8746 +#endif //GL_ATI_texture_env_combine3 + +#ifndef GL_ATIX_texture_env_route +#define GL_ATIX_texture_env_route 1 + #define GL_SECONDARY_COLOR_ATIX 0x8747 + #define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748 + #define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749 +#endif // GL_ATIX_texture_env_route + +static TexEnvCombinerArg TexEnvArgs[] = +{ + // CMB + { GL_PREVIOUS_ARB, GL_SRC_COLOR }, + // T0 + { GL_TEXTURE, GL_SRC_COLOR }, + // T1 + { GL_TEXTURE, GL_SRC_COLOR }, + // PRIM + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // SHADE + { GL_PRIMARY_COLOR_ARB, GL_SRC_COLOR }, + // ENV + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // CENTER + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // SCALE + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // CMBALPHA + { GL_PREVIOUS_ARB, GL_SRC_ALPHA }, + // T0ALPHA + { GL_TEXTURE, GL_SRC_ALPHA }, + // T1ALPHA + { GL_TEXTURE, GL_SRC_ALPHA }, + // PRIMALPHA + { GL_CONSTANT_ARB, GL_SRC_ALPHA }, + // SHADEALPHA + { GL_PRIMARY_COLOR_ARB, GL_SRC_ALPHA }, + // ENVALPHA + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // LODFRAC + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // PRIMLODFRAC + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // NOISE + { GL_TEXTURE, GL_SRC_COLOR }, + // K4 + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // K5 + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // ONE + { GL_CONSTANT_ARB, GL_SRC_COLOR }, + // ZERO + { GL_CONSTANT_ARB, GL_SRC_COLOR } +}; + +//----------------------------------------------------------------------------- +//! Constructor +//----------------------------------------------------------------------------- +AdvancedTexEnvCombiner::AdvancedTexEnvCombiner() +{ +} + +//----------------------------------------------------------------------------- +//! Destructor +//----------------------------------------------------------------------------- +AdvancedTexEnvCombiner::~AdvancedTexEnvCombiner() +{ +} + +//----------------------------------------------------------------------------- +//* Initialize +//! Checks if extensions are supported +//----------------------------------------------------------------------------- +void AdvancedTexEnvCombiner::initialize() +{ +#ifdef HAVE_GLES + ARB_texture_env_combine = true; + ARB_texture_env_crossbar = true; +#else + ARB_texture_env_combine = isExtensionSupported( "GL_ARB_texture_env_combine" ); + ARB_texture_env_crossbar = isExtensionSupported( "GL_ARB_texture_env_crossbar" ); +#endif + ATI_texture_env_combine3 = isExtensionSupported( "GL_ATI_texture_env_combine3" ); + ATIX_texture_env_route = isExtensionSupported( "GL_ATIX_texture_env_route" ); + NV_texture_env_combine4 = isExtensionSupported( "GL_NV_texture_env_combine4" );; + + if ( ARB_texture_env_crossbar || NV_texture_env_combine4 || ATIX_texture_env_route ) + { + TexEnvArgs[TEXEL0].source = GL_TEXTURE0_ARB; + TexEnvArgs[TEXEL0_ALPHA].source = GL_TEXTURE0_ARB; + TexEnvArgs[TEXEL1].source = GL_TEXTURE1_ARB; + TexEnvArgs[TEXEL1_ALPHA].source = GL_TEXTURE1_ARB; + } + + if ( ATI_texture_env_combine3 ) + { + TexEnvArgs[ONE].source = GL_ONE; + TexEnvArgs[ZERO].source = GL_ZERO; + } +} + +//----------------------------------------------------------------------------- +//* Begin Texture Update +//! Disables all textures +//----------------------------------------------------------------------------- +void AdvancedTexEnvCombiner::beginTextureUpdate() +{ + const int openGLMaxTextureUnits = 8; + + //Disable all texture channels + for (int i = 0; i usedUnits; i++) + { + glActiveTextureARB( GL_TEXTURE0_ARB + i ); + glEnable( GL_TEXTURE_2D ); + } +} + +//----------------------------------------------------------------------------- +//* Set Texture Enviroment Colors +//! Sets texture enviorment colors for all active textures +//! @param texEnv Texture environment with textures that will be assigned colors +//----------------------------------------------------------------------------- +void AdvancedTexEnvCombiner::setTextureEnviromentColors(TexEnvCombiner* texEnv) +{ + float color[4]; + + int openGLMaxTextureUnits = 8; + + for (int i = 0; i < openGLMaxTextureUnits; i++) + { + this->getCombinerColor( color, texEnv->color[i].constant, texEnv->alpha[i].constant ); + + glActiveTextureARB(GL_TEXTURE0_ARB + i); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color[0]); + } +} + +//----------------------------------------------------------------------------- +//* Set Texture Enviroment +//! Sets texture environment for all active textures +//! @param texEnv Texture environment with input data which will be +//! sent to OpenGL using function "glTexEnvi" using ARB extensions +//----------------------------------------------------------------------------- +void AdvancedTexEnvCombiner::setTextureEnviroment(TexEnvCombiner* texEnv) +{ + const int openGLMaxTextureUnits = 8; + + for (int i=0; iusedUnits ) || (i < 2 && texEnv->usesT1) ) + { + glEnable( GL_TEXTURE_2D ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, texEnv->color[i].combine ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, texEnv->color[i].arg0.source ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, texEnv->color[i].arg0.operand ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, texEnv->color[i].arg1.source ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, texEnv->color[i].arg1.operand ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, texEnv->color[i].arg2.source ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, texEnv->color[i].arg2.operand ); + glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, texEnv->alpha[i].combine ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, texEnv->alpha[i].arg0.source ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, texEnv->alpha[i].arg0.operand ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, texEnv->alpha[i].arg1.source ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, texEnv->alpha[i].arg1.operand ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, texEnv->alpha[i].arg2.source ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, texEnv->alpha[i].arg2.operand ); + } + else + { + glDisable(GL_TEXTURE_2D); + } + } +} + +//----------------------------------------------------------------------------- +//* Create New Texture Enviornment +//! Allocates a new texture enviroment +//! @param[in] colorCombiner How to combine and get a color +//! @param[in] alphaCombiner How to combine and get an alpha value +//! @return The texture enviroment that was created +//----------------------------------------------------------------------------- +TexEnvCombiner* AdvancedTexEnvCombiner::createNewTextureEnviroment(Combiner* colorCombiner, Combiner *alphaCombiner) +{ + TexEnvCombiner* envCombiner = new TexEnvCombiner(); + + int curUnit; + + const int openGLMaxTextureUnits = 8; + + //For each texture unit + for (int i = 0; i < openGLMaxTextureUnits; i++) + { + envCombiner->color[i].combine = GL_REPLACE; + envCombiner->alpha[i].combine = GL_REPLACE; + + SetColorCombinerValues( i, arg0, GL_PREVIOUS_ARB, GL_SRC_COLOR ); + SetColorCombinerValues( i, arg1, GL_PREVIOUS_ARB, GL_SRC_COLOR ); + SetColorCombinerValues( i, arg2, GL_PREVIOUS_ARB, GL_SRC_COLOR ); + envCombiner->color[i].constant = COMBINED; + envCombiner->color[i].outputTexture = GL_TEXTURE0_ARB + i; + + SetAlphaCombinerValues( i, arg0, GL_PREVIOUS_ARB, GL_SRC_ALPHA ); + SetAlphaCombinerValues( i, arg1, GL_PREVIOUS_ARB, GL_SRC_ALPHA ); + SetAlphaCombinerValues( i, arg2, GL_PREVIOUS_ARB, GL_SRC_ALPHA ); + envCombiner->alpha[i].constant = COMBINED; + envCombiner->alpha[i].outputTexture = GL_TEXTURE0_ARB + i; + } + + envCombiner->usesT0 = false; + envCombiner->usesT1 = false; + + envCombiner->vertex.color = COMBINED; + envCombiner->vertex.secondaryColor = COMBINED; + envCombiner->vertex.alpha = COMBINED; + + curUnit = 0; + + for (int i=0; inumStages; i++) + { + for (int j = 0; j < alphaCombiner->stage[i].numOps; j++) + { + float sb = 0.0f; + + if (alphaCombiner->stage[i].op[j].param1 == PRIMITIVE_ALPHA) + sb = m_primColor[3]; + else if (alphaCombiner->stage[i].op[j].param1 == ENV_ALPHA) + sb = m_envColor[3]; + else if (alphaCombiner->stage[i].op[j].param1 == ONE) + sb = 1.0f; + + if (((alphaCombiner->stage[i].numOps - j) >= 3) && + (alphaCombiner->stage[i].op[j].op == SUB) && + (alphaCombiner->stage[i].op[j+1].op == MUL) && + (alphaCombiner->stage[i].op[j+2].op == ADD) && + (sb > 0.5f) && + (ARB_texture_env_combine)) + { + envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA; + envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA; + + if (alphaCombiner->stage[i].op[j].param1 == ONE) + { + SetAlphaCombinerValues( curUnit, arg0, envCombiner->alpha[curUnit].arg0.source, GL_ONE_MINUS_SRC_ALPHA ); + } + else + { + envCombiner->alpha[curUnit].combine = GL_SUBTRACT_ARB; + SetAlphaCombinerValues( curUnit, arg1, envCombiner->alpha[curUnit].arg0.source, GL_SRC_ALPHA ); + SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); + + curUnit++; + } + + j++; + + envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA; + envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA; + + envCombiner->alpha[curUnit].combine = GL_MODULATE; + SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); + + curUnit++; + j++; + + envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA; + envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA; + + envCombiner->alpha[curUnit].combine = GL_SUBTRACT_ARB; + SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); + + curUnit++; + } + else + { + envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA; + envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA; + + switch (alphaCombiner->stage[i].op[j].op) + { + case LOAD: + if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) && + (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0)) + curUnit++; + + envCombiner->alpha[curUnit].combine = GL_REPLACE; + + SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); + break; + case SUB: + if (!ARB_texture_env_combine) + break; + + if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) && + (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0)) + curUnit++; + + if ((j > 0) && (alphaCombiner->stage[i].op[j-1].op == LOAD) && (alphaCombiner->stage[i].op[j-1].param1 == ONE)) + { + SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); + envCombiner->alpha[curUnit].arg0.operand = GL_ONE_MINUS_SRC_ALPHA; + } + else if ((ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->alpha[curUnit - 1].combine == GL_MODULATE)) + { + curUnit--; + SetAlphaCombinerValues( curUnit, arg2, envCombiner->alpha[curUnit].arg1.source, envCombiner->alpha[curUnit].arg1.operand ); + envCombiner->alpha[curUnit].combine = GL_MODULATE_SUBTRACT_ATI; + SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); + curUnit++; + } + else + { + envCombiner->alpha[curUnit].combine = GL_SUBTRACT_ARB; + SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); + curUnit++; + } + break; + case MUL: + if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && + (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0)) + curUnit++; + + envCombiner->alpha[curUnit].combine = GL_MODULATE; + + SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); + curUnit++; + break; + case ADD: + if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) && + (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0)) + curUnit++; + + if ((ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->alpha[curUnit - 1].combine == GL_MODULATE)) + { + curUnit--; + SetAlphaCombinerValues( curUnit, arg2, envCombiner->alpha[curUnit].arg1.source, envCombiner->alpha[curUnit].arg1.operand ); + envCombiner->alpha[curUnit].combine = GL_MODULATE_ADD_ATI; + SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); + } + else + { + envCombiner->alpha[curUnit].combine = GL_ADD; + SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 ); + } + curUnit++; + break; + case INTERPOLATE: + envCombiner->usesT0 |= (alphaCombiner->stage[i].op[j].param2 == TEXEL0_ALPHA) || (alphaCombiner->stage[i].op[j].param3 == TEXEL0_ALPHA); + envCombiner->usesT1 |= (alphaCombiner->stage[i].op[j].param2 == TEXEL1_ALPHA) || (alphaCombiner->stage[i].op[j].param3 == TEXEL1_ALPHA); + + envCombiner->alpha[curUnit].combine = GL_INTERPOLATE_ARB; + + SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 ); + SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param2 ); + SetAlphaCombinerArg( curUnit, arg2, alphaCombiner->stage[i].op[j].param3 ); + + curUnit++; + break; + } + } + } + } + + envCombiner->usedUnits = max( curUnit, 1 ); + + curUnit = 0; + for (int i = 0; i < colorCombiner->numStages; i++) + { + for (int j = 0; j < colorCombiner->stage[i].numOps; j++) + { + float sb = 0.0f; + + if (colorCombiner->stage[i].op[j].param1 == PRIMITIVE) + sb = (m_primColor[0] + m_primColor[2] + m_primColor[1]) / 3.0f; + else if (colorCombiner->stage[i].op[j].param1 == ENVIRONMENT) + sb = (m_envColor[0] + m_envColor[2] + m_envColor[1]) / 3.0f; + + // This helps with problems caused by not using signed values between texture units + if (((colorCombiner->stage[i].numOps - j) >= 3) && + (colorCombiner->stage[i].op[j].op == SUB) && + (colorCombiner->stage[i].op[j+1].op == MUL) && + (colorCombiner->stage[i].op[j+2].op == ADD) && + (sb > 0.5f) && + (ARB_texture_env_combine)) + { + envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA)); + envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)); + + envCombiner->color[curUnit].combine = GL_SUBTRACT_ARB; + SetColorCombinerValues( curUnit, arg1, envCombiner->color[curUnit].arg0.source, envCombiner->color[curUnit].arg0.operand ); + SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); + + curUnit++; + j++; + + envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA)); + envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)); + + envCombiner->color[curUnit].combine = GL_MODULATE; + SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); + + curUnit++; + j++; + + envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA)); + envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)); + + envCombiner->color[curUnit].combine = GL_SUBTRACT_ARB; + SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); + + curUnit++; + } + else + { + envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA)); + envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)); + + switch (colorCombiner->stage[i].op[j].op) + { + case LOAD: + if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && + ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0)) + curUnit++; + + envCombiner->color[curUnit].combine = GL_REPLACE; + + SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); + break; + case SUB: + if (!ARB_texture_env_combine) + break; + + if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) && + ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0)) + curUnit++; + + if ((j > 0) && (colorCombiner->stage[i].op[j-1].op == LOAD) && (colorCombiner->stage[i].op[j-1].param1 == ONE)) + { + SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); + envCombiner->color[curUnit].arg0.operand = GL_ONE_MINUS_SRC_COLOR; + } + else if (( ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->color[curUnit - 1].combine == GL_MODULATE)) + { + curUnit--; + SetColorCombinerValues( curUnit, arg2, envCombiner->color[curUnit].arg1.source, envCombiner->color[curUnit].arg1.operand ); + envCombiner->color[curUnit].combine = GL_MODULATE_SUBTRACT_ATI; + SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); + curUnit++; + } + else + { + envCombiner->color[curUnit].combine = GL_SUBTRACT_ARB; + SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); + curUnit++; + } + break; + case MUL: + if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && + ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0)) + curUnit++; + + envCombiner->color[curUnit].combine = GL_MODULATE; + + SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); + curUnit++; + break; + case ADD: + if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && + ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0)) + curUnit++; + + // ATI_texture_env_combine3 adds GL_MODULATE_ADD_ATI; saves texture units + if (( ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->color[curUnit - 1].combine == GL_MODULATE)) + { + curUnit--; + SetColorCombinerValues( curUnit, arg2, envCombiner->color[curUnit].arg1.source, envCombiner->color[curUnit].arg1.operand ); + envCombiner->color[curUnit].combine = GL_MODULATE_ADD_ATI; + SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); + } + else + { + envCombiner->color[curUnit].combine = GL_ADD; + SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 ); + } + curUnit++; + break; + case INTERPOLATE: + envCombiner->usesT0 |= (colorCombiner->stage[i].op[j].param2 == TEXEL0) || (colorCombiner->stage[i].op[j].param3 == TEXEL0) || (colorCombiner->stage[i].op[j].param3 == TEXEL0_ALPHA); + envCombiner->usesT1 |= (colorCombiner->stage[i].op[j].param2 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1_ALPHA); + + if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) && + ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param2 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1_ALPHA)) && (curUnit == 0)) + { + if (colorCombiner->stage[i].op[j].param1 == TEXEL0) + { + envCombiner->color[curUnit].combine = GL_REPLACE; + SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); + colorCombiner->stage[i].op[j].param1 = COMBINED; + } + if (colorCombiner->stage[i].op[j].param2 == TEXEL0) + { + envCombiner->color[curUnit].combine = GL_REPLACE; + SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param2 ) + + colorCombiner->stage[i].op[j].param2 = COMBINED; + } + if (colorCombiner->stage[i].op[j].param3 == TEXEL0) + { + envCombiner->color[curUnit].combine = GL_REPLACE; + SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param3 ); + colorCombiner->stage[i].op[j].param3 = COMBINED; + } + if (colorCombiner->stage[i].op[j].param3 == TEXEL0_ALPHA) + { + envCombiner->color[curUnit].combine = GL_REPLACE; + SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param3 ); + colorCombiner->stage[i].op[j].param3 = COMBINED_ALPHA; + } + + curUnit++; + } + + envCombiner->color[curUnit].combine = GL_INTERPOLATE_ARB; + + SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 ); + SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param2 ); + SetColorCombinerArg( curUnit, arg2, colorCombiner->stage[i].op[j].param3 ); + + curUnit++; + break; + } + } + } + } + + envCombiner->usedUnits = max( (unsigned short)curUnit, envCombiner->usedUnits ); + return envCombiner; +}