2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
36 #include "RAS_OpenGLRasterizer.h"
40 #include "RAS_ICanvas.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"
48 #include "RAS_OpenGLLight.h"
50 #include "RAS_StorageVA.h"
51 #include "RAS_StorageVBO.h"
54 #include "GPU_extensions.h"
55 #include "GPU_material.h"
56 #include "GPU_shader.h"
60 #include "BKE_DerivedMesh.h"
64 // XXX Clean these up <<<
65 #include "EXP_Value.h"
67 #include "KX_RayCast.h"
68 #include "KX_GameObject.h"
72 #define M_PI 3.14159265358979323846
76 * 32x32 bit masks for vinterlace stereo mode
78 static GLuint left_eye_vinterlace_mask[32];
79 static GLuint right_eye_vinterlace_mask[32];
82 * 32x32 bit masks for hinterlace stereo mode.
83 * Left eye = &hinterlace_mask[0]
84 * Right eye = &hinterlace_mask[1]
86 static GLuint hinterlace_mask[33];
88 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, RAS_STORAGE_TYPE storage)
89 :RAS_IRasterizer(canvas),
93 m_campos(0.0f, 0.0f, 0.0f),
95 m_stereomode(RAS_STEREO_NOSTEREO),
96 m_curreye(RAS_STEREO_LEFTEYE),
97 m_eyeseparation(0.0f),
99 m_setfocallength(false),
102 m_motionblurvalue(-1.0f),
103 m_usingoverrideshader(false),
104 m_clientobject(NULL),
105 m_auxilaryClientInfo(NULL),
106 m_drawingmode(KX_TEXTURED),
109 //m_last_alphablend(GPU_BLEND_SOLID),
110 m_last_frontface(true),
111 m_materialCachingInfo(0),
112 m_storage_type(storage)
114 m_viewmatrix.setIdentity();
115 m_viewinvmatrix.setIdentity();
117 for (int i = 0; i < 32; i++)
119 left_eye_vinterlace_mask[i] = 0x55555555;
120 right_eye_vinterlace_mask[i] = 0xAAAAAAAA;
121 hinterlace_mask[i] = (i&1)*0xFFFFFFFF;
123 hinterlace_mask[32] = 0;
125 m_prevafvalue = GPU_get_anisotropic();
127 if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE && GLEW_ARB_vertex_buffer_object*/) {
128 m_storage = new RAS_StorageVBO(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
130 else if ((m_storage_type == RAS_VA) || (m_storage_type == RAS_AUTO_STORAGE)) {
131 m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
134 printf("Unknown rasterizer storage type, falling back to vertex arrays\n");
135 m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
138 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &m_numgllights);
139 if (m_numgllights < 8)
147 RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
149 // Restore the previous AF value
150 GPU_set_anisotropic(m_prevafvalue);
156 bool RAS_OpenGLRasterizer::Init()
167 glDisable(GL_ALPHA_TEST);
168 //m_last_alphablend = GPU_BLEND_SOLID;
169 GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
172 m_last_frontface = true;
175 m_greenback = 0.4375f;
176 m_blueback = 0.4375f;
179 glClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
180 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
181 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
184 glShadeModel(GL_SMOOTH);
186 storage_init = m_storage->Init();
188 return true && storage_init;
192 void RAS_OpenGLRasterizer::SetAmbientColor(float color[3])
199 void RAS_OpenGLRasterizer::SetAmbient(float factor)
201 float ambient[] = {m_ambr * factor, m_ambg * factor, m_ambb * factor, 1.0f};
202 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
205 void RAS_OpenGLRasterizer::SetBackColor(float color[3])
207 m_redback = color[0];
208 m_greenback = color[1];
209 m_blueback = color[2];
213 void RAS_OpenGLRasterizer::SetFog(short type, float start, float dist, float intensity, float color[3])
215 float params[4] = {color[0], color[1], color[2], 1.0f};
216 glFogi(GL_FOG_MODE, GL_LINEAR);
217 glFogf(GL_FOG_DENSITY, intensity / 10.0f);
218 glFogf(GL_FOG_START, start);
219 glFogf(GL_FOG_END, start + dist);
220 glFogfv(GL_FOG_COLOR, params);
223 void RAS_OpenGLRasterizer::EnableFog(bool enable)
225 m_fogenabled = enable;
228 void RAS_OpenGLRasterizer::DisplayFog()
230 if ((m_drawingmode >= KX_SOLID) && m_fogenabled) {
238 bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
240 return mat.Activate(this, m_materialCachingInfo);
245 void RAS_OpenGLRasterizer::Exit()
249 glEnable(GL_CULL_FACE);
250 glEnable(GL_DEPTH_TEST);
252 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
253 glClearColor(m_redback, m_greenback, m_blueback, m_alphaback);
254 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
255 glDepthMask (GL_TRUE);
256 glDepthFunc(GL_LEQUAL);
257 glBlendFunc(GL_ONE, GL_ZERO);
259 glDisable(GL_POLYGON_STIPPLE);
261 glDisable(GL_LIGHTING);
262 if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
263 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
268 bool RAS_OpenGLRasterizer::BeginFrame(double time)
272 // Blender camera routine destroys the settings
273 if (m_drawingmode < KX_SOLID)
275 glDisable(GL_CULL_FACE);
276 glDisable(GL_DEPTH_TEST);
280 glEnable(GL_DEPTH_TEST);
281 glEnable(GL_CULL_FACE);
285 glDisable(GL_ALPHA_TEST);
286 //m_last_alphablend = GPU_BLEND_SOLID;
287 GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
290 m_last_frontface = true;
292 glShadeModel(GL_SMOOTH);
294 glEnable(GL_MULTISAMPLE_ARB);
296 m_2DCanvas->BeginFrame();
299 m_clientobject = NULL;
300 m_lastlightlayer = -1;
301 m_lastauxinfo = NULL;
302 m_lastlighting = true; /* force disable in DisableOpenGLLights() */
303 DisableOpenGLLights();
310 void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
312 m_drawingmode = drawingmode;
314 if (m_drawingmode == KX_WIREFRAME)
315 glDisable(GL_CULL_FACE);
317 m_storage->SetDrawingMode(drawingmode);
320 int RAS_OpenGLRasterizer::GetDrawingMode()
322 return m_drawingmode;
326 void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask)
328 glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE);
332 void RAS_OpenGLRasterizer::ClearColorBuffer()
334 m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
335 m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
339 void RAS_OpenGLRasterizer::ClearDepthBuffer()
341 m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER);
345 void RAS_OpenGLRasterizer::ClearCachingInfo(void)
347 m_materialCachingInfo = 0;
350 void RAS_OpenGLRasterizer::FlushDebugShapes(SCA_IScene *scene)
352 std::vector<OglDebugShape> &debugShapes = m_debugShapes[scene];
353 if (debugShapes.empty())
357 GLboolean light, tex;
359 light= glIsEnabled(GL_LIGHTING);
360 tex= glIsEnabled(GL_TEXTURE_2D);
362 if (light) glDisable(GL_LIGHTING);
363 if (tex) glDisable(GL_TEXTURE_2D);
367 for (unsigned int i = 0; i < debugShapes.size(); i++) {
368 if (debugShapes[i].m_type != OglDebugShape::LINE)
370 glColor4f(debugShapes[i].m_color[0], debugShapes[i].m_color[1], debugShapes[i].m_color[2], 1.0f);
371 const MT_Scalar *fromPtr = &debugShapes[i].m_pos.x();
372 const MT_Scalar *toPtr= &debugShapes[i].m_param.x();
373 glVertex3fv(fromPtr);
379 for (unsigned int i = 0; i < debugShapes.size(); i++) {
380 if (debugShapes[i].m_type != OglDebugShape::CIRCLE)
382 glBegin(GL_LINE_LOOP);
383 glColor4f(debugShapes[i].m_color[0], debugShapes[i].m_color[1], debugShapes[i].m_color[2], 1.0f);
385 static const MT_Vector3 worldUp(0.0f, 0.0f, 1.0f);
386 MT_Vector3 norm = debugShapes[i].m_param;
388 if (norm.fuzzyZero() || norm == worldUp)
394 MT_Vector3 xaxis, yaxis;
395 xaxis = MT_cross(norm, worldUp);
396 yaxis = MT_cross(xaxis, norm);
397 tr.setValue(xaxis.x(), xaxis.y(), xaxis.z(),
398 yaxis.x(), yaxis.y(), yaxis.z(),
399 norm.x(), norm.y(), norm.z());
401 MT_Scalar rad = debugShapes[i].m_param2.x();
402 int n = (int)debugShapes[i].m_param2.y();
403 for (int j = 0; j<n; j++)
405 MT_Scalar theta = j*(float)M_PI*2/n;
406 MT_Vector3 pos(cosf(theta) * rad, sinf(theta) * rad, 0.0f);
408 pos += debugShapes[i].m_pos;
409 const MT_Scalar* posPtr = &pos.x();
415 if (light) glEnable(GL_LIGHTING);
416 if (tex) glEnable(GL_TEXTURE_2D);
421 void RAS_OpenGLRasterizer::EndFrame()
423 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
425 glDisable(GL_MULTISAMPLE_ARB);
427 m_2DCanvas->EndFrame();
430 void RAS_OpenGLRasterizer::SetRenderArea()
433 // only above/below stereo method needs viewport adjustment
434 switch (m_stereomode)
436 case RAS_STEREO_ABOVEBELOW:
438 case RAS_STEREO_LEFTEYE:
439 // upper half of window
441 area.SetBottom(m_2DCanvas->GetHeight() -
442 int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
444 area.SetRight(int(m_2DCanvas->GetWidth()));
445 area.SetTop(int(m_2DCanvas->GetHeight()));
446 m_2DCanvas->SetDisplayArea(&area);
448 case RAS_STEREO_RIGHTEYE:
449 // lower half of window
452 area.SetRight(int(m_2DCanvas->GetWidth()));
453 area.SetTop(int(m_2DCanvas->GetHeight() - m_noOfScanlines) / 2);
454 m_2DCanvas->SetDisplayArea(&area);
458 case RAS_STEREO_3DTVTOPBOTTOM:
460 case RAS_STEREO_LEFTEYE:
461 // upper half of window
463 area.SetBottom(m_2DCanvas->GetHeight() -
464 m_2DCanvas->GetHeight() / 2);
466 area.SetRight(m_2DCanvas->GetWidth());
467 area.SetTop(m_2DCanvas->GetHeight());
468 m_2DCanvas->SetDisplayArea(&area);
470 case RAS_STEREO_RIGHTEYE:
471 // lower half of window
474 area.SetRight(m_2DCanvas->GetWidth());
475 area.SetTop(m_2DCanvas->GetHeight() / 2);
476 m_2DCanvas->SetDisplayArea(&area);
480 case RAS_STEREO_SIDEBYSIDE:
483 case RAS_STEREO_LEFTEYE:
484 // Left half of window
487 area.SetRight(m_2DCanvas->GetWidth()/2);
488 area.SetTop(m_2DCanvas->GetHeight());
489 m_2DCanvas->SetDisplayArea(&area);
491 case RAS_STEREO_RIGHTEYE:
492 // Right half of window
493 area.SetLeft(m_2DCanvas->GetWidth()/2);
495 area.SetRight(m_2DCanvas->GetWidth());
496 area.SetTop(m_2DCanvas->GetHeight());
497 m_2DCanvas->SetDisplayArea(&area);
502 // every available pixel
505 area.SetRight(int(m_2DCanvas->GetWidth()));
506 area.SetTop(int(m_2DCanvas->GetHeight()));
507 m_2DCanvas->SetDisplayArea(&area);
512 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode)
514 m_stereomode = stereomode;
517 RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode()
522 bool RAS_OpenGLRasterizer::Stereo()
524 if (m_stereomode > RAS_STEREO_NOSTEREO) // > 0
530 bool RAS_OpenGLRasterizer::InterlacedStereo()
532 return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
535 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye)
538 switch (m_stereomode)
540 case RAS_STEREO_QUADBUFFERED:
541 glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_LEFT : GL_BACK_RIGHT);
543 case RAS_STEREO_ANAGLYPH:
544 if (m_curreye == RAS_STEREO_LEFTEYE) {
545 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
548 //glAccum(GL_LOAD, 1.0f);
549 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
553 case RAS_STEREO_VINTERLACE:
555 // OpenGL stippling is deprecated, it is no longer possible to affect all shaders
556 // this way, offscreen rendering and then compositing may be the better solution
557 glEnable(GL_POLYGON_STIPPLE);
558 glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STEREO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask));
559 if (m_curreye == RAS_STEREO_RIGHTEYE)
563 case RAS_STEREO_INTERLACED:
565 glEnable(GL_POLYGON_STIPPLE);
566 glPolygonStipple((const GLubyte*) &hinterlace_mask[m_curreye == RAS_STEREO_LEFTEYE?0:1]);
567 if (m_curreye == RAS_STEREO_RIGHTEYE)
576 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye()
582 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation)
584 m_eyeseparation = eyeseparation;
587 float RAS_OpenGLRasterizer::GetEyeSeparation()
589 return m_eyeseparation;
592 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength)
594 m_focallength = focallength;
595 m_setfocallength = true;
598 float RAS_OpenGLRasterizer::GetFocalLength()
600 return m_focallength;
604 void RAS_OpenGLRasterizer::SwapBuffers()
606 m_2DCanvas->SwapBuffers();
611 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const
616 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const
618 return m_viewinvmatrix;
621 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
622 class RAS_IPolyMaterial* polymat)
624 bool obcolor = ms.m_bObjectColor;
625 MT_Vector4& rgba = ms.m_RGBAcolor;
626 RAS_MeshSlot::iterator it;
628 const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
630 // handle object color
632 glDisableClientState(GL_COLOR_ARRAY);
633 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
636 glEnableClientState(GL_COLOR_ARRAY);
638 for (ms.begin(it); !ms.end(it); ms.next(it)) {
640 size_t i, j, numvert;
642 numvert = it.array->m_type;
644 if (it.array->m_type == RAS_DisplayArray::LINE) {
645 // line drawing, no text
648 for (i=0; i<it.totindex; i+=2)
650 vertex = &it.vertex[it.index[i]];
651 glVertex3fv(vertex->getXYZ());
653 vertex = &it.vertex[it.index[i+1]];
654 glVertex3fv(vertex->getXYZ());
660 // triangle and quad text drawing
661 for (i=0; i<it.totindex; i+=numvert)
664 const float *v_ptr[4] = {NULL};
665 const float *uv_ptr[4] = {NULL};
668 for (j=0; j<numvert; j++) {
669 vertex = &it.vertex[it.index[i+j]];
671 v[j][0] = vertex->getXYZ()[0];
672 v[j][1] = vertex->getXYZ()[1];
673 v[j][2] = vertex->getXYZ()[2];
676 uv_ptr[j] = vertex->getUV(0);
679 // find the right opengl attribute
681 if (GLEW_ARB_vertex_program)
682 for (unit=0; unit<m_attrib_num; unit++)
683 if (m_attrib[unit] == RAS_TEXCO_UV)
687 polymat->GetMTexPoly(), polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(),
688 v_ptr, uv_ptr, glattrib);
695 glDisableClientState(GL_COLOR_ARRAY);
698 void RAS_OpenGLRasterizer::SetTexCoordNum(int num)
701 if (m_texco_num > RAS_MAX_TEXCO)
702 m_texco_num = RAS_MAX_TEXCO;
705 void RAS_OpenGLRasterizer::SetAttribNum(int num)
708 if (m_attrib_num > RAS_MAX_ATTRIB)
709 m_attrib_num = RAS_MAX_ATTRIB;
712 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit)
714 // this changes from material to material
715 if (unit < RAS_MAX_TEXCO)
716 m_texco[unit] = coords;
719 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit, int layer)
721 // this changes from material to material
722 if (unit < RAS_MAX_ATTRIB) {
723 m_attrib[unit] = coords;
724 m_attrib_layer[unit] = layer;
728 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
730 if (ms.m_pDerivedMesh)
733 m_storage->IndexPrimitives(ms);
736 // Code for hooking into Blender's mesh drawing for derived meshes.
737 // If/when we use more of Blender's drawing code, we may be able to
739 static bool current_wireframe;
740 static RAS_MaterialBucket *current_bucket;
741 static RAS_IPolyMaterial *current_polymat;
742 static RAS_MeshSlot *current_ms;
743 static RAS_MeshObject *current_mesh;
744 static int current_blmat_nr;
745 static GPUVertexAttribs current_gpu_attribs;
746 static Image *current_image;
747 static int CheckMaterialDM(int matnr, void *attribs)
749 // only draw the current material
750 if (matnr != current_blmat_nr)
752 GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
754 memcpy(gattribs, ¤t_gpu_attribs, sizeof(GPUVertexAttribs));
758 static DMDrawOption CheckTexDM(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
761 // index is the original face index, retrieve the polygon
762 if (matnr == current_blmat_nr &&
763 (mtexpoly == NULL || mtexpoly->tpage == current_image)) {
764 // must handle color.
765 if (current_wireframe)
766 return DM_DRAW_OPTION_NO_MCOL;
767 if (current_ms->m_bObjectColor) {
768 MT_Vector4& rgba = current_ms->m_RGBAcolor;
769 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
771 return DM_DRAW_OPTION_NO_MCOL;
774 // we have to set the color from the material
775 unsigned char rgba[4];
776 current_polymat->GetMaterialRGBAColor(rgba);
777 glColor4ubv((const GLubyte *)rgba);
778 return DM_DRAW_OPTION_NORMAL;
780 return DM_DRAW_OPTION_NORMAL;
782 return DM_DRAW_OPTION_SKIP;
785 void RAS_OpenGLRasterizer::DrawDerivedMesh(class RAS_MeshSlot &ms)
787 // mesh data is in derived mesh
788 current_bucket = ms.m_bucket;
789 current_polymat = current_bucket->GetPolyMaterial();
791 current_mesh = ms.m_mesh;
792 current_wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME;
793 // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
796 if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
797 this->SetCullFace(true);
799 this->SetCullFace(false);
801 if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
802 // GetMaterialIndex return the original mface material index,
803 // increment by 1 to match what derived mesh is doing
804 current_blmat_nr = current_polymat->GetMaterialIndex()+1;
805 // For GLSL we need to retrieve the GPU material attribute
806 Material* blmat = current_polymat->GetBlenderMaterial();
807 Scene* blscene = current_polymat->GetBlenderScene();
808 if (!current_wireframe && blscene && blmat)
809 GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat, false), ¤t_gpu_attribs);
811 memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs));
812 // DM draw can mess up blending mode, restore at the end
813 int current_blend_mode = GPU_get_material_alpha_blend();
814 ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
815 GPU_set_material_alpha_blend(current_blend_mode);
817 //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
818 current_blmat_nr = current_polymat->GetMaterialIndex();
819 current_image = current_polymat->GetBlenderImage();
820 ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL, DM_DRAW_USE_ACTIVE_UV);
824 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
826 glMatrixMode(GL_PROJECTION);
827 float* matrix = &mat(0, 0);
828 glLoadMatrixf(matrix);
830 m_camortho = (mat(3, 3) != 0.0f);
833 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
835 glMatrixMode(GL_PROJECTION);
837 /* Get into argument. Looks a bit dodgy, but it's ok. */
838 mat.getValue(matrix);
839 glLoadMatrixf(matrix);
841 m_camortho = (mat[3][3] != 0.0f);
844 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
857 // correction for stereo
860 float near_div_focallength;
863 // if Rasterizer.setFocalLength is not called we use the camera focallength
864 if (!m_setfocallength)
865 // if focallength is null we use a value known to be reasonable
866 m_focallength = (focallength == 0.f) ? m_eyeseparation * 30.0f
869 near_div_focallength = frustnear / m_focallength;
870 offset = 0.5f * m_eyeseparation * near_div_focallength;
872 case RAS_STEREO_LEFTEYE:
876 case RAS_STEREO_RIGHTEYE:
881 // leave bottom and top untouched
882 if (m_stereomode == RAS_STEREO_3DTVTOPBOTTOM) {
883 // restore the vertical frustum because the 3DTV will
884 // expand the top and bottom part to the full size of the screen
890 glMatrixMode(GL_PROJECTION);
892 glFrustum(left, right, bottom, top, frustnear, frustfar);
894 glGetFloatv(GL_PROJECTION_MATRIX, mat);
895 result.setValue(mat);
900 MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix(
911 // stereo is meaningless for orthographic, disable it
912 glMatrixMode(GL_PROJECTION);
914 glOrtho(left, right, bottom, top, frustnear, frustfar);
916 glGetFloatv(GL_PROJECTION_MATRIX, mat);
917 result.setValue(mat);
923 // next arguments probably contain redundant info, for later...
924 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat,
925 const MT_Matrix3x3 & camOrientMat3x3,
926 const MT_Point3 & pos,
931 // correction for stereo
932 if (Stereo() && perspective)
934 MT_Vector3 unitViewDir(0.0f, -1.0f, 0.0f); // minus y direction, Blender convention
935 MT_Vector3 unitViewupVec(0.0f, 0.0f, 1.0f);
936 MT_Vector3 viewDir, viewupVec;
940 viewDir = camOrientMat3x3 * unitViewDir; // this is the moto convention, vector on right hand side
942 viewupVec = camOrientMat3x3 * unitViewupVec;
944 // vector between eyes
945 eyeline = viewDir.cross(viewupVec);
948 case RAS_STEREO_LEFTEYE:
950 // translate to left by half the eye distance
951 MT_Transform transform;
952 transform.setIdentity();
953 transform.translate(-(eyeline * m_eyeseparation / 2.0f));
954 m_viewmatrix *= transform;
957 case RAS_STEREO_RIGHTEYE:
959 // translate to right by half the eye distance
960 MT_Transform transform;
961 transform.setIdentity();
962 transform.translate(eyeline * m_eyeseparation / 2.0f);
963 m_viewmatrix *= transform;
969 m_viewinvmatrix = m_viewmatrix;
970 m_viewinvmatrix.invert();
972 // note: getValue gives back column major as needed by OpenGL
973 MT_Scalar glviewmat[16];
974 m_viewmatrix.getValue(glviewmat);
976 glMatrixMode(GL_MODELVIEW);
977 glLoadMatrixf(glviewmat);
982 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
987 bool RAS_OpenGLRasterizer::GetCameraOrtho()
992 void RAS_OpenGLRasterizer::SetCullFace(bool enable)
995 glEnable(GL_CULL_FACE);
997 glDisable(GL_CULL_FACE);
1000 void RAS_OpenGLRasterizer::SetLines(bool enable)
1003 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1005 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1008 void RAS_OpenGLRasterizer::SetSpecularity(float specX,
1013 GLfloat mat_specular[] = {specX, specY, specZ, specval};
1014 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1019 void RAS_OpenGLRasterizer::SetShinyness(float shiny)
1021 GLfloat mat_shininess[] = { shiny };
1022 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1027 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float diffuse)
1029 GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse};
1030 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
1033 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e)
1035 GLfloat mat_emit [] = {eX,eY,eZ,e};
1036 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit);
1040 double RAS_OpenGLRasterizer::GetTime()
1045 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
1047 glPolygonOffset(mult, add);
1048 GLint mode = GL_POLYGON_OFFSET_FILL;
1049 if (m_drawingmode < KX_SHADED)
1050 mode = GL_POLYGON_OFFSET_LINE;
1051 if (mult != 0.0f || add != 0.0f)
1057 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
1059 /* don't just set m_motionblur to 1, but check if it is 0 so
1060 * we don't reset a motion blur that is already enabled */
1061 if (m_motionblur == 0)
1063 m_motionblurvalue = motionblurvalue;
1066 void RAS_OpenGLRasterizer::DisableMotionBlur()
1069 m_motionblurvalue = -1.0f;
1072 void RAS_OpenGLRasterizer::SetAlphaBlend(int alphablend)
1074 /* Variance shadow maps don't handle alpha well, best to not allow it for now */
1075 if (m_drawingmode == KX_SHADOW && m_usingoverrideshader)
1076 GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
1078 GPU_set_material_alpha_blend(alphablend);
1080 if (alphablend == m_last_alphablend)
1083 if (alphablend == GPU_BLEND_SOLID) {
1084 glDisable(GL_BLEND);
1085 glDisable(GL_ALPHA_TEST);
1086 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1088 else if (alphablend == GPU_BLEND_ADD) {
1089 glBlendFunc(GL_ONE, GL_ONE);
1091 glDisable(GL_ALPHA_TEST);
1093 else if (alphablend == GPU_BLEND_ALPHA) {
1094 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1096 glEnable(GL_ALPHA_TEST);
1097 glAlphaFunc(GL_GREATER, 0.0f);
1099 else if (alphablend == GPU_BLEND_CLIP) {
1100 glDisable(GL_BLEND);
1101 glEnable(GL_ALPHA_TEST);
1102 glAlphaFunc(GL_GREATER, 0.5f);
1105 m_last_alphablend = alphablend;
1109 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
1111 if (m_last_frontface == ccw)
1115 glFrontFace(GL_CCW);
1119 m_last_frontface = ccw;
1122 void RAS_OpenGLRasterizer::SetAnisotropicFiltering(short level)
1124 GPU_set_anisotropic((float)level);
1127 short RAS_OpenGLRasterizer::GetAnisotropicFiltering()
1129 return (short)GPU_get_anisotropic();
1132 void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val)
1134 if (val == RAS_IRasterizer::RAS_MIPMAP_LINEAR)
1136 GPU_set_linear_mipmap(1);
1139 else if (val == RAS_IRasterizer::RAS_MIPMAP_NEAREST)
1141 GPU_set_linear_mipmap(0);
1146 GPU_set_linear_mipmap(0);
1151 RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping()
1153 if (GPU_get_mipmap()) {
1154 if (GPU_get_linear_mipmap()) {
1155 return RAS_IRasterizer::RAS_MIPMAP_LINEAR;
1158 return RAS_IRasterizer::RAS_MIPMAP_NEAREST;
1162 return RAS_IRasterizer::RAS_MIPMAP_NONE;
1166 void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val)
1168 m_usingoverrideshader = val;
1171 bool RAS_OpenGLRasterizer::GetUsingOverrideShader()
1173 return m_usingoverrideshader;
1180 /* ProcessLighting performs lighting on objects. the layer is a bitfield that
1181 * contains layer information. There are 20 'official' layers in blender. A
1182 * light is applied on an object only when they are in the same layer. OpenGL
1183 * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in
1186 void RAS_OpenGLRasterizer::ProcessLighting(bool uselights, const MT_Transform& viewmat)
1188 bool enable = false;
1191 /* find the layer */
1194 layer = static_cast<KX_GameObject*>(m_clientobject)->GetLayer();
1197 /* avoid state switching */
1198 if (m_lastlightlayer == layer && m_lastauxinfo == m_auxilaryClientInfo)
1201 m_lastlightlayer = layer;
1202 m_lastauxinfo = m_auxilaryClientInfo;
1204 /* enable/disable lights as needed */
1206 //enable = ApplyLights(layer, viewmat);
1207 // taken from blender source, incompatibility between Blender Object / GameObject
1208 KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo;
1209 float glviewmat[16];
1211 std::vector<RAS_OpenGLLight*>::iterator lit = m_lights.begin();
1213 for (count=0; count<m_numgllights; count++)
1214 glDisable((GLenum)(GL_LIGHT0+count));
1216 viewmat.getValue(glviewmat);
1219 glLoadMatrixf(glviewmat);
1220 for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit)
1222 RAS_OpenGLLight* light = (*lit);
1224 if (light->ApplyFixedFunctionLighting(kxscene, layer, count))
1233 EnableOpenGLLights();
1235 DisableOpenGLLights();
1238 void RAS_OpenGLRasterizer::EnableOpenGLLights()
1240 if (m_lastlighting == true)
1243 glEnable(GL_LIGHTING);
1244 glEnable(GL_COLOR_MATERIAL);
1246 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1247 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
1248 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (GetCameraOrtho())? GL_FALSE: GL_TRUE);
1249 if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
1250 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1252 m_lastlighting = true;
1255 void RAS_OpenGLRasterizer::DisableOpenGLLights()
1257 if (m_lastlighting == false)
1260 glDisable(GL_LIGHTING);
1261 glDisable(GL_COLOR_MATERIAL);
1263 m_lastlighting = false;
1266 RAS_ILightObject *RAS_OpenGLRasterizer::CreateLight()
1268 return new RAS_OpenGLLight(this);
1271 void RAS_OpenGLRasterizer::AddLight(RAS_ILightObject* lightobject)
1273 RAS_OpenGLLight* gllight = dynamic_cast<RAS_OpenGLLight*>(lightobject);
1275 m_lights.push_back(gllight);
1278 void RAS_OpenGLRasterizer::RemoveLight(RAS_ILightObject* lightobject)
1280 RAS_OpenGLLight* gllight = dynamic_cast<RAS_OpenGLLight*>(lightobject);
1283 std::vector<RAS_OpenGLLight*>::iterator lit =
1284 std::find(m_lights.begin(),m_lights.end(),gllight);
1286 if (!(lit==m_lights.end()))
1287 m_lights.erase(lit);
1290 bool RAS_OpenGLRasterizer::RayHit(struct KX_ClientObjectInfo *client, KX_RayCast *result, float *oglmatrix)
1292 if (result->m_hitMesh) {
1294 RAS_Polygon* poly = result->m_hitMesh->GetPolygon(result->m_hitPolygon);
1295 if (!poly->IsVisible())
1298 MT_Vector3 resultnormal(result->m_hitNormal);
1299 MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
1300 MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
1301 left = (dir.cross(resultnormal)).safe_normalized();
1302 // for the up vector, we take the 'resultnormal' returned by the physics
1304 float maat[16] = {left[0], left[1], left[2], 0,
1305 dir[0], dir[1], dir[2], 0,
1306 resultnormal[0], resultnormal[1], resultnormal[2], 0,
1309 glTranslatef(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
1310 //glMultMatrixd(oglmatrix);
1311 glMultMatrixf(maat);
1319 void RAS_OpenGLRasterizer::applyTransform(float* oglmatrix,int objectdrawmode )
1322 blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const
1323 MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed.
1325 Program received signal SIGABRT, Aborted.
1326 [Switching to Thread 16384 (LWP 1519)]
1327 0x40477571 in kill () from /lib/libc.so.6
1329 #7 0x08334368 in MT_Vector3::normalized() const ()
1330 #8 0x0833e6ec in RAS_OpenGLRasterizer::applyTransform(RAS_IRasterizer*, double*, int) ()
1333 if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED ||
1334 objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED)
1336 // rotate the billboard/halo
1337 //page 360/361 3D Game Engine Design, David Eberly for a discussion
1338 // on screen aligned and axis aligned billboards
1339 // assumed is that the preprocessor transformed all billboard polygons
1340 // so that their normal points into the positive x direction (1.0f, 0.0f, 0.0f)
1341 // when new parenting for objects is done, this rotation
1342 // will be moved into the object
1344 MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]);
1345 MT_Point3 campos = GetCameraPosition();
1346 MT_Vector3 dir = (campos - objpos).safe_normalized();
1347 MT_Vector3 up(0,0,1.0f);
1349 KX_GameObject* gameobj = (KX_GameObject*)m_clientobject;
1350 // get scaling of halo object
1351 MT_Vector3 size = gameobj->GetSGNode()->GetWorldScaling();
1353 bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned
1356 up = (up - up.dot(dir) * dir).safe_normalized();
1359 dir = (dir - up.dot(dir)*up).safe_normalized();
1362 MT_Vector3 left = dir.normalized();
1363 dir = (up.cross(left)).normalized();
1365 // we have calculated the row vectors, now we keep
1366 // local scaling into account:
1372 float maat[16] = {left[0], left[1], left[2], 0,
1373 dir[0], dir[1], dir[2], 0,
1374 up[0], up[1], up[2], 0,
1377 glTranslatef(objpos[0],objpos[1],objpos[2]);
1378 glMultMatrixf(maat);
1382 if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
1384 // shadow must be cast to the ground, physics system needed here!
1385 MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
1386 KX_GameObject *gameobj = (KX_GameObject*)m_clientobject;
1387 MT_Vector3 direction = MT_Vector3(0,0,-1);
1389 direction.normalize();
1390 direction *= 100000;
1392 MT_Point3 topoint = frompoint + direction;
1394 KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo;
1395 PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment();
1396 PHY_IPhysicsController* physics_controller = gameobj->GetPhysicsController();
1398 KX_GameObject *parent = gameobj->GetParent();
1399 if (!physics_controller && parent)
1400 physics_controller = parent->GetPhysicsController();
1402 KX_RayCast::Callback<RAS_OpenGLRasterizer, float> callback(this, physics_controller, oglmatrix);
1403 if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback))
1405 // couldn't find something to cast the shadow on...
1406 glMultMatrixf(oglmatrix);
1409 { // we found the "ground", but the cast matrix doesn't take
1410 // scaling in consideration, so we must apply the object scale
1411 MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale();
1412 glScalef(size[0], size[1], size[2]);
1418 glMultMatrixf(oglmatrix);
1423 static void DisableForText()
1425 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* needed for texture fonts otherwise they render as wireframe */
1427 glDisable(GL_BLEND);
1428 glDisable(GL_ALPHA_TEST);
1430 glDisable(GL_LIGHTING);
1431 glDisable(GL_COLOR_MATERIAL);
1433 if (GLEW_ARB_multitexture) {
1434 for (int i=0; i<RAS_MAX_TEXCO; i++) {
1435 glActiveTextureARB(GL_TEXTURE0_ARB+i);
1437 if (GLEW_ARB_texture_cube_map) {
1438 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1439 glDisable(GL_TEXTURE_GEN_S);
1440 glDisable(GL_TEXTURE_GEN_T);
1441 glDisable(GL_TEXTURE_GEN_Q);
1442 glDisable(GL_TEXTURE_GEN_R);
1444 glDisable(GL_TEXTURE_2D);
1447 glActiveTextureARB(GL_TEXTURE0_ARB);
1450 if (GLEW_ARB_texture_cube_map)
1451 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1453 glDisable(GL_TEXTURE_2D);
1457 void RAS_OpenGLRasterizer::RenderBox2D(int xco,
1463 /* This is a rather important line :( The gl-mode hasn't been left
1464 * behind quite as neatly as we'd have wanted to. I don't know
1465 * what cause it, though :/ .*/
1466 glDisable(GL_DEPTH_TEST);
1468 glMatrixMode(GL_PROJECTION);
1472 glOrtho(0, width, 0, height, -100, 100);
1474 glMatrixMode(GL_MODELVIEW);
1481 /* draw in black first */
1482 glColor3ub(0, 0, 0);
1484 glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1 + 10);
1485 glVertex2f(xco + 1, yco - 1 + 10);
1486 glVertex2f(xco + 1, yco - 1);
1487 glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1);
1490 glColor3ub(255, 255, 255);
1492 glVertex2f(xco + 1 + barsize * percentage, yco + 10);
1493 glVertex2f(xco, yco + 10);
1494 glVertex2f(xco, yco);
1495 glVertex2f(xco + 1 + barsize * percentage, yco);
1498 glMatrixMode(GL_PROJECTION);
1500 glMatrixMode(GL_MODELVIEW);
1502 glEnable(GL_DEPTH_TEST);
1505 void RAS_OpenGLRasterizer::RenderText3D(
1506 int fontid, const char *text, int size, int dpi,
1507 const float color[4], const float mat[16], float aspect)
1512 /* the actual drawing */
1515 /* multiply the text matrix by the object matrix */
1516 BLF_enable(fontid, BLF_MATRIX|BLF_ASPECT);
1517 BLF_matrix(fontid, mat);
1519 /* aspect is the inverse scale that allows you to increase
1520 * your resolution without sizing the final text size
1521 * the bigger the size, the smaller the aspect */
1522 BLF_aspect(fontid, aspect, aspect, aspect);
1524 BLF_size(fontid, size, dpi);
1525 BLF_position(fontid, 0, 0, 0);
1526 BLF_draw(fontid, text, 65535);
1528 BLF_disable(fontid, BLF_MATRIX|BLF_ASPECT);
1531 void RAS_OpenGLRasterizer::RenderText2D(
1532 RAS_TEXT_RENDER_MODE mode,
1535 int width, int height)
1537 /* This is a rather important line :( The gl-mode hasn't been left
1538 * behind quite as neatly as we'd have wanted to. I don't know
1539 * what cause it, though :/ .*/
1541 glDisable(GL_DEPTH_TEST);
1543 glMatrixMode(GL_PROJECTION);
1547 glOrtho(0, width, 0, height, -100, 100);
1549 glMatrixMode(GL_MODELVIEW);
1553 if (mode == RAS_TEXT_PADDED) {
1554 /* draw in black first */
1555 glColor3ub(0, 0, 0);
1556 BLF_size(blf_mono_font, 11, 72);
1557 BLF_position(blf_mono_font, (float)xco+1, (float)(height-yco-1), 0.0f);
1558 BLF_draw(blf_mono_font, text, 65535); /* XXX, use real len */
1561 /* the actual drawing */
1562 glColor3ub(255, 255, 255);
1563 BLF_size(blf_mono_font, 11, 72);
1564 BLF_position(blf_mono_font, (float)xco, (float)(height-yco), 0.0f);
1565 BLF_draw(blf_mono_font, text, 65535); /* XXX, use real len */
1567 glMatrixMode(GL_PROJECTION);
1569 glMatrixMode(GL_MODELVIEW);
1571 glEnable(GL_DEPTH_TEST);
1574 void RAS_OpenGLRasterizer::PushMatrix()
1579 void RAS_OpenGLRasterizer::PopMatrix()
1584 void RAS_OpenGLRasterizer::MotionBlur()
1586 int state = GetMotionBlurState();
1587 float motionblurvalue;
1590 motionblurvalue = GetMotionBlurValue();
1593 // bugfix:load color buffer into accum buffer for the first time(state=1)
1594 glAccum(GL_LOAD, 1.0f);
1595 SetMotionBlurState(2);
1597 else if (motionblurvalue >= 0.0f && motionblurvalue <= 1.0f) {
1598 glAccum(GL_MULT, motionblurvalue);
1599 glAccum(GL_ACCUM, 1-motionblurvalue);
1600 glAccum(GL_RETURN, 1.0f);
1606 void RAS_OpenGLRasterizer::SetClientObject(void* obj)
1608 if (m_clientobject != obj)
1610 bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling());
1613 m_clientobject = obj;
1617 void RAS_OpenGLRasterizer::SetAuxilaryClientInfo(void* inf)
1619 m_auxilaryClientInfo = inf;
1622 void RAS_OpenGLRasterizer::PrintHardwareInfo()
1624 #define pprint(x) std::cout << x << std::endl;
1626 pprint("GL_VENDOR: " << glGetString(GL_VENDOR));
1627 pprint("GL_RENDERER: " << glGetString(GL_RENDERER));
1628 pprint("GL_VERSION: " << glGetString(GL_VERSION));
1630 pprint("Supported Extensions...");
1631 pprint(" GL_ARB_shader_objects supported? "<< (GLEW_ARB_shader_objects?"yes.":"no."));
1633 support= GLEW_ARB_vertex_shader;
1634 pprint(" GL_ARB_vertex_shader supported? "<< (support?"yes.":"no."));
1636 pprint(" ----------Details----------");
1638 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, (GLint*)&max);
1639 pprint(" Max uniform components." << max);
1641 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, (GLint*)&max);
1642 pprint(" Max varying floats." << max);
1644 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, (GLint*)&max);
1645 pprint(" Max vertex texture units." << max);
1647 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, (GLint*)&max);
1648 pprint(" Max combined texture units." << max);
1652 support=GLEW_ARB_fragment_shader;
1653 pprint(" GL_ARB_fragment_shader supported? "<< (support?"yes.":"no."));
1655 pprint(" ----------Details----------");
1657 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, (GLint*)&max);
1658 pprint(" Max uniform components." << max);
1662 support = GLEW_ARB_texture_cube_map;
1663 pprint(" GL_ARB_texture_cube_map supported? "<< (support?"yes.":"no."));
1665 pprint(" ----------Details----------");
1667 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, (GLint*)&size);
1668 pprint(" Max cubemap size." << size);
1672 support = GLEW_ARB_multitexture;
1673 pprint(" GL_ARB_multitexture supported? "<< (support?"yes.":"no."));
1675 pprint(" ----------Details----------");
1677 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&units);
1678 pprint(" Max texture units available. " << units);
1682 pprint(" GL_ARB_texture_env_combine supported? "<< (GLEW_ARB_texture_env_combine?"yes.":"no."));
1684 pprint(" GL_ARB_texture_non_power_of_two supported " << (GPU_full_non_power_of_two_support()?"yes.":"no."));