Cleanup: Nuke most of G.main from GPU code.
[blender.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_OpenGLRasterizer.cpp
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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
29  *  \ingroup bgerastogl
30  */
31
32
33 #include <math.h>
34 #include <stdlib.h>
35
36 #include "RAS_OpenGLRasterizer.h"
37
38 #include "GPU_glew.h"
39
40 #include "RAS_ICanvas.h"
41 #include "RAS_Rect.h"
42 #include "RAS_TexVert.h"
43 #include "RAS_MeshObject.h"
44 #include "RAS_Polygon.h"
45 #include "RAS_ILightObject.h"
46 #include "MT_CmMatrix4x4.h"
47
48 #include "RAS_OpenGLLight.h"
49 #include "RAS_OpenGLOffScreen.h"
50 #include "RAS_OpenGLSync.h"
51
52 #include "RAS_StorageVA.h"
53 #include "RAS_StorageVBO.h"
54
55 #include "GPU_draw.h"
56 #include "GPU_extensions.h"
57 #include "GPU_material.h"
58 #include "GPU_shader.h"
59
60 extern "C"{
61         #include "BLF_api.h"
62         #include "BKE_DerivedMesh.h"
63         #include "BKE_global.h"
64 }
65
66
67 // XXX Clean these up <<<
68 #include "EXP_Value.h"
69 #include "KX_Scene.h"
70 #include "KX_RayCast.h"
71 #include "KX_GameObject.h"
72 // >>>
73
74 #ifndef M_PI
75 #define M_PI            3.14159265358979323846
76 #endif
77
78 /**
79  *  32x32 bit masks for vinterlace stereo mode
80  */
81 static GLuint left_eye_vinterlace_mask[32];
82 static GLuint right_eye_vinterlace_mask[32];
83
84 /**
85  *  32x32 bit masks for hinterlace stereo mode.
86  *  Left eye = &hinterlace_mask[0]
87  *  Right eye = &hinterlace_mask[1]
88  */
89 static GLuint hinterlace_mask[33];
90
91 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, RAS_STORAGE_TYPE storage)
92         :RAS_IRasterizer(canvas),
93         m_2DCanvas(canvas),
94         m_fogenabled(false),
95         m_time(0.0f),
96         m_campos(0.0f, 0.0f, 0.0f),
97         m_camortho(false),
98         m_camnegscale(false),
99         m_stereomode(RAS_STEREO_NOSTEREO),
100         m_curreye(RAS_STEREO_LEFTEYE),
101         m_eyeseparation(0.0f),
102         m_focallength(0.0f),
103         m_setfocallength(false),
104         m_noOfScanlines(32),
105         m_motionblur(0),
106         m_motionblurvalue(-1.0f),
107         m_usingoverrideshader(false),
108         m_clientobject(NULL),
109         m_auxilaryClientInfo(NULL),
110         m_drawingmode(KX_TEXTURED),
111         m_texco_num(0),
112         m_attrib_num(0),
113         //m_last_alphablend(GPU_BLEND_SOLID),
114         m_last_frontface(true),
115         m_materialCachingInfo(0),
116         m_storage_type(storage)
117 {
118         m_viewmatrix.setIdentity();
119         m_viewinvmatrix.setIdentity();
120
121         for (int i = 0; i < 32; i++)
122         {
123                 left_eye_vinterlace_mask[i] = 0x55555555;
124                 right_eye_vinterlace_mask[i] = 0xAAAAAAAA;
125                 hinterlace_mask[i] = (i&1)*0xFFFFFFFF;
126         }
127         hinterlace_mask[32] = 0;
128
129         m_prevafvalue = GPU_get_anisotropic();
130
131         if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE && GLEW_ARB_vertex_buffer_object*/) {
132                 m_storage = new RAS_StorageVBO(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
133         }
134         else if ((m_storage_type == RAS_VA) || (m_storage_type == RAS_AUTO_STORAGE)) {
135                 m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
136         }
137         else {
138                 printf("Unknown rasterizer storage type, falling back to vertex arrays\n");
139                 m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
140         }
141
142         glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &m_numgllights);
143         if (m_numgllights < 8)
144                 m_numgllights = 8;
145 }
146
147
148
149 RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
150 {
151         // Restore the previous AF value
152         GPU_set_anisotropic(G_MAIN, m_prevafvalue);
153
154         if (m_storage)
155                 delete m_storage;
156 }
157
158 bool RAS_OpenGLRasterizer::Init()
159 {
160         bool storage_init;
161         GPU_state_init();
162
163
164         m_ambr = 0.0f;
165         m_ambg = 0.0f;
166         m_ambb = 0.0f;
167
168         glDisable(GL_BLEND);
169         glDisable(GL_ALPHA_TEST);
170         //m_last_alphablend = GPU_BLEND_SOLID;
171         GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
172
173         glFrontFace(GL_CCW);
174         m_last_frontface = true;
175
176         m_redback = 0.4375f;
177         m_greenback = 0.4375f;
178         m_blueback = 0.4375f;
179         m_alphaback = 0.0f;
180
181         glClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
182         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
183         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
184
185
186         glShadeModel(GL_SMOOTH);
187
188         storage_init = m_storage->Init();
189
190         return true && storage_init;
191 }
192
193
194 void RAS_OpenGLRasterizer::SetAmbientColor(float color[3])
195 {
196         m_ambr = color[0];
197         m_ambg = color[1];
198         m_ambb = color[2];
199 }
200
201 void RAS_OpenGLRasterizer::SetAmbient(float factor)
202 {
203         float ambient[] = {m_ambr * factor, m_ambg * factor, m_ambb * factor, 1.0f};
204         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
205 }
206
207 void RAS_OpenGLRasterizer::SetBackColor(float color[3])
208 {
209         m_redback = color[0];
210         m_greenback = color[1];
211         m_blueback = color[2];
212         m_alphaback = 0.0f;
213 }
214
215 void RAS_OpenGLRasterizer::SetFog(short type, float start, float dist, float intensity, float color[3])
216 {
217         float params[4] = {color[0], color[1], color[2], 1.0f};
218         glFogi(GL_FOG_MODE, GL_LINEAR);
219         glFogf(GL_FOG_DENSITY, intensity / 10.0f);
220         glFogf(GL_FOG_START, start);
221         glFogf(GL_FOG_END, start + dist);
222         glFogfv(GL_FOG_COLOR, params);
223 }
224
225 void RAS_OpenGLRasterizer::EnableFog(bool enable)
226 {
227         m_fogenabled = enable;
228 }
229
230 void RAS_OpenGLRasterizer::DisplayFog()
231 {
232         if ((m_drawingmode >= KX_SOLID) && m_fogenabled) {
233                 glEnable(GL_FOG);
234         }
235         else {
236                 glDisable(GL_FOG);
237         }
238 }
239
240 bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
241 {
242         return mat.Activate(this, m_materialCachingInfo);
243 }
244
245
246
247 void RAS_OpenGLRasterizer::Exit()
248 {
249         m_storage->Exit();
250
251         glEnable(GL_CULL_FACE);
252         glEnable(GL_DEPTH_TEST);
253         glClearDepth(1.0f);
254         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
255         glClearColor(m_redback, m_greenback, m_blueback, m_alphaback);
256         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
257         glDepthMask (GL_TRUE);
258         glDepthFunc(GL_LEQUAL);
259         glBlendFunc(GL_ONE, GL_ZERO);
260
261         glDisable(GL_POLYGON_STIPPLE);
262
263         glDisable(GL_LIGHTING);
264         if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
265                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
266
267         EndFrame();
268 }
269
270 bool RAS_OpenGLRasterizer::BeginFrame(double time)
271 {
272         m_time = time;
273
274         // Blender camera routine destroys the settings
275         if (m_drawingmode < KX_SOLID)
276         {
277                 glDisable(GL_CULL_FACE);
278                 glDisable(GL_DEPTH_TEST);
279         }
280         else
281         {
282                 glEnable(GL_DEPTH_TEST);
283                 glEnable(GL_CULL_FACE);
284         }
285
286         glDisable(GL_BLEND);
287         glDisable(GL_ALPHA_TEST);
288         //m_last_alphablend = GPU_BLEND_SOLID;
289         GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
290
291         glFrontFace(GL_CCW);
292         m_last_frontface = true;
293
294         glShadeModel(GL_SMOOTH);
295
296         glEnable(GL_MULTISAMPLE_ARB);
297
298         m_2DCanvas->BeginFrame();
299
300         // Render Tools
301         m_clientobject = NULL;
302         m_lastlightlayer = -1;
303         m_lastauxinfo = NULL;
304         m_lastlighting = true; /* force disable in DisableOpenGLLights() */
305         DisableOpenGLLights();
306
307         return true;
308 }
309
310
311
312 void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
313 {
314         m_drawingmode = drawingmode;
315
316         if (m_drawingmode == KX_WIREFRAME)
317                 glDisable(GL_CULL_FACE);
318
319         m_storage->SetDrawingMode(drawingmode);
320 }
321
322 int RAS_OpenGLRasterizer::GetDrawingMode()
323 {
324         return m_drawingmode;
325 }
326
327
328 void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask)
329 {
330         glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE);
331 }
332
333
334 void RAS_OpenGLRasterizer::ClearColorBuffer()
335 {
336         m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
337         m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
338 }
339
340
341 void RAS_OpenGLRasterizer::ClearDepthBuffer()
342 {
343         m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER);
344 }
345
346
347 void RAS_OpenGLRasterizer::ClearCachingInfo(void)
348 {
349         m_materialCachingInfo = 0;
350 }
351
352 void RAS_OpenGLRasterizer::FlushDebugShapes(SCA_IScene *scene)
353 {
354         std::vector<OglDebugShape> &debugShapes = m_debugShapes[scene];
355         if (debugShapes.empty())
356                 return;
357
358         // DrawDebugLines
359         GLboolean light, tex;
360
361         light= glIsEnabled(GL_LIGHTING);
362         tex= glIsEnabled(GL_TEXTURE_2D);
363
364         if (light) glDisable(GL_LIGHTING);
365         if (tex) glDisable(GL_TEXTURE_2D);
366
367         // draw lines
368         glBegin(GL_LINES);
369         for (unsigned int i = 0; i < debugShapes.size(); i++) {
370                 if (debugShapes[i].m_type != OglDebugShape::LINE)
371                         continue;
372                 glColor4f(debugShapes[i].m_color[0], debugShapes[i].m_color[1], debugShapes[i].m_color[2], 1.0f);
373                 const MT_Scalar *fromPtr = &debugShapes[i].m_pos.x();
374                 const MT_Scalar *toPtr= &debugShapes[i].m_param.x();
375                 glVertex3fv(fromPtr);
376                 glVertex3fv(toPtr);
377         }
378         glEnd();
379
380         // draw circles
381         for (unsigned int i = 0; i < debugShapes.size(); i++) {
382                 if (debugShapes[i].m_type != OglDebugShape::CIRCLE)
383                         continue;
384                 glBegin(GL_LINE_LOOP);
385                 glColor4f(debugShapes[i].m_color[0], debugShapes[i].m_color[1], debugShapes[i].m_color[2], 1.0f);
386
387                 static const MT_Vector3 worldUp(0.0f, 0.0f, 1.0f);
388                 MT_Vector3 norm = debugShapes[i].m_param;
389                 MT_Matrix3x3 tr;
390                 if (norm.fuzzyZero() || norm == worldUp)
391                 {
392                         tr.setIdentity();
393                 }
394                 else
395                 {
396                         MT_Vector3 xaxis, yaxis;
397                         xaxis = MT_cross(norm, worldUp);
398                         yaxis = MT_cross(xaxis, norm);
399                         tr.setValue(xaxis.x(), xaxis.y(), xaxis.z(),
400                                 yaxis.x(), yaxis.y(), yaxis.z(),
401                                 norm.x(), norm.y(), norm.z());
402                 }
403                 MT_Scalar rad = debugShapes[i].m_param2.x();
404                 int n = (int)debugShapes[i].m_param2.y();
405                 for (int j = 0; j<n; j++)
406                 {
407                         MT_Scalar theta = j*(float)M_PI*2/n;
408                         MT_Vector3 pos(cosf(theta) * rad, sinf(theta) * rad, 0.0f);
409                         pos = pos*tr;
410                         pos += debugShapes[i].m_pos;
411                         const MT_Scalar* posPtr = &pos.x();
412                         glVertex3fv(posPtr);
413                 }
414                 glEnd();
415         }
416
417         if (light) glEnable(GL_LIGHTING);
418         if (tex) glEnable(GL_TEXTURE_2D);
419
420         debugShapes.clear();
421 }
422
423 void RAS_OpenGLRasterizer::EndFrame()
424 {
425         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
426
427         glDisable(GL_MULTISAMPLE_ARB);
428
429         m_2DCanvas->EndFrame();
430 }
431
432 void RAS_OpenGLRasterizer::SetRenderArea()
433 {
434         RAS_Rect area;
435         // only above/below stereo method needs viewport adjustment
436         switch (m_stereomode)
437         {
438                 case RAS_STEREO_ABOVEBELOW:
439                         switch (m_curreye) {
440                                 case RAS_STEREO_LEFTEYE:
441                                         // upper half of window
442                                         area.SetLeft(0);
443                                         area.SetBottom(m_2DCanvas->GetHeight() -
444                                                 int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
445
446                                         area.SetRight(int(m_2DCanvas->GetWidth()));
447                                         area.SetTop(int(m_2DCanvas->GetHeight()));
448                                         m_2DCanvas->SetDisplayArea(&area);
449                                         break;
450                                 case RAS_STEREO_RIGHTEYE:
451                                         // lower half of window
452                                         area.SetLeft(0);
453                                         area.SetBottom(0);
454                                         area.SetRight(int(m_2DCanvas->GetWidth()));
455                                         area.SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
456                                         m_2DCanvas->SetDisplayArea(&area);
457                                         break;
458                         }
459                         break;
460                 case RAS_STEREO_3DTVTOPBOTTOM:
461                         switch (m_curreye) {
462                                 case RAS_STEREO_LEFTEYE:
463                                         // upper half of window
464                                         area.SetLeft(0);
465                                         area.SetBottom(m_2DCanvas->GetHeight() -
466                                                 m_2DCanvas->GetHeight() / 2);
467
468                                         area.SetRight(m_2DCanvas->GetWidth());
469                                         area.SetTop(m_2DCanvas->GetHeight());
470                                         m_2DCanvas->SetDisplayArea(&area);
471                                         break;
472                                 case RAS_STEREO_RIGHTEYE:
473                                         // lower half of window
474                                         area.SetLeft(0);
475                                         area.SetBottom(0);
476                                         area.SetRight(m_2DCanvas->GetWidth());
477                                         area.SetTop(m_2DCanvas->GetHeight() / 2);
478                                         m_2DCanvas->SetDisplayArea(&area);
479                                         break;
480                         }
481                         break;
482                 case RAS_STEREO_SIDEBYSIDE:
483                         switch (m_curreye)
484                         {
485                                 case RAS_STEREO_LEFTEYE:
486                                         // Left half of window
487                                         area.SetLeft(0);
488                                         area.SetBottom(0);
489                                         area.SetRight(m_2DCanvas->GetWidth()/2);
490                                         area.SetTop(m_2DCanvas->GetHeight());
491                                         m_2DCanvas->SetDisplayArea(&area);
492                                         break;
493                                 case RAS_STEREO_RIGHTEYE:
494                                         // Right half of window
495                                         area.SetLeft(m_2DCanvas->GetWidth()/2);
496                                         area.SetBottom(0);
497                                         area.SetRight(m_2DCanvas->GetWidth());
498                                         area.SetTop(m_2DCanvas->GetHeight());
499                                         m_2DCanvas->SetDisplayArea(&area);
500                                         break;
501                         }
502                         break;
503                 default:
504                         // every available pixel
505                         area.SetLeft(0);
506                         area.SetBottom(0);
507                         area.SetRight(int(m_2DCanvas->GetWidth()));
508                         area.SetTop(int(m_2DCanvas->GetHeight()));
509                         m_2DCanvas->SetDisplayArea(&area);
510                         break;
511         }
512 }
513
514 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode)
515 {
516         m_stereomode = stereomode;
517 }
518
519 RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode()
520 {
521         return m_stereomode;
522 }
523
524 bool RAS_OpenGLRasterizer::Stereo()
525 {
526         if (m_stereomode > RAS_STEREO_NOSTEREO) // > 0
527                 return true;
528         else
529                 return false;
530 }
531
532 bool RAS_OpenGLRasterizer::InterlacedStereo()
533 {
534         return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
535 }
536
537 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye)
538 {
539         m_curreye = eye;
540         switch (m_stereomode)
541         {
542                 case RAS_STEREO_QUADBUFFERED:
543                         glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_LEFT : GL_BACK_RIGHT);
544                         break;
545                 case RAS_STEREO_ANAGLYPH:
546                         if (m_curreye == RAS_STEREO_LEFTEYE) {
547                                 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
548                         }
549                         else {
550                                 //glAccum(GL_LOAD, 1.0f);
551                                 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
552                                 ClearDepthBuffer();
553                         }
554                         break;
555                 case RAS_STEREO_VINTERLACE:
556                 {
557                         // OpenGL stippling is deprecated, it is no longer possible to affect all shaders
558                         // this way, offscreen rendering and then compositing may be the better solution
559                         glEnable(GL_POLYGON_STIPPLE);
560                         glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STEREO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask));
561                         if (m_curreye == RAS_STEREO_RIGHTEYE)
562                                 ClearDepthBuffer();
563                         break;
564                 }
565                 case RAS_STEREO_INTERLACED:
566                 {
567                         glEnable(GL_POLYGON_STIPPLE);
568                         glPolygonStipple((const GLubyte*) &hinterlace_mask[m_curreye == RAS_STEREO_LEFTEYE?0:1]);
569                         if (m_curreye == RAS_STEREO_RIGHTEYE)
570                                 ClearDepthBuffer();
571                         break;
572                 }
573                 default:
574                         break;
575         }
576 }
577
578 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye()
579 {
580         return m_curreye;
581 }
582
583
584 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation)
585 {
586         m_eyeseparation = eyeseparation;
587 }
588
589 float RAS_OpenGLRasterizer::GetEyeSeparation()
590 {
591         return m_eyeseparation;
592 }
593
594 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength)
595 {
596         m_focallength = focallength;
597         m_setfocallength = true;
598 }
599
600 float RAS_OpenGLRasterizer::GetFocalLength()
601 {
602         return m_focallength;
603 }
604
605 RAS_IOffScreen *RAS_OpenGLRasterizer::CreateOffScreen(int width, int height, int samples, int target)
606 {
607         RAS_IOffScreen *ofs;
608
609         ofs = new RAS_OpenGLOffScreen(m_2DCanvas);
610
611         if (!ofs->Create(width, height, samples, (RAS_IOffScreen::RAS_OFS_RENDER_TARGET)target)) {
612                 delete ofs;
613                 return NULL;
614         }
615         return ofs;
616 }
617
618 RAS_ISync *RAS_OpenGLRasterizer::CreateSync(int type)
619 {
620         RAS_ISync *sync;
621
622         sync = new RAS_OpenGLSync();
623
624         if (!sync->Create((RAS_ISync::RAS_SYNC_TYPE)type)) {
625                 delete sync;
626                 return NULL;
627         }
628         return sync;
629 }
630
631 void RAS_OpenGLRasterizer::SwapBuffers()
632 {
633         m_2DCanvas->SwapBuffers();
634 }
635
636
637
638 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const
639 {
640         return m_viewmatrix;
641 }
642
643 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const
644 {
645         return m_viewinvmatrix;
646 }
647
648 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
649                                                                         class RAS_IPolyMaterial* polymat)
650 {
651         bool obcolor = ms.m_bObjectColor;
652         MT_Vector4& rgba = ms.m_RGBAcolor;
653         RAS_MeshSlot::iterator it;
654
655         const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
656
657         // handle object color
658         if (obcolor) {
659                 glDisableClientState(GL_COLOR_ARRAY);
660                 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
661         }
662         else
663                 glEnableClientState(GL_COLOR_ARRAY);
664
665         for (ms.begin(it); !ms.end(it); ms.next(it)) {
666                 RAS_TexVert *vertex;
667                 size_t i, j, numvert;
668
669                 numvert = it.array->m_type;
670
671                 if (it.array->m_type == RAS_DisplayArray::LINE) {
672                         // line drawing, no text
673                         glBegin(GL_LINES);
674
675                         for (i=0; i<it.totindex; i+=2)
676                         {
677                                 vertex = &it.vertex[it.index[i]];
678                                 glVertex3fv(vertex->getXYZ());
679
680                                 vertex = &it.vertex[it.index[i+1]];
681                                 glVertex3fv(vertex->getXYZ());
682                         }
683
684                         glEnd();
685                 }
686                 else {
687                         // triangle and quad text drawing
688                         for (i=0; i<it.totindex; i+=numvert)
689                         {
690                                 float  v[4][3];
691                                 const float  *v_ptr[4] = {NULL};
692                                 const float *uv_ptr[4] = {NULL};
693                                 int glattrib, unit;
694
695                                 for (j=0; j<numvert; j++) {
696                                         vertex = &it.vertex[it.index[i+j]];
697
698                                         v[j][0] = vertex->getXYZ()[0];
699                                         v[j][1] = vertex->getXYZ()[1];
700                                         v[j][2] = vertex->getXYZ()[2];
701                                         v_ptr[j] = v[j];
702
703                                         uv_ptr[j] = vertex->getUV(0);
704                                 }
705
706                                 // find the right opengl attribute
707                                 glattrib = -1;
708                                 if (GLEW_ARB_vertex_program)
709                                         for (unit=0; unit<m_attrib_num; unit++)
710                                                 if (m_attrib[unit] == RAS_TEXCO_UV)
711                                                         glattrib = unit;
712
713                                 GPU_render_text(
714                                         polymat->GetMTexPoly(), polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(),
715                                         v_ptr, uv_ptr, glattrib);
716
717                                 ClearCachingInfo();
718                         }
719                 }
720         }
721
722         glDisableClientState(GL_COLOR_ARRAY);
723 }
724
725 void RAS_OpenGLRasterizer::SetTexCoordNum(int num)
726 {
727         m_texco_num = num;
728         if (m_texco_num > RAS_MAX_TEXCO)
729                 m_texco_num = RAS_MAX_TEXCO;
730 }
731
732 void RAS_OpenGLRasterizer::SetAttribNum(int num)
733 {
734         m_attrib_num = num;
735         if (m_attrib_num > RAS_MAX_ATTRIB)
736                 m_attrib_num = RAS_MAX_ATTRIB;
737 }
738
739 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit)
740 {
741         // this changes from material to material
742         if (unit < RAS_MAX_TEXCO)
743                 m_texco[unit] = coords;
744 }
745
746 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit, int layer)
747 {
748         // this changes from material to material
749         if (unit < RAS_MAX_ATTRIB) {
750                 m_attrib[unit] = coords;
751                 m_attrib_layer[unit] = layer;
752         }
753 }
754
755 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
756 {
757         if (ms.m_pDerivedMesh)
758                 DrawDerivedMesh(ms);
759         else
760                 m_storage->IndexPrimitives(ms);
761 }
762
763 // Code for hooking into Blender's mesh drawing for derived meshes.
764 // If/when we use more of Blender's drawing code, we may be able to
765 // clean this up
766 static bool current_wireframe;
767 static RAS_MaterialBucket *current_bucket;
768 static RAS_IPolyMaterial *current_polymat;
769 static RAS_MeshSlot *current_ms;
770 static RAS_MeshObject *current_mesh;
771 static int current_blmat_nr;
772 static GPUVertexAttribs current_gpu_attribs;
773 static Image *current_image;
774 static int CheckMaterialDM(int matnr, void *attribs)
775 {
776         // only draw the current material
777         if (matnr != current_blmat_nr)
778                 return 0;
779         GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
780         if (gattribs)
781                 memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
782         return 1;
783 }
784
785 static DMDrawOption CheckTexDM(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
786 {
787
788         // index is the original face index, retrieve the polygon
789         if (matnr == current_blmat_nr &&
790                 (mtexpoly == NULL || mtexpoly->tpage == current_image)) {
791                 // must handle color.
792                 if (current_wireframe)
793                         return DM_DRAW_OPTION_NO_MCOL;
794                 if (current_ms->m_bObjectColor) {
795                         MT_Vector4& rgba = current_ms->m_RGBAcolor;
796                         glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
797                         // don't use mcol
798                         return DM_DRAW_OPTION_NO_MCOL;
799                 }
800                 if (!has_mcol) {
801                         // we have to set the color from the material
802                         unsigned char rgba[4];
803                         current_polymat->GetMaterialRGBAColor(rgba);
804                         glColor4ubv((const GLubyte *)rgba);
805                         return DM_DRAW_OPTION_NORMAL;
806                 }
807                 return DM_DRAW_OPTION_NORMAL;
808         }
809         return DM_DRAW_OPTION_SKIP;
810 }
811
812 void RAS_OpenGLRasterizer::DrawDerivedMesh(class RAS_MeshSlot &ms)
813 {
814         // mesh data is in derived mesh
815         current_bucket = ms.m_bucket;
816         current_polymat = current_bucket->GetPolyMaterial();
817         current_ms = &ms;
818         current_mesh = ms.m_mesh;
819         current_wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME;
820         // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
821
822         // handle two-side
823         if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
824                 this->SetCullFace(true);
825         else
826                 this->SetCullFace(false);
827
828         if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
829                 // GetMaterialIndex return the original mface material index,
830                 // increment by 1 to match what derived mesh is doing
831                 current_blmat_nr = current_polymat->GetMaterialIndex()+1;
832                 // For GLSL we need to retrieve the GPU material attribute
833                 Material* blmat = current_polymat->GetBlenderMaterial();
834                 Scene* blscene = current_polymat->GetBlenderScene();
835                 if (!current_wireframe && blscene && blmat)
836                         GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat, false), &current_gpu_attribs);
837                 else
838                         memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
839                 // DM draw can mess up blending mode, restore at the end
840                 int current_blend_mode = GPU_get_material_alpha_blend();
841                 ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
842                 GPU_set_material_alpha_blend(current_blend_mode);
843         } else {
844                 //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
845                 current_blmat_nr = current_polymat->GetMaterialIndex();
846                 current_image = current_polymat->GetBlenderImage();
847                 ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL, DM_DRAW_USE_ACTIVE_UV);
848         }
849 }
850
851 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
852 {
853         glMatrixMode(GL_PROJECTION);
854         float* matrix = &mat(0, 0);
855         glLoadMatrixf(matrix);
856
857         m_camortho = (mat(3, 3) != 0.0f);
858 }
859
860 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
861 {
862         glMatrixMode(GL_PROJECTION);
863         float matrix[16];
864         /* Get into argument. Looks a bit dodgy, but it's ok. */
865         mat.getValue(matrix);
866         glLoadMatrixf(matrix);
867
868         m_camortho = (mat[3][3] != 0.0f);
869 }
870
871 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
872         float left,
873         float right,
874         float bottom,
875         float top,
876         float frustnear,
877         float frustfar,
878         float focallength,
879         bool
880 ) {
881         MT_Matrix4x4 result;
882         float mat[16];
883
884         // correction for stereo
885         if (Stereo())
886         {
887                         float near_div_focallength;
888                         float offset;
889
890                         // if Rasterizer.setFocalLength is not called we use the camera focallength
891                         if (!m_setfocallength)
892                                 // if focallength is null we use a value known to be reasonable
893                                 m_focallength = (focallength == 0.f) ? m_eyeseparation * 30.0f
894                                         : focallength;
895
896                         near_div_focallength = frustnear / m_focallength;
897                         offset = 0.5f * m_eyeseparation * near_div_focallength;
898                         switch (m_curreye) {
899                                 case RAS_STEREO_LEFTEYE:
900                                                 left += offset;
901                                                 right += offset;
902                                                 break;
903                                 case RAS_STEREO_RIGHTEYE:
904                                                 left -= offset;
905                                                 right -= offset;
906                                                 break;
907                         }
908                         // leave bottom and top untouched
909                         if (m_stereomode == RAS_STEREO_3DTVTOPBOTTOM) {
910                                 // restore the vertical frustum because the 3DTV will
911                                 // expand the top and bottom part to the full size of the screen
912                                 bottom *= 2.0f;
913                                 top *= 2.0f;
914                         }
915         }
916
917         glMatrixMode(GL_PROJECTION);
918         glLoadIdentity();
919         glFrustum(left, right, bottom, top, frustnear, frustfar);
920
921         glGetFloatv(GL_PROJECTION_MATRIX, mat);
922         result.setValue(mat);
923
924         return result;
925 }
926
927 MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix(
928         float left,
929         float right,
930         float bottom,
931         float top,
932         float frustnear,
933         float frustfar
934 ) {
935         MT_Matrix4x4 result;
936         float mat[16];
937
938         // stereo is meaningless for orthographic, disable it
939         glMatrixMode(GL_PROJECTION);
940         glLoadIdentity();
941         glOrtho(left, right, bottom, top, frustnear, frustfar);
942
943         glGetFloatv(GL_PROJECTION_MATRIX, mat);
944         result.setValue(mat);
945
946         return result;
947 }
948
949
950 // next arguments probably contain redundant info, for later...
951 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat,
952                                                                                  const MT_Matrix3x3 & camOrientMat3x3,
953                                                                                  const MT_Point3 & pos,
954                                                                                  const MT_Vector3 &scale,
955                                                                                  bool perspective)
956 {
957         m_viewmatrix = mat;
958
959         // correction for stereo
960         if (Stereo() && perspective)
961         {
962                 MT_Vector3 unitViewDir(0.0f, -1.0f, 0.0f);  // minus y direction, Blender convention
963                 MT_Vector3 unitViewupVec(0.0f, 0.0f, 1.0f);
964                 MT_Vector3 viewDir, viewupVec;
965                 MT_Vector3 eyeline;
966
967                 // actual viewDir
968                 viewDir = camOrientMat3x3 * unitViewDir;  // this is the moto convention, vector on right hand side
969                 // actual viewup vec
970                 viewupVec = camOrientMat3x3 * unitViewupVec;
971
972                 // vector between eyes
973                 eyeline = viewDir.cross(viewupVec);
974
975                 switch (m_curreye) {
976                         case RAS_STEREO_LEFTEYE:
977                                 {
978                                 // translate to left by half the eye distance
979                                 MT_Transform transform;
980                                 transform.setIdentity();
981                                 transform.translate(-(eyeline * m_eyeseparation / 2.0f));
982                                 m_viewmatrix *= transform;
983                                 }
984                                 break;
985                         case RAS_STEREO_RIGHTEYE:
986                                 {
987                                 // translate to right by half the eye distance
988                                 MT_Transform transform;
989                                 transform.setIdentity();
990                                 transform.translate(eyeline * m_eyeseparation / 2.0f);
991                                 m_viewmatrix *= transform;
992                                 }
993                                 break;
994                 }
995         }
996
997         bool negX = (scale[0] < 0.0f);
998         bool negY = (scale[1] < 0.0f);
999         bool negZ = (scale[2] < 0.0f);
1000         if (negX || negY || negZ) {
1001                 m_viewmatrix.tscale((negX)?-1.0f:1.0f, (negY)?-1.0f:1.0f, (negZ)?-1.0f:1.0f, 1.0);
1002         }
1003         m_viewinvmatrix = m_viewmatrix;
1004         m_viewinvmatrix.invert();
1005
1006         // note: getValue gives back column major as needed by OpenGL
1007         MT_Scalar glviewmat[16];
1008         m_viewmatrix.getValue(glviewmat);
1009
1010         glMatrixMode(GL_MODELVIEW);
1011         glLoadMatrixf(glviewmat);
1012         m_campos = pos;
1013         m_camnegscale = negX ^ negY ^ negZ;
1014 }
1015
1016
1017 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
1018 {
1019         return m_campos;
1020 }
1021
1022 bool RAS_OpenGLRasterizer::GetCameraOrtho()
1023 {
1024         return m_camortho;
1025 }
1026
1027 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
1028 {
1029         if (enable)
1030                 glEnable(GL_CULL_FACE);
1031         else
1032                 glDisable(GL_CULL_FACE);
1033 }
1034
1035 void RAS_OpenGLRasterizer::SetLines(bool enable)
1036 {
1037         if (enable)
1038                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1039         else
1040                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1041 }
1042
1043 void RAS_OpenGLRasterizer::SetSpecularity(float specX,
1044                                                                                   float specY,
1045                                                                                   float specZ,
1046                                                                                   float specval)
1047 {
1048         GLfloat mat_specular[] = {specX, specY, specZ, specval};
1049         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1050 }
1051
1052
1053
1054 void RAS_OpenGLRasterizer::SetShinyness(float shiny)
1055 {
1056         GLfloat mat_shininess[] = {     shiny };
1057         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1058 }
1059
1060
1061
1062 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
1063 {
1064         GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
1065         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
1066 }
1067
1068 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e)
1069 {
1070         GLfloat mat_emit [] = {eX,eY,eZ,e};
1071         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit);
1072 }
1073
1074
1075 double RAS_OpenGLRasterizer::GetTime()
1076 {
1077         return m_time;
1078 }
1079
1080 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
1081 {
1082         glPolygonOffset(mult, add);
1083         GLint mode = GL_POLYGON_OFFSET_FILL;
1084         if (m_drawingmode < KX_SHADED)
1085                 mode = GL_POLYGON_OFFSET_LINE;
1086         if (mult != 0.0f || add != 0.0f)
1087                 glEnable(mode);
1088         else
1089                 glDisable(mode);
1090 }
1091
1092 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
1093 {
1094         /* don't just set m_motionblur to 1, but check if it is 0 so
1095          * we don't reset a motion blur that is already enabled */
1096         if (m_motionblur == 0)
1097                 m_motionblur = 1;
1098         m_motionblurvalue = motionblurvalue;
1099 }
1100
1101 void RAS_OpenGLRasterizer::DisableMotionBlur()
1102 {
1103         m_motionblur = 0;
1104         m_motionblurvalue = -1.0f;
1105 }
1106
1107 void RAS_OpenGLRasterizer::SetAlphaBlend(int alphablend)
1108 {
1109         /* Variance shadow maps don't handle alpha well, best to not allow it for now  */
1110         if (m_drawingmode == KX_SHADOW && m_usingoverrideshader)
1111                 GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
1112         else
1113                 GPU_set_material_alpha_blend(alphablend);
1114 /*
1115         if (alphablend == m_last_alphablend)
1116                 return;
1117
1118         if (alphablend == GPU_BLEND_SOLID) {
1119                 glDisable(GL_BLEND);
1120                 glDisable(GL_ALPHA_TEST);
1121                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1122         }
1123         else if (alphablend == GPU_BLEND_ADD) {
1124                 glBlendFunc(GL_ONE, GL_ONE);
1125                 glEnable(GL_BLEND);
1126                 glDisable(GL_ALPHA_TEST);
1127         }
1128         else if (alphablend == GPU_BLEND_ALPHA) {
1129                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1130                 glEnable(GL_BLEND);
1131                 glEnable(GL_ALPHA_TEST);
1132                 glAlphaFunc(GL_GREATER, 0.0f);
1133         }
1134         else if (alphablend == GPU_BLEND_CLIP) {
1135                 glDisable(GL_BLEND);
1136                 glEnable(GL_ALPHA_TEST);
1137                 glAlphaFunc(GL_GREATER, 0.5f);
1138         }
1139
1140         m_last_alphablend = alphablend;
1141 */
1142 }
1143
1144 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
1145 {
1146         if (m_camnegscale)
1147                 ccw = !ccw;
1148
1149         if (m_last_frontface == ccw)
1150                 return;
1151
1152         if (ccw)
1153                 glFrontFace(GL_CCW);
1154         else
1155                 glFrontFace(GL_CW);
1156
1157         m_last_frontface = ccw;
1158 }
1159
1160 void RAS_OpenGLRasterizer::SetAnisotropicFiltering(short level)
1161 {
1162         GPU_set_anisotropic(G_MAIN, (float)level);
1163 }
1164
1165 short RAS_OpenGLRasterizer::GetAnisotropicFiltering()
1166 {
1167         return (short)GPU_get_anisotropic();
1168 }
1169
1170 void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val)
1171 {
1172         if (val == RAS_IRasterizer::RAS_MIPMAP_LINEAR)
1173         {
1174                 GPU_set_linear_mipmap(1);
1175                 GPU_set_mipmap(G_MAIN, 1);
1176         }
1177         else if (val == RAS_IRasterizer::RAS_MIPMAP_NEAREST)
1178         {
1179                 GPU_set_linear_mipmap(0);
1180                 GPU_set_mipmap(G_MAIN, 1);
1181         }
1182         else
1183         {
1184                 GPU_set_linear_mipmap(0);
1185                 GPU_set_mipmap(G_MAIN, 0);
1186         }
1187 }
1188
1189 RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping()
1190 {
1191         if (GPU_get_mipmap()) {
1192                 if (GPU_get_linear_mipmap()) {
1193                         return RAS_IRasterizer::RAS_MIPMAP_LINEAR;
1194                 }
1195                 else {
1196                         return RAS_IRasterizer::RAS_MIPMAP_NEAREST;
1197                 }
1198         }
1199         else {
1200                 return RAS_IRasterizer::RAS_MIPMAP_NONE;
1201         }
1202 }
1203
1204 void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val)
1205 {
1206         m_usingoverrideshader = val;
1207 }
1208
1209 bool RAS_OpenGLRasterizer::GetUsingOverrideShader()
1210 {
1211         return m_usingoverrideshader;
1212 }
1213
1214 /**
1215  * Render Tools
1216  */
1217
1218 /* ProcessLighting performs lighting on objects. the layer is a bitfield that
1219  * contains layer information. There are 20 'official' layers in blender. A
1220  * light is applied on an object only when they are in the same layer. OpenGL
1221  * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in
1222  * a scene. */
1223
1224 void RAS_OpenGLRasterizer::ProcessLighting(bool uselights, const MT_Transform& viewmat)
1225 {
1226         bool enable = false;
1227         int layer= -1;
1228
1229         /* find the layer */
1230         if (uselights) {
1231                 if (m_clientobject)
1232                         layer = static_cast<KX_GameObject*>(m_clientobject)->GetLayer();
1233         }
1234
1235         /* avoid state switching */
1236         if (m_lastlightlayer == layer && m_lastauxinfo == m_auxilaryClientInfo)
1237                 return;
1238
1239         m_lastlightlayer = layer;
1240         m_lastauxinfo = m_auxilaryClientInfo;
1241
1242         /* enable/disable lights as needed */
1243         if (layer >= 0) {
1244                 //enable = ApplyLights(layer, viewmat);
1245                 // taken from blender source, incompatibility between Blender Object / GameObject
1246                 KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo;
1247                 float glviewmat[16];
1248                 unsigned int count;
1249                 std::vector<RAS_OpenGLLight*>::iterator lit = m_lights.begin();
1250
1251                 for (count=0; count<m_numgllights; count++)
1252                         glDisable((GLenum)(GL_LIGHT0+count));
1253
1254                 viewmat.getValue(glviewmat);
1255
1256                 glPushMatrix();
1257                 glLoadMatrixf(glviewmat);
1258                 for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit)
1259                 {
1260                         RAS_OpenGLLight* light = (*lit);
1261
1262                         if (light->ApplyFixedFunctionLighting(kxscene, layer, count))
1263                                 count++;
1264                 }
1265                 glPopMatrix();
1266
1267                 enable = count > 0;
1268         }
1269
1270         if (enable)
1271                 EnableOpenGLLights();
1272         else
1273                 DisableOpenGLLights();
1274 }
1275
1276 void RAS_OpenGLRasterizer::EnableOpenGLLights()
1277 {
1278         if (m_lastlighting == true)
1279                 return;
1280
1281         glEnable(GL_LIGHTING);
1282         glEnable(GL_COLOR_MATERIAL);
1283
1284         glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1285         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
1286         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (GetCameraOrtho())? GL_FALSE: GL_TRUE);
1287         if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
1288                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1289
1290         m_lastlighting = true;
1291 }
1292
1293 void RAS_OpenGLRasterizer::DisableOpenGLLights()
1294 {
1295         if (m_lastlighting == false)
1296                 return;
1297
1298         glDisable(GL_LIGHTING);
1299         glDisable(GL_COLOR_MATERIAL);
1300
1301         m_lastlighting = false;
1302 }
1303
1304 RAS_ILightObject *RAS_OpenGLRasterizer::CreateLight()
1305 {
1306         return new RAS_OpenGLLight(this);
1307 }
1308
1309 void RAS_OpenGLRasterizer::AddLight(RAS_ILightObject* lightobject)
1310 {
1311         RAS_OpenGLLight* gllight = dynamic_cast<RAS_OpenGLLight*>(lightobject);
1312         assert(gllight);
1313         m_lights.push_back(gllight);
1314 }
1315
1316 void RAS_OpenGLRasterizer::RemoveLight(RAS_ILightObject* lightobject)
1317 {
1318         RAS_OpenGLLight* gllight = dynamic_cast<RAS_OpenGLLight*>(lightobject);
1319         assert(gllight);
1320
1321         std::vector<RAS_OpenGLLight*>::iterator lit =
1322                 std::find(m_lights.begin(),m_lights.end(),gllight);
1323
1324         if (!(lit==m_lights.end()))
1325                 m_lights.erase(lit);
1326 }
1327
1328 bool RAS_OpenGLRasterizer::RayHit(struct KX_ClientObjectInfo *client, KX_RayCast *result, float *oglmatrix)
1329 {
1330         if (result->m_hitMesh) {
1331
1332                 RAS_Polygon* poly = result->m_hitMesh->GetPolygon(result->m_hitPolygon);
1333                 if (!poly->IsVisible())
1334                         return false;
1335
1336                 MT_Vector3 resultnormal(result->m_hitNormal);
1337                 MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
1338                 MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
1339                 left = (dir.cross(resultnormal)).safe_normalized();
1340                 // for the up vector, we take the 'resultnormal' returned by the physics
1341
1342                 float maat[16] = {left[0],         left[1],         left[2],         0,
1343                                        dir[0],          dir[1],          dir[2],          0,
1344                                   resultnormal[0], resultnormal[1], resultnormal[2], 0,
1345                                   0,               0,               0,               1};
1346
1347                 glTranslatef(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
1348                 //glMultMatrixd(oglmatrix);
1349                 glMultMatrixf(maat);
1350                 return true;
1351         }
1352         else {
1353                 return false;
1354         }
1355 }
1356
1357 void RAS_OpenGLRasterizer::applyTransform(float* oglmatrix,int objectdrawmode )
1358 {
1359         /* FIXME:
1360         blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const
1361         MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed.
1362
1363         Program received signal SIGABRT, Aborted.
1364         [Switching to Thread 16384 (LWP 1519)]
1365         0x40477571 in kill () from /lib/libc.so.6
1366         (gdb) bt
1367         #7  0x08334368 in MT_Vector3::normalized() const ()
1368         #8  0x0833e6ec in RAS_OpenGLRasterizer::applyTransform(RAS_IRasterizer*, double*, int) ()
1369         */
1370
1371         if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED ||
1372                 objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED)
1373         {
1374                 // rotate the billboard/halo
1375                 //page 360/361 3D Game Engine Design, David Eberly for a discussion
1376                 // on screen aligned and axis aligned billboards
1377                 // assumed is that the preprocessor transformed all billboard polygons
1378                 // so that their normal points into the positive x direction (1.0f, 0.0f, 0.0f)
1379                 // when new parenting for objects is done, this rotation
1380                 // will be moved into the object
1381
1382                 MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]);
1383                 MT_Point3 campos = GetCameraPosition();
1384                 MT_Vector3 dir = (campos - objpos).safe_normalized();
1385                 MT_Vector3 up(0,0,1.0f);
1386
1387                 KX_GameObject* gameobj = (KX_GameObject*)m_clientobject;
1388                 // get scaling of halo object
1389                 MT_Vector3  size = gameobj->GetSGNode()->GetWorldScaling();
1390
1391                 bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned
1392                 if (screenaligned)
1393                 {
1394                         up = (up - up.dot(dir) * dir).safe_normalized();
1395                 } else
1396                 {
1397                         dir = (dir - up.dot(dir)*up).safe_normalized();
1398                 }
1399
1400                 MT_Vector3 left = dir.normalized();
1401                 dir = (up.cross(left)).normalized();
1402
1403                 // we have calculated the row vectors, now we keep
1404                 // local scaling into account:
1405
1406                 left *= size[0];
1407                 dir  *= size[1];
1408                 up   *= size[2];
1409
1410                 float maat[16] = {left[0], left[1], left[2], 0,
1411                                    dir[0],  dir[1],  dir[2],  0,
1412                                    up[0],   up[1],   up[2],   0,
1413                                    0,       0,       0,       1};
1414
1415                 glTranslatef(objpos[0],objpos[1],objpos[2]);
1416                 glMultMatrixf(maat);
1417
1418         }
1419         else {
1420                 if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
1421                 {
1422                         // shadow must be cast to the ground, physics system needed here!
1423                         MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
1424                         KX_GameObject *gameobj = (KX_GameObject*)m_clientobject;
1425                         MT_Vector3 direction = MT_Vector3(0,0,-1);
1426
1427                         direction.normalize();
1428                         direction *= 100000;
1429
1430                         MT_Point3 topoint = frompoint + direction;
1431
1432                         KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo;
1433                         PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment();
1434                         PHY_IPhysicsController* physics_controller = gameobj->GetPhysicsController();
1435
1436                         KX_GameObject *parent = gameobj->GetParent();
1437                         if (!physics_controller && parent)
1438                                 physics_controller = parent->GetPhysicsController();
1439
1440                         KX_RayCast::Callback<RAS_OpenGLRasterizer, float> callback(this, physics_controller, oglmatrix);
1441                         if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback))
1442                         {
1443                                 // couldn't find something to cast the shadow on...
1444                                 glMultMatrixf(oglmatrix);
1445                         }
1446                         else
1447                         { // we found the "ground", but the cast matrix doesn't take
1448                           // scaling in consideration, so we must apply the object scale
1449                                 MT_Vector3  size = gameobj->GetSGNode()->GetLocalScale();
1450                                 glScalef(size[0], size[1], size[2]);
1451                         }
1452                 } else
1453                 {
1454
1455                         // 'normal' object
1456                         glMultMatrixf(oglmatrix);
1457                 }
1458         }
1459 }
1460
1461 static void DisableForText()
1462 {
1463         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* needed for texture fonts otherwise they render as wireframe */
1464
1465         glDisable(GL_BLEND);
1466         glDisable(GL_ALPHA_TEST);
1467
1468         glDisable(GL_LIGHTING);
1469         glDisable(GL_COLOR_MATERIAL);
1470
1471         if (GLEW_ARB_multitexture) {
1472                 for (int i=0; i<RAS_MAX_TEXCO; i++) {
1473                         glActiveTextureARB(GL_TEXTURE0_ARB+i);
1474
1475                         if (GLEW_ARB_texture_cube_map) {
1476                                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1477                                 glDisable(GL_TEXTURE_GEN_S);
1478                                 glDisable(GL_TEXTURE_GEN_T);
1479                                 glDisable(GL_TEXTURE_GEN_Q);
1480                                 glDisable(GL_TEXTURE_GEN_R);
1481                         }
1482                         glDisable(GL_TEXTURE_2D);
1483                 }
1484
1485                 glActiveTextureARB(GL_TEXTURE0_ARB);
1486         }
1487         else {
1488                 if (GLEW_ARB_texture_cube_map)
1489                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1490
1491                 glDisable(GL_TEXTURE_2D);
1492         }
1493 }
1494
1495 void RAS_OpenGLRasterizer::RenderBox2D(int xco,
1496                         int yco,
1497                         int width,
1498                         int height,
1499                         float percentage)
1500 {
1501         /* This is a rather important line :( The gl-mode hasn't been left
1502          * behind quite as neatly as we'd have wanted to. I don't know
1503          * what cause it, though :/ .*/
1504         glDisable(GL_DEPTH_TEST);
1505
1506         glMatrixMode(GL_PROJECTION);
1507         glPushMatrix();
1508         glLoadIdentity();
1509
1510         glOrtho(0, width, 0, height, -100, 100);
1511
1512         glMatrixMode(GL_MODELVIEW);
1513         glPushMatrix();
1514         glLoadIdentity();
1515
1516         yco = height - yco;
1517         int barsize = 50;
1518
1519         /* draw in black first */
1520         glColor3ub(0, 0, 0);
1521         glBegin(GL_QUADS);
1522         glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1 + 10);
1523         glVertex2f(xco + 1, yco - 1 + 10);
1524         glVertex2f(xco + 1, yco - 1);
1525         glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1);
1526         glEnd();
1527
1528         glColor3ub(255, 255, 255);
1529         glBegin(GL_QUADS);
1530         glVertex2f(xco + 1 + barsize * percentage, yco + 10);
1531         glVertex2f(xco, yco + 10);
1532         glVertex2f(xco, yco);
1533         glVertex2f(xco + 1 + barsize * percentage, yco);
1534         glEnd();
1535
1536         glMatrixMode(GL_PROJECTION);
1537         glPopMatrix();
1538         glMatrixMode(GL_MODELVIEW);
1539         glPopMatrix();
1540         glEnable(GL_DEPTH_TEST);
1541 }
1542
1543 void RAS_OpenGLRasterizer::RenderText3D(
1544         int fontid, const char *text, int size, int dpi,
1545         const float color[4], const float mat[16], float aspect)
1546 {
1547         /* gl prepping */
1548         DisableForText();
1549
1550         /* the actual drawing */
1551         glColor4fv(color);
1552
1553         /* multiply the text matrix by the object matrix */
1554         BLF_enable(fontid, BLF_MATRIX|BLF_ASPECT);
1555         BLF_matrix(fontid, mat);
1556
1557         /* aspect is the inverse scale that allows you to increase
1558          * your resolution without sizing the final text size
1559          * the bigger the size, the smaller the aspect */
1560         BLF_aspect(fontid, aspect, aspect, aspect);
1561
1562         BLF_size(fontid, size, dpi);
1563         BLF_position(fontid, 0, 0, 0);
1564         BLF_draw(fontid, text, 65535);
1565
1566         BLF_disable(fontid, BLF_MATRIX|BLF_ASPECT);
1567 }
1568
1569 void RAS_OpenGLRasterizer::RenderText2D(
1570         RAS_TEXT_RENDER_MODE mode,
1571         const char* text,
1572         int xco, int yco,
1573         int width, int height)
1574 {
1575         /* This is a rather important line :( The gl-mode hasn't been left
1576          * behind quite as neatly as we'd have wanted to. I don't know
1577          * what cause it, though :/ .*/
1578         DisableForText();
1579         glDisable(GL_DEPTH_TEST);
1580
1581         glMatrixMode(GL_PROJECTION);
1582         glPushMatrix();
1583         glLoadIdentity();
1584
1585         glOrtho(0, width, 0, height, -100, 100);
1586
1587         glMatrixMode(GL_MODELVIEW);
1588         glPushMatrix();
1589         glLoadIdentity();
1590
1591         if (mode == RAS_TEXT_PADDED) {
1592                 /* draw in black first */
1593                 glColor3ub(0, 0, 0);
1594                 BLF_size(blf_mono_font, 11, 72);
1595                 BLF_position(blf_mono_font, (float)xco+1, (float)(height-yco-1), 0.0f);
1596                 BLF_draw(blf_mono_font, text, 65535); /* XXX, use real len */
1597         }
1598
1599         /* the actual drawing */
1600         glColor3ub(255, 255, 255);
1601         BLF_size(blf_mono_font, 11, 72);
1602         BLF_position(blf_mono_font, (float)xco, (float)(height-yco), 0.0f);
1603         BLF_draw(blf_mono_font, text, 65535); /* XXX, use real len */
1604
1605         glMatrixMode(GL_PROJECTION);
1606         glPopMatrix();
1607         glMatrixMode(GL_MODELVIEW);
1608         glPopMatrix();
1609         glEnable(GL_DEPTH_TEST);
1610 }
1611
1612 void RAS_OpenGLRasterizer::PushMatrix()
1613 {
1614         glPushMatrix();
1615 }
1616
1617 void RAS_OpenGLRasterizer::PopMatrix()
1618 {
1619         glPopMatrix();
1620 }
1621
1622 void RAS_OpenGLRasterizer::MotionBlur()
1623 {
1624         int state = GetMotionBlurState();
1625         float motionblurvalue;
1626         if (state)
1627         {
1628                 motionblurvalue = GetMotionBlurValue();
1629                 if (state==1)
1630                 {
1631                         // bugfix:load color buffer into accum buffer for the first time(state=1)
1632                         glAccum(GL_LOAD, 1.0f);
1633                         SetMotionBlurState(2);
1634                 }
1635                 else if (motionblurvalue >= 0.0f && motionblurvalue <= 1.0f) {
1636                         glAccum(GL_MULT, motionblurvalue);
1637                         glAccum(GL_ACCUM, 1-motionblurvalue);
1638                         glAccum(GL_RETURN, 1.0f);
1639                         glFlush();
1640                 }
1641         }
1642 }
1643
1644 void RAS_OpenGLRasterizer::SetClientObject(void* obj)
1645 {
1646         if (m_clientobject != obj)
1647         {
1648                 bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling());
1649                 SetFrontFace(ccw);
1650
1651                 m_clientobject = obj;
1652         }
1653 }
1654
1655 void RAS_OpenGLRasterizer::SetAuxilaryClientInfo(void* inf)
1656 {
1657         m_auxilaryClientInfo = inf;
1658 }
1659
1660 void RAS_OpenGLRasterizer::PrintHardwareInfo()
1661 {
1662         #define pprint(x) std::cout << x << std::endl;
1663
1664         pprint("GL_VENDOR: " << glGetString(GL_VENDOR));
1665         pprint("GL_RENDERER: " << glGetString(GL_RENDERER));
1666         pprint("GL_VERSION:  " << glGetString(GL_VERSION));
1667         bool support=0;
1668         pprint("Supported Extensions...");
1669         pprint(" GL_ARB_shader_objects supported?       "<< (GLEW_ARB_shader_objects?"yes.":"no."));
1670
1671         support= GLEW_ARB_vertex_shader;
1672         pprint(" GL_ARB_vertex_shader supported?        "<< (support?"yes.":"no."));
1673         if (support) {
1674                 pprint(" ----------Details----------");
1675                 int max=0;
1676                 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, (GLint*)&max);
1677                 pprint("  Max uniform components." << max);
1678
1679                 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, (GLint*)&max);
1680                 pprint("  Max varying floats." << max);
1681
1682                 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, (GLint*)&max);
1683                 pprint("  Max vertex texture units." << max);
1684
1685                 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, (GLint*)&max);
1686                 pprint("  Max combined texture units." << max);
1687                 pprint("");
1688         }
1689
1690         support=GLEW_ARB_fragment_shader;
1691         pprint(" GL_ARB_fragment_shader supported?      "<< (support?"yes.":"no."));
1692         if (support) {
1693                 pprint(" ----------Details----------");
1694                 int max=0;
1695                 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, (GLint*)&max);
1696                 pprint("  Max uniform components." << max);
1697                 pprint("");
1698         }
1699
1700         support = GLEW_ARB_texture_cube_map;
1701         pprint(" GL_ARB_texture_cube_map supported?     "<< (support?"yes.":"no."));
1702         if (support) {
1703                 pprint(" ----------Details----------");
1704                 int size=0;
1705                 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, (GLint*)&size);
1706                 pprint("  Max cubemap size." << size);
1707                 pprint("");
1708         }
1709
1710         support = GLEW_ARB_multitexture;
1711         pprint(" GL_ARB_multitexture supported?         "<< (support?"yes.":"no."));
1712         if (support) {
1713                 pprint(" ----------Details----------");
1714                 int units=0;
1715                 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&units);
1716                 pprint("  Max texture units available.  " << units);
1717                 pprint("");
1718         }
1719
1720         pprint(" GL_ARB_texture_env_combine supported?  "<< (GLEW_ARB_texture_env_combine?"yes.":"no."));
1721
1722         pprint(" GL_ARB_texture_non_power_of_two supported  " << (GPU_full_non_power_of_two_support()?"yes.":"no."));
1723 }
1724