MercuryOGL.cpp

Go to the documentation of this file.
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     //Only init after we have a window.
00033     InitOpenglApiExtensions();
00034     TestCapabilities();
00035 
00036     glShadeModel(GL_SMOOTH);
00037     glClearColor(0, 0, 0, 1);               // Black Background
00038     glClearDepth(1.0f);                                 // Depth Buffer Setup
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     //Setup VSync
00054     if (m_capabilities.vsync)
00055         wglSwapIntervalEXT(PREFSMAN->GetValueB( "Rendering", "VSync", true, true ));        //VSYNC - currently always 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     //2.0 gets
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     //If we don't have full GLSlang, don't even try to do pixel shaders
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 //  glFlush(); //Finish the scene before the swap
00145 //  glFinish();  //For right now it would seem we actually need this prevent flicker
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 ); // XXX hack turn off emission on multiple passes
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     //vertices VBO
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     //indices VBO
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     //tangent VBO
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     //binormal VBO
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     //glShaderSourceARB requires **
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     // Link the program object and print out the info log...
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 //  bool lUseLight = m_useLights;
00421 //  m_useLights = false;
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     /*  Passing pointers to classes (or floats) into openGL is very flaky. Sometimes it
00437         will work just fine, other times it will not. Classes must be aligned to 16 for
00438         casting to function correctly. */
00439 
00440     if (!m_useMaterialColors)
00441         return;
00442 
00443     //This is good measure, in general for if the lighting is turned off
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     //set shader variables
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     //Check to see if the material needs to be pixel shaded.
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     //Turn the pixelshader on
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             //Bind some GLSL variables to GL texel units
00551             // GL texel 0 will be Texel0, GL texel 1 will be Texel1, and so on in GLSL
00552             // fixed functionality textures don't need to be enabled or disabled with shaders
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     //It might be a good idea to just make display take the type of mapping
00594     //and set whatever attibutes it wants.
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         //Bitwise to figure out how to handle UV map modes
00617         if (tA.m_mapMode & 1) // 0001
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) //0010
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         //Bitwise to figure out how to handle UV map modes
00634         if (tA.m_mapMode & 1) // 0001
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) //0010
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     //delete all hanging frame buffer objects BEFORE we kill the
00676     if (mercuryIsSupportFrameBufferObjectEXT)
00677     {
00678         unsigned int i;
00679         unsigned int j;
00680 
00681         for (i = 0; i < n; i++)
00682         {
00683             //if textureNames[i] is in the fboMap hash table
00684             if (m_fboMap.find(textureNames[i]) != m_fboMap.end())
00685             {
00686                 //then delete the FBO for colorID
00687                 //and delete the  RBO for depthID
00688                 glDeleteFramebuffersEXT ( 1, &m_fboMap[textureNames[i]].colorID );
00689                 glDeleteRenderbuffersEXT( 1, &m_fboMap[textureNames[i]].depthID );
00690             }
00691 
00692             //if textureNames[i] is in the fboMap hash table
00693             if (m_fboCubeMap.find(textureNames[i]) != m_fboCubeMap.end())
00694             {
00695                 for (j = 0; j < 1; j++)
00696                 {
00697                     //then delete the FBO for colorID
00698                     //and delete the  RBO for depthID
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);                  // Create The Texture
00717 
00718     // Typical Texture Generation Using Data From The Bitmap
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     // Generate The Texture
00728     unsigned int i = 0; 
00729 
00730     //For now, cube maps use linear filtering
00731     if (data->attrs.m_cube)
00732         isMipmap = false;
00733 
00734     //Mipmaps use this little loop for mipmaps
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         //      LOG.Warn(texture->GetPath() + " has and invalid color byte type.");
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);   // Linear Filtering
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             //non mipmaps don't have mipmaps
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         //      LOG.Warn(texture->GetPath() + " has and invalid color byte type.");
00802                 break;
00803             }
00804 
00805             glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
00806         }
00807         else
00808         {
00809             unsigned int faceLength = data->attrs.m_width * data->attrs.m_height * ColorBytesToSize(data->attrs.m_ColorByteType);
00810 //          faceLength = 0;
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             //non mipmaps don't have mipmaps
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         //      LOG.Warn(TEXTURE->GetPath() + " has and invalid color byte type.");
00861                 break;
00862             }
00863 
00864             glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR);   // Linear Filtering
00865         }
00866     }
00867 }
00868 
00869 void MercuryOGL::ProcessLightsInternal( const MercuryLight* light[3], unsigned int count )
00870 {
00871     static Attenuation atten; //Attenuation Type
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         //Use a transposed viewstack (from LookAt) to set static lights
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             //If a light is not static, load it into the global space
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             //OpenGL does do multiple attenuations per light
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 ) //Light warning; don't worry about it. (remove this when debugging lights)
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     //will never get here
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; //never get here
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; //never get here
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     //save time if we constantly set to the same thing
01083     if (lastPlaneConfig == &planes)
01084         return;
01085 
01086     lastPlaneConfig = &planes;
01087     max = planes.size();
01088     glcplane = GL_CLIP_PLANE0;
01089 
01090     //if there are no clipping planes, leave as it
01091     //tries to inherit from parent settings
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 //  const MVector<MercuryTextChar*> chars = text.GetCharacters();
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     //Turn off any coordinate generation
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 //  glMatrixMode( GL_MODELVIEW );
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 //  glMatrixMode( GL_TEXTURE );
01209 //  glDisable(GL_TEXTURE_2D);
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); //All the documentation says these are boolean values not floats
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  * Copyright (c) 2005-2006 Joshua Allen
01338  * All rights reserved.
01339  *
01340  * Redistribution and use in source and binary forms, with or
01341  * without modification, are permitted provided that the following
01342  * conditions are met:
01343  *  -   Redistributions of source code must retain the above
01344  *      copyright notice, this list of conditions and the following disclaimer.
01345  *  -   Redistributions in binary form must reproduce the above copyright
01346  *      notice, this list of conditions and the following disclaimer in
01347  *      the documentation and/or other materials provided with the distribution.
01348  *  -   Neither the name of the Mercury Engine nor the names of its
01349  *      contributors may be used to endorse or promote products derived from
01350  *      this software without specific prior written permission.
01351  *
01352  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
01353  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
01354  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
01355  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
01356  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
01357  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
01358  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
01359  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
01360  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
01361  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
01362  */

Hosted by SourceForge.net Logo