Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

rendcontext.cpp

Go to the documentation of this file.
00001 // rendcontext.cpp
00002 //
00003 // Copyright (C) 2004, Chris Laurel <claurel@shatters.net>
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 #include "rendcontext.h"
00011 #include "texmanager.h"
00012 #include "gl.h"
00013 #include "glext.h"
00014 #include "vecgl.h"
00015 
00016 
00017 static Mesh::Material defaultMaterial;
00018 
00019 static GLenum GLPrimitiveModes[Mesh::PrimitiveTypeMax] = 
00020 {
00021     GL_TRIANGLES,
00022     GL_TRIANGLE_STRIP,
00023     GL_TRIANGLE_FAN,
00024     GL_LINES,
00025     GL_LINE_STRIP,
00026     GL_POINTS
00027 };
00028 
00029 static GLenum GLComponentTypes[Mesh::FormatMax] = 
00030 {
00031      GL_FLOAT,          // Float1
00032      GL_FLOAT,          // Float2
00033      GL_FLOAT,          // Float3
00034      GL_FLOAT,          // Float4,
00035      GL_UNSIGNED_BYTE,  // UByte4
00036 };
00037 
00038 static int GLComponentCounts[Mesh::FormatMax] =
00039 {
00040      1,  // Float1
00041      2,  // Float2
00042      3,  // Float3
00043      4,  // Float4,
00044      4,  // UByte4
00045 };
00046 
00047 
00048 enum {
00049     TangentAttributeIndex = 6,
00050 };
00051 
00052 
00053 static void
00054 setStandardVertexArrays(const Mesh::VertexDescription& desc,
00055                         void* vertexData);
00056 static void
00057 setExtendedVertexArrays(const Mesh::VertexDescription& desc,
00058                         const void* vertexData);
00059 
00060 
00061 RenderContext::RenderContext() :
00062     material(&defaultMaterial),
00063     locked(false),
00064     renderPass(PrimaryPass)
00065 {
00066 }
00067 
00068 
00069 RenderContext::RenderContext(const Mesh::Material* _material)
00070 {
00071     if (_material == NULL)
00072         material = &defaultMaterial;
00073     else
00074         material = _material;
00075 }
00076 
00077 
00078 static void setVertexArrays(const Mesh::VertexDescription& desc)
00079 {
00080 }
00081 
00082 
00083 void
00084 RenderContext::setMaterial(const Mesh::Material* newMaterial)
00085 {
00086     if (!locked)
00087     {
00088         if (newMaterial == NULL)
00089             newMaterial = &defaultMaterial;
00090 
00091         if (renderPass == PrimaryPass)
00092         {
00093             if (newMaterial != material)
00094             {
00095                 material = newMaterial;
00096                 makeCurrent(*material);
00097             }
00098         }
00099         else if (renderPass == EmissivePass)
00100         {
00101             if (material->maps[Mesh::EmissiveMap] !=
00102                 newMaterial->maps[Mesh::EmissiveMap])
00103             {
00104                 material = newMaterial;
00105                 makeCurrent(*material);
00106             }
00107         }
00108     }
00109 }
00110 
00111 
00112 void
00113 RenderContext::drawGroup(const Mesh::PrimitiveGroup& group)
00114 {
00115     // Skip rendering if this is the emissive pass but there's no
00116     // emissive texture.
00117     if (renderPass == EmissivePass &&
00118         material->maps[Mesh::EmissiveMap] == InvalidResource)
00119     {
00120         return;
00121     }
00122 
00123     glDrawElements(GLPrimitiveModes[(int) group.prim],
00124                    group.nIndices,
00125                    GL_UNSIGNED_INT,
00126                    group.indices);
00127 }
00128 
00129 
00130 FixedFunctionRenderContext::FixedFunctionRenderContext() :
00131     RenderContext(),
00132     blendOn(false),
00133     specularOn(false)
00134 {
00135 }
00136 
00137 
00138 FixedFunctionRenderContext::FixedFunctionRenderContext(const Mesh::Material* _material) :
00139     RenderContext(_material),
00140     blendOn(false),
00141     specularOn(false)
00142 {
00143 }
00144 
00145 
00146 void
00147 FixedFunctionRenderContext::makeCurrent(const Mesh::Material& m)
00148 {
00149     if (getRenderPass() == PrimaryPass)
00150     {
00151         Texture* t = NULL;
00152         if (m.maps[Mesh::DiffuseMap] != InvalidResource)
00153             t = GetTextureManager()->find(m.maps[Mesh::DiffuseMap]);
00154 
00155         if (t == NULL)
00156         {
00157             glDisable(GL_TEXTURE_2D);
00158         }
00159         else
00160         {
00161             glEnable(GL_TEXTURE_2D);
00162             t->bind();
00163         }
00164 
00165         glColor4f(m.diffuse.red(),
00166                   m.diffuse.green(),
00167                   m.diffuse.blue(),
00168                   m.opacity);
00169 
00170         bool blendOnNow = false;
00171         if (m.opacity != 1.0f || (t != NULL && t->hasAlpha()))
00172             blendOnNow = true;
00173 
00174         if (blendOnNow != blendOn)
00175         {
00176             blendOn = blendOnNow;
00177             if (blendOn)
00178             {
00179                 glEnable(GL_BLEND);
00180                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00181                 glDepthMask(GL_FALSE);
00182             }
00183             else
00184             {
00185                 glDisable(GL_BLEND);
00186                 glDepthMask(GL_TRUE);
00187             }
00188         }
00189 
00190         if (m.specular == Color::Black)
00191         {
00192             float matSpecular[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
00193             float zero = 0.0f;
00194             glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
00195             glMaterialfv(GL_FRONT, GL_SHININESS, &zero);
00196             specularOn = false;
00197         }
00198         else
00199         {
00200             float matSpecular[4] = { m.specular.red(),
00201                                      m.specular.green(),
00202                                      m.specular.blue(),
00203                                      0.0f };
00204             glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
00205             glMaterialfv(GL_FRONT, GL_SHININESS, &m.specularPower);
00206             specularOn = true;
00207         }
00208 
00209         {
00210             float matEmissive[4] = { m.emissive.red(),
00211                                      m.emissive.green(),
00212                                      m.emissive.blue(),
00213                                      0.0f };
00214             glMaterialfv(GL_FRONT, GL_EMISSION, matEmissive);
00215         }
00216     }
00217     else if (getRenderPass() == EmissivePass)
00218     {
00219         Texture* t = NULL;
00220         if (m.maps[Mesh::EmissiveMap] != InvalidResource)
00221             t = GetTextureManager()->find(m.maps[Mesh::EmissiveMap]);
00222 
00223         if (t == NULL)
00224         {
00225             glDisable(GL_TEXTURE_2D);
00226         }
00227         else
00228         {
00229             glEnable(GL_TEXTURE_2D);
00230             t->bind();
00231         }
00232     }
00233 }
00234 
00235 
00236 void
00237 FixedFunctionRenderContext::setVertexArrays(const Mesh::VertexDescription& desc, void* vertexData)
00238 {
00239     setStandardVertexArrays(desc, vertexData);
00240 }
00241 
00242 
00243 void
00244 VP_Combiner_RenderContext::setVertexArrays(const Mesh::VertexDescription& desc, void* vertexData)
00245 {
00246     setStandardVertexArrays(desc, vertexData);
00247     setExtendedVertexArrays(desc, vertexData);
00248 }
00249 
00250 
00251 void
00252 VP_FP_RenderContext::setVertexArrays(const Mesh::VertexDescription& desc, void* vertexData)
00253 {
00254     setStandardVertexArrays(desc, vertexData);
00255     setExtendedVertexArrays(desc, vertexData);
00256 }
00257 
00258 
00259 
00260 
00261 void
00262 setStandardVertexArrays(const Mesh::VertexDescription& desc,
00263                         void* vertexData)
00264 {
00265     const Mesh::VertexAttribute& position  = desc.getAttribute(Mesh::Position);
00266     const Mesh::VertexAttribute& normal    = desc.getAttribute(Mesh::Normal);
00267     const Mesh::VertexAttribute& color0    = desc.getAttribute(Mesh::Color0);
00268     const Mesh::VertexAttribute& texCoord0 = desc.getAttribute(Mesh::Texture0);
00269 
00270     // Can't render anything unless we have positions
00271     if (position.format != Mesh::Float3)
00272         return;
00273 
00274     // Set up the vertex arrays
00275     glEnableClientState(GL_VERTEX_ARRAY);
00276     glVertexPointer(3, GL_FLOAT, desc.stride,
00277                     reinterpret_cast<char*>(vertexData) + position.offset);
00278 
00279     // Set up the normal array
00280     switch (normal.format)
00281     {
00282     case Mesh::Float3:
00283         glEnableClientState(GL_NORMAL_ARRAY);
00284         glNormalPointer(GLComponentTypes[(int) normal.format],
00285                         desc.stride,
00286                         reinterpret_cast<char*>(vertexData) + normal.offset);
00287         break;
00288     default:
00289         glDisableClientState(GL_NORMAL_ARRAY);
00290         break;
00291     }
00292 
00293     // Set up the color array
00294     switch (color0.format)
00295     {
00296     case Mesh::Float3:
00297     case Mesh::Float4:
00298     case Mesh::UByte4:
00299         glEnableClientState(GL_COLOR_ARRAY);
00300         glColorPointer(GLComponentCounts[color0.format],
00301                        GLComponentTypes[color0.format],
00302                        desc.stride,
00303                        reinterpret_cast<char*>(vertexData) + color0.offset);
00304         break;
00305     default:
00306         glDisableClientState(GL_COLOR_ARRAY);
00307         break;
00308     }
00309 
00310     // Set up the texture coordinate array
00311     switch (texCoord0.format)
00312     {
00313     case Mesh::Float1:
00314     case Mesh::Float2:
00315     case Mesh::Float3:
00316     case Mesh::Float4:
00317         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00318         glTexCoordPointer(GLComponentCounts[(int) texCoord0.format],
00319                           GLComponentTypes[(int) texCoord0.format],
00320                           desc.stride,
00321                           reinterpret_cast<char*>(vertexData) + texCoord0.offset);
00322         break;
00323     default:
00324         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00325         break;
00326     }
00327 }
00328 
00329 
00330 void
00331 setExtendedVertexArrays(const Mesh::VertexDescription& desc,
00332                         const void* vertexData)
00333 {
00334     const Mesh::VertexAttribute& tangent  = desc.getAttribute(Mesh::Tangent);
00335     const char* vertices = reinterpret_cast<const char*>(vertexData);
00336 
00337     switch (tangent.format)
00338     {
00339     case Mesh::Float3:
00340         glx::glEnableVertexAttribArrayARB(TangentAttributeIndex);
00341         glEnableClientState(GL_NORMAL_ARRAY);
00342         glx::glVertexAttribPointerARB(TangentAttributeIndex,
00343                                       GLComponentCounts[(int) tangent.format],
00344                                       GLComponentTypes[(int) tangent.format],
00345                                       GL_FALSE,
00346                                       desc.stride,
00347                                       vertices + tangent.offset);
00348         break;
00349     default:
00350         glx::glDisableVertexAttribArrayARB(TangentAttributeIndex);
00351         break;
00352     }
00353 }
00354 
00355 
00356 GLSL_RenderContext::GLSL_RenderContext(const LightingState& ls) :
00357     lightingState(ls)
00358 {
00359 }
00360 
00361 
00362 GLSL_RenderContext::GLSL_RenderContext(const LightingState& ls,
00363                                        const Mesh::Material* material) :
00364     lightingState(ls)
00365 {
00366 }
00367   
00368 
00369 
00370 void
00371 GLSL_RenderContext::makeCurrent(const Mesh::Material& m)
00372 {
00373 #if 0
00374     ShaderProperties shadprop;
00375 
00376     Texture* textures[4] = { NULL, NULL, NULL, NULL };
00377     unsigned int nTextures = 0;
00378 
00379     shadprop.nLights = min(ls.nLights, MaxShaderLights);
00380 
00381     // Set up the textures used by this object
00382     Texture* baseTex = NULL;
00383     Texture* bumpTex = NULL;
00384     Texture* specTex = NULL;
00385     Texture* emissiveTex = NULL;
00386 
00387     if (m.maps[Mesh::DiffuseMap] != InvalidResource)
00388     {
00389         baseTex = GetTextureManager()->find(m.maps[Mesh::DiffuseMap]);
00390         if (baseTex != NULL)
00391         {
00392             shadprop.texUsage = ShaderProperties::DiffuseTexture;
00393             textures[nTextures++] = baseTex;
00394         }
00395     }
00396 
00397     if (m.maps[Mesh::NormalMap] != InvalidResource)
00398     {
00399         bumpTex = GetTextureManger()->find(m.maps[Mesh::NormalMap]);
00400         if (bumpTex != NULL)
00401         {
00402             shadprop.texUsage |= ShaderProperties::NormalTexture;
00403             textures[nTextures++] = bumpTex;
00404         }
00405     }
00406 
00407     if (m.specular != Color::Black)
00408     {
00409         shadprop.lightModel = ShaderProperties::SpecularModel;
00410         specTex = GetTextureManager()->find(m.maps[Mesh::SpecularMap]);
00411         if (specTex == NULL)
00412         {
00413             shadprop.texUsage |= ShaderProperties::SpecularInDiffuseAlpha;
00414         }
00415         else
00416         {
00417             shadprop.texUsage |= ShaderProperties::SpecularTexture;
00418             textures[nTextures++] = specTex;
00419         }
00420     }
00421 
00422     if (m.maps[Mesh::EmissiveMap] != InvalidResource)
00423     {
00424         emissiveTex = GetTextureManager()->find(m.maps[Mesh::EmissiveMap]);
00425         if (emissiveTex != NULL)
00426         {
00427             shadprop.texUsage |= ShaderProperties::NightTexture;
00428             textures[nTextures++] = emissiveTex;
00429         }
00430     }
00431 
00432 #if 0    
00433     // Set the shadow information.
00434     // Track the total number of shadows; if there are too many, we'll have
00435     // to fall back to multipass.
00436     unsigned int totalShadows = 0;
00437     for (unsigned int li = 0; li < ls.nLights; li++)
00438     {
00439         if (ls.shadows[li] && !ls.shadows[li]->empty())
00440         {
00441             unsigned int nShadows = (unsigned int) min((size_t) MaxShaderShadows, ls.shadows[li]->size());
00442             shadprop.setShadowCountForLight(li, nShadows);
00443             totalShadows += nShadows;
00444         }
00445     }
00446 #endif
00447 
00448     // Get a shader for the current rendering configuration
00449     CelestiaGLProgram* prog = GetShaderManager().getShader(shadprop);
00450     if (prog == NULL)
00451         return;
00452 
00453     prog->use();
00454 
00455     setLightParameters_GLSL(*prog, shadprop, ls,
00456                             ri.color, ri.specularColor);
00457 
00458     prog->shininess = m.specularPower;
00459     prog->ambientColor = Vec3f(ri.ambientColor.red(), ri.ambientColor.green(),
00460                                ri.ambientColor.blue());
00461     
00462     if (shadprop.texUsage & ShaderProperties::RingShadowTexture)
00463     {
00464         float ringWidth = rings->outerRadius - rings->innerRadius;
00465         prog->ringRadius = rings->innerRadius / radius;
00466         prog->ringWidth = 1.0f / (ringWidth / radius);
00467     }
00468 
00469     if (shadprop.shadowCounts != 0)    
00470         setEclipseShadowShaderConstants(ls, radius, planetMat, *prog);
00471 
00472     glColor(ri.color);
00473 
00474     unsigned int attributes = LODSphereMesh::Normals;
00475     if (ri.bumpTex != NULL)
00476         attributes |= LODSphereMesh::Tangents;
00477     lodSphere->render(context,
00478                       attributes,
00479                       frustum, ri.pixWidth,
00480                       textures[0], textures[1], textures[2], textures[3]);
00481 
00482     glx::glUseProgramObjectARB(0);
00483 
00484 #if 0
00485     Texture* t = NULL;
00486     if (m.maps[Mesh::DiffuseMap] != InvalidResource)
00487         t = GetTextureManager()->find(m.maps[Mesh::DiffuseMap]);
00488 
00489     if (t == NULL)
00490     {
00491         glDisable(GL_TEXTURE_2D);
00492     }
00493     else
00494     {
00495         glEnable(GL_TEXTURE_2D);
00496         t->bind();
00497     }
00498 
00499     glColor4f(m.diffuse.red(),
00500               m.diffuse.green(),
00501               m.diffuse.blue(),
00502               m.opacity);
00503 
00504     bool blendOnNow = false;
00505     if (m.opacity != 1.0f || (t != NULL && t->hasAlpha()))
00506         blendOnNow = true;
00507 
00508     if (blendOnNow != blendOn)
00509     {
00510         blendOn = blendOnNow;
00511         if (blendOn)
00512         {
00513             glEnable(GL_BLEND);
00514             glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00515             glDepthMask(GL_FALSE);
00516         }
00517         else
00518         {
00519             glDisable(GL_BLEND);
00520             glDepthMask(GL_TRUE);
00521         }
00522     }
00523 
00524     if (m.specular == Color::Black)
00525     {
00526         float matSpecular[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
00527         float zero = 0.0f;
00528         glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
00529         glMaterialfv(GL_FRONT, GL_SHININESS, &zero);
00530         specularOn = false;
00531     }
00532     else
00533     {
00534         float matSpecular[4] = { m.specular.red(),
00535                                  m.specular.green(),
00536                                  m.specular.blue(),
00537                                  0.0f };
00538         glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
00539         glMaterialfv(GL_FRONT, GL_SHININESS, &m.specularPower);
00540         specularOn = true;
00541     }
00542 
00543     {
00544         float matEmissive[4] = { m.emissive.red(),
00545                                  m.emissive.green(),
00546                                  m.emissive.blue(),
00547                                  0.0f };
00548         glMaterialfv(GL_FRONT, GL_EMISSION, matEmissive);
00549     }
00550 #endif
00551 #endif
00552 }
00553 
00554 
00555 void
00556 GLSL_RenderContext::setVertexArrays(const Mesh::VertexDescription& desc,
00557                                     void* vertexData)
00558 {
00559 }

Generated on Sat Jan 14 22:30:28 2006 for Celestia by  doxygen 1.4.1