00001 #include "global.h"
00002 #include "MercuryFiles.h"
00003 #include "MercuryUtil.h"
00004 #include "MercuryOGL.h"
00005 #include "MercuryLog.h"
00006 #include "MercuryINI.h"
00007 #include "MercuryMath.h"
00008 #include "MercuryPoly.h"
00009 #include "ShaderComposer.h"
00010
00011 #include "MercuryInput.h"
00012
00013 #include "MercuryOGL_Ext.h"
00014
00015 #define BUFFER_OFFSET(i) ((char*)NULL + (i))
00016
00017 MercuryOGL::MercuryOGL()
00018 :MercuryDisplay()
00019 {
00020 m_shaderProgramID = -1;
00021 }
00022
00023 MercuryOGL::~MercuryOGL()
00024 {
00025 }
00026
00027 bool MercuryOGL::Init(const MString& name, unsigned int width, unsigned int height, unsigned short bpp, bool fullscreen)
00028 {
00029 if ( !MercuryDisplay::Init(name, width, height, bpp, fullscreen) )
00030 return false;
00031
00032
00033 InitOpenglApiExtensions();
00034 TestCapabilities();
00035
00036 glShadeModel(GL_SMOOTH);
00037 glClearColor(0, 0, 0, 1);
00038 glClearDepth(1.0f);
00039 EnableGLState(MGLS_DEPTHTEST | MGLS_DEPTHWRITE);
00040 glDepthFunc(GL_LESS);
00041 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
00042 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
00043
00044 glCullFace(GL_BACK);
00045 glEnable(GL_CULL_FACE);
00046 glEnable(GL_NORMALIZE);
00047
00048 DisableGLState(MGLS_STENCILTEST);
00049
00050 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00051 EnableGLState(MGLS_BLEND);
00052
00053
00054 if (m_capabilities.vsync)
00055 wglSwapIntervalEXT(PREFSMAN->GetValueB( "Rendering", "VSync", true, true ));
00056
00057 if (m_capabilities.pointsprite)
00058 glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, true );
00059
00060 glGetIntegerv(GL_MAX_LIGHTS, &m_maxLights);
00061 LOG.Info(ssprintf("Max number of lights: %d", m_maxLights));
00062
00063 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &m_maxTextures);
00064 LOG.Info(ssprintf("Max number of textures: %d", m_maxTextures));
00065
00066 if (supportAnisotrophy)
00067 {
00068 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &m_maxAnisotropy);
00069 LOG.Info(ssprintf("Max anisotrophy: %d", m_maxAnisotropy));
00070 }
00071
00072
00073 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &m_maxDrawBuffers);
00074 LOG.Info(ssprintf("Max number of draw buffers: %d", m_maxDrawBuffers));
00075 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &m_maxVertexAttributes);
00076 LOG.Info(ssprintf("Max number of vertex attributes: %d", m_maxVertexAttributes));
00077 glGetIntegerv(GL_MAX_TEXTURE_COORDS, &m_maxTextureCoordinates);
00078 LOG.Info(ssprintf("Max number of texture coords: %d", m_maxTextureCoordinates));
00079 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &m_maxShaderVertUniformComponents);
00080 LOG.Info(ssprintf("Max number of vert uniform components: %d", m_maxShaderVertUniformComponents));
00081 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &m_maxShaderFragUniformComponents);
00082 LOG.Info(ssprintf("Max number of frag uniform components: %d", m_maxShaderFragUniformComponents));
00083 MString glslver;
00084 const char* g = (char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
00085 if( g )
00086 glslver = g;
00087 else
00088 glslver = "NO GLSL Available.";
00089 LOG.Info("GLSL version: " + glslver);
00090
00091
00092 if( !m_capabilities.glsl )
00093 DisableGLState(MGLS_SHADER);
00094
00095 isRenderingToDynamicTexture = false;
00096 isRenderingToDynamicCubeMap = false;
00097 isLockRendering = false;
00098
00099 MercuryGLState gls;
00100 gls.Enable(MGLS_ALL);
00101 SetStates(gls);
00102
00103 return true;
00104 }
00105
00106
00107 void MercuryOGL::RendererInfo()
00108 {
00109 LOG.Info(ssprintf("Vendor:%s", glGetString(GL_VENDOR)));
00110 LOG.Info(ssprintf("Render:%s", glGetString(GL_RENDERER)));
00111 LOG.Info(ssprintf("Version:%s", glGetString(GL_VERSION)));
00112 LOG.Info(ssprintf("Extensions:%s", glGetString(GL_EXTENSIONS)));
00113 }
00114
00115 bool MercuryOGL::MakeWindow(const char* title, int width, int height, int bits, bool fullscreenflag)
00116 {
00117 if (m_window == NULL)
00118 {
00119 LOG.Warn( "No window to create self in!" );
00120 return false;
00121 }
00122
00123 if (!m_window->MakeRender(title, width, height, bits, fullscreenflag, RT_OGL))
00124 {
00125 LOG.Warn( "Failed to make Renderer" );
00126 m_window->DestroyWindowAndRender();
00127 return false;
00128 }
00129
00130 MercuryDisplay::MakeWindow(title, width, height, bits, fullscreenflag);
00131
00132 return true;
00133 }
00134
00135 bool MercuryOGL::BeginFrame()
00136 {
00137 glClear(GL_COLOR_BUFFER_BIT*GetGlobalState().GetState(MGLS_CLEARFRAME) | GL_DEPTH_BUFFER_BIT);
00138 return true;
00139 }
00140
00141 bool MercuryOGL::EndFrame()
00142 {
00143 ErrorCheck();
00144
00145
00146 m_window->SwapBuffers();
00147 ++m_framesDrawn;
00148 return true;
00149 }
00150
00151 void MercuryOGL::DrawMesh(const MercuryMesh& mesh)
00152 {
00153 static const int offset = sizeof(MercuryVertex);
00154 int tai = (glGetAttribLocationARB)?(m_shaderProgramID!=-1)?glGetAttribLocationARB( m_shaderProgramID, "tangent" ):-1:-1;
00155 int bai = (glGetAttribLocationARB)?(m_shaderProgramID!=-1)?glGetAttribLocationARB( m_shaderProgramID, "binormal" ):-1:-1;
00156 float* VerticeArray = (float*)mesh.GetVerticePtr();
00157 float* TangentArray = mesh.HasTangents() && (tai>=0) ? (float*)mesh.GetTangentsPtr() : NULL;
00158 float* BinormalArray = mesh.HasBinormals() && (bai>=0) ? (float*)mesh.GetBinormalsPtr() : NULL;
00159 const MercuryMaterial* mat = mesh.GetMaterial();
00160 bool isVBOinited = (mesh.GetCore()!=NULL)?mesh.GetCore()->m_VBOinited:false;
00161
00162 glBindBufferARB(GL_ARRAY_BUFFER_ARB, (unsigned int)mesh.GetVerticesVBO() * isVBOinited);
00163
00164 if ( mat )
00165 {
00166 int texUnit = GL_TEXTURE0_ARB;
00167 for (unsigned int i = 0; i < mat->NumTextures(); ++i)
00168 {
00169 glActiveTextureARBm(texUnit);
00170 glClientActiveTextureARBm(texUnit);
00171 if (isVBOinited)
00172 glTexCoordPointer(2, GL_FLOAT, offset, BUFFER_OFFSET(sizeof(float)*0));
00173 else
00174 glTexCoordPointer(2, GL_FLOAT, offset, VerticeArray);
00175
00176 ++texUnit;
00177 }
00178 }
00179
00180 if (isVBOinited)
00181 {
00182 glNormalPointer(GL_FLOAT, offset, BUFFER_OFFSET(sizeof(float)*2));
00183 glVertexPointer(3, GL_FLOAT, offset, BUFFER_OFFSET(sizeof(float)*5));
00184 }
00185 else
00186 {
00187 glNormalPointer(GL_FLOAT, offset, &VerticeArray[2]);
00188 glVertexPointer(3, GL_FLOAT, offset, &VerticeArray[5]);
00189 }
00190
00191 if ( TangentArray )
00192 {
00193 glEnableVertexAttribArrayARB(tai);
00194 if (isVBOinited)
00195 glBindBufferARB(GL_ARRAY_BUFFER_ARB, (unsigned int)mesh.GetTangentVBO());
00196 glVertexAttribPointerARB(tai, 3, GL_FLOAT, false, 0, isVBOinited?0:TangentArray);
00197 }
00198
00199 if ( BinormalArray )
00200 {
00201 glEnableVertexAttribArrayARB(bai);
00202 if (isVBOinited)
00203 glBindBufferARB(GL_ARRAY_BUFFER_ARB, (unsigned int)mesh.GetBinormalVBO());
00204 glVertexAttribPointerARB(bai, 3, GL_FLOAT, false, 0, isVBOinited?0:BinormalArray);
00205 }
00206
00207 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh.GetIndicesVBO()*isVBOinited);
00208
00209 unsigned int lightIndex = 0;
00210 int tmp = Next3Lights(m_usedLights, lightIndex);
00211 ProcessLightsInternal(m_usedLights, 3);
00212
00213 glDrawElements( ConvertDrawType(mesh.GetDrawType()), mesh.NumIndices(), GL_UNSIGNED_INT, isVBOinited?0:mesh.GetIndicesPtr() );
00214
00215 if (tmp > 0)
00216 {
00217 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00218 glEnable(GL_BLEND);
00219 glBlendFunc(GL_ONE, GL_ONE);
00220 glDepthFunc(GL_LEQUAL);
00221 float e[4];
00222 e[0] = e[1] = e[2] = e[3] = 0.0f;
00223 glMaterialfv( GL_FRONT, GL_EMISSION, e );
00224 while(tmp > 0)
00225 {
00226 tmp = Next3Lights(m_usedLights, lightIndex);
00227 ProcessLightsInternal(m_usedLights, 3);
00228 glDrawElements( ConvertDrawType(mesh.GetDrawType()), mesh.NumIndices(), GL_UNSIGNED_INT, isVBOinited?0:mesh.GetIndicesPtr() );
00229 }
00230 glPopAttrib();
00231 }
00232
00233 m_verticesDrawn += mesh.NumIndices();
00234
00235 if ( TangentArray )
00236 glDisableVertexAttribArrayARB(tai);
00237
00238 if ( BinormalArray )
00239 glDisableVertexAttribArrayARB(bai);
00240
00241 ErrorCheck();
00242 }
00243
00244 void MercuryOGL::GenerateVBO(MercuryMesh& mesh)
00245 {
00246 unsigned int buffers[4];
00247 unsigned int count = 2;
00248
00249 if (mesh.HasTangents())
00250 ++count;
00251 if (mesh.HasBinormals())
00252 ++count;
00253
00254 glGenBuffersARB(count, buffers);
00255
00256
00257 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers[0]);
00258 glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(MercuryVertex)*mesh.NumVertices(), mesh.GetVerticePtr(), GL_STATIC_DRAW_ARB);
00259 mesh.SetVerticesVBO((MVPtr)buffers[0]);
00260
00261
00262 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers[1]);
00263 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(unsigned int)*mesh.NumIndices(), mesh.GetIndicesPtr(), GL_STATIC_DRAW_ARB);
00264 mesh.SetIndicesVBO((MVPtr)buffers[1]);
00265
00266
00267 if (mesh.HasTangents())
00268 {
00269 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers[2]);
00270 glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(MercuryPoint)*mesh.NumTangents(), mesh.GetTangentsPtr(), GL_STATIC_DRAW_ARB);
00271 mesh.SetTangentVBO((MVPtr)buffers[2]);
00272 }
00273
00274
00275 if (mesh.HasBinormals())
00276 {
00277 glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers[3]);
00278 glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(MercuryPoint)*mesh.NumBinormals(), mesh.GetBinormalsPtr(), GL_STATIC_DRAW_ARB);
00279 mesh.SetBinormalVBO((MVPtr)buffers[3]);
00280 }
00281
00282 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
00283 }
00284
00285 void MercuryOGL::DestroyVBO(MercuryMesh& mesh)
00286 {
00287 unsigned int v, t, b, i;
00288 v = (unsigned int)mesh.GetVerticesVBO();
00289 t = (unsigned int)mesh.GetTangentVBO();
00290 b = (unsigned int)mesh.GetBinormalVBO();
00291 i = (unsigned int)mesh.GetIndicesVBO();
00292
00293 glDeleteBuffersARB(1, &v);
00294 mesh.SetVerticesVBO((MVPtr)NULL);
00295
00296 if (mesh.HasTangents())
00297 {
00298 glDeleteBuffersARB(1, &t);
00299 mesh.SetTangentVBO((MVPtr)NULL);
00300 }
00301
00302 if (mesh.HasBinormals())
00303 {
00304 glDeleteBuffersARB(1, &b);
00305 mesh.SetBinormalVBO((MVPtr)NULL);
00306 }
00307
00308 glDeleteBuffersARB(1, &i);
00309 mesh.SetIndicesVBO((MVPtr)NULL);
00310 }
00311
00312
00313 int MercuryOGL::CompileShader(MString vertStr, MString fragStr)
00314 {
00315 if( !GetGlobalState().GetState(MGLS_SHADER) )
00316 return -1;
00317 int programObj;
00318 int vertexShader;
00319 char *tmpString = NULL;
00320 int stringLength = 0;
00321 const char* vertexShaderStrings[1];
00322 const char* fragmentShaderStrings[1];
00323 GLint bVertCompiled;
00324 GLint bFragCompiled;
00325 GLint bLinked;
00326
00327
00328 vertexShaderStrings[0] = vertStr.c_str();
00329 vertexShader = glCreateShaderObjectARB( GL_VERTEX_SHADER_ARB );
00330 glShaderSourceARB( vertexShader, 1, vertexShaderStrings, NULL );
00331 glCompileShaderARB( vertexShader );
00332
00333
00334 glGetObjectParameterivARB( vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &bVertCompiled );
00335 glGetObjectParameterivARB( vertexShader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &stringLength );
00336 if ( stringLength > 1 )
00337 {
00338 tmpString = new char[stringLength];
00339 glGetInfoLogARB( vertexShader, stringLength, NULL, tmpString );
00340 LOG.Info( MString("SGLLang Vertex Shader Compile Log:") + tmpString );
00341 SAFE_DELETE( tmpString );
00342 }
00343
00344 int fragmentShader = glCreateShaderObjectARB( GL_FRAGMENT_SHADER_ARB );
00345 fragmentShaderStrings[0] = (char*)fragStr.c_str();
00346 glShaderSourceARB( fragmentShader, 1, fragmentShaderStrings, NULL );
00347 glCompileShaderARB( fragmentShader );
00348
00349 glGetObjectParameterivARB( fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &bFragCompiled );
00350 glGetObjectParameterivARB( fragmentShader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &stringLength );
00351 if ( stringLength > 1 )
00352 {
00353 tmpString = new char[stringLength];
00354 glGetInfoLogARB( fragmentShader, stringLength, NULL, tmpString );
00355 LOG.Info(MString("SGLLang Fragment Shader Compile Log:") + tmpString);
00356 SAFE_DELETE( tmpString );
00357 }
00358
00359 programObj = glCreateProgramObjectARB();
00360 glAttachObjectARB( programObj, vertexShader );
00361 glAttachObjectARB( programObj, fragmentShader );
00362
00363
00364
00365
00366 glLinkProgramARB( programObj );
00367 glGetObjectParameterivARB( programObj, GL_OBJECT_LINK_STATUS_ARB, &bLinked );
00368 glGetObjectParameterivARB( programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &stringLength );
00369 if ( stringLength > 1 )
00370 {
00371 tmpString = new char[stringLength];
00372 glGetInfoLogARB( programObj, stringLength, NULL, tmpString );
00373 LOG.Info(MString("SGLLang Linker Log:") + tmpString);
00374 SAFE_DELETE( tmpString );
00375 }
00376
00377 return programObj;
00378 }
00379
00380 void MercuryOGL::DestroyShaderProgram(int shaderID)
00381 {
00382 int count = 0;
00383 unsigned int *objects = NULL;
00384 glGetObjectParameterivARB(shaderID, GL_OBJECT_ATTACHED_OBJECTS_ARB, &count);
00385 if (count > 0)
00386 {
00387 objects = new unsigned int[count];
00388 glGetAttachedObjectsARB(shaderID, count, NULL, objects);
00389 for (unsigned int i = 0; i < count; ++i)
00390 {
00391 glDetachObjectARB(shaderID, objects[i]);
00392 glDeleteObjectARB(objects[i]);
00393 }
00394 }
00395 glDeleteObjectARB(shaderID);
00396 SAFE_DELETE(objects);
00397 }
00398
00399 void MercuryOGL::CompileShader(unsigned int shaderDesc)
00400 {
00401 if( GetGlobalState().GetState(MGLS_SHADER) == 0 )
00402 return;
00403 int programObj;
00404 MString vertStr;
00405 MString fragStr;
00406
00407 vertStr = ComposeGLSLangVertexshader(shaderDesc).c_str();
00408 fragStr = ComposeGLSLangPixelshader (shaderDesc).c_str();
00409
00410 programObj = CompileShader (vertStr, fragStr);
00411
00412 m_shaderObjMap[shaderDesc].id = programObj;
00413
00414
00415 m_shaderObjMap[shaderDesc].primaryTexture = glGetUniformLocationARB( programObj, "regTexSampler2D" );
00416 }
00417
00418 void MercuryOGL::DrawParticleField(const MercuryParticleField* field)
00419 {
00420
00421
00422
00423
00424 unsigned int lightIndex = 0;
00425 int tmp = Next3Lights(m_usedLights, lightIndex);
00426 ProcessLightsInternal(m_usedLights, 3);
00427 FOREACH_CONST_Object(field->m_objects, o)
00428 {
00429 SetMaterial( &o->pObject->GetFinalMaterial() );
00430 o->pObject->Draw();
00431 }
00432 }
00433
00434 void MercuryOGL::SetMaterial(const MercuryMaterial* material)
00435 {
00436
00437
00438
00439
00440 if (!m_useMaterialColors)
00441 return;
00442
00443
00444 glColor4fv( material->m_diffuse );
00445
00446 glMaterialfv( GL_FRONT, GL_AMBIENT, material->m_ambient );
00447 glMaterialfv( GL_FRONT, GL_DIFFUSE, material->m_diffuse );
00448 glMaterialfv( GL_FRONT, GL_SPECULAR, material->m_specular );
00449 glMaterialfv( GL_FRONT, GL_EMISSION, material->m_emissive );
00450
00451 glMaterialf( GL_FRONT, GL_SHININESS, material->m_shininess );
00452 }
00453
00454 void MercuryOGL::SetUniformVariables( MercuryMaterial* material )
00455 {
00456
00457 if ( (m_shaderProgramID != -1) && m_currentState.GetState(MGLS_SHADER) )
00458 {
00459 int uniform_location;
00460
00461 uniform_location = glGetUniformLocationARB(m_shaderProgramID, "eye");
00462 if ( uniform_location != -1 )
00463 glUniform3fARB(uniform_location, m_pLastCameraPos.x, m_pLastCameraPos.y, m_pLastCameraPos.z);
00464
00465 uniform_location = glGetUniformLocationARB(m_shaderProgramID, "NumEnabledLights");
00466 if ( uniform_location != -1 )
00467 glUniform1iARB(uniform_location, m_NumEnabledLights);
00468
00469 uniform_location = glGetUniformLocationARB(m_shaderProgramID, "zNear" );
00470 if ( uniform_location != -1 )
00471 glUniform1fARB(uniform_location, m_projection.m_frustumInfo.m_znear );
00472
00473 uniform_location = glGetUniformLocationARB(m_shaderProgramID, "zFar" );
00474 if ( uniform_location != -1 )
00475 glUniform1fARB(uniform_location, m_projection.m_frustumInfo.m_zfar );
00476
00477 for( unsigned i = 0; i < material->m_vUniformNames.size(); i++ )
00478 {
00479 PStack & psu = material->m_vUniformValues[i];
00480 if( psu.GetSize() == 0 )
00481 continue;
00482 uniform_location = glGetUniformLocationARB(m_shaderProgramID, material->m_vUniformNames[i] );
00483 if ( uniform_location != -1 )
00484 {
00485 if( psu[0].GetType() == PSElement::FLOAT )
00486 {
00487 switch( psu.GetSize() )
00488 {
00489 case 1: glUniform1fARB(uniform_location, psu[0].GetValueF() ); break;
00490 case 2: glUniform2fARB(uniform_location, psu[0].GetValueF(),psu[1].GetValueF() ); break;
00491 case 3: glUniform3fARB(uniform_location, psu[0].GetValueF(),psu[1].GetValueF(),psu[2].GetValueF() ); break;
00492 case 4: glUniform4fARB(uniform_location, psu[0].GetValueF(),psu[1].GetValueF(),psu[2].GetValueF(),psu[3].GetValueF() ); break;
00493 }
00494 } else
00495 {
00496 switch( psu.GetSize() )
00497 {
00498 case 1: glUniform1iARB(uniform_location, psu[0].GetValueI() ); break;
00499 case 2: glUniform2iARB(uniform_location, psu[0].GetValueI(),psu[1].GetValueI() ); break;
00500 case 3: glUniform3iARB(uniform_location, psu[0].GetValueI(),psu[1].GetValueI(),psu[2].GetValueI() ); break;
00501 case 4: glUniform4iARB(uniform_location, psu[0].GetValueI(),psu[1].GetValueI(),psu[2].GetValueI(),psu[3].GetValueI() ); break;
00502 }
00503 }
00504 }
00505 }
00506 }
00507 }
00508
00509 void MercuryOGL::EnableShaders(MercuryMaterial* material)
00510 {
00511
00512 int shaderID = material?material->GetShaderID():-1;
00513 if( !(m_currentState.GetState(MGLS_SHADER) && ( shaderID != -1 )) )
00514 {
00515 BindShader(-1);
00516 return;
00517 }
00518
00519
00520 BindShader(shaderID);
00521 SetUniformVariables( material );
00522 }
00523
00524 void MercuryOGL::EnableTextures(MercuryMaterial* material)
00525 {
00526 static int texUnit;
00527 static int texNum;
00528 static MercuryMatrix tfm;
00529 int sid = material?material->GetShaderID():-1;
00530
00531 texUnit = GL_TEXTURE0_ARB;
00532 for (int i = 0; i < m_maxTextures; ++i)
00533 {
00534 MercuryTexture* t;
00535
00536 glActiveTextureARBm(texUnit);
00537 glClientActiveTextureARBm(texUnit);
00538
00539 if (material!=NULL?(i < material->NumTextures()) && !m_disableTextures:false)
00540 {
00541 t = material->EditTexture(i);
00542 const ImageAttrs& iA = t->GetImageAttributes();
00543
00544 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00545 if (iA.m_cube)
00546 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, iA.m_ID);
00547 else
00548 glBindTexture(GL_TEXTURE_2D, iA.m_ID);
00549
00550
00551
00552
00553 if ( (sid != -1) && m_currentState.GetState(MGLS_SHADER))
00554 {
00555 int uniform_location = glGetUniformLocationARB(sid, ssprintf("Texel%d", i));
00556 glUniform1iARB(uniform_location, i);
00557 }
00558 else if ( t )
00559 {
00560 if (material->GetTexture(i)->GetMapping() != CUBE)
00561 glEnable(GL_TEXTURE_2D);
00562 else
00563 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
00564
00565 ProcessTexture(material->EditTexture(i));
00566 }
00567
00568 if (t)
00569 {
00570 t->Prerender();
00571 tfm = t->GetFinalMatrix();
00572 tfm.Transpose();
00573 glMatrixMode( GL_TEXTURE );
00574 glLoadMatrixf( tfm.Ptr() );
00575 ++texUnit;
00576 }
00577 }
00578 else
00579 {
00580 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00581 glBindTexture(GL_TEXTURE_2D, 0);
00582 glDisable(GL_TEXTURE_2D);
00583 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
00584 }
00585 }
00586 }
00587
00588 void MercuryOGL::ProcessTexture(MercuryTexture* texture)
00589 {
00590 const ImageAttrs& iA = texture->GetImageAttributes();
00591 const TextureAttrs& tA = texture->GetAttributes();
00592
00593
00594
00595 switch(tA.m_mapping)
00596 {
00597 case CUBE:
00598 glDisable(GL_TEXTURE_GEN_S);
00599 glDisable(GL_TEXTURE_GEN_T);
00600 glDisable(GL_TEXTURE_GEN_R);
00601 break;
00602 case SPHERE:
00603 glEnable(GL_TEXTURE_GEN_S);
00604 glEnable(GL_TEXTURE_GEN_T);
00605 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
00606 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
00607 break;
00608 default:
00609 glDisable(GL_TEXTURE_GEN_S);
00610 glDisable(GL_TEXTURE_GEN_T);
00611 break;
00612 }
00613
00614 if (tA.m_mapping != CUBE)
00615 {
00616
00617 if (tA.m_mapMode & 1)
00618 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00619 else
00620 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00621 if (tA.m_mapMode & 2)
00622 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00623 else
00624 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00625
00626 if (tA.m_magFilter == NEAREST)
00627 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
00628 else
00629 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00630 }
00631 else
00632 {
00633
00634 if (tA.m_mapMode & 1)
00635 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT);
00636 else
00637 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00638 if (tA.m_mapMode & 2)
00639 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT);
00640 else
00641 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00642
00643 if (tA.m_magFilter == NEAREST)
00644 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
00645 else
00646 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00647 }
00648
00649 switch (tA.m_blendMode)
00650 {
00651 case BLEND:
00652 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
00653 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture->GetFinalMaterial().m_diffuse);
00654 break;
00655 case MODULATE:
00656 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00657 break;
00658 case DECAL:
00659 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00660 break;
00661 case REPLACE:
00662 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00663 break;
00664 case ADD:
00665 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
00666 break;
00667 case COMBINE:
00668 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
00669 break;
00670 };
00671 }
00672
00673 void MercuryOGL::DeleteTextures(int n, unsigned int* textureNames)
00674 {
00675
00676 if (mercuryIsSupportFrameBufferObjectEXT)
00677 {
00678 unsigned int i;
00679 unsigned int j;
00680
00681 for (i = 0; i < n; i++)
00682 {
00683
00684 if (m_fboMap.find(textureNames[i]) != m_fboMap.end())
00685 {
00686
00687
00688 glDeleteFramebuffersEXT ( 1, &m_fboMap[textureNames[i]].colorID );
00689 glDeleteRenderbuffersEXT( 1, &m_fboMap[textureNames[i]].depthID );
00690 }
00691
00692
00693 if (m_fboCubeMap.find(textureNames[i]) != m_fboCubeMap.end())
00694 {
00695 for (j = 0; j < 1; j++)
00696 {
00697
00698
00699 glDeleteFramebuffersEXT ( 1, &m_fboCubeMap[textureNames[i]].colorID[j] );
00700 glDeleteRenderbuffersEXT( 1, &m_fboCubeMap[textureNames[i]].depthID[j] );
00701 }
00702 }
00703 }
00704 }
00705
00706 glDeleteTextures(n, textureNames);
00707 }
00708
00709 void MercuryOGL::CreateCache(RawImageData* data, unsigned int& ID)
00710 {
00711 CreateCache(data, ID, true);
00712 }
00713
00714 void MercuryOGL::CreateCache(RawImageData* data, unsigned int& ID, bool isMipmap)
00715 {
00716 glGenTextures(1, &ID);
00717
00718
00719 glBindTexture(GL_TEXTURE_2D, ID);
00720 LoadImageData(data, isMipmap);
00721 }
00722
00723 void MercuryOGL::LoadImageData(RawImageData* data, bool isMipmap)
00724 {
00725 RawImageData* rdata1 = data;
00726 RawImageData* rdata2 = NULL;
00727
00728 unsigned int i = 0;
00729
00730
00731 if (data->attrs.m_cube)
00732 isMipmap = false;
00733
00734
00735 if (isMipmap)
00736 {
00737 while (true)
00738 {
00739 switch (data->attrs.m_ColorByteType)
00740 {
00741 case RGB:
00742 glTexImage2D(GL_TEXTURE_2D, i, GL_RGB, rdata1->attrs.m_width, rdata1->attrs.m_height,
00743 0, GL_RGB, GL_UNSIGNED_BYTE, rdata1->data);
00744 break;
00745 case RGBA:
00746 glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00747 0, GL_RGBA, GL_UNSIGNED_BYTE, rdata1->data);
00748 break;
00749 case LUMINANCE_ALPHA:
00750 glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00751 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rdata1->data);
00752 break;
00753 default:
00754
00755 break;
00756 }
00757
00758 rdata2 = new RawImageData;
00759
00760 if ((rdata1->attrs.m_height > 1) || (rdata1->attrs.m_width > 1))
00761 CaclulateDiv2Texture(*rdata1, *rdata2);
00762 else
00763 break;
00764
00765 if (rdata1 != data)
00766 SAFE_DELETE(rdata1);
00767
00768 rdata1 = rdata2;
00769 rdata2 = NULL;
00770 ++i;
00771 }
00772
00773 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
00774
00775 if (supportAnisotrophy)
00776 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
00777 PREFSMAN->GetValueI("Rendering", "Anisotrophy", 1, true));
00778
00779 SAFE_DELETE(rdata1);
00780 }
00781 else
00782 {
00783 if (!data->attrs.m_cube)
00784 {
00785
00786 switch (data->attrs.m_ColorByteType)
00787 {
00788 case RGB:
00789 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rdata1->attrs.m_width, rdata1->attrs.m_height,
00790 0, GL_RGB, GL_UNSIGNED_BYTE, rdata1->data);
00791 break;
00792 case RGBA:
00793 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00794 0, GL_RGBA, GL_UNSIGNED_BYTE, rdata1->data);
00795 break;
00796 case LUMINANCE_ALPHA:
00797 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00798 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rdata1->data);
00799 break;
00800 default:
00801
00802 break;
00803 }
00804
00805 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00806 }
00807 else
00808 {
00809 unsigned int faceLength = data->attrs.m_width * data->attrs.m_height * ColorBytesToSize(data->attrs.m_ColorByteType);
00810
00811
00812 printf ("pdata = %lu\nfaceLength = %lu\nwidth = %lu\nheight = %lu\ncolorbytes = %lu\n", rdata1->data, faceLength, data->attrs.m_width, data->attrs.m_height, (unsigned int)(ColorBytesToSize(data->attrs.m_ColorByteType)));
00813
00814
00815 switch (data->attrs.m_ColorByteType)
00816 {
00817 case RGB:
00818 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, GL_RGB, rdata1->attrs.m_width, rdata1->attrs.m_height,
00819 0, GL_RGB, GL_UNSIGNED_BYTE, rdata1->data);
00820 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_RGB, rdata1->attrs.m_width, rdata1->attrs.m_height,
00821 0, GL_RGB, GL_UNSIGNED_BYTE, rdata1->data + faceLength);
00822 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, GL_RGB, rdata1->attrs.m_width, rdata1->attrs.m_height,
00823 0, GL_RGB, GL_UNSIGNED_BYTE, rdata1->data + 2*faceLength);
00824 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, GL_RGB, rdata1->attrs.m_width, rdata1->attrs.m_height,
00825 0, GL_RGB, GL_UNSIGNED_BYTE, rdata1->data + 3*faceLength);
00826 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, GL_RGB, rdata1->attrs.m_width, rdata1->attrs.m_height,
00827 0, GL_RGB, GL_UNSIGNED_BYTE, rdata1->data + 4*faceLength);
00828 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, GL_RGB, rdata1->attrs.m_width, rdata1->attrs.m_height,
00829 0, GL_RGB, GL_UNSIGNED_BYTE, rdata1->data + 5*faceLength);
00830 break;
00831 case RGBA:
00832 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00833 0, GL_RGBA, GL_UNSIGNED_BYTE, rdata1->data);
00834 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00835 0, GL_RGBA, GL_UNSIGNED_BYTE, rdata1->data + faceLength);
00836 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00837 0, GL_RGBA, GL_UNSIGNED_BYTE, rdata1->data + 2*faceLength);
00838 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00839 0, GL_RGBA, GL_UNSIGNED_BYTE, rdata1->data + 3*faceLength);
00840 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00841 0, GL_RGBA, GL_UNSIGNED_BYTE, rdata1->data + 4*faceLength);
00842 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00843 0, GL_RGBA, GL_UNSIGNED_BYTE, rdata1->data + 5*faceLength);
00844 break;
00845 case LUMINANCE_ALPHA:
00846 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00847 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rdata1->data);
00848 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00849 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rdata1->data + faceLength);
00850 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00851 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rdata1->data + 2*faceLength);
00852 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00853 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rdata1->data + 3*faceLength);
00854 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00855 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rdata1->data + 4*faceLength);
00856 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, GL_RGBA, rdata1->attrs.m_width, rdata1->attrs.m_height,
00857 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rdata1->data + 5*faceLength);
00858 break;
00859 default:
00860
00861 break;
00862 }
00863
00864 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00865 }
00866 }
00867 }
00868
00869 void MercuryOGL::ProcessLightsInternal( const MercuryLight* light[3], unsigned int count )
00870 {
00871 static Attenuation atten;
00872 static unsigned int AT;
00873 static float fLightPos[4];
00874 static unsigned int LID;
00875 static MercuryMatrix tmpView;
00876
00877 m_NumEnabledLights = 0;
00878 LID = GL_LIGHT0;
00879
00880 if (m_currentState.GetState(MGLS_LIGHTING))
00881 {
00882
00883 tmpView = m_view;
00884 tmpView.Transpose();
00885 glMatrixMode( GL_MODELVIEW );
00886 glPushMatrix();
00887 glLoadMatrixf( tmpView.Ptr() );
00888
00889 for (unsigned int i = 0; i < count; ++i)
00890 {
00891 if (!light[i])
00892 {
00893 glDisable(LID);
00894 continue;
00895 }
00896
00897 const MercuryMaterial& m = light[i]->GetFinalMaterial();
00898
00899 light[i]->GetPosition().ConvertToVector3(fLightPos);
00900 fLightPos[3] = (float)light[i]->GetLightType();
00901
00902
00903 if (!light[i]->IsStatic())
00904 {
00905 glPushMatrix();
00906 glLoadIdentity();
00907 }
00908
00909 glLightfv(LID, GL_POSITION, fLightPos);
00910 glLightfv(LID, GL_AMBIENT, m.m_ambient);
00911 glLightfv(LID, GL_DIFFUSE, m.m_diffuse);
00912 glLightfv(LID, GL_SPECULAR, m.m_specular);
00913
00914
00915 for (unsigned int j = 0; j < 3; ++j)
00916 {
00917 atten = light[i]->GetAttenuation((Attenuation::Type)j);
00918 switch (atten.type)
00919 {
00920 case Attenuation::CONSTANT:
00921 AT = GL_CONSTANT_ATTENUATION;
00922 break;
00923 case Attenuation::LINEAR:
00924 AT = GL_LINEAR_ATTENUATION;
00925 break;
00926 case Attenuation::QUADRATIC:
00927 AT = GL_QUADRATIC_ATTENUATION;
00928 break;
00929 }
00930 glLightf(LID, AT, atten.value);
00931 }
00932 glEnable(LID);
00933 ++m_NumEnabledLights;
00934
00935 if (!light[i]->IsStatic())
00936 glPopMatrix();
00937
00938 ++LID;
00939 }
00940
00941 glPopMatrix();
00942 }
00943
00944 if (m_shaderProgramID != -1)
00945 {
00946 int uniform_location = glGetUniformLocationARB(m_shaderProgramID, "NumEnabledLights");
00947 if ( uniform_location != -1 )
00948 glUniform1iARB(uniform_location, m_NumEnabledLights);
00949 }
00950 }
00951
00952 void MercuryOGL::ErrorCheck()
00953 {
00954 static int error;
00955 while ((error = glGetError()) != GL_NO_ERROR)
00956 if( error != 1282 )
00957 LOG.Warn(ssprintf("OGL Error: %d", error));
00958 }
00959
00960 void MercuryOGL::ReadFrameBuffer(RawImageData& image)
00961 {
00962 image.attrs.m_ColorByteType = RGB;
00963 image.attrs.m_dpi_x = 72;
00964 image.attrs.m_dpi_y = 72;
00965 image.attrs.m_height = m_window->GetHeight();
00966 image.attrs.m_width = m_window->GetWidth();
00967 image.data = new unsigned char[image.attrs.m_height * image.attrs.m_width * 3];
00968 glReadPixels(0,0, image.attrs.m_width, image.attrs.m_height, GL_RGB, GL_UNSIGNED_BYTE, image.data);
00969 }
00970
00971 void MercuryOGL::SendMatrixData(const MercuryMatrix& m)
00972 {
00973 static MercuryMatrix modelView;
00974
00975 modelView = m_view * m;
00976 modelView.Transpose();
00977
00978 glMatrixMode( GL_MODELVIEW );
00979 glLoadMatrixf( modelView.Ptr() );
00980 }
00981
00982 void MercuryOGL::SendProjectionMatrixData()
00983 {
00984 static MercuryMatrix projection;
00985
00986 projection = GetProjection();
00987 projection.Transpose();
00988
00989 glMatrixMode( GL_PROJECTION );
00990 glLoadMatrixf( projection.Ptr() );
00991 };
00992
00993
00994 int MercuryOGL::ConvertDrawType(DRAWTYPES drawtype)
00995 {
00996 switch(drawtype)
00997 {
00998 case MGL_TRIANGLE:
00999 return GL_TRIANGLES;
01000 case MGL_QUAD:
01001 return GL_QUADS;
01002 case MGL_POINT:
01003 return GL_POINT;
01004 default:
01005 ASSERT(drawtype != MGL_INVALID);
01006 };
01007
01008 return -1;
01009 }
01010
01011 void MercuryOGL::StencilOp(STENCILOPS fail, STENCILOPS zfail, STENCILOPS zpass)
01012 {
01013 glStencilOp( ConvertStencilOp(fail),
01014 ConvertStencilOp(zfail),
01015 ConvertStencilOp(zpass) );
01016 }
01017
01018 int MercuryOGL::ConvertStencilOp(STENCILOPS op) const
01019 {
01020 switch (op)
01021 {
01022 case SO_KEEP:
01023 return GL_KEEP;
01024 case S0_ZERO:
01025 return GL_ZERO;
01026 case S0_REPLACE:
01027 return GL_REPLACE;
01028 case SO_INCR:
01029 return GL_INCR;
01030 case SO_DECR:
01031 return GL_DECR;
01032 case SO_INVERT:
01033 return GL_INVERT;
01034 }
01035 return 0;
01036 }
01037
01038 void MercuryOGL::CullBackface(bool toggle)
01039 {
01040 if (toggle)
01041 glCullFace(GL_BACK);
01042 else
01043 glCullFace(GL_FRONT);
01044 }
01045
01046 void MercuryOGL::StencilFunc(TFUNCT func, int ref, unsigned int zref)
01047 {
01048 glStencilFunc(ConvertTestFunction(func), ref, zref);
01049 }
01050
01051 int MercuryOGL::ConvertTestFunction(TFUNCT funct) const
01052 {
01053 switch(funct)
01054 {
01055 case TF_NEVER:
01056 return GL_NEVER;
01057 case TF_LESS:
01058 return GL_LESS;
01059 case TF_LEQUAL:
01060 return GL_LEQUAL;
01061 case TF_GREATER:
01062 return GL_GREATER;
01063 case TF_GEQUAL:
01064 return GL_GEQUAL;
01065 case TF_EQUAL:
01066 return GL_EQUAL;
01067 case TF_NOTEQUAL:
01068 return GL_NOTEQUAL;
01069 case TF_ALWAYS:
01070 return GL_ALWAYS;
01071 }
01072 return 0;
01073 }
01074
01075 void MercuryOGL::DefineClippingPlanes(const MVector<MQuaternion>& planes)
01076 {
01077 static int max;
01078 static int glcplane;
01079 static double plane[4];
01080 static const MVector<MQuaternion>* lastPlaneConfig = NULL;
01081
01082
01083 if (lastPlaneConfig == &planes)
01084 return;
01085
01086 lastPlaneConfig = &planes;
01087 max = planes.size();
01088 glcplane = GL_CLIP_PLANE0;
01089
01090
01091
01092 if (max <= 0)
01093 return;
01094
01095 for (int i = 0; i < 6; ++i)
01096 {
01097 if (i < max)
01098 {
01099 plane[0] = planes[i].w;
01100 plane[1] = planes[i].x;
01101 plane[2] = planes[i].y;
01102 plane[3] = planes[i].z;
01103 glEnable(glcplane);
01104 glClipPlane(glcplane, plane);
01105 }
01106 else
01107 {
01108 glDisable(glcplane);
01109 }
01110 ++glcplane;
01111 }
01112 }
01113
01114 void MercuryOGL::RenderTranslucentObject()
01115 {
01116 PushGLState();
01117 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01118 glDepthMask(false);
01119 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01120 while (!m_translucentObjects.empty())
01121 {
01122 m_translucentObjects.front().obj->CustomRender();
01123 m_translucentObjects.pop_front();
01124 }
01125 glPopAttrib();
01126 PopGLState();
01127 }
01128
01129 void MercuryOGL::TestCapabilities()
01130 {
01131 m_capabilities.glsl = glCreateProgramObjectARB && glDeleteObjectARB && glUseProgramObjectARB &&
01132 glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB &&
01133 glGetObjectParameterivARB && glAttachObjectARB && glGetInfoLogARB &&
01134 glGetInfoLogARB && glLinkProgramARB && glLinkProgramARB &&
01135 glGetUniformLocationARB && glUniform4fARB && glUniform1iARB;
01136
01137 m_capabilities.multittexture = glMultiTexCoord1fARBm && glMultiTexCoord2fARBm && glMultiTexCoord3fARBm &&
01138 glMultiTexCoord4fARBm && glActiveTextureARBm && glClientActiveTextureARBm;
01139 ASSERT(m_capabilities.multittexture);
01140
01141 m_capabilities.pointsprite = glPointParameterfARB && glPointParameterfvARB;
01142
01143 m_capabilities.vbo = glBindBufferARB && glGenBuffersARB && glBufferDataARB;
01144
01145 m_capabilities.vsync = wglSwapIntervalEXT != 0;
01146 }
01147
01148 void MercuryOGL::RenderText(const MercuryText& text)
01149 {
01150 MercuryPoint v;
01151 int tid = text.GetGlyphData()->textureData.GetID();
01152
01153 unsigned int size = text.NumCharacters();
01154
01155 glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT);
01156
01157 glActiveTextureARBm(GL_TEXTURE0_ARB);
01158 glClientActiveTextureARBm(GL_TEXTURE0_ARB);
01159 glEnable(GL_TEXTURE_2D);
01160 glBindTexture(GL_TEXTURE_2D, tid );
01161
01162
01163 glDisable(GL_TEXTURE_GEN_S);
01164 glDisable(GL_TEXTURE_GEN_T);
01165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
01166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
01167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01168 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
01169
01170 glMatrixMode( GL_TEXTURE );
01171 glPushMatrix();
01172 glLoadIdentity();
01173
01174
01175 glBegin(GL_QUADS);
01176 for( unsigned int i = 0; i < size; ++i )
01177 {
01178 const MercuryTextChar& c = *text.GetCharacter(i);
01179
01180 glTexCoord2fv( c.vertices[0].m_uv );
01181 v.x = c.vertices[0].x + c.position.x;
01182 v.y = c.vertices[0].y + c.position.y;
01183 v.z = c.vertices[0].z + c.position.z;
01184 glVertex3fv( v );
01185
01186 glTexCoord2fv( c.vertices[1].m_uv );
01187 v.x = c.vertices[1].x + c.position.x;
01188 v.y = c.vertices[1].y + c.position.y;
01189 v.z = c.vertices[1].z + c.position.z;
01190 glVertex3fv( v );
01191
01192 glTexCoord2fv( c.vertices[2].m_uv );
01193 v.x = c.vertices[2].x + c.position.x;
01194 v.y = c.vertices[2].y + c.position.y;
01195 v.z = c.vertices[2].z + c.position.z;
01196 glVertex3fv( v );
01197
01198 glTexCoord2fv( c.vertices[3].m_uv );
01199 v.x = c.vertices[3].x + c.position.x;
01200 v.y = c.vertices[3].y + c.position.y;
01201 v.z = c.vertices[3].z + c.position.z;
01202 glVertex3fv( v );
01203 }
01204 glEnd();
01205 glPopMatrix();
01206 glPopAttrib();
01207
01208
01209
01210 }
01211
01212 void MercuryOGL::DrawSprite(const MercuryMesh& sprite)
01213 {
01214 glBegin(GL_QUADS);
01215 glTexCoord2fv( sprite[0].m_uv );
01216 glNormal3fv(sprite[0].GetNormal());
01217 glVertex3fv( &(sprite[0].x) );
01218
01219 glTexCoord2fv( sprite[1].m_uv );
01220 glNormal3fv(sprite[1].GetNormal());
01221 glVertex3fv( &(sprite[1].x) );
01222
01223 glTexCoord2fv( sprite[2].m_uv );
01224 glNormal3fv(sprite[2].GetNormal());
01225 glVertex3fv( &(sprite[2].x) );
01226
01227 glTexCoord2fv( sprite[3].m_uv );
01228 glNormal3fv(sprite[3].GetNormal());
01229 glVertex3fv( &(sprite[3].x) );
01230 glEnd();
01231 m_verticesDrawn += 4;
01232 }
01233
01234 MercuryGLState MercuryOGL::SetStates(MercuryGLState states)
01235 {
01236 MercuryGLState changedState = MercuryDisplay::SetStates(states);
01237 unsigned long changed = changedState.GetStates();
01238
01239 if (!changed)
01240 return changedState;
01241
01242 unsigned long current = m_currentState.GetStates();
01243
01244 if (changed&MGLS_DEPTHWRITE)
01245 glDepthMask(current&MGLS_DEPTHWRITE);
01246
01247 if (changed&MGLS_DEPTHTEST)
01248 {
01249 if(current&MGLS_DEPTHTEST)
01250 glEnable(GL_DEPTH_TEST);
01251 else
01252 glDisable(GL_DEPTH_TEST);
01253 }
01254
01255 if (changed&MGLS_COLORWRITE)
01256 {
01257 bool cm = current&MGLS_COLORWRITE;
01258 glColorMask(cm, cm, cm, cm);
01259 }
01260
01261 if (changed&MGLS_ALPHATEST)
01262 {
01263 if(current&MGLS_ALPHATEST)
01264 glEnable(GL_ALPHA_TEST);
01265 else
01266 glDisable(GL_ALPHA_TEST);
01267 }
01268
01269 if (changed&MGLS_BLEND)
01270 {
01271 if (current&MGLS_BLEND)
01272 glEnable(GL_BLEND);
01273 else
01274 glDisable(GL_BLEND);
01275 }
01276
01277 if (changed&MGLS_VERTEXARRAY)
01278 {
01279 if (current&MGLS_VERTEXARRAY)
01280 glEnableClientState(GL_VERTEX_ARRAY);
01281 else
01282 glDisableClientState(GL_VERTEX_ARRAY);
01283 }
01284
01285 if (changed&MGLS_NORMALARRAY)
01286 {
01287 if (current&MGLS_NORMALARRAY)
01288 glEnableClientState(GL_NORMAL_ARRAY);
01289 else
01290 glDisableClientState(GL_NORMAL_ARRAY);
01291 }
01292
01293 if (changed&MGLS_UVARRAY)
01294 {
01295 }
01296
01297 if (changed&MGLS_TEXTURING)
01298 {
01299 }
01300
01301 if (changed&MGLS_LIGHTING)
01302 {
01303 if (current&MGLS_LIGHTING)
01304 glEnable(GL_LIGHTING);
01305 else
01306 glDisable(GL_LIGHTING);
01307 }
01308
01309 if (changed&MGLS_STENCILTEST)
01310 {
01311 if (current&MGLS_STENCILTEST)
01312 glEnable(GL_STENCIL_TEST);
01313 else
01314 glDisable(GL_STENCIL_TEST);
01315 }
01316
01317 if (changed&MGLS_SHADER)
01318 if ( !m_currentState.GetState(MGLS_SHADER) )
01319 BindShader(-1);
01320
01321 return changedState;
01322 }
01323
01324 void MercuryOGL::BindShader(int shaderID)
01325 {
01326 if (m_shaderProgramID != shaderID)
01327 {
01328 if (shaderID == -1)
01329 glUseProgramObjectARB(0);
01330 else
01331 glUseProgramObjectARB(shaderID);
01332 }
01333 m_shaderProgramID = shaderID;
01334 }
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362