source: OGRE/trunk/ogrenew/RenderSystems/GL/src/OgreGLRenderSystem.cpp @ 692

Revision 692, 92.3 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://ogre.sourceforge.net/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.s
23-----------------------------------------------------------------------------
24*/
25
26
27#include "OgreGLRenderSystem.h"
28#include "OgreRenderSystem.h"
29#include "OgreLogManager.h"
30#include "OgreStringConverter.h"
31#include "OgreLight.h"
32#include "OgreCamera.h"
33#include "OgreGLTextureManager.h"
34#include "OgreGLHardwareVertexBuffer.h"
35#include "OgreGLHardwareIndexBuffer.h"
36#include "OgreGLDefaultHardwareBufferManager.h"
37#include "OgreGLUtil.h"
38#include "OgreGLGpuProgram.h"
39#include "OgreGLGpuNvparseProgram.h"
40#include "ATI_FS_GLGpuProgram.h"
41#include "OgreGLGpuProgramManager.h"
42#include "OgreException.h"
43#include "OgreGLSLExtSupport.h"
44#include "OgreGLHardwareOcclusionQuery.h"
45#include "OgreGLContext.h"
46
47#include "OgreGLFBORenderTexture.h"
48#include "OgreGLPBRenderTexture.h"
49#ifdef HAVE_CONFIG_H
50#   include "config.h"
51#endif
52
53// Convenience macro from ARB_vertex_buffer_object spec
54#define VBO_BUFFER_OFFSET(i) ((char *)NULL + (i))
55GLenum glewContextInit (Ogre::GLSupport *glSupport);
56
57namespace Ogre {
58
59    // Callback function used when registering GLGpuPrograms
60    GpuProgram* createGLArbGpuProgram(ResourceManager* creator,
61        const String& name, ResourceHandle handle,
62        const String& group, bool isManual, ManualResourceLoader* loader,
63        GpuProgramType gptype, const String& syntaxCode)
64    {
65        GLArbGpuProgram* ret = new GLArbGpuProgram(
66            creator, name, handle, group, isManual, loader);
67        ret->setType(gptype);
68        ret->setSyntaxCode(syntaxCode);
69        return ret;
70    }
71
72    GpuProgram* createGLGpuNvparseProgram(ResourceManager* creator,
73        const String& name, ResourceHandle handle,
74        const String& group, bool isManual, ManualResourceLoader* loader,
75        GpuProgramType gptype, const String& syntaxCode)
76    {
77        GLGpuNvparseProgram* ret = new GLGpuNvparseProgram(
78            creator, name, handle, group, isManual, loader);
79        ret->setType(gptype);
80        ret->setSyntaxCode(syntaxCode);
81        return ret;
82    }
83
84    GpuProgram* createGL_ATI_FS_GpuProgram(ResourceManager* creator,
85        const String& name, ResourceHandle handle,
86        const String& group, bool isManual, ManualResourceLoader* loader,
87        GpuProgramType gptype, const String& syntaxCode)
88        {
89
90        ATI_FS_GLGpuProgram* ret = new ATI_FS_GLGpuProgram(
91            creator, name, handle, group, isManual, loader);
92        ret->setType(gptype);
93        ret->setSyntaxCode(syntaxCode);
94        return ret;
95        }
96
97    GLRenderSystem::GLRenderSystem()
98      : mDepthWrite(true), mStencilMask(0xFFFFFFFF), mHardwareBufferManager(0),
99        mGpuProgramManager(0),
100        mRTTManager(0)
101    {
102        size_t i;
103
104        OgreGuard( "GLRenderSystem::GLRenderSystem" );
105
106        LogManager::getSingleton().logMessage(getName() + " created.");
107
108        // Get our GLSupport
109        mGLSupport = getGLSupport();
110
111        for( i=0; i<MAX_LIGHTS; i++ )
112            mLights[i] = NULL;
113
114        mWorldMatrix = Matrix4::IDENTITY;
115        mViewMatrix = Matrix4::IDENTITY;
116       
117        initConfigOptions();
118
119        mColourWrite[0] = mColourWrite[1] = mColourWrite[2] = mColourWrite[3] = true;
120
121        for (i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; i++)
122        {
123                        // Dummy value
124            mTextureCoordIndex[i] = 99;
125        }
126
127        for (i = 0; i < OGRE_MAX_TEXTURE_LAYERS; i++)
128        {
129            mTextureTypes[i] = 0;
130        }
131
132        mActiveRenderTarget = 0;
133        mCurrentContext = 0;
134        mMainContext = 0;
135
136        mGLInitialized = false;
137
138        mCurrentLights = 0;
139        mMinFilter = FO_LINEAR;
140        mMipFilter = FO_POINT;
141        mCurrentVertexProgram = 0;
142        mCurrentFragmentProgram = 0;
143
144        mClipPlanes.reserve(6);
145
146        OgreUnguard();
147    }
148
149    GLRenderSystem::~GLRenderSystem()
150    {
151        shutdown();
152
153        // Destroy render windows
154        RenderTargetMap::iterator i;
155        for (i = mRenderTargets.begin(); i != mRenderTargets.end(); ++i)
156        {
157            delete i->second;
158        }
159        mRenderTargets.clear();
160
161        if (mTextureManager)
162            delete mTextureManager;
163
164        delete mGLSupport;
165    }
166
167    const String& GLRenderSystem::getName(void) const
168    {
169        static String strName("OpenGL Rendering Subsystem");
170        return strName;
171    }
172
173    void GLRenderSystem::initConfigOptions(void)
174    {
175        OgreGuard("GLRenderSystem::initConfigOptions");
176        mGLSupport->addConfig();
177        OgreUnguard();
178    }
179   
180    ConfigOptionMap& GLRenderSystem::getConfigOptions(void)
181    {
182        return mGLSupport->getConfigOptions();
183    }
184
185    void GLRenderSystem::setConfigOption(const String &name, const String &value)
186    {
187        mGLSupport->setConfigOption(name, value);
188    }
189
190    String GLRenderSystem::validateConfigOptions(void)
191    {
192        // XXX Return an error string if something is invalid
193        return mGLSupport->validateConfig();
194    }
195
196    RenderWindow* GLRenderSystem::initialise(bool autoCreateWindow, const String& windowTitle)
197    {
198        mGLSupport->start();
199       
200                RenderWindow* autoWindow = mGLSupport->createWindow(autoCreateWindow, this, windowTitle);
201
202
203        _setCullingMode( mCullingMode );
204       
205        return autoWindow;
206    }
207
208    void GLRenderSystem::initGL(RenderTarget *primary)
209    {
210        // Set main and current context
211        mMainContext = 0;
212        primary->getCustomAttribute("GLCONTEXT", &mMainContext);
213        mCurrentContext = mMainContext;
214       
215        // Set primary context as active
216        if(mCurrentContext)
217            mCurrentContext->setCurrent();
218           
219        // Setup GLSupport
220        mGLSupport->initialiseExtensions();
221
222        LogManager::getSingleton().logMessage(
223            "***************************\n"
224            "*** GL Renderer Started ***\n"
225                "***************************");
226                // Get extension function pointers
227        glewContextInit(mGLSupport);
228
229        // Check for hardware mipmapping support.
230        if(GLEW_VERSION_1_4 || GLEW_SGIS_generate_mipmap)
231        {
232            mCapabilities->setCapability(RSC_AUTOMIPMAP);
233        }
234
235        // Check for blending support
236        if(GLEW_VERSION_1_3 ||
237            GLEW_ARB_texture_env_combine ||
238            GLEW_EXT_texture_env_combine)
239        {
240            mCapabilities->setCapability(RSC_BLENDING);
241        }
242
243        // Check for Multitexturing support and set number of texture units
244        if(GLEW_VERSION_1_3 ||
245           GLEW_ARB_multitexture)
246        {
247            GLint units;
248            glGetIntegerv( GL_MAX_TEXTURE_UNITS, &units );
249                        mFixedFunctionTextureUnits = units;
250
251                        if (GLEW_ARB_fragment_program)
252                        {
253                                // Also check GL_MAX_TEXTURE_IMAGE_UNITS_ARB since NV at least
254                                // only increased this on the FX/6x00 series
255                                GLint arbUnits;
256                                glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &arbUnits );
257                                if (arbUnits > units)
258                                        units = arbUnits;
259                        }
260           
261            mCapabilities->setNumTextureUnits(units);
262
263        }
264        else
265        {
266            // If no multitexture support then set one texture unit
267            mCapabilities->setNumTextureUnits(1);
268        }
269           
270        // Check for Anisotropy support
271        if(GLEW_EXT_texture_filter_anisotropic)
272        {
273            mCapabilities->setCapability(RSC_ANISOTROPY);
274        }
275
276        // Check for DOT3 support
277        if(GLEW_VERSION_1_3 ||
278           GLEW_ARB_texture_env_dot3 ||
279           GLEW_EXT_texture_env_dot3)
280        {
281            mCapabilities->setCapability(RSC_DOT3);
282        }
283
284        // Check for cube mapping
285        if(GLEW_VERSION_1_3 ||
286           GLEW_ARB_texture_cube_map ||
287           GLEW_EXT_texture_cube_map)
288        {
289            mCapabilities->setCapability(RSC_CUBEMAPPING);
290        }
291       
292        // Check for hardware stencil support and set bit depth
293        GLint stencil;
294        glGetIntegerv(GL_STENCIL_BITS,&stencil);
295
296        if(stencil)
297        {
298            mCapabilities->setCapability(RSC_HWSTENCIL);
299            mCapabilities->setStencilBufferBitDepth(stencil);
300        }
301
302        // Check for VBO support
303        if(GLEW_VERSION_1_5 || GLEW_ARB_vertex_buffer_object)
304        {
305            mCapabilities->setCapability(RSC_VBO);
306
307            mHardwareBufferManager = new GLHardwareBufferManager;
308        }
309        else
310        {
311            mHardwareBufferManager = new GLDefaultHardwareBufferManager;
312        }
313
314        // XXX Need to check for nv2 support and make a program manager for it
315        // XXX Probably nv1 as well for older cards
316        // GPU Program Manager setup
317        mGpuProgramManager = new GLGpuProgramManager();
318
319                if(GLEW_ARB_vertex_program)
320        {
321            mCapabilities->setCapability(RSC_VERTEX_PROGRAM);
322
323            // Vertex Program Properties
324            mCapabilities->setMaxVertexProgramVersion("arbvp1");
325            mCapabilities->setVertexProgramConstantBoolCount(0);
326            mCapabilities->setVertexProgramConstantIntCount(0);
327            mCapabilities->setVertexProgramConstantFloatCount(
328                GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
329
330            mGpuProgramManager->_pushSyntaxCode("arbvp1");
331            mGpuProgramManager->registerProgramFactory("arbvp1", createGLArbGpuProgram);
332                        if (GLEW_NV_vertex_program2_option)
333                        {
334                                mCapabilities->setMaxVertexProgramVersion("vp30");
335                                mGpuProgramManager->_pushSyntaxCode("vp30");
336                                mGpuProgramManager->registerProgramFactory("vp30", createGLArbGpuProgram);
337                        }
338
339                        if (GLEW_NV_vertex_program3)
340                        {
341                                mCapabilities->setMaxVertexProgramVersion("vp40");
342                                mGpuProgramManager->_pushSyntaxCode("vp40");
343                                mGpuProgramManager->registerProgramFactory("vp40", createGLArbGpuProgram);
344                        }
345                }
346
347        if (GLEW_NV_register_combiners2 &&
348            GLEW_NV_texture_shader)
349        {
350            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
351            mCapabilities->setMaxFragmentProgramVersion("fp20");
352
353            mGpuProgramManager->_pushSyntaxCode("fp20");
354            mGpuProgramManager->registerProgramFactory("fp20", createGLGpuNvparseProgram);
355        }
356
357                // NFZ - check for ATI fragment shader support
358                if (GLEW_ATI_fragment_shader)
359                {
360            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
361            mCapabilities->setMaxFragmentProgramVersion("ps_1_4");
362            // no boolean params allowed
363            mCapabilities->setFragmentProgramConstantBoolCount(0);
364            // no integer params allowed
365            mCapabilities->setFragmentProgramConstantIntCount(0);
366
367                        // only 8 Vector4 constant floats supported
368            mCapabilities->setFragmentProgramConstantFloatCount(8);
369
370            mGpuProgramManager->_pushSyntaxCode("ps_1_4");
371            mGpuProgramManager->_pushSyntaxCode("ps_1_3");
372            mGpuProgramManager->_pushSyntaxCode("ps_1_2");
373            mGpuProgramManager->_pushSyntaxCode("ps_1_1");
374
375            mGpuProgramManager->registerProgramFactory("ps_1_4", createGL_ATI_FS_GpuProgram);
376            mGpuProgramManager->registerProgramFactory("ps_1_3", createGL_ATI_FS_GpuProgram);
377            mGpuProgramManager->registerProgramFactory("ps_1_2", createGL_ATI_FS_GpuProgram);
378            mGpuProgramManager->registerProgramFactory("ps_1_1", createGL_ATI_FS_GpuProgram);
379                }
380
381        if (GLEW_ARB_fragment_program)
382        {
383            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
384            // Fragment Program Properties
385            mCapabilities->setMaxFragmentProgramVersion("arbfp1");
386            mCapabilities->setFragmentProgramConstantBoolCount(0);
387            mCapabilities->setFragmentProgramConstantIntCount(0);
388            mCapabilities->setFragmentProgramConstantFloatCount(
389                GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
390
391            mGpuProgramManager->_pushSyntaxCode("arbfp1");
392            mGpuProgramManager->registerProgramFactory("arbfp1", createGLArbGpuProgram);
393                        if (GLEW_NV_fragment_program_option)
394                        {
395                                mCapabilities->setMaxFragmentProgramVersion("fp30");
396                                mGpuProgramManager->_pushSyntaxCode("fp30");
397                                mGpuProgramManager->registerProgramFactory("fp30", createGLArbGpuProgram);
398                        }
399
400                        if (GLEW_NV_fragment_program2)
401                        {
402                                mCapabilities->setMaxFragmentProgramVersion("fp40");
403                                mGpuProgramManager->_pushSyntaxCode("fp40");
404                                mGpuProgramManager->registerProgramFactory("fp40", createGLArbGpuProgram);
405                        }       
406                }
407
408                // NFZ - Check if GLSL is supported
409                if ( GLEW_VERSION_2_0 ||
410                        (GLEW_ARB_shading_language_100 &&
411                         GLEW_ARB_shader_objects &&
412                         GLEW_ARB_fragment_shader &&
413                         GLEW_ARB_vertex_shader) )
414                {
415                        // NFZ - check for GLSL vertex and fragment shader support successful
416            mGpuProgramManager->_pushSyntaxCode("glsl");
417                        LogManager::getSingleton().logMessage("GLSL support detected");
418                }
419
420                // Check for texture compression
421        if(GLEW_VERSION_1_3 || GLEW_ARB_texture_compression)
422        {   
423            mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION);
424         
425            // Check for dxt compression
426            if(GLEW_EXT_texture_compression_s3tc)
427            {
428                mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
429            }
430            // Check for vtc compression
431            if(GLEW_NV_texture_compression_vtc)
432            {
433                mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_VTC);
434            }
435        }
436
437        // Scissor test is standard in GL 1.2 (is it emulated on some cards though?)
438        mCapabilities->setCapability(RSC_SCISSOR_TEST);
439                // As are user clipping planes
440                mCapabilities->setCapability(RSC_USER_CLIP_PLANES);
441
442        // 2-sided stencil?
443        if (GLEW_VERSION_2_0 || GLEW_EXT_stencil_two_side)
444        {
445            mCapabilities->setCapability(RSC_TWO_SIDED_STENCIL);
446        }
447        // stencil wrapping?
448        if (GLEW_VERSION_1_4 || GLEW_EXT_stencil_wrap)
449        {
450            mCapabilities->setCapability(RSC_STENCIL_WRAP);
451        }
452
453        // Check for hardware occlusion support
454        if(GLEW_NV_occlusion_query)
455        {
456            mCapabilities->setCapability(RSC_HWOCCLUSION);             
457        }
458
459                // UBYTE4 always supported
460                mCapabilities->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
461
462        // Inifinite far plane always supported
463        mCapabilities->setCapability(RSC_INFINITE_FAR_PLANE);
464
465        // Check for non-power-of-2 texture support
466                if(GLEW_ARB_texture_non_power_of_two)
467        {
468            mCapabilities->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
469        }
470
471        // Check for Float textures
472        if(GLEW_ATI_texture_float || GLEW_ARB_texture_float)
473        {
474            mCapabilities->setCapability(RSC_TEXTURE_FLOAT);
475        }
476       
477                // 3D textures should be supported by GL 1.2, which is our minimum version
478        mCapabilities->setCapability(RSC_TEXTURE_3D);
479       
480        /// Do this after extension function pointers are initialised as the extension
481        /// is used to probe further capabilities.
482                ConfigOptionMap::iterator cfi = getConfigOptions().find("RTT Preferred Mode");
483                // RTT Mode: 0 use whatever available, 1 use PBuffers, 2 force use copying
484                int rttMode = 0;
485                if (cfi != getConfigOptions().end())
486                {
487                        if (cfi->second.currentValue == "PBuffer")
488                        {
489                                rttMode = 1;
490                        }
491                        else if (cfi->second.currentValue == "Copy")
492                        {
493                                rttMode = 2;
494                        }
495                }
496         // Check for framebuffer object extension
497        if(GLEW_EXT_framebuffer_object && rttMode < 1)
498        {
499                        // Probe number of draw buffers
500                        // Only makes sense with FBO support, so probe here
501                        if(GLEW_VERSION_2_0 ||
502                                GLEW_ARB_draw_buffers ||
503                                GLEW_ATI_draw_buffers)
504                        {
505                                GLint buffers;
506                                glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &buffers);
507                                mCapabilities->setNumMultiRenderTargets(std::min(buffers, OGRE_MAX_MULTIPLE_RENDER_TARGETS));
508                                if(!GLEW_VERSION_2_0)
509                                {
510                                        // Before GL version 2.0, we need to get one of the extensions
511                                        if(GLEW_ARB_draw_buffers)
512                                                __glewDrawBuffers = glDrawBuffersARB;
513                                        else if(GLEW_ATI_draw_buffers)
514                                                __glewDrawBuffers = glDrawBuffersATI;
515                                }
516                        }
517                        // Create FBO manager
518            LogManager::getSingleton().logMessage("GL: Using GL_EXT_framebuffer_object for rendering to textures (best)");
519            //mRTTManager = new GLFBOManager(mGLSupport->getGLVendor() == "ATI");
520            mRTTManager = new GLFBOManager(false);
521            mCapabilities->setCapability(RSC_HWRENDER_TO_TEXTURE);
522        }
523        else
524        {
525            // Check GLSupport for PBuffer support
526            if(mGLSupport->supportsPBuffers() && rttMode < 2)
527            {
528                // Use PBuffers
529                mRTTManager = new GLPBRTTManager(mGLSupport, primary);
530                LogManager::getSingleton().logMessage("GL: Using PBuffers for rendering to textures");
531                mCapabilities->setCapability(RSC_HWRENDER_TO_TEXTURE);
532            }
533            else
534            {
535                // No pbuffer support either -- fallback to simplest copying from framebuffer
536                mRTTManager = new GLCopyingRTTManager();
537                LogManager::getSingleton().logMessage("GL: Using framebuffer copy for rendering to textures (worst)");
538                LogManager::getSingleton().logMessage("GL: Warning: RenderTexture size is restricted to size of framebuffer. If you are on Linux, consider using GLX instead of SDL.");
539            }
540        }
541
542                // Point size
543                float ps;
544                glGetFloatv(GL_POINT_SIZE_MAX, &ps);
545                mCapabilities->setMaxPointSize(ps);
546       
547                Log* defaultLog = LogManager::getSingleton().getDefaultLog();
548                if (defaultLog)
549                {
550                        mCapabilities->log(defaultLog);
551                }
552
553        /// Create the texture manager       
554        mTextureManager = new GLTextureManager(*mGLSupport);
555
556        mGLInitialized = true;
557    }
558
559    void GLRenderSystem::reinitialise(void)
560    {
561        this->shutdown();
562        this->initialise(true);
563    }
564
565    void GLRenderSystem::shutdown(void)
566    {
567        RenderSystem::shutdown();
568
569        // Deleting the GPU program manager and hardware buffer manager.  Has to be done before the mGLSupport->stop().
570        delete mGpuProgramManager;
571        mGpuProgramManager = 0;
572       
573        delete mHardwareBufferManager;
574        mHardwareBufferManager = 0;
575       
576        delete mRTTManager;
577        mRTTManager = 0;
578
579        mGLSupport->stop();
580        mStopRendering = true;
581    }
582
583    void GLRenderSystem::setAmbientLight(float r, float g, float b)
584    {
585        GLfloat lmodel_ambient[] = {r, g, b, 1.0};
586        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
587    }
588
589    void GLRenderSystem::setShadingType(ShadeOptions so)
590    {
591        switch(so)
592        {
593        case SO_FLAT:
594            glShadeModel(GL_FLAT);
595            break;
596        default:
597            glShadeModel(GL_SMOOTH);
598            break;
599        }
600    }
601
602        RenderWindow* GLRenderSystem::createRenderWindow(const String &name,
603                unsigned int width, unsigned int height, bool fullScreen,
604                const NameValuePairList *miscParams)
605    {
606        if (mRenderTargets.find(name) != mRenderTargets.end())
607        {
608            OGRE_EXCEPT(
609                Exception::ERR_INVALIDPARAMS,
610                "Window with name '" + name + "' already exists",
611                "GLRenderSystem::createRenderWindow" );
612        }
613                // Log a message
614                std::stringstream ss;
615                ss << "GLRenderSystem::createRenderWindow \"" << name << "\", " <<
616                        width << "x" << height << " ";
617                if(fullScreen)
618                        ss << "fullscreen ";
619                else
620                        ss << "windowed ";
621                if(miscParams)
622                {
623                        ss << " miscParams: ";
624                        NameValuePairList::const_iterator it;
625                        for(it=miscParams->begin(); it!=miscParams->end(); ++it)
626                        {
627                                ss << it->first << "=" << it->second << " ";
628                        }
629                        LogManager::getSingleton().logMessage(ss.str());
630                }
631
632        // Create the window
633        RenderWindow* win = mGLSupport->newWindow(name, width, height,
634            fullScreen, miscParams);
635
636        attachRenderTarget( *win );
637
638        if (!mGLInitialized)
639        {               
640            // Initialise GL after the first window has been created
641            initGL(win);
642           
643            // Initialise the main context
644            _oneTimeContextInitialization();
645            if(mCurrentContext)
646                mCurrentContext->setInitialized();
647        }
648
649        return win;
650    }
651
652        //-----------------------------------------------------------------------
653        MultiRenderTarget * GLRenderSystem::createMultiRenderTarget(const String & name)
654        {
655                MultiRenderTarget *retval = mRTTManager->createMultiRenderTarget(name);
656                attachRenderTarget( *retval );
657                return retval;
658        }
659
660        //-----------------------------------------------------------------------
661    void GLRenderSystem::destroyRenderWindow(RenderWindow* pWin)
662    {
663        // Find it to remove from list
664        RenderTargetMap::iterator i = mRenderTargets.begin();
665
666        while (i != mRenderTargets.end())
667        {
668            if (i->second == pWin)
669            {
670                mRenderTargets.erase(i);
671                delete pWin;
672                break;
673            }
674        }
675    }
676
677        //---------------------------------------------------------------------
678    void GLRenderSystem::_useLights(const LightList& lights, unsigned short limit)
679    {
680        // Save previous modelview
681        glMatrixMode(GL_MODELVIEW);
682        glPushMatrix();
683        // just load view matrix (identity world)
684        GLfloat mat[16];
685        makeGLMatrix(mat, mViewMatrix);
686        glLoadMatrixf(mat);
687
688        LightList::const_iterator i, iend;
689        iend = lights.end();
690        unsigned short num = 0;
691        for (i = lights.begin(); i != iend && num < limit; ++i, ++num)
692        {
693            setGLLight(num, *i);
694            mLights[num] = *i;
695        }
696        // Disable extra lights
697        for (; num < mCurrentLights; ++num)
698        {
699            setGLLight(num, NULL);
700            mLights[num] = NULL;
701        }
702        mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size()));
703
704        setLights();
705
706        // restore previous
707        glPopMatrix();
708
709    }
710
711    void GLRenderSystem::setGLLight(size_t index, Light* lt)
712    {
713        GLenum gl_index = GL_LIGHT0 + index;
714
715        if (!lt)
716        {
717            // Disable in the scene
718            glDisable(gl_index);
719        }
720        else
721        {
722            switch (lt->getType())
723            {
724            case Light::LT_SPOTLIGHT:
725                glLightf( gl_index, GL_SPOT_CUTOFF, 0.5f * lt->getSpotlightOuterAngle().valueDegrees() );
726                glLightf(gl_index, GL_SPOT_EXPONENT, lt->getSpotlightFalloff());
727                break;
728            default:
729                glLightf( gl_index, GL_SPOT_CUTOFF, 180.0 );
730                break;
731            }
732
733            // Color
734            ColourValue col;
735            col = lt->getDiffuseColour();
736
737
738            GLfloat f4vals[4] = {col.r, col.g, col.b, col.a};
739            glLightfv(gl_index, GL_DIFFUSE, f4vals);
740           
741            col = lt->getSpecularColour();
742            f4vals[0] = col.r;
743            f4vals[1] = col.g;
744            f4vals[2] = col.b;
745            f4vals[3] = col.a;
746            glLightfv(gl_index, GL_SPECULAR, f4vals);
747
748
749            // Disable ambient light for movables;
750            f4vals[0] = 0;
751            f4vals[1] = 0;
752            f4vals[2] = 0;
753            f4vals[3] = 1;
754            glLightfv(gl_index, GL_AMBIENT, f4vals);
755
756            setGLLightPositionDirection(lt, gl_index);
757
758
759            // Attenuation
760            glLightf(gl_index, GL_CONSTANT_ATTENUATION, lt->getAttenuationConstant());
761            glLightf(gl_index, GL_LINEAR_ATTENUATION, lt->getAttenuationLinear());
762            glLightf(gl_index, GL_QUADRATIC_ATTENUATION, lt->getAttenuationQuadric());
763            // Enable in the scene
764            glEnable(gl_index);
765
766        }
767
768    }
769
770    //-----------------------------------------------------------------------------
771    void GLRenderSystem::makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m)
772    {
773        size_t x = 0;
774        for (size_t i = 0; i < 4; i++)
775        {
776            for (size_t j = 0; j < 4; j++)
777            {
778                gl_matrix[x] = m[j][i];
779                x++;
780            }
781        }
782    }
783    //-----------------------------------------------------------------------------
784    void GLRenderSystem::_setWorldMatrix( const Matrix4 &m )
785    {
786        GLfloat mat[16];
787        mWorldMatrix = m;
788        makeGLMatrix( mat, mViewMatrix * mWorldMatrix );
789        glMatrixMode(GL_MODELVIEW);
790        glLoadMatrixf(mat);
791    }
792
793    //-----------------------------------------------------------------------------
794    void GLRenderSystem::_setViewMatrix( const Matrix4 &m )
795    {
796        mViewMatrix = m;
797
798        GLfloat mat[16];
799                makeGLMatrix( mat, mViewMatrix * mWorldMatrix );
800        glMatrixMode(GL_MODELVIEW);
801        glLoadMatrixf(mat);
802
803        setGLClipPlanes();
804    }
805    //-----------------------------------------------------------------------------
806    void GLRenderSystem::_setProjectionMatrix(const Matrix4 &m)
807    {
808        GLfloat mat[16];
809        makeGLMatrix(mat, m);
810        if (mActiveRenderTarget->requiresTextureFlipping())
811        {
812            // Invert transformed y
813            mat[1] = -mat[1];
814            mat[5] = -mat[5];
815            mat[9] = -mat[9];
816            mat[13] = -mat[13];
817        }
818        glMatrixMode(GL_PROJECTION);
819        glLoadMatrixf(mat);
820        glMatrixMode(GL_MODELVIEW);
821    }
822    //-----------------------------------------------------------------------------
823    void GLRenderSystem::_setSurfaceParams(const ColourValue &ambient,
824        const ColourValue &diffuse, const ColourValue &specular,
825        const ColourValue &emissive, Real shininess,
826        TrackVertexColourType tracking)
827    {
828        // XXX Cache previous values?
829        // XXX Front or Front and Back?
830
831        GLfloat f4val[4] = {diffuse.r, diffuse.g, diffuse.b, diffuse.a};
832        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, f4val);
833        f4val[0] = ambient.r;
834        f4val[1] = ambient.g;
835        f4val[2] = ambient.b;
836        f4val[3] = ambient.a;
837        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, f4val);
838        f4val[0] = specular.r;
839        f4val[1] = specular.g;
840        f4val[2] = specular.b;
841        f4val[3] = specular.a;
842        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, f4val);
843        f4val[0] = emissive.r;
844        f4val[1] = emissive.g;
845        f4val[2] = emissive.b;
846        f4val[3] = emissive.a;
847        glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, f4val);
848        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
849       
850        // Track vertex colour
851        if(tracking != TVC_NONE)
852        {
853            GLenum gt = GL_DIFFUSE;
854            // There are actually 15 different combinations for tracking, of which
855            // GL only supports the most used 5. This means that we have to do some
856            // magic to find the best match. NOTE:
857            //  GL_AMBIENT_AND_DIFFUSE != GL_AMBIENT | GL__DIFFUSE
858            if(tracking & TVC_AMBIENT)
859            {
860                if(tracking & TVC_DIFFUSE)
861                {
862                    gt = GL_AMBIENT_AND_DIFFUSE;
863                }
864                else
865                {
866                    gt = GL_AMBIENT;
867                }
868            }
869            else if(tracking & TVC_DIFFUSE)
870            {
871                gt = GL_DIFFUSE;
872            }
873            else if(tracking & TVC_SPECULAR)
874            {
875                gt = GL_SPECULAR;             
876            }
877            else if(tracking & TVC_EMISSIVE)
878            {
879                gt = GL_EMISSION;
880            }
881            glColorMaterial(GL_FRONT_AND_BACK, gt);
882           
883            glEnable(GL_COLOR_MATERIAL);
884        }
885        else
886        {
887            glDisable(GL_COLOR_MATERIAL);         
888        }
889    }
890    //-----------------------------------------------------------------------------
891        void GLRenderSystem::_setPointParameters(Real size,
892                bool attenuationEnabled, Real constant, Real linear, Real quadratic,
893                Real minSize, Real maxSize)
894    {
895
896                if(attenuationEnabled)
897                {
898                        // Point size is still calculated in pixels even when attenuation is
899                        // enabled, which is pretty awkward, since you typically want a viewport
900                        // independent size if you're looking for attenuation.
901                        // So, scale the point size up by viewport size (this is equivalent to
902                        // what D3D does as standard)
903                        Real adjSize = size * mActiveViewport->getActualHeight();
904                        Real adjMinSize = minSize * mActiveViewport->getActualHeight();
905                        Real adjMaxSize;
906                        if (maxSize == 0.0f)
907                                adjMaxSize = mCapabilities->getMaxPointSize(); // pixels
908                        else
909                                adjMaxSize = maxSize * mActiveViewport->getActualHeight();
910                        glPointSize(adjSize);
911#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
912                        // HACK - ATI/Linux segfaults when you set point attenuation!
913                        // Driver fault? Affects both ATI and Tungsten drivers
914                        if (mGLSupport->getGLVendor() != "ATI"
915                                && mGLSupport->getGLVendor() != "Tungsten")
916                        {
917#endif
918                        // XXX: why do I need this for results to be consistent with D3D?
919                        // Equations are supposedly the same once you factor in vp height
920                        Real correction = 0.005;
921                        // scaling required
922                        float val[4] = {constant, linear*correction, quadratic*correction, 1};
923                        glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, val);
924                        glPointParameterf(GL_POINT_SIZE_MIN, adjMinSize);
925                        glPointParameterf(GL_POINT_SIZE_MAX, adjMaxSize);
926#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
927                        }
928#endif
929
930                }
931                else
932                {
933                        // no scaling required
934                        // GL has no disabled flag for this so just set to constant
935                        glPointSize(size);
936#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
937                        // HACK - ATI/Linux segfaults when you set point parameters!
938                        // Driver fault!
939                        if (mGLSupport->getGLVendor() != "ATI"
940                                && mGLSupport->getGLVendor() != "Tungsten")
941                        {
942#endif
943                        float val[4] = {1, 0, 0, 1};
944                        glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, val);
945                        glPointParameterf(GL_POINT_SIZE_MIN, minSize);
946                        if (maxSize == 0.0f)
947                                maxSize = mCapabilities->getMaxPointSize();
948                        glPointParameterf(GL_POINT_SIZE_MAX, maxSize);
949#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
950                        }
951#endif
952                }
953
954
955
956    }
957        //---------------------------------------------------------------------
958        void GLRenderSystem::_setPointSpritesEnabled(bool enabled)
959        {
960                if (enabled)
961                {
962                        glEnable(GL_POINT_SPRITE);
963                }
964                else
965                {
966                        glDisable(GL_POINT_SPRITE);
967                }
968
969                // Set sprite texture coord generation
970                // Don't offer this as an option since D3D links it to sprite enabled
971                for (ushort i = 0; i < mFixedFunctionTextureUnits; ++i)
972                {
973                        glActiveTextureARB(GL_TEXTURE0 + i);
974                        glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE,
975                                enabled ? GL_TRUE : GL_FALSE);
976                }
977                glActiveTextureARB(GL_TEXTURE0);
978
979        }
980    //-----------------------------------------------------------------------------
981    void GLRenderSystem::_setTexture(size_t stage, bool enabled, const String &texname)
982    {
983        GLTexturePtr tex = TextureManager::getSingleton().getByName(texname);
984
985        GLenum lastTextureType = mTextureTypes[stage];
986
987                glActiveTextureARB( GL_TEXTURE0 + stage );
988                if (enabled)
989        {
990            if (!tex.isNull())
991            {
992                // note used
993                tex->touch();
994                mTextureTypes[stage] = tex->getGLTextureTarget();
995            }
996            else
997                // assume 2D
998                mTextureTypes[stage] = GL_TEXTURE_2D;
999
1000            if(lastTextureType != mTextureTypes[stage] && lastTextureType != 0)
1001            {
1002                                if (stage < mFixedFunctionTextureUnits)
1003                                {
1004                        glDisable( lastTextureType );
1005                                }
1006            }
1007
1008                        if (stage < mFixedFunctionTextureUnits)
1009                        {
1010                                glEnable( mTextureTypes[stage] );
1011                        }
1012
1013                        if(!tex.isNull())
1014                                glBindTexture( mTextureTypes[stage], tex->getGLID() );
1015                        else
1016                                glBindTexture( mTextureTypes[stage], static_cast<GLTextureManager*>(mTextureManager)->getWarningTextureID() );
1017        }
1018        else
1019        {
1020                        if (stage < mFixedFunctionTextureUnits)
1021                        {
1022                                if (lastTextureType != 0)
1023                                {
1024                                        glDisable( mTextureTypes[stage] );
1025                                }
1026                                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1027                        }
1028        }
1029
1030        glActiveTextureARB( GL_TEXTURE0 );
1031    }
1032
1033    //-----------------------------------------------------------------------------
1034    void GLRenderSystem::_setTextureCoordSet(size_t stage, size_t index)
1035    {
1036        mTextureCoordIndex[stage] = index;
1037    }
1038    //-----------------------------------------------------------------------------
1039    void GLRenderSystem::_setTextureCoordCalculation(size_t stage, TexCoordCalcMethod m,
1040        const Frustum* frustum)
1041    {
1042                if (stage >= mFixedFunctionTextureUnits)
1043                {
1044                        // Can't do this
1045                        return;
1046                }
1047
1048               
1049                GLfloat M[16];
1050        Matrix4 projectionBias;
1051
1052        // Default to no extra auto texture matrix
1053        mUseAutoTextureMatrix = false;
1054
1055        GLfloat eyePlaneS[] = {1.0, 0.0, 0.0, 0.0};
1056        GLfloat eyePlaneT[] = {0.0, 1.0, 0.0, 0.0};
1057        GLfloat eyePlaneR[] = {0.0, 0.0, 1.0, 0.0};
1058        GLfloat eyePlaneQ[] = {0.0, 0.0, 0.0, 1.0};
1059
1060        glActiveTextureARB( GL_TEXTURE0 + stage );
1061
1062                switch( m )
1063        {
1064        case TEXCALC_NONE:
1065            glDisable( GL_TEXTURE_GEN_S );
1066            glDisable( GL_TEXTURE_GEN_T );
1067            glDisable( GL_TEXTURE_GEN_R );
1068            glDisable( GL_TEXTURE_GEN_Q );
1069            break;
1070
1071        case TEXCALC_ENVIRONMENT_MAP:
1072            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1073            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1074
1075            glEnable( GL_TEXTURE_GEN_S );
1076            glEnable( GL_TEXTURE_GEN_T );
1077            glDisable( GL_TEXTURE_GEN_R );
1078            glDisable( GL_TEXTURE_GEN_Q );
1079
1080            // Need to use a texture matrix to flip the spheremap
1081            mUseAutoTextureMatrix = true;
1082            memset(mAutoTextureMatrix, 0, sizeof(GLfloat)*16);
1083            mAutoTextureMatrix[0] = mAutoTextureMatrix[10] = mAutoTextureMatrix[15] = 1.0f;
1084            mAutoTextureMatrix[5] = -1.0f;
1085
1086            break;
1087
1088        case TEXCALC_ENVIRONMENT_MAP_PLANAR:           
1089            // XXX This doesn't seem right?!
1090#ifdef GL_VERSION_1_3
1091            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1092            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1093            glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1094
1095            glEnable( GL_TEXTURE_GEN_S );
1096            glEnable( GL_TEXTURE_GEN_T );
1097            glEnable( GL_TEXTURE_GEN_R );
1098            glDisable( GL_TEXTURE_GEN_Q );
1099#else
1100            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1101            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1102
1103            glEnable( GL_TEXTURE_GEN_S );
1104            glEnable( GL_TEXTURE_GEN_T );
1105            glDisable( GL_TEXTURE_GEN_R );
1106            glDisable( GL_TEXTURE_GEN_Q );
1107#endif
1108            break;
1109        case TEXCALC_ENVIRONMENT_MAP_REFLECTION:
1110           
1111            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1112            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1113            glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP );
1114
1115            glEnable( GL_TEXTURE_GEN_S );
1116            glEnable( GL_TEXTURE_GEN_T );
1117            glEnable( GL_TEXTURE_GEN_R );
1118            glDisable( GL_TEXTURE_GEN_Q );
1119
1120            // We need an extra texture matrix here
1121            // This sets the texture matrix to be the inverse of the modelview matrix
1122            mUseAutoTextureMatrix = true;
1123            glGetFloatv( GL_MODELVIEW_MATRIX, M );
1124
1125            // Transpose 3x3 in order to invert matrix (rotation)
1126            // Note that we need to invert the Z _before_ the rotation
1127            // No idea why we have to invert the Z at all, but reflection is wrong without it
1128            mAutoTextureMatrix[0] = M[0]; mAutoTextureMatrix[1] = M[4]; mAutoTextureMatrix[2] = -M[8];
1129            mAutoTextureMatrix[4] = M[1]; mAutoTextureMatrix[5] = M[5]; mAutoTextureMatrix[6] = -M[9];
1130            mAutoTextureMatrix[8] = M[2]; mAutoTextureMatrix[9] = M[6]; mAutoTextureMatrix[10] = -M[10];
1131            mAutoTextureMatrix[3] = mAutoTextureMatrix[7] = mAutoTextureMatrix[11] = 0.0f;
1132            mAutoTextureMatrix[12] = mAutoTextureMatrix[13] = mAutoTextureMatrix[14] = 0.0f;
1133            mAutoTextureMatrix[15] = 1.0f;
1134
1135            break;
1136        case TEXCALC_ENVIRONMENT_MAP_NORMAL:
1137            glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP );
1138            glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP );
1139            glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP );
1140
1141            glEnable( GL_TEXTURE_GEN_S );
1142            glEnable( GL_TEXTURE_GEN_T );
1143            glEnable( GL_TEXTURE_GEN_R );
1144            glDisable( GL_TEXTURE_GEN_Q );
1145            break;
1146        case TEXCALC_PROJECTIVE_TEXTURE:
1147            glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1148            glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1149            glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1150            glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1151            glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS);
1152            glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT);
1153            glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR);
1154            glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ);
1155            glEnable(GL_TEXTURE_GEN_S);
1156            glEnable(GL_TEXTURE_GEN_T);
1157            glEnable(GL_TEXTURE_GEN_R);
1158            glEnable(GL_TEXTURE_GEN_Q);
1159
1160            mUseAutoTextureMatrix = true;
1161
1162            // Set scale and translation matrix for projective textures
1163            projectionBias = Matrix4::CLIPSPACE2DTOIMAGESPACE;
1164
1165            projectionBias = projectionBias * frustum->getProjectionMatrix();
1166            projectionBias = projectionBias * frustum->getViewMatrix();
1167            projectionBias = projectionBias * mWorldMatrix;
1168
1169            makeGLMatrix(mAutoTextureMatrix, projectionBias);
1170            break;
1171        default:
1172            break;
1173        }
1174        glActiveTextureARB( GL_TEXTURE0 );
1175    }
1176    //-----------------------------------------------------------------------------
1177        GLint GLRenderSystem::getTextureAddressingMode(
1178                TextureUnitState::TextureAddressingMode tam) const
1179        {
1180        switch(tam)
1181        {
1182        default:
1183        case TextureUnitState::TAM_WRAP:
1184            return GL_REPEAT;
1185        case TextureUnitState::TAM_MIRROR:
1186            return GL_MIRRORED_REPEAT;
1187        case TextureUnitState::TAM_CLAMP:
1188            return GL_CLAMP_TO_EDGE;
1189        case TextureUnitState::TAM_BORDER:
1190            return GL_CLAMP_TO_BORDER;
1191        }
1192               
1193        }
1194    //-----------------------------------------------------------------------------
1195    void GLRenderSystem::_setTextureAddressingMode(size_t stage, const TextureUnitState::UVWAddressingMode& uvw)
1196    {
1197        glActiveTextureARB( GL_TEXTURE0 + stage );
1198        glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_S,
1199                        getTextureAddressingMode(uvw.u));
1200        glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_T,
1201                        getTextureAddressingMode(uvw.v));
1202        glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_R,
1203                                getTextureAddressingMode(uvw.w));
1204        glActiveTextureARB( GL_TEXTURE0 );
1205    }
1206    //-----------------------------------------------------------------------------
1207    void GLRenderSystem::_setTextureBorderColour(size_t stage, const ColourValue& colour)
1208    {
1209        GLfloat border[4] = { colour.r, colour.g, colour.b, colour.a };
1210        glActiveTextureARB( GL_TEXTURE0 + stage );
1211        glTexParameterfv( mTextureTypes[stage], GL_TEXTURE_BORDER_COLOR, border);
1212        glActiveTextureARB( GL_TEXTURE0 );
1213    }
1214    //-----------------------------------------------------------------------------
1215    void GLRenderSystem::_setTextureMatrix(size_t stage, const Matrix4& xform)
1216    {
1217                if (stage >= mFixedFunctionTextureUnits)
1218                {
1219                        // Can't do this
1220                        return;
1221                }
1222
1223                GLfloat mat[16];
1224        makeGLMatrix(mat, xform);
1225
1226        glActiveTextureARB(GL_TEXTURE0 + stage);
1227        glMatrixMode(GL_TEXTURE);
1228
1229        // Load this matrix in
1230        glLoadMatrixf(mat);
1231
1232        if (mUseAutoTextureMatrix)
1233        {
1234            // Concat auto matrix
1235            glMultMatrixf(mAutoTextureMatrix);
1236        }
1237
1238        glMatrixMode(GL_MODELVIEW);
1239        glActiveTextureARB(GL_TEXTURE0);
1240    }
1241    //-----------------------------------------------------------------------------
1242    GLint GLRenderSystem::getBlendMode(SceneBlendFactor ogreBlend) const
1243    {
1244        switch(ogreBlend)
1245        {
1246        case SBF_ONE:
1247            return GL_ONE;
1248        case SBF_ZERO:
1249            return GL_ZERO;
1250        case SBF_DEST_COLOUR:
1251            return GL_DST_COLOR;
1252        case SBF_SOURCE_COLOUR:
1253            return GL_SRC_COLOR;
1254        case SBF_ONE_MINUS_DEST_COLOUR:
1255            return GL_ONE_MINUS_DST_COLOR;
1256        case SBF_ONE_MINUS_SOURCE_COLOUR:
1257            return GL_ONE_MINUS_SRC_COLOR;
1258        case SBF_DEST_ALPHA:
1259            return GL_DST_ALPHA;
1260        case SBF_SOURCE_ALPHA:
1261            return GL_SRC_ALPHA;
1262        case SBF_ONE_MINUS_DEST_ALPHA:
1263            return GL_ONE_MINUS_DST_ALPHA;
1264        case SBF_ONE_MINUS_SOURCE_ALPHA:
1265            return GL_ONE_MINUS_SRC_ALPHA;
1266        };
1267                // to keep compiler happy
1268                return GL_ONE;
1269    }
1270
1271    void GLRenderSystem::_setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor)
1272    {
1273        GLint sourceBlend = getBlendMode(sourceFactor);
1274        GLint destBlend = getBlendMode(destFactor);
1275        if(sourceFactor == SBF_ONE && destFactor == SBF_ZERO)
1276        {
1277            glDisable(GL_BLEND);
1278        }
1279        else
1280        {
1281            glEnable(GL_BLEND);
1282            glBlendFunc(sourceBlend, destBlend);
1283        }
1284    }
1285    //-----------------------------------------------------------------------------
1286    void GLRenderSystem::_setAlphaRejectSettings(CompareFunction func, unsigned char value)
1287    {
1288        if(func == CMPF_ALWAYS_PASS)
1289        {
1290            glDisable(GL_ALPHA_TEST);
1291        }
1292        else
1293        {
1294            glEnable(GL_ALPHA_TEST);
1295            glAlphaFunc(convertCompareFunction(func), value / 255.0f);
1296        }
1297    }
1298    //-----------------------------------------------------------------------------
1299    void GLRenderSystem::_setViewport(Viewport *vp)
1300    {
1301        // Check if viewport is different
1302        if (vp != mActiveViewport || vp->_isUpdated())
1303        {
1304            RenderTarget* target;
1305            target = vp->getTarget();
1306            _setRenderTarget(target);
1307            mActiveViewport = vp;
1308             
1309              GLsizei x, y, w, h;
1310 
1311              // Calculate the "lower-left" corner of the viewport
1312              w = vp->getActualWidth();
1313              h = vp->getActualHeight();
1314              x = vp->getActualLeft();
1315              y = vp->getActualTop();
1316              if (!target->requiresTextureFlipping())
1317              {
1318                  // Convert "upper-left" corner to "lower-left"
1319                  y = target->getHeight() - h - y;
1320              }
1321              glViewport(x, y, w, h);
1322 
1323              // Configure the viewport clipping
1324              glScissor(x, y, w, h);
1325 
1326              vp->_clearUpdatedFlag();
1327        }
1328    }
1329
1330        void GLRenderSystem::setLights()
1331        {
1332        for (size_t i = 0; i < MAX_LIGHTS; ++i)
1333        {
1334            if (mLights[i] != NULL)
1335            {
1336                Light* lt = mLights[i];
1337                setGLLightPositionDirection(lt, GL_LIGHT0 + i);
1338            }
1339        }
1340        }
1341
1342    //-----------------------------------------------------------------------------
1343    void GLRenderSystem::_beginFrame(void)
1344    {
1345        OgreGuard( "GLRenderSystem::_beginFrame" );
1346       
1347        if (!mActiveViewport)
1348            OGRE_EXCEPT(999, "Cannot begin frame - no viewport selected.",
1349                "GLRenderSystem::_beginFrame");
1350
1351        // Activate the viewport clipping
1352        glEnable(GL_SCISSOR_TEST);
1353        // Clear the viewport if required
1354        if (mActiveViewport->getClearEveryFrame())
1355        {
1356            clearFrameBuffer(mActiveViewport->getClearBuffers(),
1357                mActiveViewport->getBackgroundColour());
1358        }       
1359
1360        OgreUnguard();
1361    }
1362   
1363    //-----------------------------------------------------------------------------
1364    void GLRenderSystem::_endFrame(void)
1365    {
1366        // Deactivate the viewport clipping.
1367        glDisable(GL_SCISSOR_TEST);
1368    }
1369
1370    //-----------------------------------------------------------------------------
1371    void GLRenderSystem::_setCullingMode(CullingMode mode)
1372    {
1373        // NB: Because two-sided stencil API dependence of the front face, we must
1374        // use the same 'winding' for the front face everywhere. As the OGRE default
1375        // culling mode is clockwise, we also treat anticlockwise winding as front
1376        // face for consistently. On the assumption that, we can't change the front
1377        // face by glFrontFace anywhere.
1378
1379        GLenum cullMode;
1380
1381        switch( mode )
1382        {
1383        case CULL_NONE:
1384            glDisable( GL_CULL_FACE );
1385            return;
1386        case CULL_CLOCKWISE:
1387            if (mActiveRenderTarget &&
1388                ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
1389                (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)))
1390            {
1391                cullMode = GL_FRONT;
1392            }
1393            else
1394            {
1395                cullMode = GL_BACK;
1396            }
1397            break;
1398        case CULL_ANTICLOCKWISE:
1399            if (mActiveRenderTarget &&
1400                ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
1401                (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)))
1402            {
1403                cullMode = GL_BACK;
1404            }
1405            else
1406            {
1407                cullMode = GL_FRONT;
1408            }
1409            break;
1410        }
1411
1412        glEnable( GL_CULL_FACE );
1413        glCullFace( cullMode );
1414    }
1415    //-----------------------------------------------------------------------------
1416    void GLRenderSystem::_setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction)
1417    {
1418        _setDepthBufferCheckEnabled(depthTest);
1419        _setDepthBufferWriteEnabled(depthWrite);
1420        _setDepthBufferFunction(depthFunction);
1421    }
1422    //-----------------------------------------------------------------------------
1423    void GLRenderSystem::_setDepthBufferCheckEnabled(bool enabled)
1424    {
1425        if (enabled)
1426        {
1427            glClearDepth(1.0f);
1428            glEnable(GL_DEPTH_TEST);
1429        }
1430        else
1431        {
1432            glDisable(GL_DEPTH_TEST);
1433        }
1434    }
1435    //-----------------------------------------------------------------------------
1436    void GLRenderSystem::_setDepthBufferWriteEnabled(bool enabled)
1437    {
1438        GLboolean flag = enabled ? GL_TRUE : GL_FALSE;
1439        glDepthMask( flag ); 
1440        // Store for reference in _beginFrame
1441        mDepthWrite = enabled;
1442    }
1443    //-----------------------------------------------------------------------------
1444    void GLRenderSystem::_setDepthBufferFunction(CompareFunction func)
1445    {
1446        glDepthFunc(convertCompareFunction(func));
1447    }
1448    //-----------------------------------------------------------------------------
1449    void GLRenderSystem::_setDepthBias(ushort bias)
1450    {
1451        if (bias > 0)
1452        {
1453            glEnable(GL_POLYGON_OFFSET_FILL);
1454            glEnable(GL_POLYGON_OFFSET_POINT);
1455            glEnable(GL_POLYGON_OFFSET_LINE);
1456            // Bias is in {0, 16}, scale the unit addition appropriately
1457            glPolygonOffset(0.0f, -bias);
1458        }
1459        else
1460        {
1461            glDisable(GL_POLYGON_OFFSET_FILL);
1462            glDisable(GL_POLYGON_OFFSET_POINT);
1463            glDisable(GL_POLYGON_OFFSET_LINE);
1464        }
1465    }
1466        //-----------------------------------------------------------------------------
1467        void GLRenderSystem::_setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
1468        {
1469                glColorMask(red, green, blue, alpha);
1470                // record this
1471                mColourWrite[0] = red;
1472                mColourWrite[1] = blue;
1473                mColourWrite[2] = green;
1474                mColourWrite[3] = alpha;
1475        }
1476        //-----------------------------------------------------------------------------
1477    String GLRenderSystem::getErrorDescription(long errCode) const
1478    {
1479        const GLubyte *errString = gluErrorString (errCode);
1480        return String((const char*) errString);
1481    }
1482    //-----------------------------------------------------------------------------
1483    void GLRenderSystem::setLightingEnabled(bool enabled)
1484    {
1485        if (enabled)
1486        {     
1487            glEnable(GL_LIGHTING);
1488        }
1489        else
1490        {
1491            glDisable(GL_LIGHTING);
1492        }
1493    }
1494    //-----------------------------------------------------------------------------
1495    void GLRenderSystem::_setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
1496    {
1497
1498        GLint fogMode;
1499        switch (mode)
1500        {
1501        case FOG_EXP:
1502            fogMode = GL_EXP;
1503            break;
1504        case FOG_EXP2:
1505            fogMode = GL_EXP2;
1506            break;
1507        case FOG_LINEAR:
1508            fogMode = GL_LINEAR;
1509            break;
1510        default:
1511            // Give up on it
1512            glDisable(GL_FOG);
1513            return;
1514        }
1515
1516        glEnable(GL_FOG);
1517        glFogi(GL_FOG_MODE, fogMode);
1518        GLfloat fogColor[4] = {colour.r, colour.g, colour.b, colour.a};
1519        glFogfv(GL_FOG_COLOR, fogColor);
1520        glFogf(GL_FOG_DENSITY, density);
1521        glFogf(GL_FOG_START, start);
1522        glFogf(GL_FOG_END, end);
1523        // XXX Hint here?
1524    }
1525
1526        VertexElementType GLRenderSystem::getColourVertexElementType(void) const
1527    {
1528        return VET_COLOUR_ABGR;
1529    }
1530   
1531    void GLRenderSystem::_convertProjectionMatrix(const Matrix4& matrix,
1532        Matrix4& dest, bool forGpuProgram)
1533    {
1534        // no any convertion request for OpenGL
1535        dest = matrix;
1536    }
1537
1538    void GLRenderSystem::_makeProjectionMatrix(const Radian& fovy, Real aspect, Real nearPlane,
1539        Real farPlane, Matrix4& dest, bool forGpuProgram)
1540    {
1541        Radian thetaY ( fovy / 2.0f );
1542        Real tanThetaY = Math::Tan(thetaY);
1543        //Real thetaX = thetaY * aspect;
1544        //Real tanThetaX = Math::Tan(thetaX);
1545
1546        // Calc matrix elements
1547        Real w = (1.0f / tanThetaY) / aspect;
1548        Real h = 1.0f / tanThetaY;
1549        Real q, qn;
1550        if (farPlane == 0)
1551        {
1552            // Infinite far plane
1553            q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
1554            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2);
1555        }
1556        else
1557        {
1558            q = -(farPlane + nearPlane) / (farPlane - nearPlane);
1559            qn = -2 * (farPlane * nearPlane) / (farPlane - nearPlane);
1560        }
1561
1562        // NB This creates Z in range [-1,1]
1563        //
1564        // [ w   0   0   0  ]
1565        // [ 0   h   0   0  ]
1566        // [ 0   0   q   qn ]
1567        // [ 0   0   -1  0  ]
1568
1569        dest = Matrix4::ZERO;
1570        dest[0][0] = w;
1571        dest[1][1] = h;
1572        dest[2][2] = q;
1573        dest[2][3] = qn;
1574        dest[3][2] = -1;
1575
1576    }
1577   
1578    void GLRenderSystem::_makeOrthoMatrix(const Radian& fovy, Real aspect, Real nearPlane,
1579        Real farPlane, Matrix4& dest, bool forGpuProgram)
1580    {
1581        Radian thetaY (fovy / 2.0f);
1582        Real tanThetaY = Math::Tan(thetaY);
1583
1584        //Real thetaX = thetaY * aspect;
1585        Real tanThetaX = tanThetaY * aspect; //Math::Tan(thetaX);
1586        Real half_w = tanThetaX * nearPlane;
1587        Real half_h = tanThetaY * nearPlane;
1588        Real iw = 1.0 / half_w;
1589        Real ih = 1.0 / half_h;
1590        Real q;
1591        if (farPlane == 0)
1592        {
1593            q = 0;
1594        }
1595        else
1596        {
1597            q = 2.0 / (farPlane - nearPlane);
1598        }
1599        dest = Matrix4::ZERO;
1600        dest[0][0] = iw;
1601        dest[1][1] = ih;
1602        dest[2][2] = -q;
1603        dest[2][3] = - (farPlane + nearPlane)/(farPlane - nearPlane);
1604        dest[3][3] = 1;
1605        }
1606
1607    void GLRenderSystem::_setPolygonMode(PolygonMode level)
1608    {
1609        GLenum glmode;
1610        switch(level)
1611        {
1612        case PM_POINTS:
1613            glmode = GL_POINT;
1614            break;
1615        case PM_WIREFRAME:
1616            glmode = GL_LINE;
1617            break;
1618        case PM_SOLID:
1619            glmode = GL_FILL;
1620            break;
1621        }
1622        glPolygonMode(GL_FRONT_AND_BACK, glmode);
1623    }
1624    //---------------------------------------------------------------------
1625    void GLRenderSystem::setStencilCheckEnabled(bool enabled)
1626    {
1627        if (enabled)
1628        {
1629            glEnable(GL_STENCIL_TEST);
1630        }
1631        else
1632        {
1633            glDisable(GL_STENCIL_TEST);
1634        }
1635    }
1636    //---------------------------------------------------------------------
1637    void GLRenderSystem::setStencilBufferParams(CompareFunction func,
1638        uint32 refValue, uint32 mask, StencilOperation stencilFailOp,
1639        StencilOperation depthFailOp, StencilOperation passOp,
1640        bool twoSidedOperation)
1641    {
1642        bool flip;
1643                mStencilMask = mask;
1644
1645        if (twoSidedOperation)
1646        {
1647            if (!mCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
1648                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "2-sided stencils are not supported",
1649                    "GLRenderSystem::setStencilBufferParams");
1650           
1651            // NB: We should always treat CCW as front face for consistent with default
1652            // culling mode. Therefore, we must take care with two-sided stencil settings.
1653            flip = (mInvertVertexWinding && !mActiveRenderTarget->requiresTextureFlipping()) ||
1654                   (!mInvertVertexWinding && mActiveRenderTarget->requiresTextureFlipping());
1655                        if(GLEW_VERSION_2_0) // New GL2 commands
1656                        {
1657                                // Back
1658                                glStencilMaskSeparate(GL_BACK, mask);
1659                                glStencilFuncSeparate(GL_BACK, convertCompareFunction(func), refValue, mask);
1660                                glStencilOpSeparate(GL_BACK,
1661                                        convertStencilOp(stencilFailOp, !flip),
1662                                        convertStencilOp(depthFailOp, !flip),
1663                                        convertStencilOp(passOp, !flip));
1664                                // Front
1665                                glStencilMaskSeparate(GL_FRONT, mask);
1666                                glStencilFuncSeparate(GL_FRONT, convertCompareFunction(func), refValue, mask);
1667                                glStencilOpSeparate(GL_FRONT,
1668                                        convertStencilOp(stencilFailOp, flip),
1669                                        convertStencilOp(depthFailOp, flip),
1670                                        convertStencilOp(passOp, flip));
1671                        }
1672                        else // EXT_stencil_two_side
1673                        {
1674                                glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
1675                                // Back
1676                                glActiveStencilFaceEXT(GL_BACK);
1677                                glStencilMask(mask);
1678                                glStencilFunc(convertCompareFunction(func), refValue, mask);
1679                                glStencilOp(
1680                                        convertStencilOp(stencilFailOp, !flip),
1681                                        convertStencilOp(depthFailOp, !flip),
1682                                        convertStencilOp(passOp, !flip));
1683                                // Front
1684                                glActiveStencilFaceEXT(GL_FRONT);
1685                                glStencilMask(mask);
1686                                glStencilFunc(convertCompareFunction(func), refValue, mask);
1687                                glStencilOp(
1688                                        convertStencilOp(stencilFailOp, flip),
1689                                        convertStencilOp(depthFailOp, flip),
1690                                        convertStencilOp(passOp, flip));
1691                        }
1692        }
1693        else
1694        {
1695            glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
1696            flip = false;
1697                        glStencilMask(mask);
1698                        glStencilFunc(convertCompareFunction(func), refValue, mask);
1699                        glStencilOp(
1700                                convertStencilOp(stencilFailOp, flip),
1701                                convertStencilOp(depthFailOp, flip),
1702                                convertStencilOp(passOp, flip));
1703        }
1704    }
1705    //---------------------------------------------------------------------
1706    GLint GLRenderSystem::convertCompareFunction(CompareFunction func) const
1707    {
1708        switch(func)
1709        {
1710        case CMPF_ALWAYS_FAIL:
1711            return GL_NEVER;
1712        case CMPF_ALWAYS_PASS:
1713            return GL_ALWAYS;
1714        case CMPF_LESS:
1715            return GL_LESS;
1716        case CMPF_LESS_EQUAL:
1717            return GL_LEQUAL;
1718        case CMPF_EQUAL:
1719            return GL_EQUAL;
1720        case CMPF_NOT_EQUAL:
1721            return GL_NOTEQUAL;
1722        case CMPF_GREATER_EQUAL:
1723            return GL_GEQUAL;
1724        case CMPF_GREATER:
1725            return GL_GREATER;
1726        };
1727        // to keep compiler happy
1728        return GL_ALWAYS;
1729    }
1730    //---------------------------------------------------------------------
1731    GLint GLRenderSystem::convertStencilOp(StencilOperation op, bool invert) const
1732    {
1733        switch(op)
1734        {
1735        case SOP_KEEP:
1736            return GL_KEEP;
1737        case SOP_ZERO:
1738            return GL_ZERO;
1739        case SOP_REPLACE:
1740            return GL_REPLACE;
1741        case SOP_INCREMENT:
1742            return invert ? GL_DECR : GL_INCR;
1743        case SOP_DECREMENT:
1744            return invert ? GL_INCR : GL_DECR;
1745        case SOP_INCREMENT_WRAP:
1746            return invert ? GL_DECR_WRAP_EXT : GL_INCR_WRAP_EXT;
1747        case SOP_DECREMENT_WRAP:
1748            return invert ? GL_INCR_WRAP_EXT : GL_DECR_WRAP_EXT;
1749        case SOP_INVERT:
1750            return GL_INVERT;
1751        };
1752        // to keep compiler happy
1753        return SOP_KEEP;
1754    }
1755        //---------------------------------------------------------------------
1756    GLuint GLRenderSystem::getCombinedMinMipFilter(void) const
1757    {
1758        switch(mMinFilter)
1759        {
1760        case FO_ANISOTROPIC:
1761        case FO_LINEAR:
1762            switch(mMipFilter)
1763            {
1764            case FO_ANISOTROPIC:
1765            case FO_LINEAR:
1766                // linear min, linear mip
1767                return GL_LINEAR_MIPMAP_LINEAR;
1768            case FO_POINT:
1769                // linear min, point mip
1770                return GL_LINEAR_MIPMAP_NEAREST;
1771            case FO_NONE:
1772                // linear min, no mip
1773                return GL_LINEAR;
1774            }
1775            break;
1776        case FO_POINT:
1777        case FO_NONE:
1778            switch(mMipFilter)
1779            {
1780            case FO_ANISOTROPIC:
1781            case FO_LINEAR:
1782                // nearest min, linear mip
1783                return GL_NEAREST_MIPMAP_LINEAR;
1784            case FO_POINT:
1785                // nearest min, point mip
1786                return GL_NEAREST_MIPMAP_NEAREST;
1787            case FO_NONE:
1788                // nearest min, no mip
1789                return GL_NEAREST;
1790            }
1791            break;
1792        }
1793
1794        // should never get here
1795        return 0;
1796
1797    }
1798        //---------------------------------------------------------------------
1799    void GLRenderSystem::_setTextureUnitFiltering(size_t unit,
1800        FilterType ftype, FilterOptions fo)
1801        {
1802        OgreGuard( "GLRenderSystem::_setTextureUnitFiltering" );       
1803
1804                glActiveTextureARB( GL_TEXTURE0 + unit );
1805        switch(ftype)
1806        {
1807        case FT_MIN:
1808            mMinFilter = fo;
1809            // Combine with existing mip filter
1810                        glTexParameteri(
1811                mTextureTypes[unit],
1812                                GL_TEXTURE_MIN_FILTER,
1813                                getCombinedMinMipFilter());
1814            break;
1815        case FT_MAG:
1816            switch (fo)
1817            {
1818            case FO_ANISOTROPIC: // GL treats linear and aniso the same
1819            case FO_LINEAR:
1820                            glTexParameteri(
1821                    mTextureTypes[unit],
1822                                    GL_TEXTURE_MAG_FILTER,
1823                                    GL_LINEAR);
1824                break;
1825            case FO_POINT:
1826            case FO_NONE:
1827                            glTexParameteri(
1828                    mTextureTypes[unit],
1829                                    GL_TEXTURE_MAG_FILTER,
1830                                    GL_NEAREST);
1831                break;
1832            }
1833            break;
1834        case FT_MIP:
1835            mMipFilter = fo;
1836            // Combine with existing min filter
1837                        glTexParameteri(
1838                mTextureTypes[unit],
1839                                GL_TEXTURE_MIN_FILTER,
1840                                getCombinedMinMipFilter());
1841            break;
1842                }
1843
1844        glActiveTextureARB( GL_TEXTURE0 );
1845
1846                OgreUnguard();
1847        }
1848        //---------------------------------------------------------------------
1849        GLfloat GLRenderSystem::_getCurrentAnisotropy(size_t unit)
1850        {
1851                GLfloat curAniso = 0;
1852                glGetTexParameterfv(mTextureTypes[unit],
1853            GL_TEXTURE_MAX_ANISOTROPY_EXT, &curAniso);
1854                return curAniso ? curAniso : 1;
1855        }
1856        //---------------------------------------------------------------------
1857        void GLRenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
1858        {
1859       if (!mCapabilities->hasCapability(RSC_ANISOTROPY))
1860                        return;
1861
1862                GLfloat largest_supported_anisotropy = 0;
1863                glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
1864                if (maxAnisotropy > largest_supported_anisotropy)
1865                        maxAnisotropy = largest_supported_anisotropy ? largest_supported_anisotropy : 1;
1866                if (_getCurrentAnisotropy(unit) != maxAnisotropy)
1867                        glTexParameterf(mTextureTypes[unit], GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
1868        }
1869        //-----------------------------------------------------------------------------
1870    void GLRenderSystem::_setTextureBlendMode(size_t stage, const LayerBlendModeEx& bm)
1871    {       
1872                if (stage >= mFixedFunctionTextureUnits)
1873                {
1874                        // Can't do this
1875                        return;
1876                }
1877
1878                // Check to see if blending is supported
1879        if(!mCapabilities->hasCapability(RSC_BLENDING))
1880            return;
1881
1882        GLenum src1op, src2op, cmd;
1883        GLfloat cv1[4], cv2[4];
1884
1885                if (bm.blendType == LBT_COLOUR)
1886        {
1887                    cv1[0] = bm.colourArg1.r;
1888                    cv1[1] = bm.colourArg1.g;
1889                    cv1[2] = bm.colourArg1.b;
1890                    cv1[3] = bm.colourArg1.a;
1891                        mManualBlendColours[stage][0] = bm.colourArg1;
1892
1893
1894                    cv2[0] = bm.colourArg2.r;
1895                    cv2[1] = bm.colourArg2.g;
1896                    cv2[2] = bm.colourArg2.b;
1897                    cv2[3] = bm.colourArg2.a;
1898                        mManualBlendColours[stage][1] = bm.colourArg2;
1899        }
1900
1901                if (bm.blendType == LBT_ALPHA)
1902        {
1903                    cv1[0] = mManualBlendColours[stage][0].r;
1904                    cv1[1] = mManualBlendColours[stage][0].g;
1905                    cv1[2] = mManualBlendColours[stage][0].b;
1906                    cv1[3] = bm.alphaArg1;
1907
1908                    cv2[0] = mManualBlendColours[stage][1].r;
1909                    cv2[1] = mManualBlendColours[stage][1].g;
1910                    cv2[2] = mManualBlendColours[stage][1].b;
1911                    cv2[3] = bm.alphaArg2;
1912        }
1913
1914        switch (bm.source1)
1915        {
1916        case LBS_CURRENT:
1917            src1op = GL_PREVIOUS;
1918            break;
1919        case LBS_TEXTURE:
1920            src1op = GL_TEXTURE;
1921            break;
1922        case LBS_MANUAL:
1923            src1op = GL_CONSTANT;
1924                        break;
1925        case LBS_DIFFUSE:
1926            src1op = GL_PRIMARY_COLOR;
1927                        break;
1928        // XXX
1929        case LBS_SPECULAR:
1930            src1op = GL_PRIMARY_COLOR;
1931            break;
1932                default:
1933            src1op = 0;
1934        }
1935
1936        switch (bm.source2)
1937        {
1938        case LBS_CURRENT:
1939            src2op = GL_PREVIOUS;
1940            break;
1941        case LBS_TEXTURE:
1942            src2op = GL_TEXTURE;
1943            break;
1944        case LBS_MANUAL:
1945                        src2op = GL_CONSTANT;
1946                        break;
1947                case LBS_DIFFUSE:
1948            src2op = GL_PRIMARY_COLOR;
1949                        break;
1950        // XXX
1951        case LBS_SPECULAR:
1952            src2op = GL_PRIMARY_COLOR;
1953            break;
1954                default:
1955            src2op = 0;
1956        }
1957
1958        switch (bm.operation)
1959        {
1960        case LBX_SOURCE1:
1961            cmd = GL_REPLACE;
1962            break;
1963        case LBX_SOURCE2:
1964            cmd = GL_REPLACE;
1965            break;
1966        case LBX_MODULATE:
1967            cmd = GL_MODULATE;
1968            break;
1969        case LBX_MODULATE_X2:
1970            cmd = GL_MODULATE;
1971            break;
1972        case LBX_MODULATE_X4:
1973            cmd = GL_MODULATE;
1974            break;
1975        case LBX_ADD:
1976            cmd = GL_ADD;
1977            break;
1978        case LBX_ADD_SIGNED:
1979            cmd = GL_ADD_SIGNED;
1980            break;
1981        case LBX_SUBTRACT:
1982            cmd = GL_SUBTRACT;
1983            break;
1984                case LBX_BLEND_DIFFUSE_COLOUR:
1985                        cmd = GL_INTERPOLATE;
1986                        break;
1987        case LBX_BLEND_DIFFUSE_ALPHA:
1988            cmd = GL_INTERPOLATE;
1989            break;
1990        case LBX_BLEND_TEXTURE_ALPHA:
1991            cmd = GL_INTERPOLATE;
1992            break;
1993        case LBX_BLEND_CURRENT_ALPHA:
1994            cmd = GL_INTERPOLATE;
1995            break;
1996        case LBX_BLEND_MANUAL:
1997            cmd = GL_INTERPOLATE;
1998            break;
1999        case LBX_DOTPRODUCT:
2000            cmd = mCapabilities->hasCapability(RSC_DOT3)
2001                ? GL_DOT3_RGB : GL_MODULATE;
2002            break;
2003                default:
2004            cmd = 0;
2005        }
2006
2007                glActiveTextureARB(GL_TEXTURE0 + stage);
2008                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
2009
2010            if (bm.blendType == LBT_COLOUR)
2011            {
2012                    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, cmd);
2013                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, src1op);
2014                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, src2op);
2015                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
2016            }
2017            else
2018            {
2019                    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, cmd);
2020                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, src1op);
2021                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, src2op);
2022                    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
2023            }
2024
2025        float blendValue[4] = {0, 0, 0, bm.factor};
2026        switch (bm.operation)
2027        {
2028                case LBX_BLEND_DIFFUSE_COLOUR:
2029                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
2030            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
2031            break;
2032        case LBX_BLEND_DIFFUSE_ALPHA:
2033            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
2034            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
2035            break;
2036        case LBX_BLEND_TEXTURE_ALPHA:
2037                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
2038                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_TEXTURE);
2039            break;
2040        case LBX_BLEND_CURRENT_ALPHA:
2041                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS);
2042                        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PREVIOUS);
2043            break;
2044        case LBX_BLEND_MANUAL:
2045            glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, blendValue);
2046            break;
2047        default:
2048            break;
2049        };
2050
2051        switch (bm.operation)
2052        {
2053        case LBX_MODULATE_X2:
2054                        glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ?
2055                GL_RGB_SCALE : GL_ALPHA_SCALE, 2);
2056            break;
2057        case LBX_MODULATE_X4:
2058                        glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ?
2059                GL_RGB_SCALE : GL_ALPHA_SCALE, 4);
2060            break;
2061        default:
2062                        glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ?
2063                GL_RGB_SCALE : GL_ALPHA_SCALE, 1);
2064            break;
2065                }
2066
2067                if (bm.blendType == LBT_COLOUR){
2068                        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
2069                        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
2070                        if (bm.operation == LBX_BLEND_DIFFUSE_COLOUR){
2071                                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
2072                        } else {
2073                                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
2074                        }
2075                }
2076
2077                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
2078                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
2079                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
2080        if(bm.source1 == LBS_MANUAL)
2081            glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cv1);
2082        if (bm.source2 == LBS_MANUAL)
2083            glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cv2);
2084
2085        glActiveTextureARB(GL_TEXTURE0);
2086        }
2087    //---------------------------------------------------------------------
2088    void GLRenderSystem::setGLLightPositionDirection(Light* lt, GLenum lightindex)
2089    {
2090        // Set position / direction
2091        Vector4 vec;
2092                // Use general 4D vector which is the same as GL's approach
2093                vec = lt->getAs4DVector();
2094
2095#if OGRE_DOUBLE_PRECISION
2096                // Must convert to float*
2097                float tmp[4] = {vec.x, vec.y, vec.z, vec.w};
2098                glLightfv(lightindex, GL_POSITION, tmp);
2099#else
2100                glLightfv(lightindex, GL_POSITION, vec.val);
2101#endif
2102                // Set spotlight direction
2103        if (lt->getType() == Light::LT_SPOTLIGHT)
2104        {
2105            vec = lt->getDerivedDirection();
2106            vec.w = 0.0;
2107#if OGRE_DOUBLE_PRECISION
2108                        // Must convert to float*
2109                        float tmp2[4] = {vec.x, vec.y, vec.z, vec.w};
2110                        glLightfv(lightindex, GL_SPOT_DIRECTION, tmp2);
2111#else
2112            glLightfv(lightindex, GL_SPOT_DIRECTION, vec.val);
2113#endif
2114        }
2115    }
2116    //---------------------------------------------------------------------
2117        void GLRenderSystem::setVertexDeclaration(VertexDeclaration* decl)
2118        {
2119        }
2120    //---------------------------------------------------------------------
2121        void GLRenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
2122        {
2123        }
2124    //---------------------------------------------------------------------
2125    void GLRenderSystem::_render(const RenderOperation& op)
2126        {
2127        // Guard
2128        OgreGuard ("GLRenderSystem::_render");
2129        // Call super class
2130        RenderSystem::_render(op);
2131
2132        void* pBufferData = 0;
2133       
2134        const VertexDeclaration::VertexElementList& decl =
2135            op.vertexData->vertexDeclaration->getElements();
2136        VertexDeclaration::VertexElementList::const_iterator elem, elemEnd;
2137        elemEnd = decl.end();
2138
2139        for (elem = decl.begin(); elem != elemEnd; ++elem)
2140        {
2141                        if (!op.vertexData->vertexBufferBinding->isBufferBound(elem->getSource()))
2142                                continue; // skip unbound elements
2143
2144            HardwareVertexBufferSharedPtr vertexBuffer =
2145                op.vertexData->vertexBufferBinding->getBuffer(elem->getSource());
2146            if(mCapabilities->hasCapability(RSC_VBO))
2147            {
2148                glBindBufferARB(GL_ARRAY_BUFFER_ARB,
2149                    static_cast<const GLHardwareVertexBuffer*>(vertexBuffer.get())->getGLBufferId());
2150                pBufferData = VBO_BUFFER_OFFSET(elem->getOffset());
2151            }
2152            else
2153            {
2154                pBufferData = static_cast<const GLDefaultHardwareVertexBuffer*>(vertexBuffer.get())->getDataPtr(elem->getOffset());
2155            }
2156            if (op.vertexData->vertexStart)
2157            {
2158                pBufferData = static_cast<char*>(pBufferData) + op.vertexData->vertexStart * vertexBuffer->getVertexSize();
2159            }
2160
2161            unsigned int i = 0;
2162
2163            switch(elem->getSemantic())
2164            {
2165            case VES_POSITION:
2166                glVertexPointer(VertexElement::getTypeCount(
2167                    elem->getType()),
2168                    GLHardwareBufferManager::getGLType(elem->getType()),
2169                    static_cast<GLsizei>(vertexBuffer->getVertexSize()),
2170                    pBufferData);
2171                glEnableClientState( GL_VERTEX_ARRAY );
2172                break;
2173            case VES_NORMAL:
2174                glNormalPointer(
2175                    GLHardwareBufferManager::getGLType(elem->getType()),
2176                    static_cast<GLsizei>(vertexBuffer->getVertexSize()),
2177                    pBufferData);
2178                glEnableClientState( GL_NORMAL_ARRAY );
2179                break;
2180            case VES_DIFFUSE:
2181                glColorPointer(4,
2182                    GLHardwareBufferManager::getGLType(elem->getType()),
2183                    static_cast<GLsizei>(vertexBuffer->getVertexSize()),
2184                    pBufferData);
2185                glEnableClientState( GL_COLOR_ARRAY );
2186                break;
2187            case VES_SPECULAR:
2188                glSecondaryColorPointerEXT(4,
2189                    GLHardwareBufferManager::getGLType(elem->getType()),
2190                    static_cast<GLsizei>(vertexBuffer->getVertexSize()),
2191                    pBufferData);
2192                glEnableClientState( GL_SECONDARY_COLOR_ARRAY );
2193                break;
2194            case VES_TEXTURE_COORDINATES:
2195
2196                for (i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; i++)
2197                {
2198                                        // Only set this texture unit's texcoord pointer if it
2199                                        // is supposed to be using this element's index
2200                                        if (mTextureCoordIndex[i] == elem->getIndex())
2201                                        {
2202                                                glClientActiveTextureARB(GL_TEXTURE0 + i);
2203                                                glTexCoordPointer(
2204                                                        VertexElement::getTypeCount(elem->getType()),
2205                                                        GLHardwareBufferManager::getGLType(elem->getType()),
2206                            static_cast<GLsizei>(vertexBuffer->getVertexSize()),
2207                                pBufferData);
2208                                                glEnableClientState( GL_TEXTURE_COORD_ARRAY );
2209                                        }
2210                }
2211                break;
2212            case VES_BLEND_INDICES:
2213                assert(mCapabilities->hasCapability(RSC_VERTEX_PROGRAM));
2214                glVertexAttribPointerARB(
2215                    7, // matrix indices are vertex attribute 7 (no def?)
2216                    VertexElement::getTypeCount(elem->getType()),
2217                    GLHardwareBufferManager::getGLType(elem->getType()),
2218                    GL_FALSE, // normalisation disabled
2219                    static_cast<GLsizei>(vertexBuffer->getVertexSize()),
2220                    pBufferData);
2221                glEnableVertexAttribArrayARB(7);
2222                break;
2223            case VES_BLEND_WEIGHTS:
2224                assert(mCapabilities->hasCapability(RSC_VERTEX_PROGRAM));
2225                glVertexAttribPointerARB(
2226                    1, // weights are vertex attribute 1 (no def?)
2227                    VertexElement::getTypeCount(elem->getType()),
2228                    GLHardwareBufferManager::getGLType(elem->getType()),
2229                    GL_FALSE, // normalisation disabled
2230                    static_cast<GLsizei>(vertexBuffer->getVertexSize()),
2231                    pBufferData);
2232                glEnableVertexAttribArrayARB(1);
2233                break;
2234            default:
2235                break;
2236            };
2237
2238        }
2239
2240        glClientActiveTextureARB(GL_TEXTURE0);
2241
2242        // Find the correct type to render
2243        GLint primType;
2244        switch (op.operationType)
2245        {
2246        case RenderOperation::OT_POINT_LIST:
2247            primType = GL_POINTS;
2248            break;
2249        case RenderOperation::OT_LINE_LIST:
2250            primType = GL_LINES;
2251            break;
2252        case RenderOperation::OT_LINE_STRIP:
2253            primType = GL_LINE_STRIP;
2254            break;
2255        case RenderOperation::OT_TRIANGLE_LIST:
2256            primType = GL_TRIANGLES;
2257            break;
2258        case RenderOperation::OT_TRIANGLE_STRIP:
2259            primType = GL_TRIANGLE_STRIP;
2260            break;
2261        case RenderOperation::OT_TRIANGLE_FAN:
2262            primType = GL_TRIANGLE_FAN;
2263            break;
2264        }
2265
2266        if (op.useIndexes)
2267        {
2268            if(mCapabilities->hasCapability(RSC_VBO))
2269            {
2270                glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
2271                    static_cast<GLHardwareIndexBuffer*>(
2272                        op.indexData->indexBuffer.get())->getGLBufferId());
2273
2274                pBufferData = VBO_BUFFER_OFFSET(
2275                    op.indexData->indexStart * op.indexData->indexBuffer->getIndexSize());
2276            }
2277            else
2278            {
2279                pBufferData = static_cast<GLDefaultHardwareIndexBuffer*>(
2280                    op.indexData->indexBuffer.get())->getDataPtr(
2281                        op.indexData->indexStart * op.indexData->indexBuffer->getIndexSize());
2282            }
2283
2284            GLenum indexType = (op.indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
2285
2286                        do
2287                        {
2288                                glDrawElements(primType, op.indexData->indexCount, indexType, pBufferData);
2289                        } while (updatePassIterationRenderState());
2290
2291        }
2292        else
2293        {
2294                        do
2295                        {
2296                                glDrawArrays(primType, 0, op.vertexData->vertexCount);
2297                        } while (updatePassIterationRenderState());
2298        }
2299
2300        glDisableClientState( GL_VERTEX_ARRAY );
2301        for (int i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; i++)
2302        {
2303            glClientActiveTextureARB(GL_TEXTURE0 + i);
2304            glDisableClientState( GL_TEXTURE_COORD_ARRAY );
2305        }
2306        glClientActiveTextureARB(GL_TEXTURE0);
2307        glDisableClientState( GL_NORMAL_ARRAY );
2308        glDisableClientState( GL_COLOR_ARRAY );
2309        glDisableClientState( GL_SECONDARY_COLOR_ARRAY );
2310        if (mCapabilities->hasCapability(RSC_VERTEX_PROGRAM))
2311        {
2312            glDisableVertexAttribArrayARB(7); // disable indices
2313            glDisableVertexAttribArrayARB(1); // disable weights
2314        }
2315        glColor4f(1,1,1,1);
2316        glSecondaryColor3fEXT(0.0f, 0.0f, 0.0f);
2317
2318        // UnGuard
2319        OgreUnguard();
2320        }
2321    //---------------------------------------------------------------------
2322    void GLRenderSystem::setNormaliseNormals(bool normalise)
2323    {
2324        if (normalise)
2325            glEnable(GL_NORMALIZE);
2326        else
2327            glDisable(GL_NORMALIZE);
2328
2329    }
2330        //---------------------------------------------------------------------
2331    void GLRenderSystem::bindGpuProgram(GpuProgram* prg)
2332    {
2333        GLGpuProgram* glprg = static_cast<GLGpuProgram*>(prg);
2334        glprg->bindProgram();
2335        if (glprg->getType() == GPT_VERTEX_PROGRAM)
2336        {
2337            mCurrentVertexProgram = glprg;
2338        }
2339        else
2340        {
2341            mCurrentFragmentProgram = glprg;
2342        }
2343        RenderSystem::bindGpuProgram(prg);
2344    }
2345        //---------------------------------------------------------------------
2346    void GLRenderSystem::unbindGpuProgram(GpuProgramType gptype)
2347    {
2348
2349        if (gptype == GPT_VERTEX_PROGRAM && mCurrentVertexProgram)
2350        {
2351            mActiveVertexGpuProgramParameters.setNull();
2352            mCurrentVertexProgram->unbindProgram();
2353            mCurrentVertexProgram = 0;
2354        }
2355        else if (gptype == GPT_FRAGMENT_PROGRAM && mCurrentFragmentProgram)
2356        {
2357            mActiveFragmentGpuProgramParameters.setNull();
2358            mCurrentFragmentProgram->unbindProgram();
2359            mCurrentFragmentProgram = 0;
2360        }
2361        RenderSystem::unbindGpuProgram(gptype);
2362
2363    }
2364        //---------------------------------------------------------------------
2365    void GLRenderSystem::bindGpuProgramParameters(GpuProgramType gptype, GpuProgramParametersSharedPtr params)
2366    {
2367        if (gptype == GPT_VERTEX_PROGRAM)
2368        {
2369            mActiveVertexGpuProgramParameters = params;
2370            mCurrentVertexProgram->bindProgramParameters(params);
2371        }
2372        else
2373        {
2374            mActiveFragmentGpuProgramParameters = params;
2375            mCurrentFragmentProgram->bindProgramParameters(params);
2376        }
2377    }
2378        //---------------------------------------------------------------------
2379    void GLRenderSystem::bindGpuProgramPassIterationParameters(GpuProgramType gptype)
2380    {
2381        if (gptype == GPT_VERTEX_PROGRAM)
2382        {
2383            mCurrentVertexProgram->bindProgramPassIterationParameters(mActiveVertexGpuProgramParameters);
2384        }
2385        else
2386        {
2387            mCurrentFragmentProgram->bindProgramPassIterationParameters(mActiveFragmentGpuProgramParameters);
2388        }
2389    }
2390        //---------------------------------------------------------------------
2391    void GLRenderSystem::setClipPlanes(const PlaneList& clipPlanes)
2392    {
2393        size_t i;
2394        size_t numClipPlanes;
2395        GLdouble clipPlane[4];
2396
2397        numClipPlanes = clipPlanes.size();
2398        for (i = 0; i < numClipPlanes; ++i)
2399        {
2400            GLenum clipPlaneId = static_cast<GLenum>(GL_CLIP_PLANE0 + i);
2401            const Plane& plane = clipPlanes[i];
2402
2403            if (i >= 6/*GL_MAX_CLIP_PLANES*/)
2404            {
2405                OGRE_EXCEPT(0, "Unable to set clip plane",
2406                    "GLRenderSystem::setClipPlanes");
2407            }
2408
2409            clipPlane[0] = plane.normal.x;
2410            clipPlane[1] = plane.normal.y;
2411            clipPlane[2] = plane.normal.z;
2412            clipPlane[3] = plane.d;
2413
2414            glClipPlane(clipPlaneId, clipPlane);
2415            glEnable(clipPlaneId);
2416        }
2417
2418            // disable remaining clip planes
2419        for ( ; i < 6/*GL_MAX_CLIP_PLANES*/; ++i)
2420        {
2421            glDisable(static_cast<GLenum>(GL_CLIP_PLANE0 + i));
2422        }
2423    }
2424        //---------------------------------------------------------------------
2425    void GLRenderSystem::setScissorTest(bool enabled, size_t left,
2426        size_t top, size_t right, size_t bottom)
2427    {
2428        // If request texture flipping, use "upper-left", otherwise use "lower-left"
2429        bool flipping = mActiveRenderTarget->requiresTextureFlipping();
2430        //  GL measures from the bottom, not the top
2431        size_t targetHeight = mActiveRenderTarget->getHeight();
2432        // Calculate the "lower-left" corner of the viewport
2433        GLsizei w, h, x, y;
2434
2435        if (enabled)
2436        {
2437            glEnable(GL_SCISSOR_TEST);
2438            // NB GL uses width / height rather than right / bottom
2439            x = left;
2440            if (flipping)
2441                y = top;
2442            else
2443                y = targetHeight - bottom;
2444            w = right - left;
2445            h = bottom - top;
2446            glScissor(x, y, w, h);
2447        }
2448        else
2449        {
2450            glDisable(GL_SCISSOR_TEST);
2451            // GL requires you to reset the scissor when disabling
2452            w = mActiveViewport->getActualWidth();
2453            h = mActiveViewport->getActualHeight();
2454            x = mActiveViewport->getActualLeft();
2455            if (flipping)
2456                y = mActiveViewport->getActualTop();
2457            else
2458                y = targetHeight - mActiveViewport->getActualTop() - h;
2459            glScissor(x, y, w, h);
2460        }
2461    }
2462    //---------------------------------------------------------------------
2463    void GLRenderSystem::clearFrameBuffer(unsigned int buffers,
2464        const ColourValue& colour, Real depth, unsigned short stencil)
2465    {
2466
2467                bool colourMask = !mColourWrite[0] || !mColourWrite[1]
2468                        || !mColourWrite[2] || !mColourWrite[3];
2469
2470                GLbitfield flags = 0;
2471        if (buffers & FBT_COLOUR)
2472        {
2473            flags |= GL_COLOR_BUFFER_BIT;
2474                        // Enable buffer for writing if it isn't
2475                        if (colourMask)
2476                        {
2477                                glColorMask(true, true, true, true);
2478                        }
2479                        glClearColor(colour.r, colour.g, colour.b, colour.a);
2480        }
2481        if (buffers & FBT_DEPTH)
2482        {
2483            flags |= GL_DEPTH_BUFFER_BIT;
2484                        // Enable buffer for writing if it isn't
2485                        if (!mDepthWrite)
2486                        {
2487                                glDepthMask( GL_TRUE );
2488                        }
2489                        glClearDepth(depth);
2490        }
2491        if (buffers & FBT_STENCIL)
2492        {
2493            flags |= GL_STENCIL_BUFFER_BIT;
2494                        // Enable buffer for writing if it isn't
2495                        glStencilMask(0xFFFFFFFF);
2496
2497                        glClearStencil(stencil);
2498        }
2499
2500        // Clear buffers
2501        glClear(flags);
2502
2503        // Reset buffer write state
2504        if (!mDepthWrite && (buffers & FBT_DEPTH))
2505        {
2506            glDepthMask( GL_FALSE );
2507        }
2508        if (colourMask && (buffers & FBT_COLOUR))
2509        {
2510            glColorMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]);
2511        }
2512                if (buffers & FBT_STENCIL)
2513                {
2514                        glStencilMask(mStencilMask);
2515                }
2516
2517    }
2518    // ------------------------------------------------------------------
2519    void GLRenderSystem::_makeProjectionMatrix(Real left, Real right,
2520        Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest,
2521        bool forGpuProgram)
2522    {
2523        Real width = right - left;
2524        Real height = top - bottom;
2525        Real q, qn;
2526        if (farPlane == 0)
2527        {
2528            // Infinite far plane
2529            q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
2530            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2);
2531        }
2532        else
2533        {
2534            q = -(farPlane + nearPlane) / (farPlane - nearPlane);
2535            qn = -2 * (farPlane * nearPlane) / (farPlane - nearPlane);
2536        }
2537        dest = Matrix4::ZERO;
2538        dest[0][0] = 2 * nearPlane / width;
2539        dest[0][2] = (right+left) / width;
2540        dest[1][1] = 2 * nearPlane / height;
2541        dest[1][2] = (top+bottom) / height;
2542        dest[2][2] = q;
2543        dest[2][3] = qn;
2544        dest[3][2] = -1;
2545    }
2546
2547    // ------------------------------------------------------------------
2548    void GLRenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D)
2549    {
2550        if (ushort(mClipPlanes.size()) < index+1)
2551            mClipPlanes.resize(index+1);
2552        mClipPlanes[index] = Vector4 (A, B, C, D);
2553        GLdouble plane[4] = { A, B, C, D };
2554        glClipPlane (GL_CLIP_PLANE0 + index, plane);
2555    }
2556
2557    // ------------------------------------------------------------------
2558    void GLRenderSystem::setGLClipPlanes() const
2559    {
2560        size_t size = mClipPlanes.size();
2561        for (size_t i=0; i<size; i++)
2562        {
2563            const Vector4 &p = mClipPlanes[i];
2564            GLdouble plane[4] = { p.x, p.y, p.z, p.w };
2565            glClipPlane (GL_CLIP_PLANE0 + i, plane);
2566        }
2567    }
2568
2569    // ------------------------------------------------------------------
2570    void GLRenderSystem::enableClipPlane (ushort index, bool enable)
2571    {
2572        glEnable (GL_CLIP_PLANE0 + index);
2573    }
2574    //---------------------------------------------------------------------
2575    HardwareOcclusionQuery* GLRenderSystem::createHardwareOcclusionQuery(void)
2576    {
2577        GLHardwareOcclusionQuery* ret = new GLHardwareOcclusionQuery();
2578                mHwOcclusionQueries.push_back(ret);
2579                return ret;
2580    }
2581    //---------------------------------------------------------------------
2582    Real GLRenderSystem::getHorizontalTexelOffset(void)
2583    {
2584        // No offset in GL
2585        return 0.0f;
2586    }
2587    //---------------------------------------------------------------------
2588    Real GLRenderSystem::getVerticalTexelOffset(void)
2589    {
2590        // No offset in GL
2591        return 0.0f;
2592    }
2593        //---------------------------------------------------------------------
2594    void GLRenderSystem::_applyObliqueDepthProjection(Matrix4& matrix, const Plane& plane,
2595        bool forGpuProgram)
2596    {
2597        // Thanks to Eric Lenyel for posting this calculation at www.terathon.com
2598
2599        // Calculate the clip-space corner point opposite the clipping plane
2600        // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
2601        // transform it into camera space by multiplying it
2602        // by the inverse of the projection matrix
2603
2604        Vector4 q;
2605        q.x = (Math::Sign(plane.normal.x) + matrix[0][2]) / matrix[0][0];
2606        q.y = (Math::Sign(plane.normal.y) + matrix[1][2]) / matrix[1][1];
2607        q.z = -1.0F;
2608        q.w = (1.0F + matrix[2][2]) / matrix[2][3];
2609
2610        // Calculate the scaled plane vector
2611        Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
2612        Vector4 c = clipPlane4d * (2.0F / (clipPlane4d.dotProduct(q)));
2613
2614        // Replace the third row of the projection matrix
2615        matrix[2][0] = c.x;
2616        matrix[2][1] = c.y;
2617        matrix[2][2] = c.z + 1.0F;
2618        matrix[2][3] = c.w;
2619    }
2620    //---------------------------------------------------------------------
2621    void GLRenderSystem::_oneTimeContextInitialization()
2622    {
2623        // Set nicer lighting model -- d3d9 has this by default
2624        glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
2625        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);       
2626        glEnable(GL_COLOR_SUM);
2627        glDisable(GL_DITHER);
2628
2629        // Check for FSAA
2630        // Enable the extension if it was enabled by the GLSupport
2631        if (mGLSupport->checkExtension("GL_ARB_multisample"))
2632        {
2633            int fsaa_active = false;
2634            glGetIntegerv(GL_SAMPLE_BUFFERS_ARB,(GLint*)&fsaa_active);
2635            if(fsaa_active)
2636            {
2637                glEnable(GL_MULTISAMPLE_ARB);
2638                LogManager::getSingleton().logMessage("Using FSAA from GL_ARB_multisample extension.");
2639            }           
2640        }
2641    }
2642    //---------------------------------------------------------------------
2643    void GLRenderSystem::_switchContext(GLContext *context)
2644    {
2645        // Unbind GPU programs and rebind to new context later, because
2646        // scene manager treat render system as ONE 'context' ONLY, and it
2647        // cached the GPU programs using state.
2648        if (mCurrentVertexProgram)
2649            mCurrentVertexProgram->unbindProgram();
2650        if (mCurrentFragmentProgram)
2651            mCurrentFragmentProgram->unbindProgram();
2652
2653        // It's ready to switching
2654        mCurrentContext->endCurrent();
2655        mCurrentContext = context;
2656        mCurrentContext->setCurrent();
2657       
2658        // Check if the context has already done one-time initialisation
2659        if(!mCurrentContext->getInitialized())
2660        {
2661            _oneTimeContextInitialization();
2662            mCurrentContext->setInitialized();
2663        }
2664
2665        // Rebind GPU programs to new context
2666        if (mCurrentVertexProgram)
2667            mCurrentVertexProgram->bindProgram();
2668        if (mCurrentFragmentProgram)
2669            mCurrentFragmentProgram->bindProgram();
2670
2671        // Must reset depth/colour write mask to according with user desired, otherwise,
2672        // clearFrameBuffer would be wrong because the value we are recorded may be
2673        // difference with the really state stored in GL context.
2674        glDepthMask(mDepthWrite);
2675        glColorMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]);
2676                glStencilMask(mStencilMask);
2677
2678    }
2679    //---------------------------------------------------------------------
2680    void GLRenderSystem::_setRenderTarget(RenderTarget *target)
2681    {
2682        // Unbind frame buffer object
2683        if(mActiveRenderTarget)
2684            mRTTManager->unbind(mActiveRenderTarget);
2685       
2686        mActiveRenderTarget = target;
2687       
2688        // Switch context if different from current one
2689        GLContext *newContext = 0;
2690        target->getCustomAttribute("GLCONTEXT", &newContext);
2691        if(newContext && mCurrentContext != newContext)
2692        {
2693            _switchContext(newContext);
2694        }
2695       
2696        // Bind frame buffer object
2697        mRTTManager->bind(target);
2698    }
2699    //---------------------------------------------------------------------
2700    void GLRenderSystem::_unregisterContext(GLContext *context)
2701    {
2702        if(mCurrentContext == context) {
2703            // Change the context to something else so that a valid context
2704            // remains active. When this is the main context being unregistered,
2705            // we set the main context to 0.
2706            if(mCurrentContext != mMainContext) {
2707                _switchContext(mMainContext);
2708            } else {
2709                /// No contexts remain
2710                mCurrentContext->endCurrent();
2711                mCurrentContext = 0;
2712                mMainContext = 0;
2713            }
2714        }
2715    }
2716    //---------------------------------------------------------------------
2717    GLContext *GLRenderSystem::_getMainContext() {
2718        return mMainContext;
2719    }
2720    //---------------------------------------------------------------------
2721    Real GLRenderSystem::getMinimumDepthInputValue(void)
2722    {
2723        // Range [-1.0f, 1.0f]
2724        return -1.0f;
2725    }
2726    //---------------------------------------------------------------------
2727    Real GLRenderSystem::getMaximumDepthInputValue(void)
2728    {
2729        // Range [-1.0f, 1.0f]
2730        return 1.0f;
2731    }
2732
2733}
Note: See TracBrowser for help on using the repository browser.