1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdopengl.h"
21 #include "driver_opengl.h"
22 #include "nel/3d/cube_map_builder.h"
23 #include "nel/3d/texture_mem.h"
24 #include "nel/3d/texture_bump.h"
25 #include "nel/3d/material.h"
35 namespace NLDRIVERGLES
{
37 namespace NLDRIVERGL
{
41 static void convBlend(CMaterial::TBlend blend
, GLenum
& glenum
)
46 case CMaterial::one
: glenum
=GL_ONE
; break;
47 case CMaterial::zero
: glenum
=GL_ZERO
; break;
48 case CMaterial::srcalpha
: glenum
=GL_SRC_ALPHA
; break;
49 case CMaterial::invsrcalpha
:glenum
=GL_ONE_MINUS_SRC_ALPHA
; break;
50 case CMaterial::srccolor
: glenum
=GL_SRC_COLOR
; break;
51 case CMaterial::invsrccolor
:glenum
=GL_ONE_MINUS_SRC_COLOR
; break;
52 // Extended Blend modes.
54 case CMaterial::blendConstantColor
: glenum
=GL_CONSTANT_COLOR_EXT
; break;
55 case CMaterial::blendConstantInvColor
: glenum
=GL_ONE_MINUS_CONSTANT_COLOR_EXT
; break;
56 case CMaterial::blendConstantAlpha
: glenum
=GL_CONSTANT_ALPHA_EXT
; break;
57 case CMaterial::blendConstantInvAlpha
: glenum
=GL_ONE_MINUS_CONSTANT_ALPHA_EXT
; break;
64 static void convZFunction(CMaterial::ZFunc zfunc
, GLenum
& glenum
)
66 H_AUTO_OGL(convZFunction
)
69 case CMaterial::lessequal
: glenum
=GL_LEQUAL
; break;
70 case CMaterial::less
: glenum
=GL_LESS
; break;
71 case CMaterial::always
: glenum
=GL_ALWAYS
; break;
72 case CMaterial::never
: glenum
=GL_NEVER
; break;
73 case CMaterial::equal
: glenum
=GL_EQUAL
; break;
74 case CMaterial::notequal
: glenum
=GL_NOTEQUAL
; break;
75 case CMaterial::greater
: glenum
=GL_GREATER
; break;
76 case CMaterial::greaterequal
: glenum
=GL_GEQUAL
; break;
81 static void convColor(CRGBA col
, GLfloat glcol
[4])
84 static const float OO255
= 1.0f
/255;
85 glcol
[0]= col
.R
*OO255
;
86 glcol
[1]= col
.G
*OO255
;
87 glcol
[2]= col
.B
*OO255
;
88 glcol
[3]= col
.A
*OO255
;
91 static inline void convTexAddr(ITexture
*tex
, CMaterial::TTexAddressingMode mode
, GLenum
&glenum
)
93 H_AUTO_OGL(convTexAddr
)
94 nlassert(mode
< CMaterial::TexAddrCount
);
95 static const GLenum glTex2dAddrModesNV
[] =
97 GL_NONE
, GL_TEXTURE_2D
,
99 GL_PASS_THROUGH_NV
, GL_CULL_FRAGMENT_NV
,
100 GL_OFFSET_TEXTURE_2D_NV
, GL_OFFSET_TEXTURE_2D_SCALE_NV
,
101 GL_DEPENDENT_AR_TEXTURE_2D_NV
, GL_DEPENDENT_GB_TEXTURE_2D_NV
,
102 GL_DOT_PRODUCT_NV
, GL_DOT_PRODUCT_TEXTURE_2D_NV
, GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV
,
103 GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV
, GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV
,
104 GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV
, GL_DOT_PRODUCT_DEPTH_REPLACE_NV
108 static const GLenum glTexCubeAddrModesNV
[] =
110 GL_NONE
, GL_TEXTURE_CUBE_MAP_ARB
,
112 GL_PASS_THROUGH_NV
, GL_CULL_FRAGMENT_NV
,
113 GL_OFFSET_TEXTURE_2D_NV
, GL_OFFSET_TEXTURE_2D_SCALE_NV
,
114 GL_DEPENDENT_AR_TEXTURE_2D_NV
, GL_DEPENDENT_GB_TEXTURE_2D_NV
,
115 GL_DOT_PRODUCT_NV
, GL_DOT_PRODUCT_TEXTURE_2D_NV
, GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV
,
116 GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV
, GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV
,
117 GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV
, GL_DOT_PRODUCT_DEPTH_REPLACE_NV
121 if (!tex
|| !tex
->isTextureCube())
123 glenum
= glTex2dAddrModesNV
[(uint
) mode
];
127 glenum
= glTexCubeAddrModesNV
[(uint
) mode
];
131 // --------------------------------------------------
132 void CDriverGL::setTextureEnvFunction(uint stage
, CMaterial
& mat
)
134 H_AUTO_OGL(CDriverGL_setTextureEnvFunction
)
135 ITexture
*text
= mat
.getTexture(uint8(stage
));
138 CMaterial::CTexEnv
&env
= mat
._TexEnvs
[stage
];
140 // Activate the env for this stage.
141 // NB: Thoses calls use caching.
142 activateTexEnvMode(stage
, env
);
143 activateTexEnvColor(stage
, env
);
145 // Activate texture generation mapping
146 _DriverGLStates
.activeTextureARB(stage
);
147 if (mat
.getTexCoordGen (stage
))
149 // set mode and enable.
150 CMaterial::TTexCoordGenMode mode
= mat
.getTexCoordGenMode(stage
);
151 if(mode
==CMaterial::TexCoordGenReflect
)
154 if (text
->isTextureCube ())
155 _DriverGLStates
.setTexGenMode (stage
, GL_REFLECTION_MAP_ARB
);
158 _DriverGLStates
.setTexGenMode (stage
, GL_TEXTURE_CUBE_MAP_OES
);
160 _DriverGLStates
.setTexGenMode (stage
, GL_SPHERE_MAP
);
163 else if(mode
==CMaterial::TexCoordGenObjectSpace
)
166 _DriverGLStates
.setTexGenMode (stage
, GL_NORMAL_MAP_OES
);
168 _DriverGLStates
.setTexGenMode (stage
, GL_OBJECT_LINEAR
);
171 else if(mode
==CMaterial::TexCoordGenEyeSpace
)
174 _DriverGLStates
.setTexGenMode (stage
, GL_NORMAL_MAP_OES
);
176 _DriverGLStates
.setTexGenMode (stage
, GL_EYE_LINEAR
);
183 _DriverGLStates
.setTexGenMode(stage
, 0);
188 //--------------------------------
189 void CDriverGL::setupUserTextureMatrix(uint numStages
, CMaterial
& mat
)
191 H_AUTO_OGL(CDriverGL_setupUserTextureMatrix
)
193 (_UserTexMatEnabled
!= 0 && (mat
.getFlags() & IDRV_MAT_USER_TEX_MAT_ALL
) == 0)
194 || (mat
.getFlags() & IDRV_MAT_USER_TEX_MAT_ALL
) != 0
197 glMatrixMode(GL_TEXTURE
);
199 // for each stage, setup the texture matrix if needed
200 uint newMask
= (mat
.getFlags() & IDRV_MAT_USER_TEX_MAT_ALL
) >> IDRV_MAT_USER_TEX_FIRST_BIT
;
202 for (uint k
= 0; k
< numStages
; ++k
)
204 if (newMask
& shiftMask
) // user matrix for this stage
206 _DriverGLStates
.activeTextureARB(k
);
207 glLoadMatrixf(mat
.getUserTexMat(k
).get());
209 _UserTexMatEnabled
|= shiftMask
;
213 /// check if matrix disabled
215 (newMask
& shiftMask
) != (_UserTexMatEnabled
& shiftMask
)
218 _DriverGLStates
.activeTextureARB(k
);
221 _UserTexMatEnabled
&= ~shiftMask
;
226 glMatrixMode(GL_MODELVIEW
);
230 void CDriverGL::disableUserTextureMatrix()
232 H_AUTO_OGL(CDriverGL_disableUserTextureMatrix
)
233 if (_UserTexMatEnabled
!= 0)
235 glMatrixMode(GL_TEXTURE
);
240 if (_UserTexMatEnabled
& (1 << k
)) // user matrix for this stage
242 _DriverGLStates
.activeTextureARB(k
);
245 _UserTexMatEnabled
&= ~ (1 << k
);
249 while (_UserTexMatEnabled
!= 0);
250 glMatrixMode(GL_MODELVIEW
);
254 // --------------------------------------------------
255 CMaterial::TShader
CDriverGL::getSupportedShader(CMaterial::TShader shader
)
257 H_AUTO_OGL(CDriverGL_CDriverGL
)
260 case CMaterial::PerPixelLighting
: return _SupportPerPixelShader
? CMaterial::PerPixelLighting
: CMaterial::Normal
;
261 case CMaterial::PerPixelLightingNoSpec
: return _SupportPerPixelShaderNoSpec
? CMaterial::PerPixelLightingNoSpec
: CMaterial::Normal
;
262 // Lightmap and Specular work only if at least 2 text stages.
263 case CMaterial::LightMap
: return (inlGetNumTextStages()>=2) ? CMaterial::LightMap
: CMaterial::Normal
;
264 case CMaterial::Specular
: return (inlGetNumTextStages()>=2) ? CMaterial::Specular
: CMaterial::Normal
;
265 default: return shader
;
269 // --------------------------------------------------
270 void CDriverGL::setTextureShaders(const uint8
*addressingModes
, const CSmartPtr
<ITexture
> *textures
)
272 H_AUTO_OGL(CDriverGL_setTextureShaders
)
274 for (uint stage
= 0; stage
< IDRV_MAT_MAXTEXTURES
; ++stage
)
276 convTexAddr(textures
[stage
], (CMaterial::TTexAddressingMode
) addressingModes
[stage
], glAddrMode
);
278 if (glAddrMode
!= _CurrentTexAddrMode
[stage
]) // addressing mode different from the one in the device?
280 _DriverGLStates
.activeTextureARB(stage
);
282 glTexEnvi(GL_TEXTURE_SHADER_NV
, GL_SHADER_OPERATION_NV
, glAddrMode
);
284 _CurrentTexAddrMode
[stage
] = glAddrMode
;
289 // --------------------------------------------------
290 bool CDriverGL::setupMaterial(CMaterial
& mat
)
292 H_AUTO_OGL(CDriverGL_setupMaterial
)
295 _NbSetupMaterialCall
++;
297 CMaterial::TShader matShader
;
300 GLenum glenum
= GL_ZERO
;
301 uint32 touched
= mat
.getTouched();
303 // 0. Retrieve/Create driver shader.
304 //==================================
305 if (!mat
._MatDrvInfo
)
307 // insert into driver list. (so it is deleted when driver is deleted).
308 ItMatDrvInfoPtrList it
= _MatDrvInfos
.insert(_MatDrvInfos
.end(), (NL3D::IMaterialDrvInfos
*)NULL
);
309 // create and set iterator, for future deletion.
310 *it
= mat
._MatDrvInfo
= new CShaderGL(this, it
);
312 // Must create all OpenGL shader states.
313 touched
= IDRV_TOUCHED_ALL
;
315 pShader
=static_cast<CShaderGL
*>((IMaterialDrvInfos
*)(mat
._MatDrvInfo
));
317 // 1. Setup modified fields of material.
318 //=====================================
321 /* Exception: if only Textures are modified in the material, no need to "Bind OpenGL States", or even to test
322 for change, because textures are activated alone, see below.
323 No problem with delete/new problem (see below), because in this case, IDRV_TOUCHED_ALL is set (see above).
325 // If any flag is set (but a flag of texture)
326 if( touched
& (~_MaterialAllTextureTouchedFlag
) )
328 // Convert Material to driver shader.
329 if (touched
& IDRV_TOUCHED_BLENDFUNC
)
331 convBlend( mat
.getSrcBlend(),glenum
);
332 pShader
->SrcBlend
=glenum
;
333 convBlend( mat
.getDstBlend(),glenum
);
334 pShader
->DstBlend
=glenum
;
336 if (touched
& IDRV_TOUCHED_ZFUNC
)
338 convZFunction( mat
.getZFunc(),glenum
);
339 pShader
->ZComp
= glenum
;
341 if (touched
& IDRV_TOUCHED_LIGHTING
)
343 convColor(mat
.getEmissive(), pShader
->Emissive
);
344 convColor(mat
.getAmbient(), pShader
->Ambient
);
345 convColor(mat
.getDiffuse(), pShader
->Diffuse
);
346 convColor(mat
.getSpecular(), pShader
->Specular
);
347 pShader
->PackedEmissive
= mat
.getEmissive().getPacked();
348 pShader
->PackedAmbient
= mat
.getAmbient().getPacked();
349 pShader
->PackedDiffuse
= mat
.getDiffuse().getPacked();
350 pShader
->PackedSpecular
= mat
.getSpecular().getPacked();
352 if (touched
& IDRV_TOUCHED_SHADER
)
354 // Get shader. Fallback to other shader if not supported.
355 pShader
->SupportedShader
= getSupportedShader(mat
.getShader());
358 // Since modified, must rebind all openGL states. And do this also for the delete/new problem.
359 /* If an old material is deleted, _CurrentMaterial is invalid. But this is grave only if a new
360 material is created, with the same pointer (bad luck). Since an newly allocated material always
361 pass here before use, we are sure to avoid any problems.
363 _CurrentMaterial
= NULL
;
366 // Optimize: reset all flags at the end.
367 mat
.clearTouched(0xFFFFFFFF);
370 // 2b. User supplied pixel shader overrides material
371 //==================================
372 /*if (_VertexProgramEnabled)
374 if (!setUniformDriver(VertexProgram)) return false;
375 if (!setUniformMaterialInternal(VertexProgram, mat)) return false;
377 if (_PixelProgramEnabled
)
379 matShader
= CMaterial::Program
;
381 // if (!setUniformDriver(PixelProgram)) return false;
382 // if (!setUniformMaterialInternal(PixelProgram, mat)) return false;
383 if (!_LastSetuppedPP
) return false;
387 // Now we can get the supported shader from the cache.
388 matShader
= pShader
->SupportedShader
;
391 // 2b. Update more shader state
392 //==================================
393 // if the shader has changed since last time
394 if(matShader
!= _CurrentMaterialSupportedShader
)
396 // if old was lightmap, restore standard lighting
397 if(_CurrentMaterialSupportedShader
==CMaterial::LightMap
)
398 setupLightMapDynamicLighting(false);
400 // if new is lightmap, setup dynamic lighting
401 if(matShader
==CMaterial::LightMap
)
402 setupLightMapDynamicLighting(true);
406 _CurrentMaterialSupportedShader
= matShader
;
408 // 2. Setup / Bind Textures.
409 //==========================
410 // Must setup textures each frame. (need to test if touched).
411 // Must separate texture setup and texture activation in 2 "for"...
412 // because setupTexture() may disable all stage.
413 if (matShader
!= CMaterial::Water
414 && ((matShader
!= CMaterial::Program
) || (_LastSetuppedPP
->features().MaterialFlags
& CProgramFeatures::TextureStages
))
417 for (uint stage
= 0; stage
< inlGetNumTextStages(); ++stage
)
419 ITexture
*text
= mat
.getTexture(uint8(stage
));
420 if (text
!= NULL
&& !setupTexture(*text
))
424 // Here, for Lightmap materials, setup the lightmaps.
425 if(matShader
== CMaterial::LightMap
)
427 for (uint stage
= 0; stage
< mat
._LightMaps
.size(); ++stage
)
429 ITexture
*text
= mat
._LightMaps
[stage
].Texture
;
430 if (text
!= NULL
&& !setupTexture(*text
))
435 // Here, for caustic shader, setup the lightmaps
436 /*if (matShader == CMaterial::Caustics)
438 if (mat.getTexture(stage))
441 // Activate the textures.
442 // Do not do it for Lightmap and per pixel lighting , because done in multipass in a very special fashion.
443 // This avoid the useless multiple change of texture states per lightmapped object.
444 // Don't do it also for Specular because the EnvFunction and the TexGen may be special.
445 if(matShader
!= CMaterial::LightMap
446 && matShader
!= CMaterial::PerPixelLighting
447 /* && matShader != CMaterial::Caustics */
448 && matShader
!= CMaterial::Cloud
449 && matShader
!= CMaterial::Water
450 && matShader
!= CMaterial::Specular
451 && ((matShader
!= CMaterial::Program
) || (_LastSetuppedPP
->features().MaterialFlags
& CProgramFeatures::TextureStages
))
454 for(uint stage
=0 ; stage
<inlGetNumTextStages() ; stage
++)
456 ITexture
*text
= mat
.getTexture(uint8(stage
));
458 // activate the texture, or disable texturing if NULL.
459 activateTexture(stage
,text
);
461 // If texture not NULL, Change texture env function.
462 //==================================================
463 setTextureEnvFunction(stage
, mat
);
467 // 3. Bind OpenGL States.
468 //=======================
469 if (_CurrentMaterial
!=&mat
)
473 bool blend
= (mat
.getFlags()&IDRV_MAT_BLEND
)!=0;
474 _DriverGLStates
.enableBlend(blend
);
476 _DriverGLStates
.blendFunc(pShader
->SrcBlend
, pShader
->DstBlend
);
478 // Double Sided Part.
479 //===================
480 // NB: inverse state: DoubleSided <=> !CullFace.
481 uint32 twoSided
= mat
.getFlags()&IDRV_MAT_DOUBLE_SIDED
;
482 _DriverGLStates
.enableCullFace( twoSided
==0 );
487 uint32 alphaTest
= mat
.getFlags()&IDRV_MAT_ALPHA_TEST
;
488 _DriverGLStates
.enableAlphaTest(alphaTest
);
491 // setup alphaTest threshold.
492 _DriverGLStates
.alphaFunc(mat
.getAlphaTestThreshold());
495 // Bind ZBuffer Part.
496 //===================
497 _DriverGLStates
.enableZWrite(mat
.getFlags()&IDRV_MAT_ZWRITE
);
498 _DriverGLStates
.depthFunc(pShader
->ZComp
);
499 _DriverGLStates
.setZBias (mat
.getZBias () * _OODeltaZ
);
501 // Bind Stencil Buffer Part.
502 //===================
504 _DriverGLStates.enableStencilTest();
505 _DriverGLStates.stencilFunc();
506 _DriverGLStates.stencilOp();
509 // Color-Lighting Part.
510 //=====================
513 _DriverGLStates
.enableLighting(mat
.getFlags()&IDRV_MAT_LIGHTING
);
514 if(mat
.getFlags()&IDRV_MAT_LIGHTING
)
516 _DriverGLStates
.setEmissive(pShader
->PackedEmissive
, pShader
->Emissive
);
517 _DriverGLStates
.setAmbient(pShader
->PackedAmbient
, pShader
->Ambient
);
518 _DriverGLStates
.setDiffuse(pShader
->PackedDiffuse
, pShader
->Diffuse
);
519 _DriverGLStates
.setSpecular(pShader
->PackedSpecular
, pShader
->Specular
);
520 _DriverGLStates
.setShininess(mat
.getShininess());
521 _DriverGLStates
.setVertexColorLighted(mat
.isLightedVertexColor ());
526 CRGBA col
= mat
.getColor();
527 glColor4ub(col
.R
, col
.G
, col
.B
, col
.A
);
529 _DriverGLStates
.setVertexColorLighted(false);
535 // Disable fog if dest blend is ONE
536 if (blend
&& (pShader
->DstBlend
== GL_ONE
))
538 _DriverGLStates
.enableFog(false);
542 // Restore fog state to its current value
543 _DriverGLStates
.enableFog(_FogEnabled
);
546 // Texture shader part.
547 //=====================
549 if (_Extensions
.NVTextureShader
)
551 if (matShader
== CMaterial::Normal
)
553 // Texture addressing modes (support only via NVTextureShader for now)
554 //===================================================================
555 if ( mat
.getFlags() & IDRV_MAT_TEX_ADDR
)
557 enableNVTextureShader(true);
558 setTextureShaders(&mat
._TexAddrMode
[0], &mat
._Textures
[0]);
562 enableNVTextureShader(false);
567 enableNVTextureShader(false);
571 _CurrentMaterial
=&mat
;
575 //=====================================
577 // If !lightMap and prec material was lihgtmap => vertex setup is dirty!
578 if( matShader
!= CMaterial::LightMap
&& _LastVertexSetupIsLightMap
)
579 resetLightMapVertexSetup();
581 // Textures user matrix
582 if (matShader
== CMaterial::Normal
583 || ((matShader
== CMaterial::Program
) && (_LastSetuppedPP
->features().MaterialFlags
& CProgramFeatures::TextureMatrices
))
586 setupUserTextureMatrix(inlGetNumTextStages(), mat
);
590 disableUserTextureMatrix();
596 // ***************************************************************************
597 sint
CDriverGL::beginMultiPass()
599 H_AUTO_OGL(CDriverGL_beginMultiPass
)
600 // Depending on material type and hardware, return number of pass required to draw this material.
601 switch(_CurrentMaterialSupportedShader
)
603 case CMaterial::LightMap
:
604 return beginLightMapMultiPass();
605 case CMaterial::Specular
:
606 return beginSpecularMultiPass();
607 case CMaterial::Water
:
608 return beginWaterMultiPass();
609 case CMaterial::PerPixelLighting
:
610 return beginPPLMultiPass();
611 case CMaterial::PerPixelLightingNoSpec
:
612 return beginPPLNoSpecMultiPass();
613 /* case CMaterial::Caustics:
614 return beginCausticsMultiPass(); */
615 case CMaterial::Cloud
:
616 return beginCloudMultiPass();
618 // All others materials require just 1 pass.
623 // ***************************************************************************
624 void CDriverGL::setupPass(uint pass
)
626 H_AUTO_OGL(CDriverGL_setupPass
)
627 switch(_CurrentMaterialSupportedShader
)
629 case CMaterial::LightMap
:
630 setupLightMapPass (pass
);
632 case CMaterial::Specular
:
633 setupSpecularPass (pass
);
635 case CMaterial::Water
:
636 setupWaterPass(pass
);
638 case CMaterial::PerPixelLighting
:
641 case CMaterial::PerPixelLightingNoSpec
:
642 setupPPLNoSpecPass (pass
);
644 /* case CMaterial::Caustics:
645 case CMaterial::Caustics:
647 case CMaterial::Cloud
:
648 setupCloudPass (pass
);
651 // All others materials do not require multi pass.
656 // ***************************************************************************
657 void CDriverGL::endMultiPass()
659 H_AUTO_OGL(CDriverGL_endMultiPass
)
660 switch(_CurrentMaterialSupportedShader
)
662 case CMaterial::LightMap
:
663 endLightMapMultiPass();
665 case CMaterial::Specular
:
666 endSpecularMultiPass();
668 case CMaterial::Water
:
671 case CMaterial::PerPixelLighting
:
674 case CMaterial::PerPixelLightingNoSpec
:
675 endPPLNoSpecMultiPass();
677 /* case CMaterial::Caustics:
678 endCausticsMultiPass();
680 case CMaterial::Cloud
:
683 // All others materials do not require multi pass.
688 // ***************************************************************************
689 void CDriverGL::computeLightMapInfos (const CMaterial
&mat
)
691 H_AUTO_OGL(CDriverGL_computeLightMapInfos
)
692 static const uint32 RGBMaskPacked
= CRGBA(255,255,255,0).getPacked();
694 // For optimisation consideration, suppose there is not too much lightmap.
695 nlassert(mat
._LightMaps
.size()<=NL3D_DRV_MAX_LIGHTMAP
);
697 // Compute number of lightmaps really used (ie factor not NULL), and build the LUT.
699 // For all lightmaps of the material.
700 for (uint i
= 0; i
< mat
._LightMaps
.size(); ++i
)
702 // If the lightmap's factor is not null.
703 if (mat
._LightMaps
[i
].Factor
.getPacked() & RGBMaskPacked
)
705 _LightMapLUT
[_NLightMaps
] = i
;
710 // Compute how many pass, according to driver caps.
711 _NLightMapPerPass
= inlGetNumTextStages()-1;
712 // Can do more than 2 texture stages only if NVTextureEnvCombine4 or ATITextureEnvCombine3
713 if (!_Extensions
.NVTextureEnvCombine4
&& !_Extensions
.ATITextureEnvCombine3
)
715 _NLightMapPerPass
= 1;
716 _LightMapNoMulAddFallBack
= true;
720 _LightMapNoMulAddFallBack
= false;
724 _NLightMapPass
= (_NLightMaps
+ _NLightMapPerPass
-1)/(_NLightMapPerPass
);
726 // NB: _NLightMaps==0 means there is no lightmaps at all.
729 // ***************************************************************************
730 sint
CDriverGL::beginLightMapMultiPass ()
732 H_AUTO_OGL(CDriverGL_beginLightMapMultiPass
)
733 const CMaterial
&mat
= *_CurrentMaterial
;
735 // compute how many lightmap and pass we must process.
736 computeLightMapInfos (mat
);
738 // always enable lighting for lightmap (because of dynamic light)
739 _DriverGLStates
.enableLighting(true);
741 // if the dynamic lightmap light has changed since the last render (should not happen), resetup
742 // normal way is that setupLightMapDynamicLighting() is called in setupMaterial() if shader different from prec
743 if(_LightMapDynamicLightDirty
)
744 setupLightMapDynamicLighting(true);
746 // reset Ambient and specular lighting
747 static uint32 packedColorBlack
= CRGBA(0,0,0,255).getPacked();
748 static GLfloat glcolBlack
[4]= {0,0,0,1};
749 // lightmap get no specular/ambient. Emissive and Diffuse are setuped in setupLightMapPass()
750 _DriverGLStates
.setAmbient(packedColorBlack
, glcolBlack
);
751 _DriverGLStates
.setSpecular(packedColorBlack
, glcolBlack
);
753 // reset VertexColor array if necessary.
754 if (_LastVB
.VertexFormat
& CVertexBuffer::PrimaryColorFlag
)
755 _DriverGLStates
.enableColorArray(false);
757 // Manage too if no lightmaps.
758 return std::max (_NLightMapPass
, (uint
)1);
761 // ***************************************************************************
762 void CDriverGL::setupLightMapPass(uint pass
)
764 H_AUTO_OGL(CDriverGL_setupLightMapPass
)
765 const CMaterial
&mat
= *_CurrentMaterial
;
768 static uint32 packedColorBlack
= CRGBA(0,0,0,255).getPacked();
769 static GLfloat glcolBlack
[4]= {0.f
,0.f
,0.f
,1.f
};
770 static uint32 packedColorWhite
= CRGBA(255,255,255,255).getPacked();
771 static GLfloat glcolWhite
[4]= {1.f
,1.f
,1.f
,1.f
};
772 static uint32 packedColorGrey
= CRGBA(128,128,128,128).getPacked();
773 static GLfloat glcolGrey
[4]= {0.5f
,0.5f
,0.5f
,1.f
};
775 // No lightmap or all blacks??, just setup "black texture" for stage 0.
778 ITexture
*text
= mat
.getTexture(0);
779 activateTexture(0,text
);
781 // setup std modulate env
782 CMaterial::CTexEnv env
;
783 activateTexEnvMode(0, env
);
785 // Since Lighting is disabled, as well as colorArray, must setup alpha.
786 // setup color to 0 => blackness. in emissive cause texture can still be lighted by dynamic light
787 _DriverGLStates
.setEmissive(packedColorBlack
, glcolBlack
);
790 _DriverGLStates
.activeTextureARB(0);
791 _DriverGLStates
.setTexGenMode(0, 0);
793 // And disable other stages.
794 for(uint stage
= 1; stage
< inlGetNumTextStages(); stage
++)
796 // disable texturing.
797 activateTexture(stage
, NULL
);
803 nlassert(pass
<_NLightMapPass
);
805 // setup Texture Pass.
806 //=========================
809 lmapId
= pass
* _NLightMapPerPass
; // Nb lightmaps already processed
810 // N lightmaps for this pass, plus the texture.
811 nstages
= std::min(_NLightMapPerPass
, _NLightMaps
-lmapId
) + 1;
813 // For LMC (lightmap 8Bit compression) compute the total AmbientColor in vertex diffuse
814 // need only if standard MulADD version
815 if (!_LightMapNoMulAddFallBack
)
820 // sum only the ambient of lightmaps that will be drawn this pass
821 for(uint sa
=0;sa
<nstages
-1;sa
++)
823 uint wla
= _LightMapLUT
[lmapId
+sa
];
824 // must mul them by their respective mapFactor too
825 CRGBA ambFactor
= mat
._LightMaps
[wla
].Factor
;
826 CRGBA lmcAmb
= mat
._LightMaps
[wla
].LMCAmbient
;
827 r
+= ((uint32
)ambFactor
.R
* ((uint32
)lmcAmb
.R
+(lmcAmb
.R
>>7))) >>8;
828 g
+= ((uint32
)ambFactor
.G
* ((uint32
)lmcAmb
.G
+(lmcAmb
.G
>>7))) >>8;
829 b
+= ((uint32
)ambFactor
.B
* ((uint32
)lmcAmb
.B
+(lmcAmb
.B
>>7))) >>8;
831 r
= std::min(r
, (uint32
)255);
832 g
= std::min(g
, (uint32
)255);
833 b
= std::min(b
, (uint32
)255);
835 // this color will be added to the first lightmap (with help of emissive)
836 CRGBA
col((uint8
)r
,(uint8
)g
,(uint8
)b
,255);
838 convColor(col
, glcol
);
839 _DriverGLStates
.setEmissive(col
.getPacked(), glcol
);
843 for(uint stage
= 0; stage
<inlGetNumTextStages(); stage
++)
845 // if must setup a lightmap stage.
849 uint whichLightMap
= _LightMapLUT
[lmapId
];
850 // get text and factor.
851 ITexture
*text
= mat
._LightMaps
[whichLightMap
].Texture
;
852 CRGBA lmapFactor
= mat
._LightMaps
[whichLightMap
].Factor
;
853 // Modulate the factor with LightMap compression Diffuse
854 CRGBA lmcDiff
= mat
._LightMaps
[whichLightMap
].LMCDiffuse
;
855 // FallBack if the (very common) extension for MulADD was not found
856 if(_LightMapNoMulAddFallBack
)
858 lmcDiff
.addRGBOnly(lmcDiff
, mat
._LightMaps
[whichLightMap
].LMCAmbient
);
860 lmapFactor
.R
= (uint8
)(((uint32
)lmapFactor
.R
* ((uint32
)lmcDiff
.R
+(lmcDiff
.R
>>7))) >>8);
861 lmapFactor
.G
= (uint8
)(((uint32
)lmapFactor
.G
* ((uint32
)lmcDiff
.G
+(lmcDiff
.G
>>7))) >>8);
862 lmapFactor
.B
= (uint8
)(((uint32
)lmapFactor
.B
* ((uint32
)lmcDiff
.B
+(lmcDiff
.B
>>7))) >>8);
865 activateTexture(stage
,text
);
867 // If texture not NULL, Change texture env fonction.
868 //==================================================
871 static CMaterial::CTexEnv stdEnv
;
873 // fallBack if extension MulAdd not found. just mul factor with (Ambient+Diffuse)
874 if(_LightMapNoMulAddFallBack
)
876 // do not use constant color to blend lightmap, but incoming diffuse color, for stage0 only.
878 convColor(lmapFactor
, glcol
);
879 _DriverGLStates
.setEmissive(lmapFactor
.getPacked(), glcol
);
881 // Leave stage as default env (Modulate with previous)
882 activateTexEnvMode(stage
, stdEnv
);
885 _DriverGLStates
.activeTextureARB(stage
);
886 _DriverGLStates
.setTexGenMode(stage
, 0);
890 // Here, we are sure that texEnvCombine4 or texEnvCombine3 is OK.
891 nlassert(_Extensions
.NVTextureEnvCombine4
|| _Extensions
.ATITextureEnvCombine3
);
893 // setup constant color with Lightmap factor.
894 stdEnv
.ConstantColor
=lmapFactor
;
895 activateTexEnvColor(stage
, stdEnv
);
897 // Setup env for texture stage.
898 _DriverGLStates
.activeTextureARB(stage
);
899 _DriverGLStates
.setTexGenMode(stage
, 0);
901 // setup TexEnvCombine4 (ignore alpha part).
902 if(_CurrentTexEnvSpecial
[stage
] != TexEnvSpecialLightMap
)
904 // TexEnv is special.
905 _CurrentTexEnvSpecial
[stage
] = TexEnvSpecialLightMap
;
908 // What we want to setup is Texture*Constant + Previous.
909 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE
);
911 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB
, GL_ADD
);
912 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA
, GL_ADD
);
914 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC0_RGB
, GL_TEXTURE
);
915 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB
, GL_SRC_COLOR
);
917 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC2_RGB
, GL_CONSTANT
);
918 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB
, GL_SRC_COLOR
);
920 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC1_RGB
, GL_PREVIOUS
);
921 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB
, GL_SRC_COLOR
);
923 if (_Extensions
.NVTextureEnvCombine4
)
925 // What we want to setup is Texture*Constant + Previous*1.
926 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE4_NV
);
929 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_ADD
);
930 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_ADD
);
932 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
933 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
935 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_CONSTANT_EXT
);
936 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
938 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_PREVIOUS_EXT
);
939 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
941 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_RGB_NV
, GL_ZERO
);
942 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_RGB_NV
, GL_ONE_MINUS_SRC_COLOR
);
947 // What we want to setup is Texture*Constant + Previous.
948 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
950 glTexEnvf(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_MODULATE_ADD_ATI
);
951 glTexEnvf(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_MODULATE_ADD_ATI
);
953 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
954 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
956 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_CONSTANT_EXT
);
957 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
959 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_PREVIOUS_EXT
);
960 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
966 // setup UV, with UV1. Only if needed (cached)
967 if( !_LastVertexSetupIsLightMap
|| _LightMapUVMap
[stage
]!=1 )
969 setupUVPtr(stage
, _LastVB
, 1);
970 _LightMapUVMap
[stage
]= 1;
977 else if(stage
<nstages
)
979 // optim: do this only for first pass, and last pass only if stage!=nLMapPerPass
980 // (meaning not the same stage as preceding passes).
981 if(pass
==0 || (pass
==_NLightMapPass
-1 && stage
!=_NLightMapPerPass
))
983 // activate the texture at last stage.
984 ITexture
*text
= mat
.getTexture(0);
985 activateTexture(stage
,text
);
987 // setup ModulateRGB/ReplaceAlpha env. (this may disable possible COMBINE4_NV setup).
988 activateTexEnvMode(stage
, _LightMapLastStageEnv
);
991 _DriverGLStates
.activeTextureARB(stage
);
992 _DriverGLStates
.setTexGenMode(stage
, 0);
994 // setup UV, with UV0. Only if needed (cached)
995 if( !_LastVertexSetupIsLightMap
|| _LightMapUVMap
[stage
]!=0 )
997 setupUVPtr(stage
, _LastVB
, 0);
998 _LightMapUVMap
[stage
]= 0;
1001 if (mat
._LightMapsMulx2
)
1004 glTexEnvi(GL_TEXTURE_ENV
, GL_RGB_SCALE_EXT
, 2);
1010 // else all other stages are disabled.
1011 activateTexture(stage
,NULL
);
1015 // setup blend / lighting.
1016 //=========================
1018 /* If multi-pass, then must setup a black Fog color for 1+ pass (just do it for the pass 1).
1019 This is because Transparency ONE/ONE is used.
1021 if(pass
==1 && _FogEnabled
)
1023 static GLfloat blackFog
[4]= {0,0,0,0};
1024 glFogfv(GL_FOG_COLOR
, blackFog
);
1027 // Blend is different if the material is blended or not
1028 if( !mat
.getBlend() )
1030 // Not blended, std case.
1033 // no transparency for first pass.
1034 _DriverGLStates
.enableBlend(false);
1038 // setup an Additive transparency (only for pass 1, will be kept for successives pass).
1039 _DriverGLStates
.enableBlend(true);
1040 _DriverGLStates
.blendFunc(GL_ONE
, GL_ONE
);
1045 /* 1st pass, std alphaBlend. 2nd pass, add to background. Demo:
1047 l0: lightmap (or group of lightmap) of pass 0.
1048 l1: lightmap (or group of lightmap) of pass 1. (same thing with 2,3 etc....)
1050 A: Alpha of texture.
1052 finalResult= T*(l0+l1) * A + B * (1-A).
1054 We get it in two pass:
1055 fint= T*l0 * A + B * (1-A).
1056 finalResult= T*l1 * A + fint = T*l1 * A + T*l0 * A + B * (1-A)=
1057 T* (l0+l1) * A + B * (1-A)
1061 // no transparency for first pass.
1062 _DriverGLStates
.enableBlend(true);
1063 _DriverGLStates
.blendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1067 // setup an Additive transparency (only for pass 1, will be kept for successives pass).
1068 _DriverGLStates
.enableBlend(true);
1069 _DriverGLStates
.blendFunc(GL_SRC_ALPHA
, GL_ONE
);
1073 // Dynamic lighting: The influence of the dynamic light must be added only in the first pass (only one time)
1076 // If the lightmap is in x2 mode, then must divide effect of the dynamic light too
1077 if (mat
._LightMapsMulx2
)
1078 _DriverGLStates
.setDiffuse(packedColorGrey
, glcolGrey
);
1080 _DriverGLStates
.setDiffuse(packedColorWhite
, glcolWhite
);
1082 // no need to reset for pass after 1, since same than prec pass (black)!
1084 _DriverGLStates
.setDiffuse(packedColorBlack
, glcolBlack
);
1087 // ***************************************************************************
1088 void CDriverGL::endLightMapMultiPass()
1090 H_AUTO_OGL(CDriverGL_endLightMapMultiPass
)
1091 // Flag the fact that VertexSetup is dirty (special lightmap). reseted in activeVertexBuffer(), and setupMaterial()
1092 // NB: if no lightmaps, no setupUVPtr() has been called => don't need to flag
1093 // (important else crash if graphist error while exporting a Lightmap material, with a MeshVertexProgram (WindTree) )
1095 _LastVertexSetupIsLightMap
= true;
1097 // If multi-pass, then must reset the fog color
1098 if(_NLightMapPass
>=2 && _FogEnabled
)
1100 glFogfv(GL_FOG_COLOR
, _CurrentFogColor
);
1103 // nothing to do with blending/lighting, since always setuped in activeMaterial().
1104 // If material is the same, then it is still a lightmap material (if changed => touched => different!)
1105 // So no need to reset blending/lighting here.
1107 // Clean up all stage for Multiply x 2
1108 if (_CurrentMaterial
->_LightMapsMulx2
)
1110 for (uint32 i
= 0; i
< (_NLightMapPerPass
+1); ++i
)
1112 _DriverGLStates
.activeTextureARB(i
);
1113 glTexEnvi(GL_TEXTURE_ENV
, GL_RGB_SCALE_EXT
, 1);
1118 // ***************************************************************************
1119 void CDriverGL::resetLightMapVertexSetup()
1121 H_AUTO_OGL(CDriverGL_resetLightMapVertexSetup
)
1122 // special for all stage, std UV behavior.
1123 for(uint i
= 0; i
< inlGetNumTextStages(); i
++)
1125 // normal behavior: each texture has its own UV.
1126 setupUVPtr(i
, _LastVB
, i
);
1128 _LightMapUVMap
[i
]= -1;
1131 // pop VertexColor array if necessary.
1132 if (_LastVB
.VertexFormat
& CVertexBuffer::PrimaryColorFlag
)
1133 _DriverGLStates
.enableColorArray(true);
1136 _LastVertexSetupIsLightMap
= false;
1139 // ***************************************************************************
1140 void CDriverGL::startSpecularBatch()
1142 H_AUTO_OGL(CDriverGL_startSpecularBatch
)
1143 _SpecularBatchOn
= true;
1145 setupSpecularBegin();
1148 // ***************************************************************************
1149 void CDriverGL::endSpecularBatch()
1151 H_AUTO_OGL(CDriverGL_endSpecularBatch
)
1152 _SpecularBatchOn
= false;
1157 // ***************************************************************************
1158 void CDriverGL::setupSpecularBegin()
1160 H_AUTO_OGL(CDriverGL_setupSpecularBegin
)
1161 // ---- Reset any textures with id>=2
1163 for(; stage
< inlGetNumTextStages(); stage
++)
1165 // disable texturing
1166 activateTexture(stage
, NULL
);
1169 // ---- Stage 0 Common Setup.
1170 // Setup the env for stage 0 only.
1171 // Result RGB : Texture*Diffuse, Alpha : Texture
1172 CMaterial::CTexEnv env
;
1173 env
.Env
.OpAlpha
= CMaterial::Replace
;
1174 activateTexEnvMode(0, env
);
1176 // Disable texGen for stage 0
1177 _DriverGLStates
.activeTextureARB(0);
1178 _DriverGLStates
.setTexGenMode(0, 0);
1180 // ---- Stage 1 Common Setup.
1181 // NB don't setup the TexEnv here (stage1 setuped in setupSpecularPass() according to extensions)
1182 // For all cases, setup the TexCoord gen for stage1
1183 _DriverGLStates
.activeTextureARB(1);
1185 // todo hulud remove
1186 // _DriverGLStates.setTextureMode(CDriverGLStates::TextureCubeMap);
1187 _DriverGLStates
.setTexGenMode (1, GL_REFLECTION_MAP_ARB
);
1189 // setup the good matrix for stage 1.
1190 glMatrixMode(GL_TEXTURE
);
1191 glLoadMatrixf( _SpecularTexMtx
.get() );
1192 glMatrixMode(GL_MODELVIEW
);
1195 // ***************************************************************************
1196 void CDriverGL::setupSpecularEnd()
1198 H_AUTO_OGL(CDriverGL_setupSpecularEnd
)
1199 // Disable Texture coord generation.
1200 _DriverGLStates
.activeTextureARB(1);
1201 _DriverGLStates
.setTexGenMode(1, 0);
1203 // Happiness !!! we have already enabled the stage 1
1204 glMatrixMode(GL_TEXTURE
);
1206 glMatrixMode(GL_MODELVIEW
);
1209 // ***************************************************************************
1210 sint
CDriverGL::beginSpecularMultiPass()
1212 H_AUTO_OGL(CDriverGL_beginSpecularMultiPass
)
1213 const CMaterial
&mat
= *_CurrentMaterial
;
1215 // activate the 2 textures here
1217 uint numStages
= std::min((uint
)2, inlGetNumTextStages());
1218 for(stage
=0 ; stage
<numStages
; stage
++)
1220 ITexture
*text
= mat
.getTexture(uint8(stage
));
1222 // activate the texture, or disable texturing if NULL.
1223 activateTexture(stage
,text
);
1226 // End specular , only if not Batching mode.
1227 if(!_SpecularBatchOn
)
1228 setupSpecularBegin();
1230 // Manage the rare case when the SpecularMap is not provided (fault of graphist).
1231 if(mat
.getTexture(1)==NULL
)
1234 if(!_Extensions
.ARBTextureCubeMap
)
1237 if( _Extensions
.NVTextureEnvCombine4
|| _Extensions
.ATITextureEnvCombine3
) // NVidia or ATI optimization
1243 // ***************************************************************************
1244 void CDriverGL::setupSpecularPass(uint pass
)
1246 H_AUTO_OGL(CDriverGL_setupSpecularPass
)
1247 const CMaterial
&mat
= *_CurrentMaterial
;
1249 // Manage the rare case when the SpecularMap is not provided (error of a graphist).
1250 if(mat
.getTexture(1)==NULL
)
1252 // Just display the texture
1253 // NB: setupMaterial() code has correclty setuped textures.
1259 // Ok we can do it in a single pass
1262 // Special: not the same special env if there is or not texture in stage 0.
1263 CTexEnvSpecial newEnvStage1
;
1264 if( mat
.getTexture(0) == NULL
)
1265 newEnvStage1
= TexEnvSpecialSpecularStage1NoText
;
1267 newEnvStage1
= TexEnvSpecialSpecularStage1
;
1268 // Test if same env as prec.
1269 if(_CurrentTexEnvSpecial
[1] != newEnvStage1
)
1271 // TexEnv is special.
1272 _CurrentTexEnvSpecial
[1] = newEnvStage1
;
1274 _DriverGLStates
.activeTextureARB(1);
1275 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE
);
1276 // Operator Add (Arg0*Arg2+Arg1)
1277 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB
, GL_ADD
);
1278 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA
, GL_ADD
);
1280 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC0_RGB
, GL_TEXTURE
);
1281 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB
, GL_SRC_COLOR
);
1283 if( newEnvStage1
== TexEnvSpecialSpecularStage1NoText
)
1285 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC2_RGB
, GL_ZERO
);
1286 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB
, GL_ONE_MINUS_SRC_COLOR
);
1290 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC2_RGB
, GL_PREVIOUS
);
1291 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB
, GL_SRC_ALPHA
);
1294 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC1_RGB
, GL_PREVIOUS
);
1295 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB
, GL_SRC_COLOR
);
1296 // Result : Texture*Previous.Alpha+Previous
1297 // Setup Alpha Diffuse Copy
1298 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC0_ALPHA
, GL_PRIMARY_COLOR
);
1299 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA
, GL_SRC_ALPHA
);
1301 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC2_ALPHA
, GL_ZERO
);
1302 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1304 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC1_ALPHA
, GL_ZERO
);
1305 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA
, GL_SRC_ALPHA
);
1309 /// Support NVidia combine 4 extension to do specular map in a single pass
1310 if( _Extensions
.NVTextureEnvCombine4
)
1311 { // Ok we can do it in a single pass
1314 // Special: not the same sepcial env if there is or not texture in stage 0.
1315 CTexEnvSpecial newEnvStage1
;
1316 if( mat
.getTexture(0) == NULL
)
1317 newEnvStage1
= TexEnvSpecialSpecularStage1NoText
;
1319 newEnvStage1
= TexEnvSpecialSpecularStage1
;
1320 // Test if same env as prec.
1321 if(_CurrentTexEnvSpecial
[1] != newEnvStage1
)
1323 // TexEnv is special.
1324 _CurrentTexEnvSpecial
[1] = newEnvStage1
;
1326 _DriverGLStates
.activeTextureARB(1);
1327 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE4_NV
);
1328 // Operator Add (Arg0*Arg1+Arg2*Arg3)
1329 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_ADD
);
1330 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_ADD
);
1332 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
1333 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
1335 if( newEnvStage1
== TexEnvSpecialSpecularStage1NoText
)
1337 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_ZERO
);
1338 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_ONE_MINUS_SRC_COLOR
);
1342 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_PREVIOUS_EXT
);
1343 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_ALPHA
);
1346 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_PREVIOUS_EXT
);
1347 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
1349 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_RGB_NV
, GL_ZERO
);
1350 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_RGB_NV
, GL_ONE_MINUS_SRC_COLOR
);
1351 // Result : Texture*Previous.Alpha+Previous
1352 // Setup Alpha Diffuse Copy
1353 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
, GL_PRIMARY_COLOR_EXT
);
1354 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
, GL_SRC_ALPHA
);
1356 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_ALPHA_EXT
, GL_ZERO
);
1357 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA_EXT
, GL_ONE_MINUS_SRC_ALPHA
);
1359 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, GL_ZERO
);
1360 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_SRC_ALPHA
);
1362 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_ALPHA_NV
, GL_ZERO
);
1363 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_ALPHA_NV
, GL_SRC_ALPHA
);
1366 else if (_Extensions
.ATITextureEnvCombine3
)
1368 // Ok we can do it in a single pass
1371 // Special: not the same special env if there is or not texture in stage 0.
1372 CTexEnvSpecial newEnvStage1
;
1373 if( mat
.getTexture(0) == NULL
)
1374 newEnvStage1
= TexEnvSpecialSpecularStage1NoText
;
1376 newEnvStage1
= TexEnvSpecialSpecularStage1
;
1377 // Test if same env as prec.
1378 if(_CurrentTexEnvSpecial
[1] != newEnvStage1
)
1380 // TexEnv is special.
1381 _CurrentTexEnvSpecial
[1] = newEnvStage1
;
1383 _DriverGLStates
.activeTextureARB(1);
1384 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1385 // Operator Add (Arg0*Arg2+Arg1)
1386 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_MODULATE_ADD_ATI
);
1387 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_MODULATE_ADD_ATI
);
1389 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
1390 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
1392 if( newEnvStage1
== TexEnvSpecialSpecularStage1NoText
)
1394 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_ZERO
);
1395 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_ONE_MINUS_SRC_COLOR
);
1399 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_PREVIOUS_EXT
);
1400 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_ALPHA
);
1403 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_PREVIOUS_EXT
);
1404 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
1405 // Result : Texture*Previous.Alpha+Previous
1406 // Setup Alpha Diffuse Copy
1407 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
, GL_PRIMARY_COLOR_EXT
);
1408 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
, GL_SRC_ALPHA
);
1410 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, GL_ZERO
);
1411 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_ONE_MINUS_SRC_ALPHA
);
1413 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_ALPHA_EXT
, GL_ZERO
);
1414 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA_EXT
, GL_SRC_ALPHA
);
1420 // We have to do it in 2 passes
1421 // For Both Pass, setup correct Env.
1424 // Just display the texture
1425 _DriverGLStates
.enableBlend(false);
1426 _DriverGLStates
.activeTextureARB(1);
1427 _DriverGLStates
.setTextureMode(CDriverGLStates::TextureDisabled
);
1431 // Disabled because of Intel GPU texture bug (issue 310)
1432 // CMake options to debug
1433 // -DDEBUG_OGL_SPECULAR_FALLBACK=ON enables this
1434 // -DDEBUG_OGL_COMBINE43_DISABLE=ON disables GL_NV_texture_env_combine4/GL_ATI_texture_env_combine3
1435 #ifdef DEBUG_OGL_SPECULAR_FALLBACK
1436 // Multiply texture1 by alpha_texture0 and display with add
1437 _DriverGLStates
.enableBlend(true);
1438 _DriverGLStates
.blendFunc(GL_ONE
, GL_ONE
);
1441 _DriverGLStates
.activeTextureARB(0);
1442 CMaterial::CTexEnv env
;
1444 env
.Env
.OpRGB
= CMaterial::Replace
;
1445 env
.Env
.SrcArg0RGB
= CMaterial::Texture
;
1446 env
.Env
.OpArg0RGB
= CMaterial::SrcAlpha
;
1448 activateTexEnvMode(0, env
);
1451 if( mat
.getTexture(0) == NULL
)
1453 env
.Env
.OpRGB
= CMaterial::Replace
;
1454 env
.Env
.SrcArg0RGB
= CMaterial::Texture
;
1455 env
.Env
.OpArg0RGB
= CMaterial::SrcColor
;
1459 env
.Env
.OpRGB
= CMaterial::Modulate
;
1460 env
.Env
.SrcArg0RGB
= CMaterial::Texture
;
1461 env
.Env
.OpArg0RGB
= CMaterial::SrcColor
;
1463 env
.Env
.SrcArg1RGB
= CMaterial::Previous
;
1464 env
.Env
.OpArg1RGB
= CMaterial::SrcColor
;
1467 activateTexEnvMode(1, env
);
1468 #endif // DEBUG_OGL_SPECULAR_FALLBACK
1473 // ***************************************************************************
1474 void CDriverGL::endSpecularMultiPass()
1476 H_AUTO_OGL(CDriverGL_endSpecularMultiPass
)
1477 // End specular , only if not Batching mode.
1478 if(!_SpecularBatchOn
)
1482 // a functor that can is used to generate a cube map used for specular / diffuse lighting
1483 struct CSpecCubeMapFunctor
: ICubeMapFunctor
1485 CSpecCubeMapFunctor(float exp
) : Exp(exp
) {}
1486 virtual NLMISC::CRGBA
operator()(const NLMISC::CVector
&v
)
1488 H_AUTO_OGL(CSpecCubeMapFunctor_operator_parenthesis
)
1489 uint8 intensity
= (uint8
) (255.f
* ::powf(std::max(v
.normed().z
, 0.f
), Exp
));
1490 return NLMISC::CRGBA(intensity
, intensity
, intensity
, intensity
);
1491 //return Exp == 1.f ? CRGBA((uint8)(v.x*127+127), (uint8)(v.y*127+127), (uint8)(v.z*127+127), 0): CRGBA::Black;
1493 virtual ~CSpecCubeMapFunctor() {}
1497 /* /// parameters for specular cube map generation
1498 const uint MaxSpecularExp = 64;
1499 const uint SpecularExpStep = 8;
1500 const uint SpecularMapSize = 32; */
1502 // ***************************************************************************
1503 CTextureCube
*CDriverGL::getSpecularCubeMap(uint exp
)
1505 H_AUTO_OGL(CDriverGL__getSpecularCubeMap
)
1506 const uint DiffuseMapSize
= 64;
1507 const uint SpecularMapSize
= 32;
1508 const uint SpecularMapSizeHighExponent
= 64;
1509 const float HighExponent
= 128.f
;
1510 const uint MaxExponent
= 512;
1511 // this gives the cube map to use given an exponent (from 0 to 128)
1512 static uint16 expToCubeMap
[MaxExponent
];
1513 // this gives the exponent used by a given cube map (not necessarily ordered)
1514 static float cubeMapExp
[] =
1516 1.f
, 4.f
, 8.f
, 24.f
, 48.f
, 128.f
, 256.f
, 511.f
1518 const uint numCubeMap
= sizeof(cubeMapExp
) / sizeof(float);
1519 static bool tableBuilt
= false;
1523 for (uint k
= 0; k
< MaxExponent
; ++k
)
1526 float diff
= (float) MaxExponent
;
1527 // look for the nearest exponent
1528 for (uint l
= 0; l
< numCubeMap
; ++l
)
1530 float newDiff
= ::fabsf(k
- cubeMapExp
[l
]);
1537 expToCubeMap
[k
] = uint16(nearest
);
1542 if (_SpecularTextureCubes
.empty())
1544 _SpecularTextureCubes
.resize(MaxExponent
);
1547 NLMISC::clamp(exp
, 1u, (MaxExponent
- 1));
1549 uint cubeMapIndex
= expToCubeMap
[exp
];
1550 nlassert(cubeMapIndex
< numCubeMap
);
1552 if (_SpecularTextureCubes
[cubeMapIndex
] != NULL
) // has the cube map already been cted ?
1554 return _SpecularTextureCubes
[cubeMapIndex
];
1556 else // build the cube map
1558 float exponent
= cubeMapExp
[cubeMapIndex
];
1559 CSpecCubeMapFunctor
scmf(exponent
);
1560 const uint bufSize
= 128;
1562 NLMISC::smprintf(name
, bufSize
, "#SM%d", cubeMapIndex
);
1566 tc
= BuildCubeMap(DiffuseMapSize
, scmf
, false, name
);
1570 tc
= BuildCubeMap(exponent
>= HighExponent
? SpecularMapSizeHighExponent
1577 static const CTextureCube::TFace numToFace
[] =
1578 { CTextureCube::positive_x
,
1579 CTextureCube::negative_x
,
1580 CTextureCube::positive_y
,
1581 CTextureCube::negative_y
,
1582 CTextureCube::positive_z
,
1583 CTextureCube::negative_z
1586 if (exponent
!= 1.f
)
1588 // force 16 bit for specular part, 32 bit if exponent is 1 (diffuse part)
1589 for (uint k
= 0; k
< 6; ++k
)
1591 nlassert(tc
->getTexture(numToFace
[k
]));
1592 tc
->getTexture(numToFace
[k
])->setUploadFormat(ITexture::RGB565
);
1596 _SpecularTextureCubes
[cubeMapIndex
] = tc
;
1601 // ***************************************************************************
1602 sint
CDriverGL::beginPPLMultiPass()
1604 H_AUTO_OGL(CDriverGL_beginPPLMultiPass
)
1606 nlassert(supportPerPixelLighting(true)); // make sure the hardware can do that
1611 // ***************************************************************************
1612 void CDriverGL::setupPPLPass(uint pass
)
1614 H_AUTO_OGL(CDriverGL_setupPPLPass
)
1615 const CMaterial
&mat
= *_CurrentMaterial
;
1617 nlassert(pass
== 0);
1619 /* ITexture *tex0 = getSpecularCubeMap(1);
1620 if (tex0) setupTexture(*tex0);
1621 activateTexture(0, tex0);
1624 static CMaterial::CTexEnv env;
1625 env.Env.SrcArg0Alpha = CMaterial::Diffuse;
1626 env.Env.SrcArg1Alpha = CMaterial::Constant;
1627 env.Env.SrcArg0RGB = CMaterial::Diffuse;
1628 env.Env.SrcArg1RGB = CMaterial::Constant;
1629 env.Env.OpRGB = CMaterial::Replace;
1630 env.Env.OpAlpha = CMaterial::Replace;
1631 activateTexEnvMode(0, env);
1635 ITexture
*tex0
= getSpecularCubeMap(1);
1636 if (tex0
) setupTexture(*tex0
);
1637 ITexture
*tex2
= getSpecularCubeMap((uint
) mat
.getShininess());
1638 if (tex2
) setupTexture(*tex2
);
1639 if (mat
.getTexture(0)) setupTexture(*mat
.getTexture(0));
1641 // tex coord 0 = texture coordinates
1642 // tex coord 1 = normal in tangent space
1643 // tex coord 2 = half angle vector in tangent space
1645 activateTexture(0, tex0
);
1646 activateTexture(1, mat
.getTexture(0));
1647 activateTexture(2, tex2
);
1649 for (uint k
= 3; k
< inlGetNumTextStages(); ++k
)
1651 activateTexture(k
, NULL
);
1654 // setup the tex envs
1656 // Stage 0 is rgb = DiffuseCubeMap * LightColor + DiffuseGouraud * 1
1657 if(_CurrentTexEnvSpecial
[0] != TexEnvSpecialPPLStage0
)
1659 // TexEnv is special.
1660 _CurrentTexEnvSpecial
[0] = TexEnvSpecialPPLStage0
;
1661 _DriverGLStates
.activeTextureARB(0);
1664 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE
);
1666 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB
, GL_MODULATE
);
1667 // Arg0 = Diffuse read in cube map
1668 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC0_RGB
, GL_TEXTURE
);
1669 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB
, GL_SRC_COLOR
);
1670 // Arg1 = Light color
1671 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC2_RGB
, GL_CONSTANT
);
1672 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB
, GL_SRC_COLOR
);
1673 // Arg2 = Primary color (other light diffuse and
1674 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC1_RGB
, GL_PRIMARY_COLOR
);
1675 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB
, GL_SRC_COLOR
);
1677 if (_Extensions
.NVTextureEnvCombine4
)
1679 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE4_NV
);
1681 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_ADD
);
1682 // Arg0 = Diffuse read in cube map
1683 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
1684 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
1685 // Arg1 = Light color
1686 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_CONSTANT_EXT
);
1687 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
1688 // Arg2 = Primary color (other light diffuse and
1689 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_PRIMARY_COLOR_EXT
);
1690 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
1691 // Arg3 = White (= ~ Black)
1692 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_RGB_NV
, GL_ZERO
);
1693 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_RGB_NV
, GL_ONE_MINUS_SRC_COLOR
);
1695 else // use ATI extension
1697 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1699 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_MODULATE_ADD_ATI
);
1700 // Arg0 = Diffuse read in cube map
1701 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
1702 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
1703 // Arg1 = Light color
1704 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_CONSTANT_EXT
);
1705 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
1706 // Arg2 = Primary color (other light diffuse and
1707 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_PRIMARY_COLOR_EXT
);
1708 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
1712 activateTexEnvColor(0, _PPLightDiffuseColor
);
1715 static CMaterial::CTexEnv env
;
1716 env
.Env
.SrcArg1Alpha
= CMaterial::Diffuse
;
1717 activateTexEnvMode(1, env
);
1719 // Stage 2 is rgb = SpecularCubeMap * SpecularLightColor + Prec * 1
1720 // alpha = prec alpha
1722 if(_CurrentTexEnvSpecial
[2] != TexEnvSpecialPPLStage2
)
1724 // TexEnv is special.
1725 _CurrentTexEnvSpecial
[2] = TexEnvSpecialPPLStage2
;
1726 _DriverGLStates
.activeTextureARB(2);
1729 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE
);
1731 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB
, GL_MODULATE
);
1732 // Arg0 = Specular read in cube map
1733 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC0_RGB
, GL_TEXTURE
);
1734 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB
, GL_SRC_COLOR
);
1735 // Arg2 = Light color
1736 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC2_RGB
, GL_CONSTANT
);
1737 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB
, GL_SRC_COLOR
);
1738 // Arg1 = Primary color ( + other light diffuse)
1739 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC1_RGB
, GL_PREVIOUS
);
1740 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB
, GL_SRC_COLOR
);
1743 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA
, GL_MODULATE
);
1744 // Arg0 = PREVIOUS ALPHA
1745 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC0_ALPHA
, GL_PREVIOUS
);
1746 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA
, GL_SRC_COLOR
);
1748 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC2_ALPHA
, GL_ZERO
);
1749 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA
, GL_ONE_MINUS_SRC_COLOR
);
1751 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC1_ALPHA
, GL_ZERO
);
1752 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA
, GL_SRC_COLOR
);
1754 if (_Extensions
.NVTextureEnvCombine4
)
1756 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE4_NV
);
1758 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_ADD
);
1759 // Arg0 = Specular read in cube map
1760 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
1761 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
1762 // Arg1 = Light color
1763 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_CONSTANT_EXT
);
1764 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
1765 // Arg2 = Primary color ( + other light diffuse )
1766 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_PREVIOUS_EXT
);
1767 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
1768 // Arg3 = White (= ~ Black)
1769 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_RGB_NV
, GL_ZERO
);
1770 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_RGB_NV
, GL_ONE_MINUS_SRC_COLOR
);
1773 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_ADD
);
1774 // Arg0 = PREVIOUS ALPHA
1775 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
, GL_PREVIOUS_EXT
);
1776 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
, GL_SRC_COLOR
);
1778 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_ALPHA_EXT
, GL_ZERO
);
1779 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA_EXT
, GL_ONE_MINUS_SRC_COLOR
);
1781 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, GL_ZERO
);
1782 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_SRC_COLOR
);
1784 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_ALPHA_NV
, GL_ZERO
);
1785 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_ALPHA_NV
, GL_SRC_COLOR
);
1787 else // ATI EnvCombine3
1789 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1791 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_MODULATE_ADD_ATI
);
1792 // Arg0 = Specular read in cube map
1793 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
1794 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
1795 // Arg2 = Light color
1796 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_CONSTANT_EXT
);
1797 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
1798 // Arg1 = Primary color ( + other light diffuse)
1799 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_PREVIOUS_EXT
);
1800 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
1803 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_MODULATE_ADD_ATI
);
1804 // Arg0 = PREVIOUS ALPHA
1805 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
, GL_PREVIOUS_EXT
);
1806 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
, GL_SRC_COLOR
);
1808 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, GL_ZERO
);
1809 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_ONE_MINUS_SRC_COLOR
);
1811 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_ALPHA_EXT
, GL_ZERO
);
1812 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA_EXT
, GL_SRC_COLOR
);
1816 activateTexEnvColor(2, _PPLightSpecularColor
);
1820 // ***************************************************************************
1821 void CDriverGL::endPPLMultiPass()
1823 H_AUTO_OGL(CDriverGL_endPPLMultiPass
)
1824 // nothing to do there ...
1827 // ******PER PIXEL LIGHTING, NO SPECULAR**************************************
1828 sint
CDriverGL::beginPPLNoSpecMultiPass()
1830 H_AUTO_OGL(CDriverGL_beginPPLNoSpecMultiPass
)
1832 nlassert(supportPerPixelLighting(false)); // make sure the hardware can do that
1837 // ******PER PIXEL LIGHTING, NO SPECULAR**************************************
1838 void CDriverGL::setupPPLNoSpecPass(uint pass
)
1840 H_AUTO_OGL(CDriverGL_setupPPLNoSpecPass
)
1841 const CMaterial
&mat
= *_CurrentMaterial
;
1843 nlassert(pass
== 0);
1845 ITexture
*tex0
= getSpecularCubeMap(1);
1846 if (tex0
) setupTexture(*tex0
);
1848 if (mat
.getTexture(0)) setupTexture(*mat
.getTexture(0));
1850 // tex coord 0 = texture coordinates
1851 // tex coord 1 = normal in tangent space
1853 activateTexture(0, tex0
);
1854 activateTexture(1, mat
.getTexture(0));
1856 for (uint k
= 2; k
< inlGetNumTextStages(); ++k
)
1858 activateTexture(k
, NULL
);
1861 // setup the tex envs
1863 // Stage 0 is rgb = DiffuseCubeMap * LightColor + DiffuseGouraud * 1 (TODO : EnvCombine3)
1864 if(_CurrentTexEnvSpecial
[0] != TexEnvSpecialPPLStage0
)
1866 // TexEnv is special.
1867 _CurrentTexEnvSpecial
[0] = TexEnvSpecialPPLStage0
;
1868 _DriverGLStates
.activeTextureARB(0);
1871 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE
);
1873 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB
, GL_MODULATE
);
1874 // Arg0 = Diffuse read in cube map alpha
1875 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC0_RGB
, GL_TEXTURE
);
1876 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB
, GL_SRC_COLOR
);
1877 // Arg2 = Light color
1878 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC2_RGB
, GL_CONSTANT
);
1879 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB
, GL_SRC_COLOR
);
1880 // Arg1 = Primary color (other light diffuse and
1881 glTexEnvi(GL_TEXTURE_ENV
, GL_SRC1_RGB
, GL_PRIMARY_COLOR
);
1882 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB
, GL_SRC_COLOR
);
1884 if (_Extensions
.NVTextureEnvCombine4
)
1886 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE4_NV
);
1888 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_ADD
);
1889 // Arg0 = Diffuse read in cube map alpha
1890 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
1891 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
1892 // Arg1 = Light color
1893 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_CONSTANT_EXT
);
1894 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
1895 // Arg2 = Primary color (other light diffuse and
1896 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_PRIMARY_COLOR_EXT
);
1897 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
1898 // Arg3 = White (= ~ Black)
1899 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_RGB_NV
, GL_ZERO
);
1900 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_RGB_NV
, GL_ONE_MINUS_SRC_COLOR
);
1904 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1906 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_MODULATE_ADD_ATI
);
1907 // Arg0 = Diffuse read in cube map alpha
1908 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_TEXTURE
);
1909 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
1910 // Arg2 = Light color
1911 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_CONSTANT_EXT
);
1912 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
1913 // Arg1 = Primary color (other light diffuse and
1914 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_PRIMARY_COLOR_EXT
);
1915 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
1919 activateTexEnvColor(0, _PPLightDiffuseColor
);
1922 static CMaterial::CTexEnv env
;
1923 env
.Env
.SrcArg1Alpha
= CMaterial::Diffuse
;
1924 activateTexEnvMode(1, env
);
1928 // ******PER PIXEL LIGHTING, NO SPECULAR**************************************
1929 void CDriverGL::endPPLNoSpecMultiPass()
1931 H_AUTO_OGL(CDriverGL_endPPLNoSpecMultiPass
)
1932 // nothing to do there ...
1935 // ***************************************************************************
1936 /* sint CDriverGL::beginCausticsMultiPass(const CMaterial &mat)
1938 nlassert(mat.getShader() == CMaterial::Caustics);
1939 if (!_Extensions.ARBTextureCubeMap) return 1;
1940 switch (inlGetNumTextStages())
1949 // ***************************************************************************
1950 /*inline void CDriverGL::setupCausticsFirstTex(const CMaterial &mat)
1953 activateTexture(0, mat.getTexture(0));
1955 /// texture environment 0
1956 setTextureEnvFunction(0, mat);
1958 /// texture matrix 0
1959 setupUserTextureMatrix(0, mat);
1962 // ***************************************************************************
1963 inline void CDriverGL::setupCausticsSecondTex(uint stage)
1965 activateTexture(stage, mat.getTexture(0));
1969 // ***************************************************************************
1970 void CDriverGL::setupCausticsPass(const CMaterial &mat, uint pass)
1972 nlassert(mat.getShader() == CMaterial::Caustics);
1974 if (inlGetNumTextStages() == 1 || !_Extensions.ARBTextureCubeMap)
1976 setupCausticsFirstTex(mat);
1979 if (inlGetNumTextStages() >= 3) /// do it in one pass
1981 nlassert(pass == 0);
1983 setupCausticsFirstTex(mat);
1985 else if (inlGetNumTextStages() == 2) /// do in in 2 pass
1990 setupCausticsFirstTex(mat);
1992 else /// caustics setup
1994 /// setup additif blending
1995 _DriverGLStates.enableBlend();
1996 _DriverGLStates.blendFunc(pShader->SrcBlend, pShader->DstBlend);
2001 // ***************************************************************************
2002 void CDriverGL::endCausticsMultiPass(const CMaterial &mat)
2004 nlassert(mat.getShader() == CMaterial::Caustics);
2009 // ***************************************************************************
2010 sint
CDriverGL::beginCloudMultiPass ()
2012 H_AUTO_OGL(CDriverGL_beginCloudMultiPass
)
2013 nlassert(_CurrentMaterial
->getShader() == CMaterial::Cloud
);
2017 // ***************************************************************************
2018 void CDriverGL::setupCloudPass (uint
/* pass */)
2020 H_AUTO_OGL(CDriverGL_setupCloudPass
)
2021 nlassert(_CurrentMaterial
->getShader() == CMaterial::Cloud
);
2023 const CMaterial
&mat
= *_CurrentMaterial
;
2025 activateTexture(0, mat
.getTexture(0));
2026 activateTexture(1, mat
.getTexture(0));
2028 if (_CurrentTexEnvSpecial
[0] != TexEnvSpecialCloudStage0
)
2030 #ifndef USE_OPENGLES
2031 if (_Extensions
.NVTextureEnvCombine4
)
2033 _CurrentTexEnvSpecial
[0] = TexEnvSpecialCloudStage0
;
2034 _CurrentTexEnvSpecial
[1] = TexEnvSpecialCloudStage1
;
2037 _DriverGLStates
.activeTextureARB(0);
2038 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE4_NV
);
2040 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_ADD
);
2042 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_ZERO
);
2043 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
2045 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_ZERO
);
2046 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
2048 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_ZERO
);
2049 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
2051 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_RGB_NV
, GL_ZERO
);
2052 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_RGB_NV
, GL_SRC_COLOR
);
2055 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_ADD
);
2057 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
, GL_TEXTURE0_ARB
);
2058 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
, GL_SRC_ALPHA
);
2060 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_ALPHA_EXT
, GL_PRIMARY_COLOR_EXT
);
2061 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA_EXT
, GL_SRC_ALPHA
);
2063 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, GL_TEXTURE1_ARB
);
2064 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_SRC_ALPHA
);
2066 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_ALPHA_NV
, GL_PRIMARY_COLOR_EXT
);
2067 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_ALPHA_NV
, GL_ONE_MINUS_SRC_ALPHA
);
2070 _DriverGLStates
.activeTextureARB(1);
2071 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE4_NV
);
2073 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_ADD
);
2075 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_ZERO
);
2076 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
2078 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_ZERO
);
2079 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
2081 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_ZERO
);
2082 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
2084 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_RGB_NV
, GL_ZERO
);
2085 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_RGB_NV
, GL_SRC_COLOR
);
2088 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_ADD
);
2089 // Arg0 = AT0*AWPOS+AT1*(1-AWPOS)
2090 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
, GL_PREVIOUS_EXT
);
2091 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
, GL_SRC_ALPHA
);
2093 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_ALPHA_EXT
, GL_CONSTANT_EXT
);
2094 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA_EXT
, GL_SRC_ALPHA
);
2096 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, GL_ZERO
);
2097 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_SRC_ALPHA
);
2099 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_ALPHA_NV
, GL_ZERO
);
2100 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_ALPHA_NV
, GL_SRC_ALPHA
);
2101 activateTexEnvColor (1, mat
.getColor());
2103 else if (ATICloudShaderHandle
)
2105 // TODO : for now the state is not cached in _CurrentTexEnvSpecial
2106 nglBindFragmentShaderATI(ATICloudShaderHandle
);
2107 glEnable(GL_FRAGMENT_SHADER_ATI
);
2108 float cst
[4] = { 0.f
, 0.f
, 0.f
, mat
.getColor().A
/ 255.f
};
2109 nglSetFragmentShaderConstantATI(GL_CON_0_ATI
, cst
);
2113 _DriverGLStates
.activeTextureARB(0);
2114 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
2116 glTexEnvf(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_INTERPOLATE_EXT
);
2117 glTexEnvf(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_INTERPOLATE_EXT
);
2119 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_ZERO
);
2120 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
2121 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
, GL_TEXTURE0_ARB
);
2122 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
, GL_SRC_ALPHA
);
2124 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_ZERO
);
2125 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
2126 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_ALPHA_EXT
, GL_TEXTURE1_ARB
);
2127 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA_EXT
, GL_SRC_ALPHA
);
2129 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, GL_ZERO
);
2130 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_COLOR
);
2131 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, GL_PRIMARY_COLOR_EXT
);
2132 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_SRC_ALPHA
);
2133 _DriverGLStates
.activeTextureARB(1);
2134 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
2136 glTexEnvf(GL_TEXTURE_ENV
, GL_COMBINE_RGB_EXT
, GL_MODULATE
);
2137 glTexEnvf(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA_EXT
, GL_MODULATE
);
2139 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
, GL_ZERO
);
2140 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
, GL_SRC_COLOR
);
2141 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
, GL_PREVIOUS_EXT
);
2142 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
, GL_SRC_ALPHA
);
2144 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB_EXT
, GL_ZERO
);
2145 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB_EXT
, GL_SRC_COLOR
);
2146 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_ALPHA_EXT
, GL_CONSTANT_EXT
);
2147 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA_EXT
, GL_SRC_ALPHA
);
2151 if (_Extensions
.NVTextureEnvCombine4
)
2152 activateTexEnvColor (1, mat
.getColor());
2155 // ***************************************************************************
2156 void CDriverGL::endCloudMultiPass()
2158 H_AUTO_OGL(CDriverGL_endCloudMultiPass
)
2159 nlassert(_CurrentMaterial
->getShader() == CMaterial::Cloud
);
2160 if (ATICloudShaderHandle
)
2162 #ifndef USE_OPENGLES
2163 glDisable(GL_FRAGMENT_SHADER_ATI
);
2168 // ***************************************************************************
2169 sint
CDriverGL::beginWaterMultiPass()
2171 H_AUTO_OGL(CDriverGL_beginWaterMultiPass
)
2172 nlassert(_CurrentMaterial
->getShader() == CMaterial::Water
);
2177 // ***************************************************************************
2178 /** water setup for ATI
2180 void CDriverGL::setupWaterPassR200(const CMaterial
&mat
)
2182 H_AUTO_OGL(CDriverGL_setupWaterPassR200
);
2184 #ifndef USE_OPENGLES
2186 ITexture
*tex
= mat
.getTexture(0);
2189 // if (tex->isBumpMap())
2191 // CTextureBump *tb = static_cast<CTextureBump *>(tex);
2194 activateTexture(0, tex
);
2196 tex
= mat
.getTexture(1);
2199 // if (tex->isBumpMap())
2201 // CTextureBump *tb = static_cast<CTextureBump *>(tex);
2204 activateTexture(1, tex
);
2206 tex
= mat
.getTexture(2);
2210 activateTexture(2, tex
);
2212 tex
= mat
.getTexture(3);
2216 activateTexture(3, tex
);
2218 for (k
= 4; k
< inlGetNumTextStages(); ++k
)
2220 activateTexture(k
, NULL
);
2222 if (mat
.getTexture(3) != NULL
) // is there a diffuse map ?
2224 nglBindFragmentShaderATI(ATIWaterShaderHandle
);
2228 nglBindFragmentShaderATI(ATIWaterShaderHandleNoDiffuseMap
);
2230 glEnable(GL_FRAGMENT_SHADER_ATI
);
2233 if (mat
.getTexture(0) && mat
.getTexture(0)->isBumpMap())
2235 float factor
= NLMISC::safe_cast
<CTextureBump
*>(mat
.getTexture(0))->getNormalizationFactor();
2236 float cst
[4] = { factor
, factor
, factor
, 0.f
};
2237 nglSetFragmentShaderConstantATI(GL_CON_0_ATI
, cst
);
2241 float cst
[4] = { 1.f
, 1.f
, 1.f
, 0.f
};
2242 nglSetFragmentShaderConstantATI(GL_CON_0_ATI
, cst
);
2245 if (mat
.getTexture(1) && mat
.getTexture(1)->isBumpMap())
2247 float factor
= NLMISC::safe_cast
<CTextureBump
*>(mat
.getTexture(1))->getNormalizationFactor();
2248 float cst
[4] = { factor
, factor
, factor
, 0.f
};
2249 nglSetFragmentShaderConstantATI(GL_CON_1_ATI
, cst
);
2253 float cst
[4] = { 1.f
, 1.f
, 1.f
, 0.f
};
2254 nglSetFragmentShaderConstantATI(GL_CON_0_ATI
, cst
);
2259 // ***************************************************************************
2260 /** water setup for ARB_fragment_program
2262 void CDriverGL::setupWaterPassARB(const CMaterial
&mat
)
2264 H_AUTO_OGL(CDriverGL_setupWaterPassARB
);
2266 #ifndef USE_OPENGLES
2268 ITexture
*tex
= mat
.getTexture(0);
2271 tex
->setUploadFormat(ITexture::RGBA8888
);
2273 activateTexture(0, tex
);
2275 tex
= mat
.getTexture(1);
2278 tex
->setUploadFormat(ITexture::RGBA8888
);
2280 activateTexture(1, tex
);
2282 tex
= mat
.getTexture(2);
2286 activateTexture(2, tex
);
2288 tex
= mat
.getTexture(3);
2292 activateTexture(3, tex
);
2294 for (k
= 4; k
< inlGetNumTextStages(); ++k
)
2296 activateTexture(k
, NULL
);
2298 nglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, ARBWaterShader
[(_FogEnabled
? 1 : 0) | (mat
.getTexture(3) != NULL
? 2 : 0)]);
2299 glEnable(GL_FRAGMENT_PROGRAM_ARB
);
2301 // setup the constant
2302 if (mat
.getTexture(0) && mat
.getTexture(0)->isBumpMap())
2304 float factor
= 0.25f
* NLMISC::safe_cast
<CTextureBump
*>(mat
.getTexture(0))->getNormalizationFactor();
2305 nglProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB
, 0, 2.f
* factor
, -1.f
* factor
, 0.f
, 0.f
); // scale_bias from [0, 1] to [-1, 1] and factor applied
2309 nglProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB
, 0, 2.f
, -1.f
, 0.f
, 0.f
); // scale_bias from [0, 1] to [-1, 1] and factor applied
2312 // setup the constant
2313 if (mat
.getTexture(1) && mat
.getTexture(1)->isBumpMap())
2315 float factor
= NLMISC::safe_cast
<CTextureBump
*>(mat
.getTexture(1))->getNormalizationFactor();
2316 nglProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB
, 1, 2.f
* factor
, -1.f
* factor
, 0.f
, 0.f
); // scale_bias from [0, 1] to [-1, 1] and factor applied
2320 nglProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB
, 1, 2.f
, -1.f
, 0.f
, 0.f
); // scale_bias from [0, 1] to [-1, 1] and factor applied
2325 if (_FogStart
== _FogEnd
)
2327 nglProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB
, 2, 0.f
, 0.f
, 0.f
, 0.f
);
2331 /** Unfortunately, the EXT_vertex_shader extension has to output the fog values in the [0, 1] range to work with the standard pipeline.
2332 * So we must add a special path for this case, where the fog coordinate is 'unscaled' again.
2333 * NB : this is fixed in later drivers (from 6.14.10.6343), so check this
2335 if (_Extensions
.EXTVertexShader
&& !_ATIFogRangeFixed
)
2337 nglProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB
, 2, 1.f
, 0.f
, 0.f
, 0.f
);
2341 nglProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB
, 2, - 1.f
/ (_FogEnd
- _FogStart
), _FogEnd
/ (_FogEnd
- _FogStart
), 0.f
, 0.f
);
2348 // ***************************************************************************
2349 /** Presetupped texture shader for water shader on NV20
2351 static const uint8 WaterNoDiffuseTexAddrMode
[IDRV_MAT_MAXTEXTURES
] =
2353 CMaterial::FetchTexture
,
2354 CMaterial::OffsetTexture
,
2355 CMaterial::OffsetTexture
,
2356 CMaterial::TextureOff
2359 static const uint8 WaterTexAddrMode
[IDRV_MAT_MAXTEXTURES
] =
2361 CMaterial::FetchTexture
,
2362 CMaterial::OffsetTexture
,
2363 CMaterial::OffsetTexture
,
2364 CMaterial::FetchTexture
2367 static const float IdentityTexMat
[4] = { 1.f
, 0.f
, 0.f
, 1.f
};
2369 // ***************************************************************************
2370 void CDriverGL::setupWaterPassNV20(const CMaterial
&mat
)
2372 H_AUTO_OGL(CDriverGL_setupWaterPassNV20
);
2374 #ifndef USE_OPENGLES
2375 static bool setupDone
= false;
2376 static CMaterial::CTexEnv texEnvReplace
;
2377 static CMaterial::CTexEnv texEnvModulate
;
2381 texEnvReplace
.Env
.OpRGB
= CMaterial::Replace
;
2382 texEnvReplace
.Env
.OpAlpha
= CMaterial::Replace
;
2383 // use default setup for texenv modulate
2387 // activate the textures & set the matrixs
2388 ITexture
*tex
= mat
.getTexture(0);
2392 activateTexture(0, tex
);
2393 _DriverGLStates
.activeTextureARB(1);
2394 if (tex
->isBumpMap())
2396 CTextureBump
*tb
= static_cast<CTextureBump
*>(tex
);
2397 // set the matrix for the texture shader
2398 float factor
= tb
->getNormalizationFactor();
2399 float tsMatrix
[4] = { 0.25f
* factor
, 0.f
, 0.f
, 0.25f
* factor
};
2400 glTexEnvfv(GL_TEXTURE_SHADER_NV
, GL_OFFSET_TEXTURE_MATRIX_NV
, tsMatrix
);
2404 glTexEnvfv(GL_TEXTURE_SHADER_NV
, GL_OFFSET_TEXTURE_MATRIX_NV
, IdentityTexMat
);
2407 tex
= mat
.getTexture(1);
2411 activateTexture(1, tex
);
2412 _DriverGLStates
.activeTextureARB(2);
2413 if (tex
->isBumpMap())
2415 CTextureBump
*tb
= static_cast<CTextureBump
*>(tex
);
2416 // set the matrix for the texture shader
2417 float factor
= tb
->getNormalizationFactor();
2418 float tsMatrix
[4] = { factor
, 0.f
, 0.f
, factor
};
2419 glTexEnvfv(GL_TEXTURE_SHADER_NV
, GL_OFFSET_TEXTURE_MATRIX_NV
, tsMatrix
);
2423 glTexEnvfv(GL_TEXTURE_SHADER_NV
, GL_OFFSET_TEXTURE_MATRIX_NV
, IdentityTexMat
);
2426 tex
= mat
.getTexture(2);
2430 activateTexture(2, tex
);
2432 tex
= mat
.getTexture(3);
2436 activateTexture(3, tex
);
2438 for (uint k
= 4; k
< inlGetNumTextStages(); ++k
)
2440 activateTexture(k
, NULL
);
2443 // setup the texture shaders
2444 enableNVTextureShader(true);
2445 activateTexEnvMode(0, texEnvReplace
);
2446 activateTexEnvMode(1, texEnvReplace
);
2447 nlctassert(IDRV_MAT_MAXTEXTURES
== 4); // if this value changes, may have to change the arrays WaterNoDiffuseTexAddrMode & WaterTexAddrMode
2448 if (mat
.getTexture(3) == NULL
)
2450 setTextureShaders(WaterNoDiffuseTexAddrMode
, mat
._Textures
);
2451 activateTexEnvMode(2, texEnvReplace
);
2455 setTextureShaders(WaterTexAddrMode
, mat
._Textures
);
2456 activateTexEnvMode(2, texEnvReplace
);
2457 activateTexEnvMode(3, texEnvModulate
);
2462 // ***************************************************************************
2463 void CDriverGL::setupWaterPass(uint
/* pass */)
2465 H_AUTO_OGL(CDriverGL_setupWaterPass
)
2466 nlassert (_CurrentMaterial
);
2467 CMaterial
&mat
= *_CurrentMaterial
;
2468 nlassert(_CurrentMaterial
->getShader() == CMaterial::Water
);
2470 if (_Extensions
.NVTextureShader
)
2472 setupWaterPassNV20(mat
);
2474 else if (ARBWaterShader
[0])
2476 setupWaterPassARB(mat
);
2478 else if (ATIWaterShaderHandleNoDiffuseMap
)
2480 setupWaterPassR200(mat
);
2484 // ***************************************************************************
2485 void CDriverGL::endWaterMultiPass()
2487 H_AUTO_OGL(CDriverGL_endWaterMultiPass
);
2489 #ifndef USE_OPENGLES
2490 nlassert(_CurrentMaterial
->getShader() == CMaterial::Water
);
2491 // NB : as fragment shaders / programs bypass the texture envs, no special env enum is added (c.f CTexEnvSpecial)
2492 if (_Extensions
.NVTextureShader
) return;
2493 if (ARBWaterShader
[0])
2495 glDisable(GL_FRAGMENT_PROGRAM_ARB
);
2497 else if (ATIWaterShaderHandleNoDiffuseMap
)
2499 glDisable(GL_FRAGMENT_SHADER_ATI
);