# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

driver_opengl_material.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdopengl.h"
00027 #include "3d/cube_map_builder.h"
00028 #include "3d/texture_mem.h"
00029 
00030 
00031 namespace NL3D {
00032 
00033 static void convBlend(CMaterial::TBlend blend, GLenum& glenum)
00034 {
00035         switch(blend)
00036         {
00037                 case CMaterial::one:            glenum=GL_ONE; break;
00038                 case CMaterial::zero:           glenum=GL_ZERO; break;
00039                 case CMaterial::srcalpha:       glenum=GL_SRC_ALPHA; break;
00040                 case CMaterial::invsrcalpha:glenum=GL_ONE_MINUS_SRC_ALPHA; break;
00041                 case CMaterial::srccolor:       glenum=GL_SRC_COLOR; break;
00042                 case CMaterial::invsrccolor:glenum=GL_ONE_MINUS_SRC_COLOR; break;
00043                 // Extended Blend modes.
00044                 case CMaterial::blendConstantColor:             glenum=GL_CONSTANT_COLOR_EXT; break;
00045                 case CMaterial::blendConstantInvColor:  glenum=GL_ONE_MINUS_CONSTANT_COLOR_EXT; break;
00046                 case CMaterial::blendConstantAlpha:             glenum=GL_CONSTANT_ALPHA_EXT; break;
00047                 case CMaterial::blendConstantInvAlpha:  glenum=GL_ONE_MINUS_CONSTANT_ALPHA_EXT; break;
00048                 default: nlstop;
00049         }
00050 }
00051 
00052 static void convZFunction(CMaterial::ZFunc zfunc, GLenum& glenum)
00053 {
00054         switch(zfunc)
00055         {
00056                 case CMaterial::lessequal:      glenum=GL_LEQUAL; break;
00057                 case CMaterial::less:           glenum=GL_LESS; break;
00058                 case CMaterial::always:         glenum=GL_ALWAYS; break;
00059                 case CMaterial::never:          glenum=GL_NEVER; break;
00060                 case CMaterial::equal:          glenum=GL_EQUAL; break;
00061                 case CMaterial::notequal:       glenum=GL_NOTEQUAL; break;
00062                 case CMaterial::greater:        glenum=GL_GREATER; break;
00063                 case CMaterial::greaterequal:   glenum=GL_GEQUAL; break;
00064                 default: nlstop;
00065         }
00066 }
00067 
00068 static void     convColor(CRGBA col, GLfloat glcol[4])
00069 {
00070         static  const float     OO255= 1.0f/255;
00071         glcol[0]= col.R*OO255;
00072         glcol[1]= col.G*OO255;
00073         glcol[2]= col.B*OO255;
00074         glcol[3]= col.A*OO255;
00075 }
00076 
00077 static inline void convTexAddr(ITexture *tex, CMaterial::TTexAddressingMode mode, GLenum &glenum)
00078 {       
00079         nlassert(mode < CMaterial::TexAddrCount);
00080         static const GLenum glTex2dAddrModesNV[] =
00081         {
00082                 GL_NONE, GL_TEXTURE_2D, GL_PASS_THROUGH_NV, GL_CULL_FRAGMENT_NV,
00083                 GL_OFFSET_TEXTURE_2D_NV, GL_OFFSET_TEXTURE_2D_SCALE_NV,
00084                 GL_DEPENDENT_AR_TEXTURE_2D_NV, GL_DEPENDENT_GB_TEXTURE_2D_NV,
00085                 GL_DOT_PRODUCT_NV, GL_DOT_PRODUCT_TEXTURE_2D_NV, GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV,
00086                 GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV, GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV,
00087                 GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV, GL_DOT_PRODUCT_DEPTH_REPLACE_NV
00088         };
00089 
00090 
00091         static const GLenum glTexCubedAddrModesNV[] =
00092         {
00093                 GL_NONE, GL_TEXTURE_CUBE_MAP_ARB, GL_PASS_THROUGH_NV, GL_CULL_FRAGMENT_NV,
00094                 GL_OFFSET_TEXTURE_2D_NV, GL_OFFSET_TEXTURE_2D_SCALE_NV,
00095                 GL_DEPENDENT_AR_TEXTURE_2D_NV, GL_DEPENDENT_GB_TEXTURE_2D_NV,
00096                 GL_DOT_PRODUCT_NV, GL_DOT_PRODUCT_TEXTURE_2D_NV, GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV,
00097                 GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV, GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV,
00098                 GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV, GL_DOT_PRODUCT_DEPTH_REPLACE_NV
00099         };
00100 
00101         
00102         if (!tex || !tex->isTextureCube())
00103         {       
00104                 glenum = glTex2dAddrModesNV[(uint) mode];
00105         }
00106         else
00107         {
00108                 glenum = glTexCubedAddrModesNV[(uint) mode];
00109         }
00110 }
00111 
00112 
00113 // --------------------------------------------------
00114 void CDriverGL::setTextureEnvFunction(uint stage, CMaterial& mat)
00115 {
00116         ITexture        *text= mat.getTexture(stage);
00117         if(text)
00118         {
00119                 CMaterial::CTexEnv      &env= mat._TexEnvs[stage];
00120 
00121                 // Activate the env for this stage.
00122                 // NB: Thoses calls use caching.
00123                 activateTexEnvMode(stage, env);
00124                 activateTexEnvColor(stage, env);
00125 
00126                 // Activate texture generation mapping
00127                 _DriverGLStates.activeTextureARB(stage);
00128                 if (mat.getTexCoordGen (stage))
00129                 {
00130                         // Enable it
00131                         _DriverGLStates.enableTexGen (stage, true);
00132 
00133                         // Cubic or normal ?
00134                         if (text->isTextureCube ())
00135                                 _DriverGLStates.setTexGenMode (stage, GL_REFLECTION_MAP_ARB);
00136                         else
00137                                 _DriverGLStates.setTexGenMode (stage, GL_SPHERE_MAP);
00138                 }
00139                 else
00140                 {
00141                         _DriverGLStates.enableTexGen (stage, false);
00142                 }
00143         }
00144 }
00145 
00146 
00147 //--------------------------------
00148 void CDriverGL::setupUserTextureMatrix(uint numStages, CMaterial& mat)
00149 { 
00150         if (
00151                 (_UserTexMatEnabled != 0 && (mat.getFlags() & IDRV_MAT_USER_TEX_MAT_ALL) == 0)          
00152                 || (mat.getFlags() & IDRV_MAT_USER_TEX_MAT_ALL) != 0
00153            )
00154         {
00155                 glMatrixMode(GL_TEXTURE);
00156                 // for each stage, setup the texture matrix if needed
00157                 uint newMask = (mat.getFlags() & IDRV_MAT_USER_TEX_MAT_ALL) >> IDRV_MAT_USER_TEX_FIRST_BIT;
00158                 uint shiftMask = 1;
00159                 for (uint k = 0; k < numStages ; ++k)
00160                 {
00161                         if (newMask & shiftMask) // user matrix for this stage
00162                         {               
00163                                 _DriverGLStates.activeTextureARB(k);
00164                                 glLoadMatrixf(mat.getUserTexMat(k).get());
00165                                 _UserTexMatEnabled |= shiftMask;
00166                         }
00167                         else
00168                         {
00170                                 if (
00171                                         (newMask & shiftMask) != (_UserTexMatEnabled & shiftMask)
00172                                    )
00173                                 {
00174                                         _DriverGLStates.activeTextureARB(k);
00175                                         glLoadIdentity();
00176                                         _UserTexMatEnabled &= ~shiftMask;
00177                                 }                               
00178                         }
00179                         shiftMask <<= 1;
00180                 }
00181                 glMatrixMode(GL_MODELVIEW);
00182         }
00183 }
00184 
00185 void CDriverGL::disableUserTextureMatrix()
00186 { 
00187         if (_UserTexMatEnabled != 0)            
00188         {
00189                 glMatrixMode(GL_TEXTURE);               
00190                 uint k = 0;
00191                 do
00192                 {
00193                         if (_UserTexMatEnabled & (1 << k)) // user matrix for this stage
00194                         {                                               
00195                                 _DriverGLStates.activeTextureARB(k);
00196                                 glLoadIdentity();
00197                                 _UserTexMatEnabled &= ~ (1 << k);
00198                                                                 
00199                         }                       
00200                         ++k;
00201                 }
00202                 while (_UserTexMatEnabled != 0);
00203                 glMatrixMode(GL_MODELVIEW);
00204         }
00205 }
00206 
00207 
00208 // --------------------------------------------------
00209 CMaterial::TShader      CDriverGL::getSupportedShader(CMaterial::TShader shader)
00210 {
00211         switch (shader)
00212         {
00213         case CMaterial::PerPixelLighting: return _SupportPerPixelShader ? CMaterial::PerPixelLighting : CMaterial::Normal;
00214         case CMaterial::PerPixelLightingNoSpec: return _SupportPerPixelShaderNoSpec ? CMaterial::PerPixelLightingNoSpec : CMaterial::Normal;
00215         // Lightmap and Specular work only if at least 2 text stages.
00216         case CMaterial::LightMap: return (inlGetNumTextStages()>=2) ? CMaterial::LightMap : CMaterial::Normal;
00217         case CMaterial::Specular: return (inlGetNumTextStages()>=2) ? CMaterial::Specular : CMaterial::Normal;
00218                 default: return shader;         
00219         }
00220 }
00221 
00222 
00223 // --------------------------------------------------
00224 
00225 bool CDriverGL::setupMaterial(CMaterial& mat)
00226 {
00227         CShaderGL*      pShader;
00228         GLenum          glenum;
00229         uint32          touched=mat.getTouched();
00230         sint            stage;
00231 
00232 
00233         // profile.
00234         _NbSetupMaterialCall++;
00235 
00236 
00237         // 0. Retrieve/Create driver shader.
00238         //==================================
00239         if (!mat.pShader)
00240         {
00241                 // insert into driver list. (so it is deleted when driver is deleted).
00242                 ItShaderPtrList         it= _Shaders.insert(_Shaders.end());
00243                 // create and set iterator, for future deletion.
00244                 *it= mat.pShader= new CShaderGL(this, it);
00245 
00246                 // Must create all OpenGL shader states.
00247                 touched= IDRV_TOUCHED_ALL;
00248         }
00249         pShader=static_cast<CShaderGL*>((IShader*)(mat.pShader));
00250 
00251 
00252         // 1. Setup modified fields of material.
00253         //=====================================
00254         if( touched ) 
00255         {
00256                 /* Exception: if only Textures are modified in the material, no need to "Bind OpenGL States", or even to test
00257                         for change, because textures are activated alone, see below.
00258                         No problem with delete/new problem (see below), because in this case, IDRV_TOUCHED_ALL is set (see above).
00259                 */
00260                 // If any flag is set (but a flag of texture)
00261                 if( touched & (~_MaterialAllTextureTouchedFlag) )
00262                 {
00263                         // Convert Material to driver shader.
00264                         if (touched & IDRV_TOUCHED_BLENDFUNC)
00265                         {
00266                                 convBlend( mat.getSrcBlend(),glenum );
00267                                 pShader->SrcBlend=glenum;
00268                                 convBlend( mat.getDstBlend(),glenum );
00269                                 pShader->DstBlend=glenum;
00270                         }
00271                         if (touched & IDRV_TOUCHED_ZFUNC)
00272                         {
00273                                 convZFunction( mat.getZFunc(),glenum);
00274                                 pShader->ZComp= glenum;
00275                         }
00276                         if (touched & IDRV_TOUCHED_LIGHTING)
00277                         {
00278                                 convColor(mat.getEmissive(), pShader->Emissive);
00279                                 convColor(mat.getAmbient(), pShader->Ambient);
00280                                 convColor(mat.getDiffuse(), pShader->Diffuse);
00281                                 convColor(mat.getSpecular(), pShader->Specular);
00282                                 pShader->PackedEmissive= mat.getEmissive().getPacked();
00283                                 pShader->PackedAmbient= mat.getAmbient().getPacked();
00284                                 pShader->PackedDiffuse= mat.getDiffuse().getPacked();
00285                                 pShader->PackedSpecular= mat.getSpecular().getPacked();
00286                         }
00287                         if (touched & IDRV_TOUCHED_SHADER)
00288                         {
00289                                 // Get shader. Fallback to other shader if not supported.
00290                                 pShader->SupportedShader= getSupportedShader(mat.getShader());
00291                         }
00292 
00293 
00294                         // Since modified, must rebind all openGL states. And do this also for the delete/new problem.
00295                         /* If an old material is deleted, _CurrentMaterial is invalid. But this is grave only if a new 
00296                                 material is created, with the same pointer (bad luck). Since an newly allocated material always 
00297                                 pass here before use, we are sure to avoid any problems.
00298                         */
00299                         _CurrentMaterial= NULL;
00300                 }
00301 
00302                 // Optimize: reset all flags at the end.
00303                 mat.clearTouched(0xFFFFFFFF);
00304         }
00305 
00306 
00307         // Now we can get the supported shader from the cache.
00308         CMaterial::TShader matShader = pShader->SupportedShader;
00309 
00310         // setup the global
00311         _CurrentMaterialSupportedShader= matShader;
00312 
00313 
00314         // 2. Setup / Bind Textures.
00315         //==========================
00316         // Must setup textures each frame. (need to test if touched).
00317         // Must separate texture setup and texture activation in 2 "for"...
00318         // because setupTexture() may disable all stage.
00319         for(stage=0 ; stage<inlGetNumTextStages() ; stage++)
00320         {
00321                 ITexture        *text= mat.getTexture(stage);
00322                 if (text != NULL && !setupTexture(*text))
00323                         return(false);
00324         }
00325         // Here, for Lightmap materials, setup the lightmaps.
00326         if(matShader == CMaterial::LightMap)
00327         {
00328                 for(stage=0 ; stage<(sint)mat._LightMaps.size() ; stage++)
00329                 {
00330                         ITexture        *text= mat._LightMaps[stage].Texture;
00331                         if (text != NULL && !setupTexture(*text))
00332                                 return(false);
00333                 }
00334         }
00335 
00336         // Here, for caustic shader, setup the lightmaps
00337         /*if (matShader == CMaterial::Caustics)
00338         {
00339                 if (mat.getTexture(stage))
00340         }*/
00341         
00342 
00343         // Activate the textures.
00344         // Do not do it for Lightmap and per pixel lighting , because done in multipass in a very special fashion.
00345         // This avoid the useless multiple change of texture states per lightmapped object.
00346         if(matShader != CMaterial::LightMap
00347                 && matShader != CMaterial::PerPixelLighting
00348                 /* && matShader != CMaterial::Caustics  */
00349                 && matShader != CMaterial::Cloud
00350            )
00351         {
00352                 for(stage=0 ; stage<inlGetNumTextStages() ; stage++)
00353                 {
00354                         ITexture        *text= mat.getTexture(stage);
00355 
00356                         // activate the texture, or disable texturing if NULL.
00357                         activateTexture(stage,text);
00358 
00359                         // If texture not NULL, Change texture env fonction.
00360                         //==================================================
00361                         setTextureEnvFunction(stage, mat);
00362                 }                               
00363         }
00364 
00365 
00366         // 3. Bind OpenGL States.
00367         //=======================
00368         if (_CurrentMaterial!=&mat)
00369         {
00370                 // Bind Blend Part.
00371                 //=================
00372                 _DriverGLStates.enableBlend(mat.getFlags()&IDRV_MAT_BLEND);
00373                 if(mat.getFlags()&IDRV_MAT_BLEND)
00374                         _DriverGLStates.blendFunc(pShader->SrcBlend, pShader->DstBlend);
00375 
00376                 // Double Sided Part.
00377                 //===================
00378                 // NB: inverse state: DoubleSided <=> !CullFace.
00379                 uint32  twoSided= mat.getFlags()&IDRV_MAT_DOUBLE_SIDED;
00380                 _DriverGLStates.enableCullFace( twoSided==0 );
00381 
00382 
00383                 // Alpha Test Part.
00384                 //=================
00385                 uint32  alphaTest= mat.getFlags()&IDRV_MAT_ALPHA_TEST;
00386                 _DriverGLStates.enableAlphaTest(alphaTest);
00387                 if(alphaTest)
00388                 {
00389                         // setup alphaTest threshold.
00390                         _DriverGLStates.alphaFunc(mat.getAlphaTestThreshold());
00391                 }
00392 
00393 
00394                 // Bind ZBuffer Part.
00395                 //===================
00396                 _DriverGLStates.enableZWrite(mat.getFlags()&IDRV_MAT_ZWRITE);
00397                 _DriverGLStates.depthFunc(pShader->ZComp);
00398                 _DriverGLStates.setDepthRange (mat.getZBias () * _OODeltaZ);
00399 
00400 
00401                 // Color-Lighting Part.
00402                 //=====================
00403 
00404                 // Light Part.
00405                 _DriverGLStates.enableLighting(mat.getFlags()&IDRV_MAT_LIGHTING);
00406                 if(mat.getFlags()&IDRV_MAT_LIGHTING)
00407                 {
00408                         _DriverGLStates.setEmissive(pShader->PackedEmissive, pShader->Emissive);
00409                         _DriverGLStates.setAmbient(pShader->PackedAmbient, pShader->Ambient);
00410                         _DriverGLStates.setDiffuse(pShader->PackedDiffuse, pShader->Diffuse);
00411                         _DriverGLStates.setSpecular(pShader->PackedSpecular, pShader->Specular);
00412                         _DriverGLStates.setShininess(mat.getShininess());
00413                         _DriverGLStates.setVertexColorLighted(mat.isLightedVertexColor ());
00414                 }
00415                 else
00416                 {
00417                         // Color unlit part.
00418                         CRGBA   col= mat.getColor();
00419                         glColor4ub(col.R, col.G, col.B, col.A);
00420                         _DriverGLStates.setVertexColorLighted(false);
00421                 }
00422                 
00423                 
00424                 // Texture shader part.
00425                 //=====================
00426 
00427                 if (_Extensions.NVTextureShader)
00428                 {
00429                         if (matShader == CMaterial::Normal)
00430                         {
00431                                 // Texture addressing modes (support only via NVTextureShader for now)
00432                                 //===================================================================                                                           
00433                                 if ( mat.getFlags() & IDRV_MAT_TEX_ADDR )
00434                                 {               
00435                                         enableNVTextureShader(true);
00436 
00437                                         GLenum glAddrMode;
00438                                         for (stage = 0; stage < inlGetNumTextStages(); ++stage)
00439                                         {                                                                               
00440                                                 convTexAddr(mat.getTexture(stage), (CMaterial::TTexAddressingMode) (mat._TexAddrMode[stage]), glAddrMode);
00441 
00442                                                 if (glAddrMode != _CurrentTexAddrMode[stage]) // addressing mode different from the one in the device?
00443                                         
00444                                                 {
00445                                                         _DriverGLStates.activeTextureARB(stage);
00446                                                         glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, glAddrMode);                            
00447                                                         _CurrentTexAddrMode[stage] = glAddrMode;                                        
00448                                                 }
00449                                         }                                                                                                               
00450                                 }
00451                                 else
00452                                 {
00453                                         enableNVTextureShader(false);
00454                                 }                               
00455                         }
00456                         else 
00457                         {
00458                                 enableNVTextureShader(false);
00459                         }
00460                 }               
00461 
00462                 _CurrentMaterial=&mat;
00463         }
00464 
00465 
00466         // 4. Misc
00467         //=====================================
00468 
00469         // If !lightMap and prec material was lihgtmap => vertex setup is dirty!
00470         if( matShader != CMaterial::LightMap && _LastVertexSetupIsLightMap )
00471                 resetLightMapVertexSetup();
00472 
00473         // Textures user matrix
00474         if (matShader == CMaterial::Normal)
00475         {
00476                 setupUserTextureMatrix((uint) inlGetNumTextStages(), mat);              
00477         }
00478         else // deactivate texture matrix
00479         {
00480                 disableUserTextureMatrix();
00481         }
00482 
00483         return true;
00484 }
00485 
00486 
00487 // ***************************************************************************
00488 sint                    CDriverGL::beginMultiPass()
00489 {
00490         // Depending on material type and hardware, return number of pass required to draw this material.
00491         switch(_CurrentMaterialSupportedShader)
00492         {
00493         case CMaterial::LightMap: 
00494                 return  beginLightMapMultiPass();
00495         case CMaterial::Specular: 
00496                 return  beginSpecularMultiPass();
00497         case CMaterial::PerPixelLighting:
00498                 return  beginPPLMultiPass();
00499         case CMaterial::PerPixelLightingNoSpec:
00500                 return  beginPPLNoSpecMultiPass();      
00501         /* case CMaterial::Caustics:
00502                 return  beginCausticsMultiPass(); */
00503         case CMaterial::Cloud:
00504                 return  beginCloudMultiPass();
00505 
00506         // All others materials require just 1 pass.
00507         default: return 1;
00508         }
00509 }
00510 // ***************************************************************************
00511 void                    CDriverGL::setupPass(uint pass)
00512 {
00513         switch(_CurrentMaterialSupportedShader)
00514         {
00515         case CMaterial::LightMap: 
00516                 setupLightMapPass (pass);
00517                 break;
00518         case CMaterial::Specular: 
00519                 setupSpecularPass (pass);
00520                 break;
00521         case CMaterial::PerPixelLighting:
00522                 setupPPLPass (pass);
00523                 break;
00524         case CMaterial::PerPixelLightingNoSpec:
00525                 setupPPLNoSpecPass (pass);
00526                 break;  
00527         /* case CMaterial::Caustics:
00528                 case CMaterial::Caustics:
00529                 break; */
00530         case CMaterial::Cloud:
00531                 setupCloudPass (pass);
00532                 break;  
00533 
00534         // All others materials do not require multi pass.
00535         default: return;
00536         }
00537 }
00538 
00539 
00540 // ***************************************************************************
00541 void                    CDriverGL::endMultiPass()
00542 {
00543         switch(_CurrentMaterialSupportedShader)
00544         {
00545         case CMaterial::LightMap: 
00546                 endLightMapMultiPass();
00547                 break;
00548         case CMaterial::Specular: 
00549                 endSpecularMultiPass();
00550                 break;
00551         case CMaterial::PerPixelLighting:
00552                 endPPLMultiPass();
00553                 break;
00554         case CMaterial::PerPixelLightingNoSpec:
00555                 endPPLNoSpecMultiPass();
00556                 break;  
00557         /* case CMaterial::Caustics:
00558                 endCausticsMultiPass();
00559                 break; */
00560         case CMaterial::Cloud:
00561                 endCloudMultiPass();
00562                 break;  
00563         // All others materials do not require multi pass.
00564         default: return;
00565         }
00566 }
00567 
00568 
00569 // ***************************************************************************
00570 void CDriverGL::computeLightMapInfos (const CMaterial &mat)
00571 {
00572         static const uint32 RGBMaskPacked = CRGBA(255,255,255,0).getPacked();
00573 
00574         // For optimisation consideration, suppose there is not too much lightmap.
00575         nlassert(mat._LightMaps.size()<=NL3D_DRV_MAX_LIGHTMAP);
00576 
00577         // Compute number of lightmaps really used (ie factor not NULL), and build the LUT.
00578         _NLightMaps = 0;
00579         // For all lightmaps of the material.
00580         for (uint i = 0; i < mat._LightMaps.size(); ++i)
00581         {
00582                 // If the lightmap's factor is not null.
00583                 if (mat._LightMaps[i].Factor.getPacked() & RGBMaskPacked)
00584                 {
00585                         _LightMapLUT[_NLightMaps] = i;
00586                         ++_NLightMaps;
00587                 }
00588         }
00589 
00590         // Compute how many pass, according to driver caps.
00591         _NLightMapPerPass = inlGetNumTextStages()-1;
00592         // Can do more than 2 texture stages only if NVTextureEnvCombine4 or ATIXTextureEnvCombine3
00593         if (!_Extensions.NVTextureEnvCombine4 || !_Extensions.ATIXTextureEnvCombine3)
00594                 _NLightMapPerPass = 1;
00595 
00596         // Number of pass.
00597         _NLightMapPass = (_NLightMaps + _NLightMapPerPass-1)/(_NLightMapPerPass);
00598 
00599         // NB: _NLightMaps==0 means there is no lightmaps at all.
00600 }
00601 
00602 
00603 // ***************************************************************************
00604 sint CDriverGL::beginLightMapMultiPass ()
00605 {
00606         const CMaterial &mat= *_CurrentMaterial;
00607 
00608         // compute how many lightmap and pass we must process.
00609         computeLightMapInfos (mat);
00610 
00611         // Too be sure, disable vertex coloring / lightmap.
00612         _DriverGLStates.enableLighting(false);
00613         // reset VertexColor array if necessary.
00614         if (_LastVB.VertexFormat & CVertexBuffer::PrimaryColorFlag)
00615                 _DriverGLStates.enableColorArray(false);
00616 
00617         // Manage too if no lightmaps.
00618         return  std::max (_NLightMapPass, (uint)1);
00619 }
00620 // ***************************************************************************
00621 void                    CDriverGL::setupLightMapPass(uint pass)
00622 {
00623         const CMaterial &mat= *_CurrentMaterial;
00624 
00625         // No lightmap or all blacks??, just setup "black texture" for stage 0.
00626         if(_NLightMaps==0)
00627         {
00628                 ITexture        *text= mat.getTexture(0);
00629                 activateTexture(0,text);
00630 
00631                 // setup std modulate env
00632                 CMaterial::CTexEnv      env;
00633                 activateTexEnvMode(0, env);
00634                 // Since Lighting is disabled, as well as colorArray, must setup alpha.
00635                 // setup color to 0 => blackness
00636                 glColor4ub(0, 0, 0, 255);
00637 
00638                 // Setup gen tex off
00639                 _DriverGLStates.activeTextureARB(0);
00640                 _DriverGLStates.enableTexGen (0, false);
00641 
00642                 // And disable other stages.
00643                 for(sint stage=1 ; stage<inlGetNumTextStages() ; stage++)
00644                 {
00645                         // disable texturing.
00646                         activateTexture(stage, NULL);
00647                 }
00648 
00649                 return;
00650         }
00651 
00652         nlassert(pass<_NLightMapPass);
00653 
00654 
00655         // setup Texture Pass.
00656         //=========================
00657         uint    lmapId;
00658         uint    nstages;
00659         lmapId= pass * _NLightMapPerPass; // Nb lightmaps already processed
00660         // N lightmaps for this pass, plus the texture.
00661         nstages= std::min(_NLightMapPerPass, _NLightMaps-lmapId) + 1;
00662         // setup all stages.
00663         for(uint stage= 0; stage<(uint)inlGetNumTextStages(); stage++)
00664         {
00665                 // if must setup a lightmap stage.
00666                 if(stage<nstages-1)
00667                 {
00668                         // setup lightMap.
00669                         uint    whichLightMap= _LightMapLUT[lmapId];
00670                         // get text and factor.
00671                         ITexture *text   = mat._LightMaps[whichLightMap].Texture;
00672                         CRGBA lmapFactor = mat._LightMaps[whichLightMap].Factor;
00673                         lmapFactor.A= 255;
00674 
00675                         activateTexture(stage,text);
00676 
00677                         // If texture not NULL, Change texture env fonction.
00678                         //==================================================
00679                         if(text)
00680                         {
00681                                 static CMaterial::CTexEnv       stdEnv;
00682 
00683                                 // NB, !_Extensions.NVTextureEnvCombine4, nstages==2, so here always stage==0.
00684                                 if (stage==0)
00685                                 {
00686                                         // do not use consant color to blend lightmap, but incoming diffuse color, for stage0 only.
00687                                         // (NB: lighting and vertexcolorArray are disabled here)
00688                                         glColor4ub(lmapFactor.R, lmapFactor.G, lmapFactor.B, 255);
00689 
00690                                         // Leave stage as default env (Modulate with previous)
00691                                         activateTexEnvMode(stage, stdEnv);
00692 
00693                                         // Setup gen tex off
00694                                         _DriverGLStates.activeTextureARB(stage);
00695                                         _DriverGLStates.enableTexGen (stage, false);
00696                                 }
00697                                 else
00698                                 {
00699                                         // Here, we are sure that texEnvCombine4 or texEnvCombine3 is OK.
00700                                         nlassert(_Extensions.NVTextureEnvCombine4 || _Extensions.ATIXTextureEnvCombine3);
00701 
00702                                         // setup constant color with Lightmap factor.
00703                                         stdEnv.ConstantColor=lmapFactor;
00704                                         activateTexEnvColor(stage, stdEnv);
00705 
00706 
00707                                         // TexEnv is special.
00708                                         _CurrentTexEnvSpecial[stage] = TexEnvSpecialLightMap;
00709 
00710                                         // Setup env for texture stage.
00711                                         _DriverGLStates.activeTextureARB(stage);
00712 
00713                                         // setup TexEnvCombine4 (ignore alpha part).
00714                                         if(_CurrentTexEnvSpecial[stage] != TexEnvSpecialLightMap)
00715                                         {
00716                                                 if (_Extensions.NVTextureEnvCombine4)
00717                                                 {                                                                                       
00718                                                         // What we want to setup is  Texture*Constant + Previous*1.
00719                                                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
00720 
00721                                                         // Operator.
00722                                                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD );
00723                                                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD );
00724                                                         // Arg0.
00725                                                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE );
00726                                                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
00727                                                         // Arg1.
00728                                                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT );
00729                                                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
00730                                                         // Arg2.
00731                                                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT );
00732                                                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
00733                                                         // Arg3.
00734                                                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
00735                                                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
00736                                                 }                                                                                                                               
00737                                                 else
00738                                                 {
00739                                                         // ATI EnvCombine3
00740                                                         // What we want to setup is  Texture*Constant + Previous.
00741                                                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
00742                                                         // Operator.
00743                                                         glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE_ADD_ATIX);
00744                                                         glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE_ADD_ATIX);                                          
00745                                                         // Arg0.
00746                                                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE );
00747                                                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
00748                                                         // Arg1.
00749                                                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT );
00750                                                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
00751                                                         // Arg2.
00752                                                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT );
00753                                                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
00754                                                 }
00755                                         }
00756                                 }
00757 
00758                                 // setup UV, with UV1. Only if needed (cached)
00759                                 if( !_LastVertexSetupIsLightMap || _LightMapUVMap[stage]!=1 )
00760                                 {
00761                                         setupUVPtr(stage, _LastVB, 1);
00762                                         _LightMapUVMap[stage]= 1;
00763                                 }
00764                         }
00765 
00766                         // Next lightmap.
00767                         lmapId++;
00768                 }
00769                 else if(stage<nstages)
00770                 {
00771                         // optim: do this only for first pass, and last pass only if stage!=nLMapPerPass 
00772                         // (meaning not the same stage as preceding passes).
00773                         if(pass==0 || (pass==_NLightMapPass-1 && stage!=_NLightMapPerPass))
00774                         {
00775                                 // activate the texture at last stage.
00776                                 ITexture        *text= mat.getTexture(0);
00777                                 activateTexture(stage,text);
00778 
00779                                 // setup ModulateRGB/ReplaceAlpha env. (this may disable possible COMBINE4_NV setup).
00780                                 activateTexEnvMode(stage, _LightMapLastStageEnv);
00781 
00782                                 // Setup gen tex off
00783                                 _DriverGLStates.activeTextureARB(stage);
00784                                 _DriverGLStates.enableTexGen (stage, false);
00785 
00786                                 // setup UV, with UV0. Only if needed (cached)
00787                                 if( !_LastVertexSetupIsLightMap || _LightMapUVMap[stage]!=0 )
00788                                 {
00789                                         setupUVPtr(stage, _LastVB, 0);
00790                                         _LightMapUVMap[stage]= 0;
00791                                 }
00792                         }
00793                 }
00794                 else
00795                 {
00796                         // else all other stages are disabled.
00797                         activateTexture(stage,NULL);
00798                 }
00799         }
00800 
00801 
00802         // setup blend / lighting.
00803         //=========================
00804 
00805         /* If multi-pass, then must setup a black Fog color for 1+ pass (just do it for the pass 1).
00806                 This is because Transparency ONE/ONE is used.
00807         */
00808         if(pass==1 && _FogEnabled)
00809         {
00810                 static  GLfloat         blackFog[4]= {0,0,0,0};
00811                 glFogfv(GL_FOG_COLOR, blackFog);
00812         }
00813 
00814         // Blend is different if the material is blended or not
00815         if( !mat.getBlend() )
00816         {
00817                 // Not blended, std case.
00818                 if(pass==0)
00819                 {
00820                         // no transparency for first pass.
00821                         _DriverGLStates.enableBlend(false);
00822                 }
00823                 else if(pass==1)
00824                 {
00825                         // setup an Additive transparency (only for pass 1, will be kept for successives pass).
00826                         _DriverGLStates.enableBlend(true);
00827                         _DriverGLStates.blendFunc(GL_ONE, GL_ONE);
00828                 }
00829         }
00830         else
00831         {
00832                 /* 1st pass, std alphaBlend. 2nd pass, add to background. Demo:
00833                         T: texture.
00834                         l0: lightmap (or group of lightmap) of pass 0.
00835                         l1: lightmap (or group of lightmap) of pass 1. (same thing with 2,3 etc....)
00836                         B:      Background.
00837                         A:      Alpha of texture.
00838 
00839                         finalResult= T*(l0+l1) * A + B * (1-A).
00840 
00841                         We get it in two pass:
00842                                 fint=                   T*l0 * A + B * (1-A).
00843                                 finalResult=    T*l1 * A + fint = T*l1 * A + T*l0 * A + B * (1-A)=
00844                                         T* (l0+l1) * A + B * (1-A)
00845                 */
00846                 if(pass==0)
00847                 {
00848                         // no transparency for first pass.
00849                         _DriverGLStates.enableBlend(true);
00850                         _DriverGLStates.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00851                 }
00852                 else if(pass==1)
00853                 {
00854                         // setup an Additive transparency (only for pass 1, will be kept for successives pass).
00855                         _DriverGLStates.enableBlend(true);
00856                         _DriverGLStates.blendFunc(GL_SRC_ALPHA, GL_ONE);
00857                 }
00858         }
00859 
00860 }
00861 // ***************************************************************************
00862 void                    CDriverGL::endLightMapMultiPass()
00863 {
00864         // Cache it. reseted in setupGLArrays(), and setupMaterial()
00865         _LastVertexSetupIsLightMap= true;
00866 
00867         // If multi-pass, then must reset the fog color
00868         if(_NLightMapPass>=2 && _FogEnabled)
00869         {
00870                 glFogfv(GL_FOG_COLOR, _CurrentFogColor);
00871         }
00872 
00873         // nothing to do with blending/lighting, since always setuped in activeMaterial().
00874         // If material is the same, then it is still a lightmap material (if changed => touched => different!)
00875         // So no need to reset lighting/blending here.
00876 }
00877 
00878 
00879 // ***************************************************************************
00880 void                    CDriverGL::resetLightMapVertexSetup()
00881 {
00882         // special for all stage, std UV behavior.
00883         for(sint i=0; i<inlGetNumTextStages(); i++)
00884         {
00885                 // normal behavior: each texture has its own UV.
00886                 setupUVPtr(i, _LastVB, i);
00887                 // reset cache
00888                 _LightMapUVMap[i]= -1;
00889         }
00890 
00891         // pop VertexColor array if necessary.
00892         if (_LastVB.VertexFormat & CVertexBuffer::PrimaryColorFlag)
00893                 _DriverGLStates.enableColorArray(true);
00894 
00895         // flag
00896         _LastVertexSetupIsLightMap= false;
00897 }
00898 
00899 
00900 // ***************************************************************************
00901 sint                    CDriverGL::beginSpecularMultiPass()
00902 {
00903         const CMaterial &mat= *_CurrentMaterial;
00904 
00905         _DriverGLStates.activeTextureARB(1);
00906         glMatrixMode(GL_TEXTURE);
00907         glLoadMatrixf( _TexMtx.get() );
00908         glMatrixMode(GL_MODELVIEW);
00909 
00910         // Manage the rare case when the SpecularMap is not provided (fault of graphist).
00911         if(mat.getTexture(1)==NULL)
00912                 return 1;
00913 
00914         if(!_Extensions.ARBTextureCubeMap)
00915                 return 1;
00916 
00917         if( _Extensions.NVTextureEnvCombine4 || _Extensions.ATIXTextureEnvCombine3) // NVidia or ATI optimization
00918                 return 1;
00919         else
00920                 return 2;
00921 
00922 }
00923 // ***************************************************************************
00924 void                    CDriverGL::setupSpecularPass(uint pass)
00925 {
00926         const CMaterial &mat= *_CurrentMaterial;
00927 
00928         // Manage the rare case when the SpecularMap is not provided (error of a graphist).
00929         if(mat.getTexture(1)==NULL)
00930         {
00931                 // Just display the texture forcing no blend (as in std case).
00932                 // NB: setupMaterial() code has correclty setuped textures.
00933                 _DriverGLStates.enableBlend(false);
00934                 return;
00935         }
00936 
00938         if( _Extensions.NVTextureEnvCombine4 )
00939         {       // Ok we can do it in a single pass
00940                 _DriverGLStates.enableBlend(false);
00941 
00942                 // Stage 0
00943                 if(_CurrentTexEnvSpecial[0] != TexEnvSpecialSpecularStage0)
00944                 {
00945                         // TexEnv is special.
00946                         _CurrentTexEnvSpecial[0] = TexEnvSpecialSpecularStage0;
00947 
00948                         _DriverGLStates.activeTextureARB(0);
00949                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
00950                         // Operator.
00951                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD );
00952                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD );
00953                         // Arg0.
00954                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE );
00955                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
00956                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
00957                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
00958                         // Arg1.
00959                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
00960                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
00961                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO );
00962                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA );
00963                         // Arg2.
00964                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_ZERO );
00965                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR );
00966                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_ZERO );
00967                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA );
00968                         // Arg3.
00969                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO );
00970                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
00971                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO );
00972                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA );
00973                         // Result RGB : Texture*Diffuse, Alpha : Texture
00974                 }
00975 
00976                 // Set Stage 1
00977                 // Special: not the same sepcial env if there is or not texture in stage 0.
00978                 CTexEnvSpecial          newEnvStage1;
00979                 if( mat.getTexture(0) == NULL )
00980                         newEnvStage1= TexEnvSpecialSpecularStage1NoText;
00981                 else
00982                         newEnvStage1= TexEnvSpecialSpecularStage1;
00983                 // Test if same env as prec.
00984                 if(_CurrentTexEnvSpecial[1] != newEnvStage1)
00985                 {
00986                         // TexEnv is special.
00987                         _CurrentTexEnvSpecial[1] = newEnvStage1;
00988 
00989                         _DriverGLStates.activeTextureARB(1);
00990                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
00991                         // Operator Add (Arg0*Arg1+Arg2*Arg3)
00992                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD );
00993                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD );
00994                         // Arg0.
00995                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE );
00996                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
00997                         // Arg1.
00998                         if( newEnvStage1 == TexEnvSpecialSpecularStage1NoText )
00999                         {
01000                                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_ZERO );
01001                                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_COLOR);
01002                         }
01003                         else
01004                         {
01005                                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT );
01006                                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_ALPHA );
01007                         }
01008                         // Arg2.
01009                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT );
01010                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR );
01011                         // Arg3.
01012                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO );
01013                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
01014                         // Result : Texture*Previous.Alpha+Previous
01015                 }
01016 
01017                 // Setup TexCoord gen for stage1.
01018                 _DriverGLStates.activeTextureARB(1);
01019                 _DriverGLStates.setTextureMode(CDriverGLStates::TextureCubeMap);
01020                 _DriverGLStates.setTexGenMode (1, GL_REFLECTION_MAP_ARB);
01021                 _DriverGLStates.enableTexGen (1, true);
01022         }
01023         else if (_Extensions.ATIXTextureEnvCombine3)
01024         {
01025                 // Ok we can do it in a single pass
01026                 _DriverGLStates.enableBlend(false);
01027 
01028                 // Stage 0
01029                 if(_CurrentTexEnvSpecial[0] != TexEnvSpecialSpecularStage0)
01030                 {
01031                         // TexEnv is special.
01032                         _CurrentTexEnvSpecial[0] = TexEnvSpecialSpecularStage0;
01033 
01034                         _DriverGLStates.activeTextureARB(0);            
01035                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
01036                         // Operator Mad (Arg0 * Arg2 + Arg1)                    
01037                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE );
01038                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
01039                         // Arg0.
01040                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE );
01041                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
01042                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
01043                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
01044                         // Arg1.
01045                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
01046                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);                   
01047                         // Result RGB : Texture*Diffuse, Alpha : Texture
01048                 }
01049 
01050                 // Set Stage 1
01051                 // Special: not the same sepcial env if there is or not texture in stage 0.
01052                 CTexEnvSpecial          newEnvStage1;
01053                 if( mat.getTexture(0) == NULL )
01054                         newEnvStage1= TexEnvSpecialSpecularStage1NoText;
01055                 else
01056                         newEnvStage1= TexEnvSpecialSpecularStage1;
01057                 // Test if same env as prec.
01058                 if(_CurrentTexEnvSpecial[1] != newEnvStage1)
01059                 {
01060                         // TexEnv is special.
01061                         _CurrentTexEnvSpecial[1] = newEnvStage1;
01062 
01063                         _DriverGLStates.activeTextureARB(1);
01064                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
01065                         // Operator Add (Arg0*Arg1+Arg2*Arg3)
01066                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE_ADD_ATIX );
01067                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE_ADD_ATIX );
01068                         // Arg0.
01069                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE );
01070                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
01071                         // Arg2.
01072                         if( newEnvStage1 == TexEnvSpecialSpecularStage1NoText )
01073                         {
01074                                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_ZERO );
01075                                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_COLOR);
01076                         }
01077                         else
01078                         {
01079                                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT );
01080                                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );
01081                         }
01082                         // Arg1.
01083                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT );
01084                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );                  
01085                         // Result : Texture*Previous.Alpha+Previous
01086                 }
01087 
01088                 // Setup TexCoord gen for stage1.
01089                 _DriverGLStates.activeTextureARB(1);
01090                 _DriverGLStates.setTextureMode(CDriverGLStates::TextureCubeMap);
01091                 _DriverGLStates.setTexGenMode (1, GL_REFLECTION_MAP_ARB);
01092                 _DriverGLStates.enableTexGen (1, true);
01093         }
01094         else
01095         { // We have to do it in 2 passes
01096 
01097                 if( pass == 0 )
01098                 { // Just display the texture
01099                         _DriverGLStates.enableBlend(false);
01100                         _DriverGLStates.activeTextureARB(1);
01101                         _DriverGLStates.setTextureMode(CDriverGLStates::TextureDisabled);
01102                 }
01103                 else
01104                 { // Multiply texture1 by alpha_texture0 and display with add
01105                         _DriverGLStates.enableBlend(true);
01106                         _DriverGLStates.blendFunc(GL_ONE, GL_ONE);
01107 
01108                         // Set stage 0
01109                         _DriverGLStates.activeTextureARB(0);
01110                         CMaterial::CTexEnv      env;
01111 
01112                         env.Env.OpRGB = CMaterial::Replace;
01113                         env.Env.SrcArg0RGB = CMaterial::Texture;
01114                         env.Env.OpArg0RGB = CMaterial::SrcAlpha;
01115 
01116                         activateTexEnvMode(0, env);
01117 
01118 
01119                         // Set stage 1
01120                         if( mat.getTexture(0) == NULL )
01121                         {
01122                                 env.Env.OpRGB = CMaterial::Replace;
01123                                 env.Env.SrcArg0RGB = CMaterial::Texture;
01124                                 env.Env.OpArg0RGB = CMaterial::SrcColor;
01125                         }
01126                         else
01127                         {
01128                                 env.Env.OpRGB = CMaterial::Modulate;
01129                                 env.Env.SrcArg0RGB = CMaterial::Texture;
01130                                 env.Env.OpArg0RGB = CMaterial::SrcColor;
01131                         
01132                                 env.Env.SrcArg1RGB = CMaterial::Previous;
01133                                 env.Env.OpArg1RGB = CMaterial::SrcColor;
01134                         }
01135 
01136                         activateTexEnvMode(1, env);
01137 
01138                         // Set Stage 1
01139                         _DriverGLStates.activeTextureARB(1);
01140                         _DriverGLStates.setTextureMode(CDriverGLStates::TextureCubeMap);
01141                         _DriverGLStates.setTexGenMode (1, GL_REFLECTION_MAP_ARB);
01142                         _DriverGLStates.enableTexGen (1, true);
01143                 }
01144         }
01145 }
01146 // ***************************************************************************
01147 void                    CDriverGL::endSpecularMultiPass()
01148 {
01149         // Disable Texture coord generation.
01150         _DriverGLStates.activeTextureARB(1);
01151         _DriverGLStates.enableTexGen (1, false);
01152         //_DriverGLStates.setTextureMode(1, CDriverGLStates::TextureDisabled);
01153 
01154         // Happiness !!! we have already enabled the stage 1
01155         glMatrixMode(GL_TEXTURE);
01156         glLoadIdentity();
01157         glMatrixMode(GL_MODELVIEW);
01158 }
01159 
01160 
01161 // a functor that can is used to generate a cube map used for specular / diffuse lighting
01162 struct CSpecCubeMapFunctor : ICubeMapFunctor
01163 {
01164         CSpecCubeMapFunctor(float exp) : Exp(exp) {}
01165         virtual NLMISC::CRGBA operator()(const NLMISC::CVector &v)
01166         {
01167                 
01168                 uint8 intensity = (uint8) (255.f * ::powf(std::max(v.normed().z, 0.f), Exp));
01169                 return NLMISC::CRGBA(intensity, intensity, intensity, intensity);               
01170                 //return Exp == 1.f ? CRGBA((uint8)(v.x*127+127), (uint8)(v.y*127+127), (uint8)(v.z*127+127), 0): CRGBA::Black;
01171         }
01172         float Exp;
01173 };
01174 
01175 
01176 /* 
01177 const uint MaxSpecularExp = 64;
01178 const uint SpecularExpStep = 8;
01179 const uint SpecularMapSize = 32; */
01180 
01181 
01182 // ***************************************************************************
01183 CTextureCube    *CDriverGL::getSpecularCubeMap(uint exp)
01184 {
01185         const uint SpecularMapSize = 32;
01186         const uint SpecularMapSizeHighExponent = 64;
01187         const float HighExponent = 128.f;
01188         const uint MaxExponent = 512;
01189         // this gives the cube map to use given an exponent (from 0 to 128)
01190         static uint16 expToCubeMap[MaxExponent];        
01191         // this gives the exponent used by a given cube map (not necessarily ordered)
01192         static float cubeMapExp[] = 
01193         {
01194                 1.f, 4.f, 8.f, 24.f, 48.f, 128.f, 256.f, 511.f
01195         };
01196         const uint numCubeMap = sizeof(expToCubeMap) / sizeof(float);
01197         static bool tableBuilt = false;
01198 
01199         if (!tableBuilt)
01200         {
01201                 for (uint k = 0; k < MaxExponent; ++k)
01202                 {                       
01203                         uint nearest = 0;
01204                         float diff = (float) MaxExponent;
01205                         // look for the nearest exponent
01206                         for (uint l = 0; l < numCubeMap; ++l)
01207                         {
01208                                 float newDiff = ::fabsf(k - cubeMapExp[l]);
01209                                 if (newDiff < diff)
01210                                 {
01211                                         diff = newDiff;
01212                                         nearest = l;
01213                                 }
01214                         }
01215                         expToCubeMap[k] = nearest;
01216                 }
01217                 tableBuilt = true;              
01218         }
01219 
01220         if (_SpecularTextureCubes.empty())
01221         {
01222                 _SpecularTextureCubes.resize(MaxExponent);
01223         }
01224 
01225                 
01226         NLMISC::clamp(exp, 1u, (MaxExponent - 1));
01227 
01228 
01229         uint cubeMapIndex = expToCubeMap[(uint) exp];
01230         nlassert(cubeMapIndex < numCubeMap);    
01231         
01232         
01233         if (_SpecularTextureCubes[cubeMapIndex] != NULL) // has the cube map already been cted ?
01234         { 
01235                 return _SpecularTextureCubes[cubeMapIndex]; 
01236         }
01237         else // build the cube map
01238         {               
01239                 float exponent    = cubeMapExp[cubeMapIndex];
01240                 CSpecCubeMapFunctor scmf(exponent);
01241                 const uint bufSize = 128;
01242                 char name[bufSize];
01243                 NLMISC::smprintf(name, bufSize, "#SM%d", cubeMapIndex);
01244                 CTextureCube *tc = BuildCubeMap(exponent >= HighExponent ? SpecularMapSizeHighExponent
01245                                                                                                                                 : SpecularMapSize,
01246                                                                                 scmf,
01247                                                                                 false,
01248                                                                                 name);
01249 
01250                 static const CTextureCube::TFace numToFace[] =
01251                 { CTextureCube::positive_x,
01252                   CTextureCube::negative_x, 
01253                   CTextureCube::positive_y, 
01254                   CTextureCube::negative_y, 
01255                   CTextureCube::positive_z, 
01256                   CTextureCube::negative_z 
01257                 };
01258 
01259                 if (exponent != 1.f)
01260                 {
01261                         // force 16 bit for specular part, 32 bit if exponent is 1 (diffuse part)
01262                         for (uint k = 0; k < 6; ++k)
01263                         {
01264                                 nlassert(tc->getTexture(numToFace[k]));
01265                                 tc->getTexture(numToFace[k])->setUploadFormat(ITexture::RGB565);
01266                         }
01267                 }
01268 
01269                 _SpecularTextureCubes[cubeMapIndex] = tc;
01270                 return tc;
01271         }
01272 }
01273 
01274 // ***************************************************************************
01275 sint                    CDriverGL::beginPPLMultiPass()
01276 {
01277         #ifdef NL_DEBUG
01278                 nlassert(supportPerPixelLighting(true)); // make sure the hardware can do that
01279         #endif
01280         return 1;
01281 }
01282 
01283 // ***************************************************************************
01284 void                    CDriverGL::setupPPLPass(uint pass)
01285 {
01286         const CMaterial &mat= *_CurrentMaterial;
01287 
01288         nlassert(pass == 0);
01289 
01290 /*      ITexture *tex0 = getSpecularCubeMap(1);
01291         if (tex0) setupTexture(*tex0);
01292         activateTexture(0, tex0);
01293         
01294 
01295         static CMaterial::CTexEnv       env;
01296         env.Env.SrcArg0Alpha = CMaterial::Diffuse;              
01297         env.Env.SrcArg1Alpha = CMaterial::Constant;             
01298         env.Env.SrcArg0RGB = CMaterial::Diffuse;        
01299         env.Env.SrcArg1RGB = CMaterial::Constant;
01300         env.Env.OpRGB = CMaterial::Replace;
01301         env.Env.OpAlpha = CMaterial::Replace;
01302         activateTexEnvMode(0, env);
01303 
01304         return;*/
01305 
01306         ITexture *tex0 = getSpecularCubeMap(1); 
01307         if (tex0) setupTexture(*tex0);
01308         ITexture *tex2 = getSpecularCubeMap((uint) mat.getShininess());
01309         if (tex2) setupTexture(*tex2);
01310         if (mat.getTexture(0)) setupTexture(*mat.getTexture(0));
01311 
01312         // tex coord 0 = texture coordinates
01313         // tex coord 1 = normal in tangent space
01314         // tex coord 2 = half angle vector in tangent space
01315 
01316         activateTexture(0, tex0);
01317         activateTexture(1, mat.getTexture(0));
01318         activateTexture(2, tex2);
01319 
01320         for (uint k = 3; k < (uint) inlGetNumTextStages(); ++k)
01321         {
01322                 activateTexture(k, NULL);
01323         }
01324 
01325         // setup the tex envs
01326 
01327 
01328         // Stage 0 is rgb = DiffuseCubeMap * LightColor + DiffuseGouraud * 1 (TODO : EnvCombine3)
01329         if(_CurrentTexEnvSpecial[0] != TexEnvSpecialPPLStage0)
01330         {
01331                 // TexEnv is special.
01332                 _CurrentTexEnvSpecial[0] = TexEnvSpecialPPLStage0;
01333                 _DriverGLStates.activeTextureARB(0);
01334 
01335                 if (_Extensions.NVTextureEnvCombine4)
01336                 {               
01337                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
01338                         
01339                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);                  
01340                         // Arg0 = Diffuse read in cube map
01341                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
01342                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
01343                         // Arg1 = Light color
01344                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT);
01345                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
01346                         // Arg2 = Primary color (other light diffuse and 
01347                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR_EXT);
01348                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
01349                         // Arg3 = White (= ~ Black)
01350                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
01351                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
01352                 }
01353                 else // use ATI extension
01354                 {
01355                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
01356                         
01357                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE_ADD_ATIX);                    
01358                         // Arg0 = Diffuse read in cube map
01359                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
01360                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
01361                         // Arg1 = Light color
01362                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT);
01363                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
01364                         // Arg2 = Primary color (other light diffuse and 
01365                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
01366                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);                   
01367                 }
01368         }
01369         activateTexEnvColor(0, _PPLightDiffuseColor);
01370 
01371         // Stage 1      
01372         static CMaterial::CTexEnv       env;
01373         env.Env.SrcArg1Alpha = CMaterial::Diffuse;              
01374         activateTexEnvMode(1, env);
01375 
01376 
01377 
01378         // Stage 2 is rgb = SpecularCubeMap * SpecularLightColor + Prec * 1
01379         // alpha = prec alpha
01380         
01381         if(_CurrentTexEnvSpecial[2] != TexEnvSpecialPPLStage2)
01382         {
01383                 // TexEnv is special.
01384                 _CurrentTexEnvSpecial[2] = TexEnvSpecialPPLStage2;
01385                 _DriverGLStates.activeTextureARB(2);
01386 
01387                 if (_Extensions.NVTextureEnvCombine4)
01388                 {
01389                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);         
01390                         //== colors ==
01391                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
01392                         // Arg0 = Specular read in cube map
01393                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
01394                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
01395                         // Arg1 = Light color
01396                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT);
01397                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
01398                         // Arg2 = Primary color ( + other light diffuse )
01399                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT);
01400                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
01401                         // Arg3 = White (= ~ Black)
01402                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
01403                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
01404 
01405                         //== alpha ==
01406                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);                        
01407                         // Arg0 = PREVIOUS ALPHA
01408                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT);
01409                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_COLOR);
01410                         // Arg1 = 1
01411                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
01412                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_COLOR);
01413                         // Arg2 = 0
01414                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_ZERO);
01415                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_COLOR);
01416                         // Arg3 = 0
01417                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
01418                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_COLOR);
01419                 }
01420                 else // ATI EnvCombine3
01421                 {
01422                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);         
01423                         //== colors ==
01424                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE_ADD_ATIX);                    
01425                         // Arg0 = Specular read in cube map
01426                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
01427                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
01428                         // Arg2 = Light color
01429                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT);
01430                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
01431                         // Arg1 = Primary color ( + other light diffuse)
01432                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT);
01433                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);                   
01434 
01435                         //== alpha ==
01436                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE_ADD_ATIX);                  
01437                         // Arg0 = PREVIOUS ALPHA
01438                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT);
01439                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_COLOR);
01440                         // Arg2 = 1
01441                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_ZERO);
01442                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_ONE_MINUS_SRC_COLOR);
01443                         // Arg1 = 0
01444                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
01445                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_COLOR);
01446                 }
01447         }
01448         activateTexEnvColor(2, _PPLightSpecularColor);  
01449 
01450 }
01451 
01452 // ***************************************************************************
01453 void                    CDriverGL::endPPLMultiPass()
01454 {       
01455         // nothing to do there ...
01456 }
01457 
01458 
01459 // ******PER PIXEL LIGHTING, NO SPECULAR**************************************
01460 sint                    CDriverGL::beginPPLNoSpecMultiPass()
01461 {
01462         #ifdef NL_DEBUG
01463                 nlassert(supportPerPixelLighting(false)); // make sure the hardware can do that
01464         #endif
01465         return 1;
01466 }
01467 
01468 // ******PER PIXEL LIGHTING, NO SPECULAR**************************************
01469 void                    CDriverGL::setupPPLNoSpecPass(uint pass)
01470 {
01471         const CMaterial &mat= *_CurrentMaterial;
01472 
01473         nlassert(pass == 0);
01474 
01475         ITexture *tex0 = getSpecularCubeMap(1);
01476         if (tex0) setupTexture(*tex0);
01477         
01478         if (mat.getTexture(0)) setupTexture(*mat.getTexture(0));
01479 
01480         // tex coord 0 = texture coordinates
01481         // tex coord 1 = normal in tangent space        
01482 
01483         activateTexture(0, tex0);
01484         activateTexture(1, mat.getTexture(0));
01485 
01486 
01487         for (uint k = 2; k < (uint) inlGetNumTextStages(); ++k)
01488         {
01489                 activateTexture(k, NULL);
01490         }
01491 
01492         // setup the tex envs
01493 
01494 
01495         // Stage 0 is rgb = DiffuseCubeMap * LightColor + DiffuseGouraud * 1 (TODO : EnvCombine3)
01496         if(_CurrentTexEnvSpecial[0] != TexEnvSpecialPPLStage0)
01497         {
01498                 // TexEnv is special.
01499                 _CurrentTexEnvSpecial[0] = TexEnvSpecialPPLStage0;
01500                 _DriverGLStates.activeTextureARB(0);
01501 
01502                 if (_Extensions.NVTextureEnvCombine4)
01503                 {
01504                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
01505                         
01506                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);                  
01507                         // Arg0 = Diffuse read in cube map alpha
01508                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
01509                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
01510                         // Arg1 = Light color
01511                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT);
01512                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
01513                         // Arg2 = Primary color (other light diffuse and 
01514                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR_EXT);
01515                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
01516                         // Arg3 = White (= ~ Black)
01517                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
01518                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
01519                 }
01520                 else
01521                 {
01522                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
01523                         
01524                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE_ADD_ATIX);                    
01525                         // Arg0 = Diffuse read in cube map alpha
01526                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
01527                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
01528                         // Arg2 = Light color
01529                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT);
01530                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
01531                         // Arg1 = Primary color (other light diffuse and 
01532                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
01533                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);                   
01534                 }
01535         }
01536         activateTexEnvColor(0, _PPLightDiffuseColor);
01537 
01538         // Stage 1      
01539         static CMaterial::CTexEnv       env;
01540         env.Env.SrcArg1Alpha = CMaterial::Diffuse;              
01541         activateTexEnvMode(1, env);
01542 
01543 }
01544 
01545 // ******PER PIXEL LIGHTING, NO SPECULAR**************************************
01546 void                    CDriverGL::endPPLNoSpecMultiPass()
01547 {       
01548         // nothing to do there ...
01549 }
01550 
01551 // ***************************************************************************
01552 /* sint         CDriverGL::beginCausticsMultiPass(const CMaterial &mat)
01553 {
01554         nlassert(mat.getShader() == CMaterial::Caustics);
01555         if (!_Extensions.ARBTextureCubeMap) return 1;
01556         switch (inlGetNumTextStages())
01557         {
01558                 case 1: return 3;
01559                 case 2: return 2;
01560                 default:
01561                                 return 1;
01562         }
01563 }*/
01564 
01565 
01566 // ***************************************************************************
01567 /*inline void           CDriverGL::setupCausticsFirstTex(const CMaterial &mat)
01568 {
01570         activateTexture(0, mat.getTexture(0));
01571 
01573         setTextureEnvFunction(0, mat);
01574 
01576         setupUserTextureMatrix(0, mat);
01577 }
01578 
01579 // ***************************************************************************
01580 inline void             CDriverGL::setupCausticsSecondTex(uint stage)
01581 {
01582         activateTexture(stage, mat.getTexture(0));
01583         _CausticCubeMap
01584 }
01585 
01586 // ***************************************************************************
01587 void            CDriverGL::setupCausticsPass(const CMaterial &mat, uint pass)
01588 {
01589         
01590         nlassert(mat.getShader() == CMaterial::Caustics);
01591 
01592         if (inlGetNumTextStages() == 1 || !_Extensions.ARBTextureCubeMap)
01593         {
01594                 setupCausticsFirstTex(mat);
01595         }
01596         else
01597         if (inlGetNumTextStages() >= 3) 
01598         {
01599                 nlassert(pass == 0);            
01600 
01601                 setupCausticsFirstTex(mat);
01602                 
01603 
01604         }
01605         else if (inlGetNumTextStages() == 2) 
01606         {
01607                 nlassert(pass < 2);
01608                 if (pass == 0) 
01609                 {
01610                         setupCausticsFirstTex(mat);     
01611                 }
01612                 else 
01613                 {
01615                         _DriverGLStates.enableBlend();                  
01616                         _DriverGLStates.blendFunc(pShader->SrcBlend, pShader->DstBlend);
01617 
01618 
01619                 }
01620         }
01621 }
01622 
01623 // ***************************************************************************
01624 void            CDriverGL::endCausticsMultiPass(const CMaterial &mat)
01625 {
01626         nlassert(mat.getShader() == CMaterial::Caustics);       
01627 
01628 }
01629 */
01630 
01632 
01633 // ***************************************************************************
01634 sint            CDriverGL::beginCloudMultiPass ()
01635 {
01636         nlassert(_CurrentMaterial->getShader() == CMaterial::Cloud);
01637         return 1;
01638 }
01639 
01640 // ***************************************************************************
01641 void            CDriverGL::setupCloudPass (uint pass)
01642 {
01643         nlassert(_CurrentMaterial->getShader() == CMaterial::Cloud);
01644 
01645         const CMaterial &mat= *_CurrentMaterial;
01646         
01647         activateTexture(0, mat.getTexture(0));
01648         activateTexture(1, mat.getTexture(0));
01649 
01650         if (_CurrentTexEnvSpecial[0] != TexEnvSpecialCloudStage0)
01651         {
01652                 _CurrentTexEnvSpecial[0] = TexEnvSpecialCloudStage0;
01653                 _CurrentTexEnvSpecial[1] = TexEnvSpecialCloudStage1;
01654 
01655                 if (_Extensions.NVTextureEnvCombine4)
01656                 {
01657                         // Setup 1st Stage
01658                         _DriverGLStates.activeTextureARB(0);
01659                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);         
01660                         //== colors ==
01661                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
01662                         // Arg0 = 0
01663                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_ZERO);
01664                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
01665                         // Arg1 = 0
01666                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_ZERO);
01667                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
01668                         // Arg2 = 0
01669                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_ZERO);
01670                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
01671                         // Arg3 = 0
01672                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
01673                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
01674 
01675                         //== alpha ==
01676                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
01677                         // Arg0 = AT0
01678                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE0_ARB);
01679                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
01680                         // Arg1 = AWPOS
01681                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
01682                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA);
01683                         // Arg2 = AT1
01684                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_TEXTURE1_ARB);
01685                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
01686                         // Arg3 = 1-AWPOS
01687                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_PRIMARY_COLOR_EXT);
01688                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
01689 
01690                         // Setup 2nd Stage
01691                         _DriverGLStates.activeTextureARB(1);
01692                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);         
01693                         //== colors ==
01694                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
01695                         // Arg0 = 0
01696                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_ZERO);
01697                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
01698                         // Arg1 = 0
01699                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_ZERO);
01700                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
01701                         // Arg2 = 0
01702                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_ZERO);
01703                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
01704                         // Arg3 = 0
01705                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
01706                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
01707 
01708                         //== alpha ==
01709                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
01710                         // Arg0 = AT0*AWPOS+AT1*(1-AWPOS)
01711                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT);
01712                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
01713                         // Arg1 = AINT
01714                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_CONSTANT_EXT);
01715                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA);
01716                         // Arg2 = 0
01717                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_ZERO);
01718                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
01719                         // Arg3 = 0
01720                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
01721                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
01722 
01723                 }
01724                 else // ATI EnvCombine3
01725                 {
01726                         /*glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);               
01727                         //== colors ==
01728                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE_ADD_ATIX);                    
01729                         // Arg0 = Specular read in cube map
01730                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
01731                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
01732                         // Arg2 = Light color
01733                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT);
01734                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
01735                         // Arg1 = Primary color ( + other light diffuse)
01736                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT);
01737                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);                   
01738 
01739                         //== alpha ==
01740                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE_ADD_ATIX);                  
01741                         // Arg0 = PREVIOUS ALPHA
01742                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT);
01743                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_COLOR);
01744                         // Arg2 = 1
01745                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_ZERO);
01746                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_ONE_MINUS_SRC_COLOR);
01747                         // Arg1 = 0
01748                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
01749                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_COLOR);*/
01750                 }
01751         }
01752         activateTexEnvColor (1, mat.getColor());
01753 }
01754 
01755 // ***************************************************************************
01756 void            CDriverGL::endCloudMultiPass()
01757 {
01758         nlassert(_CurrentMaterial->getShader() == CMaterial::Cloud);
01759 }
01760 
01761 } // NL3D