b530edbd17ce8925adb55827161df47669b3db32
[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         // 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
922 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
923 {
924 #ifdef GL_ARB_fragment_shader
925         if( !RAS_EXT_support._ARB_fragment_shader) {
926                 if(!mModified)
927                         spit("Fragment shaders not supported");
928         
929                 mModified = true;
930                 Py_Return;
931         }
932 #endif
933
934 #ifdef GL_ARB_vertex_shader
935         if( !RAS_EXT_support._ARB_vertex_shader) {
936                 if(!mModified)
937                         spit("Vertex shaders not supported");
938
939                 mModified = true;
940                 Py_Return;
941         }
942 #endif
943
944 #ifdef GL_ARB_shader_objects
945         if(!RAS_EXT_support._ARB_shader_objects)  {
946                 if(!mModified)
947                         spit("GLSL not supported");
948                 mModified = true;
949                 Py_Return;
950         }
951         else {
952                 // returns Py_None on error
953                 // the calling script will need to check
954
955                 if(!mShader && !mModified) {
956                         mShader = new BL_Shader();
957                         for(int i= 0; i<mMaterial->num_enabled; i++) {
958                                 if(mMaterial->mapping[i].mapping & USEENV )
959                                         mShader->InitializeSampler(SAMP_CUBE, i, 0, mTextures[i]);
960                                 else
961                                         mShader->InitializeSampler(SAMP_2D, i, 0, mTextures[i]);
962                         }
963                         mModified = true;
964                 }
965
966                 if(mShader && !mShader->GetError()) {
967                         Py_INCREF(mShader);
968                         return mShader;
969                 }else
970                 {
971                         // decref all references to the object
972                         // then delete it!
973                         // We will then go back to fixed functionality
974                         // for this material
975                         if(mShader) {
976                                 if(mShader->ob_refcnt > 1) {
977                                         Py_DECREF(mShader);
978                                 }
979                                 else {
980                                         delete mShader;
981                                         mShader=0;
982                                 }
983                         }
984                 }
985                 Py_Return;
986         }
987         PyErr_Format(PyExc_ValueError, "GLSL Error");
988         return NULL;
989
990 #else
991         Py_Return;
992 #endif//GL_ARB_shader_objects
993 }
994
995 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
996 {
997         return PyInt_FromLong( mMaterial->material_index );
998 }
999
1000 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
1001 {
1002         // TODO: enable python switching
1003         return NULL;
1004 }
1005
1006 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)")
1007 {
1008         // TODO: enable python switching
1009         return NULL;
1010 }
1011
1012 static unsigned int GL_array[11] = {
1013         GL_ZERO,
1014         GL_ONE,
1015         GL_SRC_COLOR,
1016         GL_ONE_MINUS_SRC_COLOR,
1017         GL_DST_COLOR,
1018         GL_ONE_MINUS_DST_COLOR,
1019         GL_SRC_ALPHA,
1020         GL_ONE_MINUS_SRC_ALPHA,
1021         GL_DST_ALPHA,
1022         GL_ONE_MINUS_DST_ALPHA,
1023         GL_SRC_ALPHA_SATURATE
1024 };
1025
1026 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.src, GameLogic.dest)")
1027 {
1028         unsigned int b[2];
1029         if(PyArg_ParseTuple(args, "ii", &b[0], &b[1]))
1030         {
1031                 bool value_found[2] = {false, false};
1032                 for(int i=0; i<11; i++)
1033                 {
1034                         if(b[0] == GL_array[i]) {
1035                                 value_found[0] = true;
1036                                 mBlendFunc[0] = b[0];
1037                         }
1038                         if(b[1] == GL_array[i]) {
1039                                 value_found[1] = true;
1040                                 mBlendFunc[1] = b[1];
1041                         }
1042                         if(value_found[0] && value_found[1]) break;
1043                 }
1044                 if(!value_found[0] || !value_found[1]) {
1045                         PyErr_Format(PyExc_ValueError, "invalid enum.");
1046                         return NULL;
1047                 }
1048                 mUserDefBlend = true;
1049                 Py_Return;
1050         }
1051         return NULL;
1052 }
1053