attempt to fix reported problems with glsl shader on OS X (and other platforms)....
[blender.git] / source / gameengine / Ketsji / KX_BlenderMaterial.cpp
1
2 // ------------------------------------
3 // ...
4 // ------------------------------------
5 #ifdef HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #ifdef WIN32
10 #include <windows.h>
11 #endif // WIN32
12 #ifdef __APPLE__
13 #define GL_GLEXT_LEGACY 1
14 #include <OpenGL/gl.h>
15 #include <OpenGL/glu.h>
16 #else
17 #include <GL/gl.h>
18 #include <GL/glu.h>
19 #endif
20
21 #include "KX_BlenderMaterial.h"
22 #include "BL_Material.h"
23 #include "KX_Scene.h"
24 #include "KX_Light.h"
25 #include "KX_GameObject.h"
26 #include "KX_MeshProxy.h"
27
28 #include "MT_Vector3.h"
29 #include "MT_Vector4.h"
30 #include "MT_Matrix4x4.h"
31
32 #include "RAS_MeshObject.h"
33 #include "RAS_IRasterizer.h"
34 #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
35 #include "RAS_OpenGLRasterizer/ARB_multitexture.h"
36
37 extern "C" {
38 #include "BDR_drawmesh.h"
39 }
40
41 #include "STR_HashedString.h"
42
43 // ------------------------------------
44 #include "DNA_object_types.h"
45 #include "DNA_material_types.h"
46 #include "DNA_image_types.h"
47 #include "DNA_mesh_types.h"
48 #include "BKE_mesh.h"
49 // ------------------------------------
50 using namespace bgl;
51 #define spit(x) std::cout << x << std::endl;
52
53 //static PyObject *gTextureDict = 0;
54
55 KX_BlenderMaterial::KX_BlenderMaterial(
56     KX_Scene *scene,
57         BL_Material *data,
58         bool skin,
59         int lightlayer,
60         void *clientobject,
61         PyTypeObject *T
62         )
63 :       PyObjectPlus(T),
64         RAS_IPolyMaterial(
65                 STR_String( data->texname[0] ),
66                 STR_String( data->matname ), // needed for physics!
67                 data->tile,
68                 data->tilexrep[0],
69                 data->tileyrep[0],
70                 data->mode,
71                 ((data->ras_mode &TRANSP)!=0),
72                 ((data->ras_mode &ZSORT)!=0),
73                 lightlayer,
74                 ((data->ras_mode &TRIANGLE)!=0),
75                 clientobject
76         ),
77         mMaterial(data),
78         mShader(0),
79         mScene(scene),
80         mUserDefBlend(0),
81         mModified(0),
82         mPass(0)
83
84 {
85         ///RAS_EXT_support._ARB_multitexture == true if were here
86
87         // --------------------------------
88         // RAS_IPolyMaterial variables... 
89         m_flag |=RAS_BLENDERMAT;
90         m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0;
91         m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0;
92         
93         // figure max
94         #ifdef GL_ARB_multitexture
95         int enabled = mMaterial->num_enabled;
96         mMaterial->num_enabled = enabled>=bgl::max_texture_units?bgl::max_texture_units:enabled;
97         #else
98         mMaterial->num_enabled=0;
99         #endif
100
101         m_enabled = mMaterial->num_enabled;
102
103         // test the sum of the various modes for equality
104         // so we can ether accept or reject this material 
105         // as being equal, this is rather important to 
106         // prevent material bleeding
107         for(int i=0; i<mMaterial->num_enabled; i++) {
108                 m_multimode     +=
109                         ( mMaterial->flag[i]    +
110                           mMaterial->blend_mode[i]
111                          );
112         }
113         m_multimode += mMaterial->IdMode+mMaterial->ras_mode;
114
115 }
116
117
118 KX_BlenderMaterial::~KX_BlenderMaterial()
119 {
120         // cleanup work
121         OnExit();
122 }
123
124
125 TFace* KX_BlenderMaterial::GetTFace(void) const 
126 {
127         // fonts on polys
128         MT_assert(mMaterial->tface);
129         return mMaterial->tface;
130 }
131
132 void KX_BlenderMaterial::OnConstruction()
133 {
134         // for each unique material...
135         #ifdef GL_ARB_multitexture
136 /*      will be used to switch textures
137         if(!gTextureDict)
138                 gTextureDict = PyDict_New();
139 */
140         int i;
141         for(i=0; i<mMaterial->num_enabled; i++) {
142         bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i);
143                 #ifdef GL_ARB_texture_cube_map
144                 if( mMaterial->mapping[i].mapping & USEENV ) {
145                         if(!RAS_EXT_support._ARB_texture_cube_map) {
146                                 spit("CubeMap textures not supported");
147                                 continue;
148                         }
149                         if(!mTextures[i].InitCubeMap( mMaterial->cubemap[i] ) )
150                                 spit("unable to initialize image("<<i<<") in "<< 
151                                                 mMaterial->matname<< ", image will not be available");
152                 } 
153         
154                 else {
155                 #endif//GL_ARB_texture_cube_map
156                         if( mMaterial->img[i] ) {
157                                 if( ! mTextures[i].InitFromImage(mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 ))
158                                         spit("unable to initialize image("<<i<<") in "<< 
159                                                  mMaterial->matname<< ", image will not be available");
160                         }
161                 #ifdef GL_ARB_texture_cube_map
162                 }
163                 #endif//GL_ARB_texture_cube_map
164                 /*PyDict_SetItemString(gTextureDict, mTextures[i].GetName().Ptr(), PyInt_FromLong(mTextures[i]));*/
165         }
166         #endif//GL_ARB_multitexture
167
168         mBlendFunc[0] =0;
169         mBlendFunc[1] =0;
170 }
171
172 void KX_BlenderMaterial::OnExit()
173 {
174         #ifdef GL_ARB_multitexture
175         
176         #ifdef GL_ARB_shader_objects
177         if( RAS_EXT_support._ARB_shader_objects && mShader ) {
178                  //note, the shader here is allocated, per unique material
179                  //and this function is called per face
180                 bgl::blUseProgramObjectARB(0);
181                 delete mShader;
182                 mShader = 0;
183         }
184         #endif //GL_ARB_shader_objects
185
186         for(int i=0; i<mMaterial->num_enabled; i++) {
187                 bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i);
188
189                 mTextures[i].DeleteTex();
190
191                 glMatrixMode(GL_TEXTURE);
192                 glLoadIdentity();
193                 glMatrixMode(GL_MODELVIEW);
194
195                 #ifdef GL_ARB_texture_cube_map
196                 if(RAS_EXT_support._ARB_texture_cube_map)
197                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
198                 #endif//GL_ARB_texture_cube_map
199
200                 glDisable(GL_TEXTURE_2D);
201                 glDisable(GL_TEXTURE_GEN_S);
202                 glDisable(GL_TEXTURE_GEN_T);
203                 glDisable(GL_TEXTURE_GEN_R);
204                 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
205         }
206         
207         /*if (gTextureDict) {
208                 PyDict_Clear(gTextureDict);
209                 Py_DECREF(gTextureDict);
210                 gTextureDict = 0;
211         }*/
212
213         bgl::blActiveTextureARB(GL_TEXTURE0_ARB);
214
215         #ifdef GL_ARB_texture_cube_map
216         if(RAS_EXT_support._ARB_texture_cube_map)
217                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
218         #endif//GL_ARB_texture_cube_map
219
220         glDisable(GL_TEXTURE_2D);
221
222         #endif//GL_ARB_multitexture
223
224         // make sure multi texture units 
225         // revert back to blender...
226         // --
227         if( mMaterial->tface ) 
228                 set_tpage(mMaterial->tface);
229 }
230
231
232 void KX_BlenderMaterial::DisableTexData()
233 {
234         glDisable(GL_BLEND);
235         #ifdef GL_ARB_multitexture
236         int i=(MAXTEX>=bgl::max_texture_units?bgl::max_texture_units:MAXTEX)-1;
237         for(; i>=0; i--) {
238                 bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i);
239                 glMatrixMode(GL_TEXTURE);
240                 glLoadIdentity();
241                 glMatrixMode(GL_MODELVIEW);
242
243                 #ifdef GL_ARB_texture_cube_map
244                 if(RAS_EXT_support._ARB_texture_cube_map)
245                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
246                 #endif//GL_ARB_texture_cube_map
247
248                 glDisable(GL_TEXTURE_2D);       
249                 glDisable(GL_TEXTURE_GEN_S);
250                 glDisable(GL_TEXTURE_GEN_T);
251                 glDisable(GL_TEXTURE_GEN_R);
252                 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
253         }
254         #endif//GL_ARB_multitexture
255 }
256
257
258 void KX_BlenderMaterial::setShaderData( bool enable )
259 {
260         #ifdef GL_ARB_multitexture 
261         #ifdef GL_ARB_shader_objects 
262
263         MT_assert(RAS_EXT_support._ARB_shader_objects && mShader);
264
265         int i;
266         if( !enable || !mShader->Ok() ) {
267                 // frame cleanup.
268                 bgl::blUseProgramObjectARB( 0 );
269                 DisableTexData();
270                 return;
271         }
272
273         DisableTexData();
274         bgl::blUseProgramObjectARB( mShader->GetProg() );
275         
276         // for each enabled unit
277         for(i=0; i<mMaterial->num_enabled; i++) {
278
279                 const uSampler *samp = mShader->getSampler(i);
280                 if( samp->loc == -1 || samp->glTexture == 0 ) continue;
281
282                 bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i);
283
284                 #ifdef GL_ARB_texture_cube_map
285                 if( mMaterial->mapping[i].mapping &USEENV ) {
286                         glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, samp->glTexture /* mTextures[i]*/ );    
287                         glEnable( GL_TEXTURE_CUBE_MAP_ARB );
288                 } 
289                 else {
290                 #endif//GL_ARB_texture_cube_map
291                         glBindTexture( GL_TEXTURE_2D, samp->glTexture   /*mTextures[i]*/ );     
292                         glEnable( GL_TEXTURE_2D );
293                 #ifdef GL_ARB_texture_cube_map
294                 }
295                 #endif//GL_ARB_texture_cube_map
296                 // use a sampler
297                 bgl::blUniform1iARB(samp->loc, i );
298         }
299
300         if(!mUserDefBlend) {
301                 setDefaultBlending();
302         }else
303         {
304                 glEnable(GL_BLEND);
305                 // tested to be valid enums
306                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
307         }
308
309         #endif//GL_ARB_shader_objects
310         #endif//GL_ARB_multitexture
311 }
312
313
314 void KX_BlenderMaterial::setTexData( bool enable )
315 {
316         #ifdef GL_ARB_multitexture
317         int i;
318
319         #ifdef GL_ARB_shader_objects
320         if(RAS_EXT_support._ARB_shader_objects) {
321                 // switch back to fixed func
322                 bgl::blUseProgramObjectARB( 0 );
323         }
324         #endif//GL_ARB_shader_objects
325
326         if( !enable ) {
327                  // frame cleanup.
328                 DisableTexData();
329                 return;
330         }
331         
332         DisableTexData();
333
334         if( mMaterial->IdMode == DEFAULT_BLENDER ) {
335                 setDefaultBlending();
336                 return;
337         }
338
339         if( mMaterial->IdMode == TEXFACE ) {
340
341                 // no material connected to the object
342                 if( mTextures[0] ) {
343                         if( !mTextures[0].Ok() ) return;
344                         bgl::blActiveTextureARB(GL_TEXTURE0_ARB);
345                         glBindTexture( GL_TEXTURE_2D, mTextures[0] );   
346                         glEnable(GL_TEXTURE_2D);
347                         setTextureEnvironment( -1 ); // modulate
348                         setEnvMap( (mMaterial->mapping[0].mapping &USEREFL)!=0 );
349                         setDefaultBlending(); 
350                 }
351                 return;
352         }
353
354         int lastblend = 0;
355
356         // for each enabled unit
357         for(i=0; (i<mMaterial->num_enabled); i++) {
358                 if( !mTextures[i].Ok() ) continue;
359
360                 bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i);
361
362                 #ifdef GL_ARB_texture_cube_map
363                 // use environment maps
364                 if( mMaterial->mapping[i].mapping &USEENV && RAS_EXT_support._ARB_texture_cube_map ) {
365                         glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTextures[i] ); 
366                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
367                         setTextureEnvironment( i );
368
369                         if( mMaterial->mapping[i].mapping &USEREFL )
370                                 setEnvMap( true, true );
371                         else if(mMaterial->mapping[i].mapping &USEOBJ)
372                                 setObjectMatrixData(i);
373                         else
374                                 setTexMatrixData( i );
375                 } 
376                 // 2d textures
377                 else { 
378                 #endif//GL_ARB_texture_cube_map
379                         glBindTexture( GL_TEXTURE_2D, mTextures[i] );   
380                         glEnable( GL_TEXTURE_2D );
381                         setTextureEnvironment( i );
382                         
383                         if( mMaterial->mapping[i].mapping &USEREFL ){
384                                 setEnvMap( true );
385                         }
386                         else if(mMaterial->mapping[i].mapping &USEOBJ){
387                                 setObjectMatrixData(i);
388                         }
389                         else {
390                                 setTexMatrixData( i );
391                         }
392
393                 #ifdef GL_ARB_texture_cube_map
394                 }
395                 #endif//GL_ARB_texture_cube_map
396         }
397         if(!mUserDefBlend) {
398                 setDefaultBlending();
399         }else
400         {
401                 glEnable(GL_BLEND);
402                 // tested to be valid enums
403                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
404         }
405
406         #endif//GL_ARB_multitexture
407 }
408
409 void
410 KX_BlenderMaterial::ActivatShaders(
411         RAS_IRasterizer* rasty, 
412         TCachingInfo& cachingInfo)const
413 {
414         if (GetCachingInfo() != cachingInfo) {
415                 KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
416
417                 if (!cachingInfo)
418                         tmp->setShaderData( false );
419                 
420                 cachingInfo = GetCachingInfo();
421         
422                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED ) {
423                         tmp->setShaderData( true );
424                         rasty->EnableTextures(true);
425                 }
426                 else {
427                         tmp->setShaderData( false );
428                         rasty->EnableTextures(false);
429                 }
430
431                 if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
432                         rasty->SetCullFace(false);
433                 else
434                         rasty->SetCullFace(true);
435
436                 if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES)
437                         rasty->SetLines(true);
438                 else
439                         rasty->SetLines(false);
440         }
441         
442         // shaders have access to the variables set here
443         // via builtin GLSL variables
444         // eg: gl_FrontMaterial.diffuse
445         // --
446         rasty->SetSpecularity(
447                 mMaterial->speccolor[0]*mMaterial->spec_f,
448                 mMaterial->speccolor[1]*mMaterial->spec_f,
449                 mMaterial->speccolor[2]*mMaterial->spec_f,
450                 mMaterial->spec_f
451         );
452
453         rasty->SetShinyness( mMaterial->hard );
454
455         rasty->SetDiffuse(
456                 mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, 
457                 mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit,
458                 mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
459                 1.0f);
460
461         rasty->SetEmissive(     
462                 mMaterial->matcolor[0]*mMaterial->emit,
463                 mMaterial->matcolor[1]*mMaterial->emit,
464                 mMaterial->matcolor[2]*mMaterial->emit,
465                 1.0
466                 );
467
468         // Lagan's patch...
469         // added material factor
470         rasty->SetAmbient(mMaterial->amb);
471
472         if (mMaterial->material)
473                 rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0);
474 }
475
476 void
477 KX_BlenderMaterial::ActivateMat( 
478         RAS_IRasterizer* rasty,  
479         TCachingInfo& cachingInfo
480         )const
481 {
482         if (GetCachingInfo() != cachingInfo) {
483                 KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
484
485                 if (!cachingInfo) 
486                         tmp->setTexData( false );
487                 
488                 cachingInfo = GetCachingInfo();
489
490                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
491                         tmp->setTexData( true );
492                         rasty->EnableTextures(true);
493                 }
494                 else{
495                         tmp->setTexData( false );
496                         rasty->EnableTextures(false);
497                 }
498
499                 if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
500                         rasty->SetCullFace(false);
501                 else
502                         rasty->SetCullFace(true);
503
504                 if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES)
505                         rasty->SetLines(true);
506                 else
507                         rasty->SetLines(false);
508         }
509                 
510         rasty->SetSpecularity(
511                 mMaterial->speccolor[0]*mMaterial->spec_f,
512                 mMaterial->speccolor[1]*mMaterial->spec_f,
513                 mMaterial->speccolor[2]*mMaterial->spec_f,
514                 mMaterial->spec_f
515         );
516
517         rasty->SetShinyness( mMaterial->hard );
518
519         rasty->SetDiffuse(
520                 mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, 
521                 mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit,
522                 mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
523                 1.0f);
524
525         rasty->SetEmissive(     
526                 mMaterial->matcolor[0]*mMaterial->emit,
527                 mMaterial->matcolor[1]*mMaterial->emit,
528                 mMaterial->matcolor[2]*mMaterial->emit,
529                 1.0
530                 );
531         
532         // Lagan's patch...
533         // added material factor
534         rasty->SetAmbient(mMaterial->amb);
535
536         if (mMaterial->material)
537                 rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0);
538 }
539
540 bool 
541 KX_BlenderMaterial::Activate( 
542         RAS_IRasterizer* rasty,  
543         TCachingInfo& cachingInfo
544         )const
545 {
546         bool dopass = false;
547         #ifdef GL_ARB_shader_objects
548         if( RAS_EXT_support._ARB_shader_objects &&
549                 ( mShader && mShader->Ok() ) ) {
550
551                 if( (mPass++) < mShader->getNumPass() ) {
552                         ActivatShaders(rasty, cachingInfo);
553                         dopass = true;
554                         return dopass;
555                 }
556                 else {
557                         bgl::blUseProgramObjectARB( 0 );
558                         mPass = 0;
559                         dopass = false;
560                         return dopass;
561                 }
562         }
563         else {
564         #endif//GL_ARB_shader_objects
565                 switch (mPass++)
566                 {
567                         case 0:
568                                 ActivateMat(rasty, cachingInfo);
569                                 dopass = true;
570                                 break;
571                         default:
572                                 mPass = 0;
573                                 dopass = false;
574                                 break;
575                 }
576         #ifdef GL_ARB_shader_objects
577         }
578         #endif//GL_ARB_shader_objects
579         return dopass;
580 }
581
582 void KX_BlenderMaterial::setTextureEnvironment( int textureIndex )
583 {
584 #ifndef GL_ARB_texture_env_combine
585         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
586         return;
587 #else
588         if(textureIndex == -1 || !RAS_EXT_support._ARB_texture_env_combine){
589                 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
590                 return;
591         }
592
593         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
594
595         GLfloat blend_operand           = GL_SRC_COLOR;
596         GLfloat blend_operand_prev  = GL_SRC_COLOR;
597
598         GLenum combiner = GL_COMBINE_RGB_ARB;
599         GLenum source0 = GL_SOURCE0_RGB_ARB;
600         GLenum source1 = GL_SOURCE1_RGB_ARB;
601         GLenum source2 = GL_SOURCE2_RGB_ARB;
602         GLenum op0 = GL_OPERAND0_RGB_ARB;
603         GLenum op1 = GL_OPERAND1_RGB_ARB;
604         GLenum op2 = GL_OPERAND2_RGB_ARB;
605         GLfloat alphaOp = GL_SRC_ALPHA;
606
607         // switch to alpha combiners
608         if( (mMaterial->flag[textureIndex] &TEXALPHA) ) {
609                 combiner = GL_COMBINE_ALPHA_ARB;
610                 source0  = GL_SOURCE0_ALPHA_ARB;
611                 source1 = GL_SOURCE1_ALPHA_ARB;
612                 source2 = GL_SOURCE2_ALPHA_ARB;
613                 op0 = GL_OPERAND0_ALPHA_ARB;
614                 op1 = GL_OPERAND1_ALPHA_ARB;
615                 op2 = GL_OPERAND2_ALPHA_ARB;
616                 blend_operand = GL_SRC_ALPHA;
617                 
618                 // invert
619                 if(mMaterial->flag[textureIndex] &TEXNEG) {
620                         blend_operand_prev = GL_ONE_MINUS_SRC_ALPHA;
621                         blend_operand = GL_ONE_MINUS_SRC_ALPHA;
622                 }
623         }
624         else {
625                 if(mMaterial->flag[textureIndex] &TEXNEG) {
626                         blend_operand_prev=GL_ONE_MINUS_SRC_COLOR;
627                         blend_operand = GL_ONE_MINUS_SRC_COLOR;
628                 }
629         }
630         bool using_alpha = false;
631
632         if(mMaterial->flag[textureIndex] &USEALPHA){
633                 alphaOp = GL_ONE_MINUS_SRC_ALPHA;
634                 using_alpha=true;
635         }
636         else if(mMaterial->flag[textureIndex] &USENEGALPHA){
637                 alphaOp = GL_SRC_ALPHA;
638                 using_alpha = true;
639         }
640
641         switch( mMaterial->blend_mode[textureIndex] ) {
642                 case BLEND_MIX:
643                         {
644                                 // ------------------------------
645                                 if(!using_alpha) {
646                                         GLfloat base_col[4];
647                                         base_col[0]      = base_col[1]  = base_col[2]  = 0.f;
648                                         base_col[3]      = 1.f-mMaterial->color_blend[textureIndex];
649                                         glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,base_col );
650                                 }
651                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_INTERPOLATE_ARB);
652                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB);
653                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
654                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
655                                 glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
656                                 if(!using_alpha)
657                                         glTexEnvf(      GL_TEXTURE_ENV, source2,        GL_CONSTANT_ARB );
658                                 else
659                                         glTexEnvf(      GL_TEXTURE_ENV, source2,        GL_TEXTURE );
660
661                                 glTexEnvf(      GL_TEXTURE_ENV, op2,            alphaOp);
662                         }break;
663                 case BLEND_MUL: 
664                         {
665                                 // ------------------------------
666                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_MODULATE);
667                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB);
668                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev);
669                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
670                                 if(using_alpha)
671                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
672                                 else
673                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
674                         }break;
675                 case BLEND_ADD: 
676                         {
677                                 // ------------------------------
678                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_ADD_SIGNED_ARB);
679                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
680                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
681                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
682                                 if(using_alpha)
683                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
684                                 else
685                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
686                         }break;
687                 case BLEND_SUB: 
688                         {
689                                 // ------------------------------
690                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_SUBTRACT_ARB);
691                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
692                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
693                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
694                                 glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
695                         }break;
696                 case BLEND_SCR: 
697                         {
698                                 // ------------------------------
699                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_ADD);
700                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
701                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
702                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
703                                 if(using_alpha)
704                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
705                                 else
706                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
707                         } break;
708         }
709         glTexEnvf(      GL_TEXTURE_ENV, GL_RGB_SCALE_ARB,       1.0);
710 #endif //!GL_ARB_texture_env_combine
711 }
712
713 bool KX_BlenderMaterial::setDefaultBlending()
714 {
715         if( mMaterial->transp &TF_ADD) {
716                 glEnable(GL_BLEND);
717                 glBlendFunc(GL_ONE, GL_ONE);
718                 return true;
719         }
720         
721         if( mMaterial->transp & TF_ALPHA ) {
722                 glEnable(GL_BLEND);
723                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
724                 return true;
725         }
726         
727         glDisable(GL_BLEND);
728         return false;
729 }
730
731 void KX_BlenderMaterial::setEnvMap(bool val, bool cube)
732 {
733         #ifdef GL_ARB_texture_cube_map
734         if( cube && RAS_EXT_support._ARB_texture_cube_map ) 
735         {
736                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
737                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
738                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
739
740                 glEnable(GL_TEXTURE_GEN_S);
741                 glEnable(GL_TEXTURE_GEN_T);
742                 glEnable(GL_TEXTURE_GEN_R);
743         }
744         else {
745         #endif//GL_ARB_texture_cube_map
746                 if( val ) {
747                         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
748                         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
749                         
750                         glEnable(GL_TEXTURE_GEN_S);
751                         glEnable(GL_TEXTURE_GEN_T);
752                         glEnable(GL_TEXTURE_GEN_R);
753                 }
754                 else {
755                         glDisable(GL_TEXTURE_GEN_S);
756                         glDisable(GL_TEXTURE_GEN_T);
757                         glDisable(GL_TEXTURE_GEN_R);
758                 }
759         #ifdef GL_ARB_texture_cube_map
760         }
761         #endif//GL_ARB_texture_cube_map
762 }
763
764
765 void KX_BlenderMaterial::setTexMatrixData(int i)
766 {
767         glMatrixMode(GL_TEXTURE);
768         glLoadIdentity();
769
770         glScalef( 
771                 mMaterial->mapping[i].scale[0], 
772                 mMaterial->mapping[i].scale[1], 
773                 mMaterial->mapping[i].scale[2]
774         );
775         glTranslatef(
776                 mMaterial->mapping[i].offsets[0],
777                 mMaterial->mapping[i].offsets[1], 
778                 mMaterial->mapping[i].offsets[2]
779         );
780
781         glMatrixMode(GL_MODELVIEW);
782
783 }
784
785 static void GetProjPlane(BL_Material *mat, int index,int num, float*param)
786 {
787         param[0]=param[1]=param[2]=param[3]=0.f;
788         if( mat->mapping[index].projplane[num] == PROJX )
789                 param[0] = 1.f;
790         else if( mat->mapping[index].projplane[num] == PROJY )
791                 param[1] = 1.f;
792         else if( mat->mapping[index].projplane[num] == PROJZ)
793                 param[2] = 1.f;
794 }
795
796
797 void KX_BlenderMaterial::setObjectMatrixData(int i)
798 {
799         // will work without cubemaps
800         // but a cubemap will look the best
801         KX_GameObject *obj = 
802                 (KX_GameObject*)
803                 mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame);
804
805         if(!obj)
806                 return;
807
808         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
809         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
810         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
811
812         GLenum plane = GL_EYE_PLANE;
813
814         // figure plane gen
815         float proj[4]= {0.f,0.f,0.f,0.f};
816         GetProjPlane(mMaterial, i, 0, proj);
817         glTexGenfv(GL_S, plane, proj);
818         
819         GetProjPlane(mMaterial, i, 1, proj);
820         glTexGenfv(GL_T, plane, proj);
821
822         GetProjPlane(mMaterial, i, 2, proj);
823         glTexGenfv(GL_R, plane, proj);
824
825         glEnable(GL_TEXTURE_GEN_S);
826         glEnable(GL_TEXTURE_GEN_T);
827         glEnable(GL_TEXTURE_GEN_R);
828
829         float matr[16];
830         glGetFloatv(GL_MODELVIEW_MATRIX, matr);
831         MT_Matrix4x4 mvmat(matr);
832
833         glMatrixMode(GL_TEXTURE);
834         glLoadIdentity();
835         glScalef( 
836                 mMaterial->mapping[i].scale[0], 
837                 mMaterial->mapping[i].scale[1], 
838                 mMaterial->mapping[i].scale[2]
839         );
840
841         MT_Point3 pos = obj->NodeGetWorldPosition();
842         MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f);
843         MT_Vector4 t = mvmat*matmul;
844
845         glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) );
846
847         glMatrixMode(GL_MODELVIEW);
848
849 }
850
851
852 // ------------------------------------
853 void KX_BlenderMaterial::UpdateIPO(
854         MT_Vector4 rgba,
855         MT_Vector3 specrgb,
856         MT_Scalar hard,
857         MT_Scalar spec,
858         MT_Scalar ref,
859         MT_Scalar emit,
860         MT_Scalar alpha
861         )
862 {
863         // only works one deep now
864         mMaterial->speccolor[0] = (float)(specrgb)[0];
865         mMaterial->speccolor[1] = (float)(specrgb)[1];
866         mMaterial->speccolor[2] = (float)(specrgb)[2];
867         mMaterial->matcolor[0]  = (float)(rgba[0]);
868         mMaterial->matcolor[1]  = (float)(rgba[1]);
869         mMaterial->matcolor[2]  = (float)(rgba[2]);
870         mMaterial->alpha                = (float)(alpha);
871         mMaterial->hard                 = (float)(hard);
872         mMaterial->emit                 = (float)(emit);
873         mMaterial->spec_f               = (float)(spec);
874 }
875
876
877 PyMethodDef KX_BlenderMaterial::Methods[] = 
878 {
879         KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ),
880         KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ),
881         KX_PYMETHODTABLE( KX_BlenderMaterial, setBlending ),
882 //      KX_PYMETHODTABLE( KX_BlenderMaterial, getTexture ),
883 //      KX_PYMETHODTABLE( KX_BlenderMaterial, setTexture ),
884
885         {NULL,NULL} //Sentinel
886 };
887
888
889 PyTypeObject KX_BlenderMaterial::Type = {
890         PyObject_HEAD_INIT(&PyType_Type)
891                 0,
892                 "KX_BlenderMaterial",
893                 sizeof(KX_BlenderMaterial),
894                 0,
895                 PyDestructor,
896                 0,
897                 __getattr,
898                 __setattr,
899                 0,
900                 __repr,
901                 0
902 };
903
904
905 PyParentObject KX_BlenderMaterial::Parents[] = {
906         &PyObjectPlus::Type,
907         &KX_BlenderMaterial::Type,
908         NULL
909 };
910
911
912 PyObject* KX_BlenderMaterial::_getattr(const STR_String& attr)
913 {
914         // nodda ?
915         _getattr_up(PyObjectPlus);
916 }
917
918 int KX_BlenderMaterial::_setattr(const STR_String& attr, PyObject *pyvalue)
919 {
920         return PyObjectPlus::_setattr(attr, pyvalue);
921 }
922
923
924 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
925 {
926 #ifdef GL_ARB_fragment_shader
927         if( !RAS_EXT_support._ARB_fragment_shader) {
928                 if(!mModified)
929                         spit("Fragment shaders not supported");
930         
931                 mModified = true;
932                 Py_Return;
933         }
934 #endif
935
936 #ifdef GL_ARB_vertex_shader
937         if( !RAS_EXT_support._ARB_vertex_shader) {
938                 if(!mModified)
939                         spit("Vertex shaders not supported");
940
941                 mModified = true;
942                 Py_Return;
943         }
944 #endif
945
946 #ifdef GL_ARB_shader_objects
947         if(!RAS_EXT_support._ARB_shader_objects)  {
948                 if(!mModified)
949                         spit("GLSL not supported");
950                 mModified = true;
951                 Py_Return;
952         }
953         else {
954                 // returns Py_None on error
955                 // the calling script will need to check
956
957                 if(!mShader && !mModified) {
958                         mShader = new BL_Shader();
959                         for(int i= 0; i<mMaterial->num_enabled; i++) {
960                                 if(mMaterial->mapping[i].mapping & USEENV )
961                                         mShader->InitializeSampler(SAMP_CUBE, i, 0, mTextures[i]);
962                                 else
963                                         mShader->InitializeSampler(SAMP_2D, i, 0, mTextures[i]);
964                         }
965                         mModified = true;
966                 }
967
968                 if(mShader && !mShader->GetError()) {
969                         Py_INCREF(mShader);
970                         return mShader;
971                 }else
972                 {
973                         // decref all references to the object
974                         // then delete it!
975                         // We will then go back to fixed functionality
976                         // for this material
977                         if(mShader) {
978                                 if(mShader->ob_refcnt > 1) {
979                                         Py_DECREF(mShader);
980                                 }
981                                 else {
982                                         delete mShader;
983                                         mShader=0;
984                                 }
985                         }
986                 }
987                 Py_Return;
988         }
989         PyErr_Format(PyExc_ValueError, "GLSL Error");
990         return NULL;
991
992 #else
993         Py_Return;
994 #endif//GL_ARB_shader_objects
995 }
996
997 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
998 {
999         return PyInt_FromLong( mMaterial->material_index );
1000 }
1001
1002 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
1003 {
1004         // TODO: enable python switching
1005         return NULL;
1006 }
1007
1008 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)")
1009 {
1010         // TODO: enable python switching
1011         return NULL;
1012 }
1013
1014 static unsigned int GL_array[11] = {
1015         GL_ZERO,
1016         GL_ONE,
1017         GL_SRC_COLOR,
1018         GL_ONE_MINUS_SRC_COLOR,
1019         GL_DST_COLOR,
1020         GL_ONE_MINUS_DST_COLOR,
1021         GL_SRC_ALPHA,
1022         GL_ONE_MINUS_SRC_ALPHA,
1023         GL_DST_ALPHA,
1024         GL_ONE_MINUS_DST_ALPHA,
1025         GL_SRC_ALPHA_SATURATE
1026 };
1027
1028 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.src, GameLogic.dest)")
1029 {
1030         unsigned int b[2];
1031         if(PyArg_ParseTuple(args, "ii", &b[0], &b[1]))
1032         {
1033                 bool value_found[2] = {false, false};
1034                 for(int i=0; i<11; i++)
1035                 {
1036                         if(b[0] == GL_array[i]) {
1037                                 value_found[0] = true;
1038                                 mBlendFunc[0] = b[0];
1039                         }
1040                         if(b[1] == GL_array[i]) {
1041                                 value_found[1] = true;
1042                                 mBlendFunc[1] = b[1];
1043                         }
1044                         if(value_found[0] && value_found[1]) break;
1045                 }
1046                 if(!value_found[0] || !value_found[1]) {
1047                         PyErr_Format(PyExc_ValueError, "invalid enum.");
1048                         return NULL;
1049                 }
1050                 mUserDefBlend = true;
1051                 Py_Return;
1052         }
1053         return NULL;
1054 }
1055