LEFT | RIGHT |
| 1 /* |
| 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
| 3 * |
| 4 * This program is free software; you can redistribute it and/or |
| 5 * modify it under the terms of the GNU General Public License |
| 6 * as published by the Free Software Foundation; either version 2 |
| 7 * of the License, or (at your option) any later version. |
| 8 * |
| 9 * This program is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 14 * You should have received a copy of the GNU General Public License |
| 15 * along with this program; if not, write to the Free Software Foundation, |
| 16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 17 * |
| 18 * ***** END GPL LICENSE BLOCK ***** |
| 19 */ |
| 20 |
1 /** \file gameengine/Ketsji/KX_BlenderMaterial.cpp | 21 /** \file gameengine/Ketsji/KX_BlenderMaterial.cpp |
2 * \ingroup ketsji | 22 * \ingroup ketsji |
3 */ | 23 */ |
4 | 24 |
5 // ------------------------------------ | |
6 // ... | |
7 // ------------------------------------ | |
8 #include "GL/glew.h" | 25 #include "GL/glew.h" |
9 | 26 |
10 #include "KX_BlenderMaterial.h" | 27 #include "KX_BlenderMaterial.h" |
11 #include "BL_Material.h" | 28 #include "BL_Material.h" |
12 #include "KX_Scene.h" | 29 #include "KX_Scene.h" |
13 #include "KX_Light.h" | 30 #include "KX_Light.h" |
14 #include "KX_GameObject.h" | 31 #include "KX_GameObject.h" |
15 #include "KX_MeshProxy.h" | 32 #include "KX_MeshProxy.h" |
16 | 33 |
17 #include "MT_Vector3.h" | |
18 #include "MT_Vector4.h" | |
19 #include "MT_Matrix4x4.h" | |
20 | |
21 #include "RAS_BucketManager.h" | |
22 #include "RAS_MeshObject.h" | |
23 #include "RAS_IRasterizer.h" | |
24 #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h" | |
25 | |
26 #include "GPU_draw.h" | |
27 | |
28 #include "STR_HashedString.h" | |
29 | |
30 // ------------------------------------ | |
31 #include "DNA_object_types.h" | |
32 #include "DNA_material_types.h" | |
33 #include "DNA_image_types.h" | |
34 #include "DNA_meshdata_types.h" | 34 #include "DNA_meshdata_types.h" |
35 #include "BKE_mesh.h" | 35 #include "BKE_mesh.h" |
36 // ------------------------------------ | 36 // ------------------------------------ |
37 #include "BLI_utildefines.h" | |
38 | |
39 #define spit(x) std::cout << x << std::endl; | 37 #define spit(x) std::cout << x << std::endl; |
40 | 38 |
41 BL_Shader *KX_BlenderMaterial::mLastShader = NULL; | 39 BL_Shader *KX_BlenderMaterial::mLastShader = NULL; |
42 BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL; | |
43 | |
44 //static PyObject *gTextureDict = 0; | |
45 | |
46 KX_BlenderMaterial::KX_BlenderMaterial() | |
47 : PyObjectPlus(), | |
48 RAS_IPolyMaterial(), | |
49 mMaterial(NULL), | |
50 mShader(0), | |
51 mBlenderShader(0), | |
52 mScene(NULL), | |
53 mUserDefBlend(0), | |
54 mModified(0), | |
55 mConstructed(false), | |
56 mPass(0) | |
57 { | |
58 } | |
59 | |
60 void KX_BlenderMaterial::Initialize( | |
61 KX_Scene *scene, | |
62 BL_Material *data, | |
63 GameOptions *gameopt) | |
64 { | |
65 //convert gameopt to flag awesome based system BGEmodes | |
66 RAS_IPolyMaterial::Initialize( | |
67 data->texname[0], | |
68 data->matname, | |
69 data->materialindex, data->tile, | |
70 data->tilexrep[0], | |
71 data->tileyrep[0], | |
72 data->transp, | |
73 ((data->ras_mode &ALPHA)!=0), | |
74 ((data->ras_mode &ZSORT)!=0), | |
75 ((data->ras_mode &USE_LIGHT)!=0), | |
76 ((data->ras_mode &TEX)), | |
77 gameopt | |
78 ); | |
79 mMaterial = data; | |
80 mShader = 0; | |
81 mBlenderShader = 0; | |
82 mScene = scene; | |
83 mUserDefBlend = 0; | |
84 mModified = 0; | |
85 mConstructed = false; | |
86 mPass = 0; | |
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 m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0; | |
93 | |
94 // figure max | |
95 int enabled = mMaterial->num_enabled; | |
96 int max = BL_Texture::GetMaxUnits(); | |
97 mMaterial->num_enabled = enabled>=max?max:enabled; | |
98 | |
99 // test the sum of the various modes for equality | |
100 // so we can ether accept or reject this material· | |
101 // as being equal, this is rather important to· | |
102 // prevent material bleeding | |
103 for(int i=0; i<mMaterial->num_enabled; i++) { | |
104 m_multimode += | |
105 ( mMaterial->flag[i] + | |
106 mMaterial->blend_mode[i] | |
107 ); | |
108 } | |
109 m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(USE_LIGHT)); | |
110 } | |
111 | |
112 KX_BlenderMaterial::~KX_BlenderMaterial() | |
113 { | |
114 // cleanup work | |
115 if (mConstructed) | |
116 // clean only if material was actually used | |
117 OnExit(); | |
118 } | |
119 | |
120 MTFace* KX_BlenderMaterial::GetMTFace(void) const· | |
121 { | |
122 // fonts on polys | |
123 MT_assert(mMaterial->tface); | |
124 return mMaterial->tface; | |
125 } | |
126 | |
127 unsigned int* KX_BlenderMaterial::GetMCol(void) const· | |
128 { | |
129 // fonts on polys | |
130 return mMaterial->rgb; | |
131 } | |
132 | |
133 void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const | |
134 { | |
135 if (mMaterial) { | |
136 *rgba++ = (unsigned char) (mMaterial->matcolor[0]*255.0); | |
137 *rgba++ = (unsigned char) (mMaterial->matcolor[1]*255.0); | |
138 *rgba++ = (unsigned char) (mMaterial->matcolor[2]*255.0); | |
139 *rgba++ = (unsigned char) (mMaterial->matcolor[3]*255.0); | |
140 } else | |
141 RAS_IPolyMaterial::GetMaterialRGBAColor(rgba); | |
142 } | |
143 | |
144 Material *KX_BlenderMaterial::GetBlenderMaterial() const | |
145 { | |
146 return mMaterial->material; | |
147 } | |
148 | |
149 Scene* KX_BlenderMaterial::GetBlenderScene() const | |
150 { | |
151 return mScene->GetBlenderScene(); | |
152 } | |
153 | |
154 void KX_BlenderMaterial::ReleaseMaterial() | |
155 { | |
156 if (mBlenderShader) | |
157 mBlenderShader->ReloadMaterial(); | |
158 } | |
159 | |
160 void KX_BlenderMaterial::OnConstruction(int layer) | |
161 { | |
162 if (mConstructed) | |
163 // when material are reused between objects | |
164 return; | |
165 ········ | |
166 if(mMaterial->glslmat) | |
167 SetBlenderGLSLShader(layer); | |
168 | |
169 // for each unique material... | |
170 int i; | |
171 for(i=0; i<mMaterial->num_enabled; i++) { | |
172 if( mMaterial->mapping[i].mapping & USEENV ) { | |
173 if(!GLEW_ARB_texture_cube_map) { | |
174 spit("CubeMap textures not supported"); | |
175 continue; | |
176 } | |
177 if(!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] )
) | |
178 spit("unable to initialize image("<<i<<") in "<<······· | |
179 mMaterial->matname<< ", image w
ill not be available"); | |
180 }· | |
181 ········ | |
182 else { | |
183 if( mMaterial->img[i] ) { | |
184 if( ! mTextures[i].InitFromImage(i, mMaterial->i
mg[i], (mMaterial->flag[i] &MIPMAP)!=0 )) | |
185 spit("unable to initialize image("<<i<<"
) in "<<· | |
186 mMaterial->matname<< ", image wi
ll not be available"); | |
187 } | |
188 } | |
189 } | |
190 | |
191 mBlendFunc[0] =0; | |
192 mBlendFunc[1] =0; | |
193 mConstructed = true; | |
194 } | |
195 | |
196 void KX_BlenderMaterial::EndFrame() | |
197 { | |
198 if(mLastBlenderShader) { | |
199 mLastBlenderShader->SetProg(false); | |
200 mLastBlenderShader = NULL; | |
201 } | |
202 | |
203 if(mLastShader) { | |
204 mLastShader->SetProg(false); | |
205 mLastShader = NULL; | |
206 } | |
207 } | |
208 | |
209 void KX_BlenderMaterial::OnExit() | |
210 { | |
211 if( mShader ) { | |
212 //note, the shader here is allocated, per unique material | |
213 //and this function is called per face | |
214 if(mShader == mLastShader) { | |
215 mShader->SetProg(false); | |
216 mLastShader = NULL; | |
217 } | |
218 | |
219 delete mShader; | |
220 mShader = 0; | |
221 } | |
222 | |
223 if( mBlenderShader ) { | |
224 if(mBlenderShader == mLastBlenderShader) { | |
225 mBlenderShader->SetProg(false); | |
226 mLastBlenderShader = NULL; | |
227 } | |
228 | |
229 delete mBlenderShader; | |
230 mBlenderShader = 0; | |
231 } | |
232 | |
233 BL_Texture::ActivateFirst(); | |
234 for(int i=0; i<mMaterial->num_enabled; i++) { | |
235 BL_Texture::ActivateUnit(i); | |
236 mTextures[i].DeleteTex(); | |
237 mTextures[i].DisableUnit(); | |
238 } | |
239 | |
240 if( mMaterial->tface )· | |
241 GPU_set_tpage(mMaterial->tface, 1, mMaterial->transp); | |
242 } | |
243 | |
244 | |
245 void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) | |
246 { | |
247 MT_assert(GLEW_ARB_shader_objects && mShader); | |
248 | |
249 int i; | |
250 if( !enable || !mShader->Ok() ) { | |
251 // frame cleanup. | |
252 if(mShader == mLastShader) { | |
253 mShader->SetProg(false); | |
254 mLastShader = NULL; | |
255 } | |
256 | |
257 ras->SetBlendingMode(TF_SOLID); | |
258 BL_Texture::DisableAllTextures(); | |
259 return; | |
260 } | |
261 | |
262 BL_Texture::DisableAllTextures(); | |
263 mShader->SetProg(true); | |
264 mLastShader = mShader; | |
265 ········ | |
266 BL_Texture::ActivateFirst(); | |
267 | |
268 mShader->ApplyShader(); | |
269 | |
270 // for each enabled unit | |
271 for(i=0; i<mMaterial->num_enabled; i++) { | |
272 if(!mTextures[i].Ok()) continue; | |
273 mTextures[i].ActivateTexture(); | |
274 mTextures[0].SetMapping(mMaterial->mapping[i].mapping); | |
275 } | |
276 | |
277 if(!mUserDefBlend) { | |
278 ras->SetBlendingMode(mMaterial->transp); | |
279 } | |
280 else { | |
281 ras->SetBlendingMode(TF_SOLID); | |
282 ras->SetBlendingMode(-1); // indicates custom mode | |
283 | |
284 // tested to be valid enums | |
285 glEnable(GL_BLEND); | |
286 glBlendFunc(mBlendFunc[0], mBlendFunc[1]); | |
287 } | |
288 } | |
289 | |
290 void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras
) | |
291 { | |
292 if( !enable || !mBlenderShader->Ok() ) { | |
293 ras->SetBlendingMode(TF_SOLID); | |
294 | |
295 // frame cleanup. | |
296 if(mLastBlenderShader) { | |
297 mLastBlenderShader->SetProg(false); | |
298 mLastBlenderShader= NULL; | |
299 } | |
300 else | |
301 BL_Texture::DisableAllTextures(); | |
302 | |
303 return; | |
304 } | |
305 | |
306 if(!mBlenderShader->Equals(mLastBlenderShader)) { | |
307 ras->SetBlendingMode(mMaterial->transp); | |
308 | |
309 if(mLastBlenderShader) | |
310 mLastBlenderShader->SetProg(false); | |
311 else | |
312 BL_Texture::DisableAllTextures(); | |
313 | |
314 mBlenderShader->SetProg(true, ras->GetTime()); | |
315 mLastBlenderShader= mBlenderShader; | |
316 } | |
317 } | |
318 | |
319 void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) | |
320 { | |
321 BL_Texture::DisableAllTextures(); | |
322 | |
323 if( !enable ) { | |
324 ras->SetBlendingMode(TF_SOLID); | |
325 return; | |
326 } | |
327 | |
328 BL_Texture::ActivateFirst(); | |
329 | |
330 if( mMaterial->IdMode == DEFAULT_BLENDER ) { | |
331 ras->SetBlendingMode(mMaterial->transp); | |
332 return; | |
333 } | |
334 | |
335 if( mMaterial->IdMode == TEXFACE ) { | |
336 // no material connected to the object | |
337 if( mTextures[0].Ok() ) { | |
338 mTextures[0].ActivateTexture(); | |
339 mTextures[0].setTexEnv(0, true); | |
340 mTextures[0].SetMapping(mMaterial->mapping[0].mapping); | |
341 ras->SetBlendingMode(mMaterial->transp); | |
342 } | |
343 return; | |
344 } | |
345 | |
346 int mode = 0,i=0; | |
347 for(i=0; (i<mMaterial->num_enabled && i<MAXTEX); i++) { | |
348 if( !mTextures[i].Ok() ) continue; | |
349 | |
350 mTextures[i].ActivateTexture(); | |
351 mTextures[i].setTexEnv(mMaterial); | |
352 mode = mMaterial->mapping[i].mapping; | |
353 | |
354 if(mode &USEOBJ) | |
355 setObjectMatrixData(i, ras); | |
356 else | |
357 mTextures[i].SetMapping(mode); | |
358 ················ | |
359 if(!(mode &USEOBJ)) | |
360 setTexMatrixData( i ); | |
361 } | |
362 | |
363 if(!mUserDefBlend) { | |
364 ras->SetBlendingMode(mMaterial->transp); | |
365 } | |
366 else { | |
367 ras->SetBlendingMode(TF_SOLID); | |
368 ras->SetBlendingMode(-1); // indicates custom mode | |
369 | |
370 glEnable(GL_BLEND); | |
371 glBlendFunc(mBlendFunc[0], mBlendFunc[1]); | |
372 } | |
373 } | |
374 | |
375 void | |
376 KX_BlenderMaterial::ActivatShaders( | |
377 RAS_IRasterizer* rasty,· | |
378 TCachingInfo& cachingInfo)const | |
379 { | |
380 KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); | |
381 | |
382 // reset...· | |
383 if(tmp->mMaterial->IsShared())· | |
384 cachingInfo =0; | |
385 | |
386 if(mLastBlenderShader) { | |
387 mLastBlenderShader->SetProg(false); | |
388 mLastBlenderShader= NULL; | |
389 } | |
390 | |
391 if (GetCachingInfo() != cachingInfo) { | |
392 | |
393 if (!cachingInfo) | |
394 tmp->setShaderData(false, rasty); | |
395 ················ | |
396 cachingInfo = GetCachingInfo(); | |
397 ········ | |
398 if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) | |
399 tmp->setShaderData(true, rasty); | |
400 else | |
401 tmp->setShaderData(false, rasty); | |
402 | |
403 if (mMaterial->ras_mode &TWOSIDED) | |
404 rasty->SetCullFace(false); | |
405 else | |
406 rasty->SetCullFace(true); | |
407 | |
408 if ((mMaterial->ras_mode &WIRE) || | |
409 (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) | |
410 {··············· | |
411 if (mMaterial->ras_mode &WIRE)· | |
412 rasty->SetCullFace(false); | |
413 rasty->SetLines(true); | |
414 } | |
415 else | |
416 rasty->SetLines(false); | |
417 ActivatGLMaterials(rasty); | |
418 ActivateTexGen(rasty); | |
419 } | |
420 | |
421 //ActivatGLMaterials(rasty); | |
422 //ActivateTexGen(rasty); | |
423 } | |
424 | |
425 void | |
426 KX_BlenderMaterial::ActivateBlenderShaders( | |
427 RAS_IRasterizer* rasty,· | |
428 TCachingInfo& cachingInfo)const | |
429 { | |
430 KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); | |
431 | |
432 if(mLastShader) { | |
433 mLastShader->SetProg(false); | |
434 mLastShader= NULL; | |
435 } | |
436 | |
437 if (GetCachingInfo() != cachingInfo) { | |
438 if (!cachingInfo) | |
439 tmp->setBlenderShaderData(false, rasty); | |
440 ················ | |
441 cachingInfo = GetCachingInfo(); | |
442 ········ | |
443 if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) | |
444 tmp->setBlenderShaderData(true, rasty); | |
445 else | |
446 tmp->setBlenderShaderData(false, rasty); | |
447 | |
448 if (mMaterial->ras_mode &TWOSIDED) | |
449 rasty->SetCullFace(false); | |
450 else | |
451 rasty->SetCullFace(true); | |
452 | |
453 if ((mMaterial->ras_mode &WIRE) || | |
454 (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) | |
455 {··············· | |
456 if (mMaterial->ras_mode &WIRE)· | |
457 rasty->SetCullFace(false); | |
458 rasty->SetLines(true); | |
459 } | |
460 else | |
461 rasty->SetLines(false); | |
462 | |
463 ActivatGLMaterials(rasty); | |
464 mBlenderShader->SetAttribs(rasty, mMaterial); | |
465 } | |
466 } | |
467 | |
468 void | |
469 KX_BlenderMaterial::ActivateMat(· | |
470 RAS_IRasterizer* rasty,·· | |
471 TCachingInfo& cachingInfo | |
472 )const | |
473 { | |
474 KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); | |
475 | |
476 if(mLastShader) { | |
477 mLastShader->SetProg(false); | |
478 mLastShader= NULL; | |
479 } | |
480 | |
481 if(mLastBlenderShader) { | |
482 mLastBlenderShader->SetProg(false); | |
483 mLastBlenderShader= NULL; | |
484 } | |
485 | |
486 if (GetCachingInfo() != cachingInfo) { | |
487 if (!cachingInfo)· | |
488 tmp->setTexData( false,rasty ); | |
489 ················ | |
490 cachingInfo = GetCachingInfo(); | |
491 | |
492 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) | |
493 tmp->setTexData( true,rasty ); | |
494 else | |
495 tmp->setTexData( false,rasty); | |
496 | |
497 if (mMaterial->ras_mode &TWOSIDED) | |
498 rasty->SetCullFace(false); | |
499 else | |
500 rasty->SetCullFace(true); | |
501 | |
502 if ((mMaterial->ras_mode &WIRE) || | |
503 (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) | |
504 {··············· | |
505 if (mMaterial->ras_mode &WIRE)· | |
506 rasty->SetCullFace(false); | |
507 rasty->SetLines(true); | |
508 } | |
509 else | |
510 rasty->SetLines(false); | |
511 ActivatGLMaterials(rasty); | |
512 ActivateTexGen(rasty); | |
513 } | |
514 | |
515 //ActivatGLMaterials(rasty); | |
516 //ActivateTexGen(rasty); | |
517 } | |
518 | |
519 bool· | |
520 KX_BlenderMaterial::Activate(· | |
521 RAS_IRasterizer* rasty,·· | |
522 TCachingInfo& cachingInfo | |
523 )const | |
524 { | |
525 if(GLEW_ARB_shader_objects && (mShader && mShader->Ok())) { | |
526 if((mPass++) < mShader->getNumPass() ) { | |
527 ActivatShaders(rasty, cachingInfo); | |
528 return true; | |
529 } | |
530 else { | |
531 if(mShader == mLastShader) { | |
532 mShader->SetProg(false); | |
533 mLastShader = NULL; | |
534 } | |
535 mPass = 0; | |
536 return false; | |
537 } | |
538 } | |
539 else if( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->O
k() ) ) { | |
540 if(mPass++ == 0) { | |
541 ActivateBlenderShaders(rasty, cachingInfo); | |
542 return true; | |
543 } | |
544 else { | |
545 mPass = 0; | |
546 return false; | |
547 } | |
548 } | |
549 else { | |
550 if(mPass++ == 0) { | |
551 ActivateMat(rasty, cachingInfo); | |
552 return true; | |
553 } | |
554 else { | |
555 mPass = 0; | |
556 return false; | |
557 } | |
558 } | |
559 } | |
560 | |
561 bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const | |
562 { | |
563 if(!RAS_IPolyMaterial::UsesLighting(rasty)) | |
564 return false; | |
565 | |
566 if(mShader && mShader->Ok()) | |
567 return true; | |
568 else if(mBlenderShader && mBlenderShader->Ok()) | |
569 return false; | |
570 else | |
571 return true; | |
572 } | |
573 | |
574 void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasteriz
er* rasty) const | |
575 { | |
576 if(mShader && GLEW_ARB_shader_objects) { | |
577 mShader->Update(ms, rasty); | |
578 } | |
579 else if(mBlenderShader && GLEW_ARB_shader_objects) { | |
580 int blendmode; | |
581 | |
582 mBlenderShader->Update(ms, rasty); | |
583 | |
584 /* we do blend modes here, because they can change per object | |
585 * with the same material due to obcolor/obalpha */ | |
586 blendmode = mBlenderShader->GetBlendMode(); | |
587 if(ELEM3(blendmode, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT)
&& mMaterial->transp != GEMAT_SOLID) | |
588 blendmode = mMaterial->transp; | |
589 | |
590 rasty->SetBlendingMode(blendmode); | |
591 } | |
592 } | |
593 | |
594 void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const | |
595 { | |
596 if(mShader || !mBlenderShader) { | |
597 rasty->SetSpecularity( | |
598 mMaterial->speccolor[0]*mMaterial->spec_f, | |
599 mMaterial->speccolor[1]*mMaterial->spec_f, | |
600 mMaterial->speccolor[2]*mMaterial->spec_f, | |
601 mMaterial->spec_f | |
602 ); | |
603 | |
604 rasty->SetShinyness( mMaterial->hard ); | |
605 | |
606 rasty->SetDiffuse( | |
607 mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit,· | |
608 mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit, | |
609 mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit, | |
610 1.0f); | |
611 | |
612 rasty->SetEmissive(····· | |
613 mMaterial->matcolor[0]*mMaterial->emit, | |
614 mMaterial->matcolor[1]*mMaterial->emit, | |
615 mMaterial->matcolor[2]*mMaterial->emit, | |
616 1.0 ); | |
617 | |
618 rasty->SetAmbient(mMaterial->amb); | |
619 } | |
620 | |
621 if (mMaterial->material) | |
622 rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0); | |
623 } | |
624 | |
625 | |
626 void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const | |
627 { | |
628 if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { | |
629 ras->SetAttribNum(0); | |
630 if(mShader && GLEW_ARB_shader_objects) { | |
631 if(mShader->GetAttribute() == BL_Shader::SHD_TANGENT) { | |
632 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABL
E, 0); | |
633 ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT,
1); | |
634 ras->SetAttribNum(2); | |
635 } | |
636 } | |
637 | |
638 ras->SetTexCoordNum(mMaterial->num_enabled); | |
639 | |
640 for(int i=0; i<mMaterial->num_enabled; i++) { | |
641 int mode = mMaterial->mapping[i].mapping; | |
642 | |
643 if (mode &USECUSTOMUV) | |
644 { | |
645 if (!mMaterial->mapping[i].uvCoName.IsEmpty()) | |
646 ras->SetTexCoord(RAS_IRasterizer::RAS_TE
XCO_UV2, i); | |
647 continue; | |
648 } | |
649 | |
650 if( mode &(USEREFL|USEOBJ)) | |
651 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_GEN,
i); | |
652 else if(mode &USEORCO) | |
653 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_ORCO
, i); | |
654 else if(mode &USENORM) | |
655 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_NORM
, i); | |
656 else if(mode &USEUV) | |
657 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV1,
i); | |
658 else if(mode &USETANG) | |
659 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXTANGENT
, i); | |
660 else· | |
661 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISA
BLE, i); | |
662 } | |
663 } | |
664 } | |
665 | |
666 void KX_BlenderMaterial::setTexMatrixData(int i) | |
667 { | |
668 glMatrixMode(GL_TEXTURE); | |
669 glLoadIdentity(); | |
670 | |
671 if( GLEW_ARB_texture_cube_map &&· | |
672 mTextures[i].GetTextureType() == GL_TEXTURE_CUBE_MAP_ARB &&· | |
673 mMaterial->mapping[i].mapping & USEREFL) { | |
674 glScalef(· | |
675 mMaterial->mapping[i].scale[0],· | |
676 -mMaterial->mapping[i].scale[1],· | |
677 -mMaterial->mapping[i].scale[2] | |
678 ); | |
679 } | |
680 else | |
681 { | |
682 glScalef(· | |
683 mMaterial->mapping[i].scale[0],· | |
684 mMaterial->mapping[i].scale[1],· | |
685 mMaterial->mapping[i].scale[2] | |
686 ); | |
687 } | |
688 glTranslatef( | |
689 mMaterial->mapping[i].offsets[0], | |
690 mMaterial->mapping[i].offsets[1],· | |
691 mMaterial->mapping[i].offsets[2] | |
692 ); | |
693 | |
694 glMatrixMode(GL_MODELVIEW); | |
695 | |
696 } | |
697 | |
698 static void GetProjPlane(BL_Material *mat, int index,int num, float*param) | |
699 { | |
700 param[0]=param[1]=param[2]=param[3]=0.f; | |
701 if( mat->mapping[index].projplane[num] == PROJX ) | |
702 param[0] = 1.f; | |
703 else if( mat->mapping[index].projplane[num] == PROJY ) | |
704 param[1] = 1.f; | |
705 else if( mat->mapping[index].projplane[num] == PROJZ) | |
706 param[2] = 1.f; | |
707 } | |
708 | |
709 void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras) | |
710 { | |
711 KX_GameObject *obj =· | |
712 (KX_GameObject*) | |
713 mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objcona
me); | |
714 | |
715 if(!obj) return; | |
716 | |
717 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); | |
718 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); | |
719 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); | |
720 | |
721 GLenum plane = GL_EYE_PLANE; | |
722 | |
723 // figure plane gen | |
724 float proj[4]= {0.f,0.f,0.f,0.f}; | |
725 GetProjPlane(mMaterial, i, 0, proj); | |
726 glTexGenfv(GL_S, plane, proj); | |
727 ········ | |
728 GetProjPlane(mMaterial, i, 1, proj); | |
729 glTexGenfv(GL_T, plane, proj); | |
730 | |
731 GetProjPlane(mMaterial, i, 2, proj); | |
732 glTexGenfv(GL_R, plane, proj); | |
733 | |
734 glEnable(GL_TEXTURE_GEN_S); | |
735 glEnable(GL_TEXTURE_GEN_T); | |
736 glEnable(GL_TEXTURE_GEN_R); | |
737 | |
738 const MT_Matrix4x4& mvmat = ras->GetViewMatrix(); | |
739 | |
740 glMatrixMode(GL_TEXTURE); | |
741 glLoadIdentity(); | |
742 glScalef(· | |
743 mMaterial->mapping[i].scale[0],· | |
744 mMaterial->mapping[i].scale[1],· | |
745 mMaterial->mapping[i].scale[2] | |
746 ); | |
747 | |
748 MT_Point3 pos = obj->NodeGetWorldPosition(); | |
749 MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f); | |
750 MT_Vector4 t = mvmat*matmul; | |
751 | |
752 glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) ); | |
753 | |
754 glMatrixMode(GL_MODELVIEW); | |
755 | |
756 } | |
757 | |
758 // ------------------------------------ | |
759 void KX_BlenderMaterial::UpdateIPO( | |
760 MT_Vector4 rgba, | |
761 MT_Vector3 specrgb, | |
762 MT_Scalar hard, | |
763 MT_Scalar spec, | |
764 MT_Scalar ref, | |
765 MT_Scalar emit, | |
766 MT_Scalar alpha | |
767 ) | |
768 { | |
769 // only works one deep now | |
770 mMaterial->speccolor[0] = (float)(specrgb)[0]; | |
771 mMaterial->speccolor[1] = (float)(specrgb)[1]; | |
772 mMaterial->speccolor[2] = (float)(specrgb)[2]; | |
773 mMaterial->matcolor[0] = (float)(rgba[0]); | |
774 mMaterial->matcolor[1] = (float)(rgba[1]); | |
775 mMaterial->matcolor[2] = (float)(rgba[2]); | |
776 mMaterial->alpha = (float)(alpha); | |
777 mMaterial->hard = (float)(hard); | |
778 mMaterial->emit = (float)(emit); | |
779 mMaterial->spec_f = (float)(spec); | |
780 mMaterial->ref = (float)(ref); | |
781 } | |
782 | |
783 void KX_BlenderMaterial::SetBlenderGLSLShader(int layer) | |
784 { | |
785 if(!mBlenderShader) | |
786 mBlenderShader = new BL_BlenderShader(mScene, mMaterial->materia
l, layer); | |
787 | |
788 if(!mBlenderShader->Ok()) { | |
789 delete mBlenderShader; | |
790 mBlenderShader = 0; | |
791 } | |
792 } | |
793 | |
794 #ifdef WITH_PYTHON | |
795 | |
796 PyMethodDef KX_BlenderMaterial::Methods[] =· | |
797 { | |
798 KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ), | |
799 KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ), | |
800 KX_PYMETHODTABLE( KX_BlenderMaterial, setBlending ), | |
801 {NULL,NULL} //Sentinel | |
802 }; | |
803 | |
804 PyAttributeDef KX_BlenderMaterial::Attributes[] = { | |
805 KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shad
er), | |
806 KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_
get_materialIndex), | |
807 KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_bl
ending, pyattr_set_blending), | |
808 { NULL } //Sentinel | |
809 }; | |
810 | |
811 PyTypeObject KX_BlenderMaterial::Type = { | |
812 PyVarObject_HEAD_INIT(NULL, 0) | |
813 "KX_BlenderMaterial", | |
814 sizeof(PyObjectPlus_Proxy), | |
815 0, | |
816 py_base_dealloc, | |
817 0, | |
818 0, | |
819 0, | |
820 0, | |
821 py_base_repr, | |
822 0,0,0,0,0,0,0,0,0, | |
823 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | |
824 0,0,0,0,0,0,0, | |
825 Methods, | |
826 0, | |
827 0, | |
828 &PyObjectPlus::Type, | |
829 0,0,0,0,0,0, | |
830 py_base_new | |
831 }; | |
832 | |
833 PyObject* KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBU
TE_DEF *attrdef) | |
834 { | |
835 KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v); | |
836 return self->PygetShader(NULL, NULL); | |
837 } | |
838 | |
839 PyObject* KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PY
ATTRIBUTE_DEF *attrdef) | |
840 { | |
841 KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v); | |
842 return PyLong_FromSsize_t(self->GetMaterialIndex()); | |
843 } | |
844 | |
845 PyObject* KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRI
BUTE_DEF *attrdef) | |
846 { | |
847 KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v); | |
848 unsigned int* bfunc = self->getBlendFunc(); | |
849 return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]); | |
850 } | |
851 | |
852 int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_D
EF *attrdef, PyObject *value) | |
853 { | |
854 KX_BlenderMaterial* self= static_cast<KX_BlenderMaterial*>(self_v); | |
855 PyObject* obj = self->PysetBlending(value, NULL); | |
856 if(obj) | |
857 { | |
858 Py_DECREF(obj); | |
859 return 0; | |
860 } | |
861 return -1; | |
862 } | |
863 | |
864 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") | |
865 { | |
866 if( !GLEW_ARB_fragment_shader) { | |
867 if(!mModified) | |
868 spit("Fragment shaders not supported"); | |
869 ········ | |
870 mModified = true; | |
871 Py_RETURN_NONE; | |
872 } | |
873 | |
874 if( !GLEW_ARB_vertex_shader) { | |
875 if(!mModified) | |
876 spit("Vertex shaders not supported"); | |
877 | |
878 mModified = true; | |
879 Py_RETURN_NONE; | |
880 } | |
881 | |
882 if(!GLEW_ARB_shader_objects) { | |
883 if(!mModified) | |
884 spit("GLSL not supported"); | |
885 mModified = true; | |
886 Py_RETURN_NONE; | |
887 } | |
888 else { | |
889 // returns Py_None on error | |
890 // the calling script will need to check | |
891 | |
892 if(!mShader && !mModified) { | |
893 mShader = new BL_Shader(); | |
894 mModified = true; | |
895 } | |
896 | |
897 if(mShader && !mShader->GetError()) { | |
898 m_flag &= ~RAS_BLENDERGLSL; | |
899 mMaterial->SetSharedMaterial(true); | |
900 mScene->GetBucketManager()->ReleaseDisplayLists(this); | |
901 return mShader->GetProxy(); | |
902 }else | |
903 { | |
904 // decref all references to the object | |
905 // then delete it! | |
906 // We will then go back to fixed functionality | |
907 // for this material | |
908 if(mShader) { | |
909 delete mShader; /* will handle python de-referen
cing */ | |
910 mShader=0; | |
911 } | |
912 } | |
913 Py_RETURN_NONE; | |
914 } | |
915 PyErr_SetString(PyExc_ValueError, "material.getShader(): KX_BlenderMater
ial, GLSL Error"); | |
916 return NULL; | |
917 } | |
918 | |
919 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") | |
920 { | |
921 return PyLong_FromSsize_t( GetMaterialIndex() ); | |
922 } | |
923 | |
924 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" ) | |
925 { | |
926 // TODO: enable python switching | |
927 return NULL; | |
928 } | |
929 | |
930 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)") | |
931 { | |
932 // TODO: enable python switching | |
933 return NULL; | |
934 } | |
935 | |
936 static unsigned int GL_array[11] = { | |
937 GL_ZERO, | |
938 GL_ONE, | |
939 GL_SRC_COLOR, | |
940 GL_ONE_MINUS_SRC_COLOR, | |
941 GL_DST_COLOR, | |
942 GL_ONE_MINUS_DST_COLOR, | |
943 GL_SRC_ALPHA, | |
944 GL_ONE_MINUS_SRC_ALPHA, | |
945 GL_DST_ALPHA, | |
946 GL_ONE_MINUS_DST_ALPHA, | |
947 GL_SRC_ALPHA_SATURATE | |
948 }; | |
949 | |
950 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( bge.logic.sr
c, bge.logic.dest)") | |
951 { | |
952 unsigned int b[2]; | |
953 if(PyArg_ParseTuple(args, "ii:setBlending", &b[0], &b[1])) | |
954 { | |
955 bool value_found[2] = {false, false}; | |
956 for(int i=0; i<11; i++) | |
957 { | |
958 if(b[0] == GL_array[i]) { | |
959 value_found[0] = true; | |
960 mBlendFunc[0] = b[0]; | |
961 } | |
962 if(b[1] == GL_array[i]) { | |
963 value_found[1] = true; | |
964 mBlendFunc[1] = b[1]; | |
965 } | |
966 if(value_found[0] && value_found[1]) break; | |
967 } | |
968 if(!value_found[0] || !value_found[1]) { | |
969 PyErr_SetString(PyExc_ValueError, "material.setBlending(
int, int): KX_BlenderMaterial, invalid enum."); | |
970 return NULL; | |
971 } | |
972 mUserDefBlend = true; | |
973 Py_RETURN_NONE; | |
974 } | |
975 return NULL; | |
976 } | |
977 | |
978 #endif // WITH_PYTHON | |
LEFT | RIGHT |