00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00045
00046
00047
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
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
00129 IRenderWindow* win = new CWin32Window();
00130 win->Create(strName, nWidth, nHeight, nColourDepth, bFullScreen);
00131
00132 AttachRenderTarget( *win );
00133
00134 if (!m_bGLInitialized)
00135 {
00136
00137 InitGL();
00138 }
00139
00140 return win;
00141 }
00142
00143
00144 void COGLRenderSystem::InitGL(void)
00145 {
00146 ILogger::Log("--> Initialise OpenGL");
00147
00148
00149 m_strExtensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
00150
00151
00152 LoadExtensions();
00153
00154
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
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
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
00217 if (CheckExtension("GL_SGIS_generate_mipmap"))
00218 {
00219 m_pCapabilities->SetCapability(CAP_HW_MIPMAPPING);
00220 }
00221
00222 if (CheckExtension("GL_ARB_texture_compression") && CheckExtension("GL_EXT_texture_compression_s3tc"))
00223 {
00224 m_pCapabilities->SetCapability(CAP_TEXTURE_COMPRESSION_DXT);
00225 }
00226
00227 if (CheckExtension("GL_ARB_texture_non_power_of_two"))
00228 {
00229 m_pCapabilities->SetCapability(CAP_NON_POWER_OF_2_TEXTURES);
00230 }
00231
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
00241 m_pCapabilities->SetNumTextureUnits(1);
00242 }
00243
00244
00245 if (CheckExtension("GL_ARB_vertex_program"))
00246 {
00247 m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
00248
00249
00250 m_pCapabilities->SetMaxVertexProgramVersion("arbvp1");
00251
00252
00253
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
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
00277 ILogger::Log("ATI fragment shader not supported by Keos Engine (Cg Compiler)");
00278
00279
00280
00281
00282
00283
00284
00285
00286 }
00287
00288 if (CheckExtension("GL_ARB_fragment_program"))
00289 {
00290 m_pCapabilities->SetCapability(CAP_FRAGMENT_PROGRAM);
00291
00292 m_pCapabilities->SetMaxFragmentProgramVersion("arbfp1");
00293
00294
00295
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
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
00334 }
00335
00336
00337 IBufferBase* COGLRenderSystem::_CreateVB(ulong nSize, ulong nStride, ulong nFlags) const
00338 {
00339
00340 uint nVertexBuffer = 0;
00341 glGenBuffersARB(1, &nVertexBuffer);
00342
00343
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
00355 uint nIndexBuffer = 0;
00356 glGenBuffersARB(1, &nIndexBuffer);
00357
00358
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
00369 COGLDeclaration* Declaration = new COGLDeclaration;
00370
00371
00372 std::vector<int> Offset(nCount, 0);
00373 for (const TDeclarationElement* Elt = Elements; Elt < Elements + nCount; ++Elt)
00374 {
00375
00376 COGLDeclaration::TElement CurrentElement;
00377 CurrentElement.Usage = Elt->Usage;
00378 CurrentElement.Type = Elt->DataType;
00379 CurrentElement.Offset = Offset[Elt->Stream];
00380
00381
00382 Declaration->AddElement(Elt->Stream, CurrentElement);
00383
00384
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
00400 const COGLVertexBuffer* pVertexBuffer = static_cast<const COGLVertexBuffer*>(pBuffer);
00401 glBindBufferARB(GL_ARRAY_BUFFER_ARB, pVertexBuffer->GetBuffer());
00402
00403
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
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
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
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
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
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
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
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
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
00482 glEnableClientState(GL_INDEX_ARRAY);
00483 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, pIndexBuffer->GetBuffer());
00484
00485
00486 m_nIndexStride = nStride;
00487 }
00488
00489
00490 void COGLRenderSystem::SetDeclaration(const IDeclaration* pDeclaration)
00491 {
00492
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
00504 m_CurrentDeclaration = static_cast<const COGLDeclaration*>(pDeclaration);
00505 }
00506
00507
00508 void COGLRenderSystem::DrawPrimitives(TPrimitiveType Type, ulong nFirstVertex, ulong nCount) const
00509 {
00510
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
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
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
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
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
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
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
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
00830 Col = pLight->GetDiffuseColor();
00831 Col.ToFloat(f4vals);
00832 glLightfv(gl_index, GL_DIFFUSE, f4vals);
00833
00834
00835 Col = pLight->GetSpecularColor();
00836 Col.ToFloat(f4vals);
00837 glLightfv(gl_index, GL_SPECULAR, f4vals);
00838
00839
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
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
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
00879 glEnable(gl_index);
00880 }
00881
00882
00883 glPopMatrix();
00884 }
00885
00886
00887 void COGLRenderSystem::SetFillMode(TFillMode Mode)
00888 {
00889 glPolygonMode(GL_FRONT_AND_BACK, COGLEnum::Get(Mode));
00890 }
00891
00892 }