KeosOGLRenderSystem.cpp

Go to the documentation of this file.
00001 /*
00002  * This source file is part of KEOS (Free 3D Engine)
00003  * For the latest info, see http://www.keosengine.org/
00004  * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
00005  *
00006  * This program is free software; you can redistribute it and/or modify it under
00007  * the terms of the GNU Lesser General Public License as published by the Free Software
00008  * Foundation; either version 2 of the License, or (at your option) any later
00009  * version.
00010  *
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License along with
00016  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00017  * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00018  * http://www.gnu.org/copyleft/lesser.txt.
00019  *
00020  */
00021 
00022 #include "KeosOGLRenderSystem.h"
00023 #include "KeosWin32Window.h"
00024 #include "KeosOGLException.h"
00025 #include "KeosLogger.h"
00026 #include "KeosOGLEnum.h"
00027 #include "KeosOGLBuffer.h"
00028 #include "KeosOGLDeclaration.h"
00029 #include "KeosMatrix4.h"
00030 #include "KeosColor.h"
00031 #include "KeosRenderSystemCapabilities.h"
00032 #include "KeosOGLTexture.h"
00033 #include "KeosPixelUtils.h"
00034 #include "KeosString.h"
00035 #include "KeosOGLShader.h"
00036 #include "KeosLight.h"
00037 #include "KeosUtil.h"
00038 #include "Cg/cgGL.h"
00039 
00040 
00041 namespace Keos
00042 {
00043   //=======================================================================
00044   // COGLRenderSystem implementation
00045   //=======================================================================
00046 
00047   // Functions ant macros for extensions loading
00048   template <class T> inline void LoadExtension(T& Proc, const char* strName)
00049   {
00050     if (!(Proc = reinterpret_cast<T>(wglGetProcAddress(strName))))
00051       OGL_EXCEPT("wglGetProcAddress", "LoadExtension");
00052   }
00053 #define LOAD_EXTENSION(Ext) LoadExtension(Ext, #Ext)
00054 
00055   // OpenGL Extensions
00056   PFNGLBINDBUFFERARBPROC              COGLRenderSystem::glBindBufferARB;
00057   PFNGLDELETEBUFFERSARBPROC           COGLRenderSystem::glDeleteBuffersARB;
00058   PFNGLGENBUFFERSARBPROC              COGLRenderSystem::glGenBuffersARB;
00059   PFNGLBUFFERDATAARBPROC              COGLRenderSystem::glBufferDataARB;
00060   PFNGLBUFFERSUBDATAARBPROC           COGLRenderSystem::glBufferSubDataARB;
00061   PFNGLGETBUFFERSUBDATAARBPROC        COGLRenderSystem::glGetBufferSubDataARB;
00062   PFNGLMAPBUFFERARBPROC               COGLRenderSystem::glMapBufferARB;
00063   PFNGLUNMAPBUFFERARBPROC             COGLRenderSystem::glUnmapBufferARB;
00064   PFNGLACTIVETEXTUREARBPROC           COGLRenderSystem::glActiveTextureARB;
00065   PFNGLCLIENTACTIVETEXTUREARBPROC     COGLRenderSystem::glClientActiveTextureARB;
00066   PFNGLCOMPRESSEDTEXIMAGE2DARBPROC    COGLRenderSystem::glCompressedTexImage2DARB;
00067   PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC COGLRenderSystem::glCompressedTexSubImage2DARB;
00068 
00069   //-----------------------------------------------------------------------
00070   COGLRenderSystem::COGLRenderSystem()
00071   {
00072     m_bGLInitialized = false;
00073   }
00074 
00075   //-----------------------------------------------------------------------
00076   COGLRenderSystem::~COGLRenderSystem()
00077   {
00078     Shutdown();
00079   }
00080 
00081   //-----------------------------------------------------------------------
00082   const String& COGLRenderSystem::GetName(void) const
00083   {
00084     static String strName("OpenGL");
00085     return strName;
00086   }
00087 
00088   //-----------------------------------------------------------------------
00089   IRenderWindow* COGLRenderSystem::Initialise(bool bAutoCreateWindow, const String& strWindowTitle)
00090   {
00091     ILogger::Log("--> Starting Win32GL Subsystem");
00092 
00093     ConfigOptionMap::iterator opt = m_Options.find("Video Mode");
00094     if (opt == m_Options.end())
00095       OGL_EXCEPT("Can't find \"Video Mode\" option", "COGLRenderSystem::Initialise");
00096     String val = opt->second.currentValue;
00097     String::size_type pos = val.find('x');
00098     if (pos == String::npos)
00099       OGL_EXCEPT("Invalid Video Mode provided", "COGLRenderSystem::Initialise");
00100     uint w = CStringConverter::ParseUnsignedInt(val.substr(0, pos));
00101     uint h = CStringConverter::ParseUnsignedInt(val.substr(pos + 1));
00102 
00103     opt = m_Options.find("Color Depth");
00104     if (opt == m_Options.end())
00105       OGL_EXCEPT("Can't find \"Color Depth\" option", "COGLRenderSystem::Initialise");
00106     val = opt->second.currentValue;
00107     uint d = CStringConverter::ParseUnsignedInt(val);
00108     if (d == 0)
00109       OGL_EXCEPT("Invalid Color Depth provided", "COGLRenderSystem::Initialise");
00110 
00111     opt = m_Options.find("Fullscreen");
00112     if (opt == m_Options.end())
00113       OGL_EXCEPT("Can't find \"Fullscreen\" option", "COGLRenderSystem::Initialise");
00114     val = opt->second.currentValue;
00115     bool f = CStringConverter::ParseBool(val);
00116 
00117 
00118     IRenderWindow* pAutoWindow = CreateRenderWindow(strWindowTitle, w, h, d, f);
00119 
00120     return pAutoWindow;
00121   }
00122 
00123   //-----------------------------------------------------------------------
00124   IRenderWindow* COGLRenderSystem::CreateRenderWindow(const String &strName, uint nWidth, uint nHeight, uint nColourDepth, bool bFullScreen)
00125   {
00126     ILogger::Log("--> Create Win32 render window");
00127 
00128     // Create the window
00129     IRenderWindow* win = new CWin32Window();
00130     win->Create(strName, nWidth, nHeight, nColourDepth, bFullScreen);
00131 
00132     AttachRenderTarget( *win );
00133 
00134     if (!m_bGLInitialized)
00135     {
00136       // Initialise GL after the first window has been created
00137       InitGL();
00138     }
00139 
00140     return win;
00141   }
00142 
00143   //-----------------------------------------------------------------------
00144   void COGLRenderSystem::InitGL(void)
00145   {
00146     ILogger::Log("--> Initialise OpenGL");
00147 
00148     // Retrieve extensions
00149     m_strExtensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
00150 
00151     // Load OpenGL extensions
00152     LoadExtensions();
00153 
00154     // Setup Cg OGL Runtime
00155     if (m_pCapabilities->HasCapability(CAP_VERTEX_PROGRAM))
00156     {
00157       m_VSProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
00158       cgGLSetOptimalOptions(m_VSProfile);
00159       m_VSOptions[0] = NULL;
00160     }
00161     if (m_pCapabilities->HasCapability(CAP_FRAGMENT_PROGRAM))
00162     {
00163       m_PSProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
00164       cgGLSetOptimalOptions(m_PSProfile);
00165       m_PSOptions[0] = NULL;
00166     }
00167 
00168     // Default states
00169     SetClearColor(CColor::Black);
00170     glClearDepth(1.0f);
00171     glClearStencil(0x00);
00172     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
00173     glShadeModel(GL_SMOOTH);
00174     glEnable(GL_DEPTH_TEST);
00175 
00176     glCullFace(GL_BACK);
00177     m_bGLInitialized = true;
00178   }
00179 
00180   //-----------------------------------------------------------------------
00181   void COGLRenderSystem::Reinitialise(void)
00182   {
00183     this->Shutdown();
00184     this->Initialise(true);
00185   }
00186 
00187   //-----------------------------------------------------------------------
00188   void COGLRenderSystem::Shutdown(void)
00189   {
00190     IRenderSystem::Shutdown();
00191   }
00192 
00193   //-----------------------------------------------------------------------
00194   bool COGLRenderSystem::CheckExtension(const String& strExtension) const
00195   {
00196     return m_strExtensions.find(strExtension) != String::npos;
00197   }
00198 
00199   //-----------------------------------------------------------------------
00200   void COGLRenderSystem::LoadExtensions()
00201   {
00202     // Load extensions
00203     LOAD_EXTENSION(glBindBufferARB);
00204     LOAD_EXTENSION(glDeleteBuffersARB);
00205     LOAD_EXTENSION(glGenBuffersARB);
00206     LOAD_EXTENSION(glBufferDataARB);
00207     LOAD_EXTENSION(glBufferSubDataARB);
00208     LOAD_EXTENSION(glGetBufferSubDataARB);
00209     LOAD_EXTENSION(glMapBufferARB);
00210     LOAD_EXTENSION(glUnmapBufferARB);
00211     LOAD_EXTENSION(glActiveTextureARB);
00212     LOAD_EXTENSION(glClientActiveTextureARB);
00213     LOAD_EXTENSION(glCompressedTexImage2DARB);
00214     LOAD_EXTENSION(glCompressedTexSubImage2DARB);
00215 
00216     // Check for hardware mipmapping support
00217     if (CheckExtension("GL_SGIS_generate_mipmap"))
00218     {
00219       m_pCapabilities->SetCapability(CAP_HW_MIPMAPPING);
00220     }
00221     // Check for texture dxt compression
00222     if (CheckExtension("GL_ARB_texture_compression") && CheckExtension("GL_EXT_texture_compression_s3tc"))
00223     {
00224       m_pCapabilities->SetCapability(CAP_TEXTURE_COMPRESSION_DXT);
00225     }
00226     // Check for non-power-of-2 texture support
00227     if (CheckExtension("GL_ARB_texture_non_power_of_two"))
00228     {
00229       m_pCapabilities->SetCapability(CAP_NON_POWER_OF_2_TEXTURES);
00230     }
00231     // Check for Multitexturing support and set number of texture units
00232     if ( CheckExtension("GL_ARB_multitexture"))
00233     {
00234       GLint units;
00235       glGetIntegerv( GL_MAX_TEXTURE_UNITS, &units );
00236       m_pCapabilities->SetNumTextureUnits(units);
00237     }
00238     else
00239     {
00240       // If no multitexture support then set one texture unit
00241       m_pCapabilities->SetNumTextureUnits(1);
00242     }
00243 
00244     // Check for Vertex Program support and set version number
00245     if (CheckExtension("GL_ARB_vertex_program"))
00246     {
00247       m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
00248 
00249       // Vertex Program Properties
00250       m_pCapabilities->SetMaxVertexProgramVersion("arbvp1");
00251       //mCapabilities->setVertexProgramConstantBoolCount(0);
00252       //mCapabilities->setVertexProgramConstantIntCount(0);
00253       //mCapabilities->setVertexProgramConstantFloatCount(GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
00254 
00255       if (CheckExtension("GL_NV_vertex_program2_option"))
00256       {
00257         m_pCapabilities->SetMaxVertexProgramVersion("vp30");
00258       }
00259 
00260       if (CheckExtension("GL_NV_vertex_program3"))
00261       {
00262         m_pCapabilities->SetMaxVertexProgramVersion("vp40");
00263       }
00264     }
00265 
00266     // Check for Fragment Program support and set version number
00267     if (CheckExtension("GL_NV_register_combiners2") &&
00268         CheckExtension("GL_NV_texture_shader"))
00269     {
00270       m_pCapabilities->SetCapability(CAP_FRAGMENT_PROGRAM);
00271       m_pCapabilities->SetMaxFragmentProgramVersion("fp20");
00272     }
00273 
00274     if (CheckExtension("GL_ATI_fragment_shader"))
00275     {
00276       // ATI fragment shader not supported by Cg Compiler
00277       ILogger::Log("ATI fragment shader not supported by Keos Engine (Cg Compiler)");
00278       //m_pCapabilities->SetCapability(RSC_FRAGMENT_PROGRAM);
00279       //m_pCapabilities->SetMaxFragmentProgramVersion("ps_1_4");
00280       // no boolean params allowed
00281       //m_pCapabilities->SetFragmentProgramConstantBoolCount(0);
00282       // no integer params allowed
00283       //m_pCapabilities->SetFragmentProgramConstantIntCount(0);
00284       // only 8 Vector4 constant floats supported
00285       //m_pCapabilities->SetFragmentProgramConstantFloatCount(8);
00286     }
00287 
00288     if (CheckExtension("GL_ARB_fragment_program"))
00289     {
00290       m_pCapabilities->SetCapability(CAP_FRAGMENT_PROGRAM);
00291       // Fragment Program Properties
00292       m_pCapabilities->SetMaxFragmentProgramVersion("arbfp1");
00293       //m_pCapabilities->SetFragmentProgramConstantBoolCount(0);
00294       //m_pCapabilities->SetFragmentProgramConstantIntCount(0);
00295       //m_pCapabilities->SetFragmentProgramConstantFloatCount(GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
00296 
00297       if (CheckExtension("GL_NV_fragment_program_option"))
00298       {
00299         m_pCapabilities->SetMaxFragmentProgramVersion("fp30");
00300       }
00301 
00302       if (CheckExtension("GL_NV_fragment_program2"))
00303       {
00304         m_pCapabilities->SetMaxFragmentProgramVersion("fp40");
00305       }
00306     }
00307 
00308     m_pCapabilities->Log();
00309   }
00310 
00311   //-----------------------------------------------------------------------
00312   void COGLRenderSystem::BeginScene() const
00313   {
00314     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
00315   }
00316 
00317   //-----------------------------------------------------------------------
00318   void COGLRenderSystem::EndScene() const
00319     {  }
00320 
00321   //-----------------------------------------------------------------------
00322   void COGLRenderSystem::PrintInfo() const
00323   {
00324     printf("OpenGL informations :\n");
00325     // Print informations about OpenGL
00326     char *exten;
00327     exten = (char *) glGetString(GL_VENDOR);
00328     printf("%s\n", exten);
00329     exten = (char *) glGetString(GL_RENDERER);
00330     printf("%s\n", exten);
00331     exten = (char *) glGetString(GL_VERSION);
00332     printf("%s\n", exten);
00333     //printf("Extensions: %s\n",m_strExtensions.data());
00334   }
00335 
00336   //-----------------------------------------------------------------------
00337   IBufferBase* COGLRenderSystem::_CreateVB(ulong nSize, ulong nStride, ulong nFlags) const
00338   {
00339     // Buffer creation
00340     uint nVertexBuffer = 0;
00341     glGenBuffersARB(1, &nVertexBuffer);
00342 
00343     // Fill buffer
00344     glBindBufferARB(GL_ARRAY_BUFFER_ARB, nVertexBuffer);
00345     glBufferDataARB(GL_ARRAY_BUFFER_ARB, nSize * nStride, NULL, COGLEnum::BufferFlags(nFlags));
00346 
00347     return new COGLVertexBuffer(nSize, nVertexBuffer);
00348   }
00349 
00350 
00351   //-----------------------------------------------------------------------
00352   IBufferBase* COGLRenderSystem::_CreateIB(ulong nSize, ulong nStride, ulong nFlags) const
00353   {
00354     // Buffer creation
00355     uint nIndexBuffer = 0;
00356     glGenBuffersARB(1, &nIndexBuffer);
00357 
00358     // Fill buffer
00359     glBindBufferARB(GL_ARRAY_BUFFER_ARB, nIndexBuffer);
00360     glBufferDataARB(GL_ARRAY_BUFFER_ARB, nSize * nStride, NULL, COGLEnum::BufferFlags(nFlags));
00361 
00362     return new COGLIndexBuffer(nSize, nIndexBuffer);
00363   }
00364 
00365   //-----------------------------------------------------------------------
00366   IDeclaration* COGLRenderSystem::CreateDeclaration(const TDeclarationElement* Elements, size_t nCount) const
00367   {
00368     // OpenGL declaration creation
00369     COGLDeclaration* Declaration = new COGLDeclaration;
00370 
00371     // For each elements of the declaration, conversion in OGL element
00372     std::vector<int> Offset(nCount, 0);
00373     for (const TDeclarationElement* Elt = Elements; Elt < Elements + nCount; ++Elt)
00374     {
00375       // Build OGL element
00376       COGLDeclaration::TElement CurrentElement;
00377       CurrentElement.Usage  = Elt->Usage;
00378       CurrentElement.Type   = Elt->DataType;
00379       CurrentElement.Offset = Offset[Elt->Stream];
00380 
00381       // Addition of the element
00382       Declaration->AddElement(Elt->Stream, CurrentElement);
00383 
00384       // Increment offset
00385       static const uint Size[] =
00386         {
00387           4, 8, 12, 16, 4
00388         };
00389       Offset[Elt->Stream] += Size[Elt->DataType];
00390     }
00391 
00392     return Declaration;
00393   }
00394 
00395 
00396   //-----------------------------------------------------------------------
00397   void COGLRenderSystem::_SetVB(uint nStream, const IBufferBase* pBuffer, ulong nStride, ulong nMinVertex, ulong nMaxVertex)
00398   {
00399     // Sending of the buffer OGL in the API
00400     const COGLVertexBuffer* pVertexBuffer = static_cast<const COGLVertexBuffer*>(pBuffer);
00401     glBindBufferARB(GL_ARRAY_BUFFER_ARB, pVertexBuffer->GetBuffer());
00402 
00403     // Tables of correspondence
00404     static const uint Size[] =
00405       {
00406         1, 2, 3, 4, 4
00407       };
00408     static const uint Type[] =
00409       {
00410         GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE
00411       };
00412 
00413     // glPointer setup
00414     const COGLDeclaration::TElementArray& StreamDesc = m_CurrentDeclaration->GetStreamElements(nStream);
00415     for (COGLDeclaration::TElementArray::const_iterator i = StreamDesc.begin(); i != StreamDesc.end(); ++i)
00416     {
00417       switch (i->Usage)
00418       {
00419           // Position
00420         case ELT_USAGE_POSITION :
00421           glEnableClientState(GL_VERTEX_ARRAY);
00422           glVertexPointer(Size[i->Type], Type[i->Type], nStride, BUFFER_OFFSET(i->Offset + nMinVertex * nStride));
00423           break;
00424 
00425           // Normal
00426         case ELT_USAGE_NORMAL :
00427           glEnableClientState(GL_NORMAL_ARRAY);
00428           glNormalPointer(Type[i->Type], nStride, BUFFER_OFFSET(i->Offset + nMinVertex * nStride));
00429           break;
00430 
00431           // Diffuse color
00432         case ELT_USAGE_DIFFUSE :
00433           glEnableClientState(GL_COLOR_ARRAY);
00434           glColorPointer(Size[i->Type], Type[i->Type], nStride, BUFFER_OFFSET(i->Offset + nMinVertex * nStride));
00435           break;
00436 
00437           // Texture coordinates 0
00438         case ELT_USAGE_TEXCOORD0 :
00439           glActiveTextureARB(GL_TEXTURE0_ARB);
00440           glEnable(GL_TEXTURE_2D);
00441           glClientActiveTextureARB(GL_TEXTURE0_ARB);
00442           glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00443           glTexCoordPointer(Size[i->Type], Type[i->Type], nStride, BUFFER_OFFSET(i->Offset + nMinVertex * nStride));
00444           break;
00445 
00446           // Texture coordinates 1
00447         case ELT_USAGE_TEXCOORD1 :
00448           glActiveTextureARB(GL_TEXTURE0_ARB);
00449           glEnable(GL_TEXTURE_2D);
00450           glClientActiveTextureARB(GL_TEXTURE0_ARB);
00451           glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00452           glTexCoordPointer(Size[i->Type], Type[i->Type], nStride, BUFFER_OFFSET(i->Offset + nMinVertex * nStride));
00453           break;
00454 
00455           // Texture coordinates 2
00456         case ELT_USAGE_TEXCOORD2 :
00457           glActiveTextureARB(GL_TEXTURE0_ARB);
00458           glEnable(GL_TEXTURE_2D);
00459           glClientActiveTextureARB(GL_TEXTURE0_ARB);
00460           glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00461           glTexCoordPointer(Size[i->Type], Type[i->Type], nStride, BUFFER_OFFSET(i->Offset + nMinVertex * nStride));
00462           break;
00463 
00464           // Texture coordinates 3
00465         case ELT_USAGE_TEXCOORD3 :
00466           glActiveTextureARB(GL_TEXTURE0_ARB);
00467           glEnable(GL_TEXTURE_2D);
00468           glClientActiveTextureARB(GL_TEXTURE0_ARB);
00469           glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00470           glTexCoordPointer(Size[i->Type], Type[i->Type], nStride, BUFFER_OFFSET(i->Offset + nMinVertex * nStride));
00471           break;
00472       }
00473     }
00474   }
00475 
00476   //-----------------------------------------------------------------------
00477   void COGLRenderSystem::_SetIB(const IBufferBase* pBuffer, ulong nStride)
00478   {
00479     const COGLIndexBuffer* pIndexBuffer = static_cast<const COGLIndexBuffer*>(pBuffer);
00480 
00481     // Sending of the buffer in the API
00482     glEnableClientState(GL_INDEX_ARRAY);
00483     glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, pIndexBuffer->GetBuffer());
00484 
00485     // Save the indices size
00486     m_nIndexStride = nStride;
00487   }
00488 
00489   //-----------------------------------------------------------------------
00490   void COGLRenderSystem::SetDeclaration(const IDeclaration* pDeclaration)
00491   {
00492     // Deactivation of the previous states
00493     glColor4f(1, 1, 1, 1);
00494     glDisableClientState(GL_VERTEX_ARRAY);
00495     glDisableClientState(GL_NORMAL_ARRAY);
00496     glDisableClientState(GL_COLOR_ARRAY);
00497     for (int i = 0; i < 4; ++i)
00498     {
00499       glActiveTextureARB(GL_TEXTURE0_ARB + i);
00500       glDisable(GL_TEXTURE_2D);
00501     }
00502 
00503     // Save the declaration
00504     m_CurrentDeclaration = static_cast<const COGLDeclaration*>(pDeclaration);
00505   }
00506 
00507   //-----------------------------------------------------------------------
00508   void COGLRenderSystem::DrawPrimitives(TPrimitiveType Type, ulong nFirstVertex, ulong nCount) const
00509   {
00510     // Display of the primitives
00511     switch (Type)
00512     {
00513       case PT_TRIANGLELIST :
00514         glDrawArrays(GL_TRIANGLES,      nFirstVertex, nCount * 3);
00515         break;
00516       case PT_TRIANGLESTRIP :
00517         glDrawArrays(GL_TRIANGLE_STRIP, nFirstVertex, nCount + 2);
00518         break;
00519       case PT_TRIANGLEFAN :
00520         glDrawArrays(GL_TRIANGLE_FAN,   nFirstVertex, nCount + 1);
00521         break;
00522       case PT_LINELIST :
00523         glDrawArrays(GL_LINES,          nFirstVertex, nCount * 2);
00524         break;
00525       case PT_LINESTRIP :
00526         glDrawArrays(GL_LINE_STRIP,     nFirstVertex, nCount + 1);
00527         break;
00528       case PT_POINTLIST :
00529         glDrawArrays(GL_POINTS,         nFirstVertex, nCount);
00530         break;
00531     }
00532   }
00533 
00534   //-----------------------------------------------------------------------
00535   void COGLRenderSystem::DrawIndexedPrimitives(TPrimitiveType Type, ulong nFirstIndex, ulong nCount) const
00536   {
00537     ulong nIndicesType = (m_nIndexStride == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT);
00538     const void*   Offset      = BUFFER_OFFSET(nFirstIndex * m_nIndexStride);
00539 
00540     // Display of the primitives
00541     switch (Type)
00542     {
00543       case PT_TRIANGLELIST :
00544         glDrawElements(GL_TRIANGLES,      nCount * 3, nIndicesType, Offset);
00545         break;
00546       case PT_TRIANGLESTRIP :
00547         glDrawElements(GL_TRIANGLE_STRIP, nCount + 2, nIndicesType, Offset);
00548         break;
00549       case PT_TRIANGLEFAN :
00550         glDrawElements(GL_TRIANGLE_FAN,   nCount + 1, nIndicesType, Offset);
00551         break;
00552       case PT_LINELIST :
00553         glDrawElements(GL_LINES,          nCount * 2, nIndicesType, Offset);
00554         break;
00555       case PT_LINESTRIP :
00556         glDrawElements(GL_LINE_STRIP,     nCount + 1, nIndicesType, Offset);
00557         break;
00558       case PT_POINTLIST :
00559         glDrawElements(GL_POINTS,         nCount,     nIndicesType, Offset);
00560         break;
00561     }
00562   }
00563 
00564   //-----------------------------------------------------------------------
00565   void COGLRenderSystem::PushMatrix(TMatrixType Type)
00566   {
00567     if (Type >= MAT_TEXTURE_0)
00568       glActiveTextureARB(GL_TEXTURE0_ARB + Type - MAT_TEXTURE_0);
00569 
00570     glMatrixMode(COGLEnum::Get(Type));
00571     glPushMatrix();
00572   }
00573 
00574   //-----------------------------------------------------------------------
00575   void COGLRenderSystem::PopMatrix(TMatrixType Type)
00576   {
00577     if (Type >= MAT_TEXTURE_0)
00578       glActiveTextureARB(GL_TEXTURE0_ARB + Type - MAT_TEXTURE_0);
00579 
00580     glMatrixMode(COGLEnum::Get(Type));
00581     glPopMatrix();
00582   }
00583 
00584   //-----------------------------------------------------------------------
00585   void COGLRenderSystem::LoadMatrix(TMatrixType Type, const CMatrix4& Matrix)
00586   {
00587     if (Type >= MAT_TEXTURE_0)
00588       glActiveTextureARB(GL_TEXTURE0_ARB + Type - MAT_TEXTURE_0);
00589 
00590     glMatrixMode(COGLEnum::Get(Type));
00591     glLoadMatrixf(Matrix);
00592   }
00593 
00594   //-----------------------------------------------------------------------
00595   void COGLRenderSystem::LoadMatrixMult(TMatrixType Type, const CMatrix4& Matrix)
00596   {
00597     if (Type >= MAT_TEXTURE_0)
00598       glActiveTextureARB(GL_TEXTURE0_ARB + Type - MAT_TEXTURE_0);
00599 
00600     glMatrixMode(COGLEnum::Get(Type));
00601     glMultMatrixf(Matrix);
00602   }
00603 
00604   //-----------------------------------------------------------------------
00605   void COGLRenderSystem::GetMatrix(TMatrixType Type, CMatrix4& Matrix) const
00606   {
00607     if (Type >= MAT_TEXTURE_0)
00608       glActiveTextureARB(GL_TEXTURE0_ARB + Type - MAT_TEXTURE_0);
00609 
00610     glGetFloatv(COGLEnum::GetMatrix(Type), Matrix);
00611   }
00612 
00613   //-----------------------------------------------------------------------
00614   ulong COGLRenderSystem::ConvertColor(const CColor& Color) const
00615   {
00616     return Color.ToABGR();
00617   }
00618 
00619   //-----------------------------------------------------------------------
00620   ITextureBase* COGLRenderSystem::CreateTexture(const TVector2I& Size, TPixelFormat Format, ulong nFlags) const
00621   {
00622     uint nTexture;
00623     glGenTextures(1, &nTexture);
00624 
00625     glBindTexture(GL_TEXTURE_2D, nTexture);
00626 
00627     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00628     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00629     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00630     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
00631 
00633     //int NbMipmaps = nFlags & TEX_NOMIPMAP ? GetNbMipLevels(Size.x, Size.y) : 0;
00634     int NbMipmaps = nFlags & TEX_NOMIPMAP ? 0 : GetNbMipLevels(Size.x, Size.y);
00635 
00636     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, NbMipmaps);
00637 
00638     if ((NbMipmaps > 0) && (GetCapabilities()->HasCapability(CAP_HW_MIPMAPPING)))
00639       glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
00640 
00641     int Width  = Size.x;
00642     int Height = Size.y;
00643     for (int i = 0; i <= NbMipmaps; ++i)
00644     {
00645       glTexImage2D(GL_TEXTURE_2D, i, COGLEnum::Get(Format).Internal, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
00646 
00647       if (Width > 1)  Width  /= 2;
00648       if (Height > 1) Height /= 2;
00649     }
00650 
00651     glBindTexture(GL_TEXTURE_2D, 0);
00652 
00653     return new COGLTexture(Size, Format, NbMipmaps > 0, GetCapabilities()->HasCapability(CAP_HW_MIPMAPPING), nTexture);
00654   }
00655 
00656   //-----------------------------------------------------------------------
00657   void COGLRenderSystem::SetTexture(uint nUnit, const ITextureBase* Texture) const
00658   {
00659     glActiveTextureARB(GL_TEXTURE0_ARB + nUnit);
00660     const COGLTexture* OGLTexture = static_cast<const COGLTexture*>(Texture);
00661 
00662     if (Texture)
00663     {
00664       glEnable(GL_TEXTURE_2D);
00665       glBindTexture(GL_TEXTURE_2D, OGLTexture->GetOGLTexture());
00666     }
00667     else
00668     {
00669       glDisable(GL_TEXTURE_2D);
00670       glBindTexture(GL_TEXTURE_2D, 0);
00671     }
00672   }
00673 
00674   //-----------------------------------------------------------------------
00675   void COGLRenderSystem::SetupAlphaBlending(TBlend Src, TBlend Dest) const
00676   {
00677     glBlendFunc(COGLEnum::Get(Src), COGLEnum::Get(Dest));
00678   }
00679 
00680   //-----------------------------------------------------------------------
00681   void COGLRenderSystem::SetupTextureUnit(uint nUnit, TTextureOp Op, TTextureArg Arg1, TTextureArg Arg2, const CColor& Constant) const
00682   {
00683     // Activate the unit texture
00684     glEnable(GL_TEXTURE_2D);
00685     glActiveTextureARB(GL_TEXTURE0_ARB + nUnit);
00686     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
00687 
00688     // Operators and arguments
00689     if (Op < TXO_ALPHA_FIRSTARG)
00690     {
00691       glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, COGLEnum::Get(Op));
00692       glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, COGLEnum::Get(Arg1));
00693       glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, COGLEnum::Get(Arg2));
00694       glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
00695       glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
00696     }
00697     else
00698     {
00699       glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, COGLEnum::Get(Op));
00700       glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, COGLEnum::Get(Arg1));
00701       glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, COGLEnum::Get(Arg2));
00702       glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
00703       glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA);
00704     }
00705 
00706     // Constants
00707     if ((Arg1 == TXA_CONSTANT) || (Arg2 == TXA_CONSTANT))
00708     {
00709       float Color[4];
00710       Constant.ToFloat(Color);
00711       glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, Color);
00712     }
00713   }
00714 
00715   //-----------------------------------------------------------------------
00716   void COGLRenderSystem::Enable(TRenderParameter Param, bool bValue) const
00717   {
00718     switch (Param)
00719     {
00720       case RENDER_ZWRITE :
00721       {
00722         glDepthMask(bValue);
00723         break;
00724       }
00725 
00726       default :
00727       {
00728         if (bValue)
00729           glEnable(COGLEnum::Get(Param));
00730         else
00731           glDisable(COGLEnum::Get(Param));
00732       }
00733     }
00734   }
00735 
00736   //-----------------------------------------------------------------------
00737   IShaderBase* COGLRenderSystem::CreateShader(CGprogram Program, TShaderType Type) const
00738   {
00739     return new COGLShader(Program, Type);
00740   }
00741 
00742   //-----------------------------------------------------------------------
00743   void COGLRenderSystem::SetVertexShader(const IShaderBase* pShader)
00744   {
00745     const COGLShader* pOGLShader = static_cast<const COGLShader*>(pShader);
00746 
00747     if (pOGLShader)
00748     {
00749       if (pOGLShader->GetType() != SHADER_VERTEX)
00750         OGL_EXCEPT("Incorrect shader type (Pixel Shader)", "COGLRenderSystem::SetVertexShader");
00751 
00752       cgGLBindProgram(pOGLShader->GetProgram());
00753       cgGLEnableProfile(m_VSProfile);
00754     }
00755     else
00756     {
00757       cgGLDisableProfile(m_VSProfile);
00758       cgGLUnbindProgram(m_VSProfile);
00759     }
00760   }
00761 
00762   //-----------------------------------------------------------------------
00763   void COGLRenderSystem::SetPixelShader(const IShaderBase* pShader)
00764   {
00765     const COGLShader* pOGLShader = static_cast<const COGLShader*>(pShader);
00766 
00767     if (pOGLShader)
00768     {
00769       if (pOGLShader->GetType() != SHADER_PIXEL)
00770         OGL_EXCEPT("Incorrect shader type (Vertex Shader)", "COGLRenderSystem::SetPixelShader");
00771 
00772       cgGLBindProgram(pOGLShader->GetProgram());
00773       cgGLEnableProfile(m_PSProfile);
00774     }
00775     else
00776     {
00777       cgGLDisableProfile(m_PSProfile);
00778       cgGLUnbindProgram(m_PSProfile);
00779     }
00780   }
00781 
00782   //-----------------------------------------------------------------------
00783   void COGLRenderSystem::SetClearColor(const CColor& Color)
00784   {
00785     float rgba[4];
00786     Color.ToFloat(rgba);
00787 
00788     m_ClearColor = Color;
00789 
00790     glClearColor(rgba[0], rgba[1], rgba[2], rgba[3]);
00791   }
00792 
00793   //-----------------------------------------------------------------------
00794   void COGLRenderSystem::SetLight(uint nIndex, CLight* pLight)
00795   {
00796     // Save previous modelview
00797     glMatrixMode(GL_MODELVIEW);
00798     glPushMatrix();
00799     CMatrix4 id;
00800     id.Identity();
00801     glLoadMatrixf(id);
00802 
00803     GLenum gl_index = GL_LIGHT0 + nIndex;
00804 
00805     if (!pLight)
00806     {
00807       // Disable in the scene
00808       glDisable(gl_index);
00809     }
00810     else
00811     {
00812       switch (pLight->GetType())
00813       {
00814         case CLight::LT_SPOT:
00815 
00816           glLightf( gl_index, GL_SPOT_CUTOFF, 0.5f * pLight->GetSpotOuterAngle().valueDegrees() );
00817           glLightf(gl_index, GL_SPOT_EXPONENT, pLight->GetSpotFalloff());
00818           break;
00819         case CLight::LT_DIRECTIONAL:
00820         case CLight::LT_POINT:
00821         default:
00822           glLightf( gl_index, GL_SPOT_CUTOFF, 180.0 );
00823           break;
00824       }
00825 
00826       CColor Col;
00827       GLfloat f4vals[4];
00828 
00829       // Diffuse Color
00830       Col = pLight->GetDiffuseColor();
00831       Col.ToFloat(f4vals);
00832       glLightfv(gl_index, GL_DIFFUSE, f4vals);
00833 
00834       // Specular Color
00835       Col = pLight->GetSpecularColor();
00836       Col.ToFloat(f4vals);
00837       glLightfv(gl_index, GL_SPECULAR, f4vals);
00838 
00839       // Disable ambient light for movables;
00840       f4vals[0] = 0;
00841       f4vals[1] = 0;
00842       f4vals[2] = 0;
00843       f4vals[3] = 1;
00844       glLightfv(gl_index, GL_AMBIENT, f4vals);
00845 
00846       // Set position / direction
00847       TVector3F Vec;
00848       float w;
00849       if (pLight->GetType() == CLight::LT_DIRECTIONAL)
00850       {
00851         Vec = TVector3F(0, 0, 0) - pLight->GetDirection();
00852         w = 0.0f;
00853       }
00854       else
00855       {
00856         Vec = pLight->GetPosition();
00857         w = 1.0f;
00858       }
00859 
00860 
00861       float tmp[4] = {Vec.x, Vec.y, Vec.z, w};
00862       glLightfv(gl_index, GL_POSITION, tmp);
00863       if (pLight->GetType() == CLight::LT_SPOT)
00864       {
00865         Vec = pLight->GetDirection();
00866         w = 0.0f;
00867         float tmp2[4] = {Vec.x, Vec.y, Vec.z, w};
00868         glLightfv(gl_index, GL_SPOT_DIRECTION, tmp2);
00869       }
00870 
00871       // Attenuation
00872       glLightf(gl_index, GL_CONSTANT_ATTENUATION, pLight->GetAttenuationConstant());
00873       glLightf(gl_index, GL_LINEAR_ATTENUATION, pLight->GetAttenuationLinear());
00874       glLightf(gl_index, GL_QUADRATIC_ATTENUATION, pLight->GetAttenuationQuadric());
00875 
00876       glEnable(GL_COLOR_MATERIAL);
00877 
00878       // Enable in the scene
00879       glEnable(gl_index);
00880     }
00881 
00882     // restore previous
00883     glPopMatrix();
00884   }
00885 
00886   //-----------------------------------------------------------------------
00887   void COGLRenderSystem::SetFillMode(TFillMode Mode)
00888   {
00889     glPolygonMode(GL_FRONT_AND_BACK, COGLEnum::Get(Mode));
00890   }
00891 
00892 } // namespace Keos

Generated on Fri Mar 9 14:29:04 2007 for Keos by  doxygen 1.5.1-p1