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