rendcontext.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:28k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // rendcontext.cpp
  2. //
  3. // Copyright (C) 2004-2009, the Celestia Development Team
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. #include <vector>
  10. #include "rendcontext.h"
  11. #include "texmanager.h"
  12. #include "gl.h"
  13. #include "glext.h"
  14. #include "vecgl.h"
  15. using namespace std;
  16. static Mesh::Material defaultMaterial;
  17. static GLenum GLPrimitiveModes[Mesh::PrimitiveTypeMax] =
  18. {
  19.     GL_TRIANGLES,
  20.     GL_TRIANGLE_STRIP,
  21.     GL_TRIANGLE_FAN,
  22.     GL_LINES,
  23.     GL_LINE_STRIP,
  24.     GL_POINTS,
  25.     GL_POINTS,
  26. };
  27. static GLenum GLComponentTypes[Mesh::FormatMax] =
  28. {
  29.      GL_FLOAT,          // Float1
  30.      GL_FLOAT,          // Float2
  31.      GL_FLOAT,          // Float3
  32.      GL_FLOAT,          // Float4,
  33.      GL_UNSIGNED_BYTE,  // UByte4
  34. };
  35. static int GLComponentCounts[Mesh::FormatMax] =
  36. {
  37.      1,  // Float1
  38.      2,  // Float2
  39.      3,  // Float3
  40.      4,  // Float4,
  41.      4,  // UByte4
  42. };
  43. enum {
  44.     TangentAttributeIndex = 6,
  45.     PointSizeAttributeIndex = 7,
  46. };
  47. static void
  48. setStandardVertexArrays(const Mesh::VertexDescription& desc,
  49.                         void* vertexData);
  50. static void
  51. setExtendedVertexArrays(const Mesh::VertexDescription& desc,
  52.                         const void* vertexData);
  53. RenderContext::RenderContext() :
  54.     material(&defaultMaterial),
  55.     locked(false),
  56.     renderPass(PrimaryPass),
  57.     pointScale(1.0f),
  58.     usePointSize(false),
  59.     useNormals(true),
  60.     useColors(false),
  61.     useTexCoords(true)
  62. {
  63. }
  64. RenderContext::RenderContext(const Mesh::Material* _material)
  65. {
  66.     if (_material == NULL)
  67.         material = &defaultMaterial;
  68.     else
  69.         material = _material;
  70. }
  71. const Mesh::Material*
  72. RenderContext::getMaterial() const
  73. {
  74.     return material;
  75. }
  76. void
  77. RenderContext::setMaterial(const Mesh::Material* newMaterial)
  78. {
  79.     if (!locked)
  80.     {
  81.         if (newMaterial == NULL)
  82.             newMaterial = &defaultMaterial;
  83.         if (renderPass == PrimaryPass)
  84.         {
  85.             if (newMaterial != material)
  86.             {
  87.                 material = newMaterial;
  88.                 makeCurrent(*material);
  89.             }
  90.         }
  91.         else if (renderPass == EmissivePass)
  92.         {
  93.             if (material->maps[Mesh::EmissiveMap] !=
  94.                 newMaterial->maps[Mesh::EmissiveMap])
  95.             {
  96.                 material = newMaterial;
  97.                 makeCurrent(*material);
  98.             }
  99.         }
  100.     }
  101. }
  102. void
  103. RenderContext::setPointScale(float _pointScale)
  104. {
  105.     pointScale = _pointScale;
  106. }
  107. float
  108. RenderContext::getPointScale() const
  109. {
  110.     return pointScale;
  111. }
  112. void
  113. RenderContext::setCameraOrientation(const Quatf& q)
  114. {
  115.     cameraOrientation = q;
  116. }
  117. Quatf
  118. RenderContext::getCameraOrientation() const
  119. {
  120.     return cameraOrientation;
  121. }
  122. void
  123. RenderContext::drawGroup(const Mesh::PrimitiveGroup& group)
  124. {
  125.     // Skip rendering if this is the emissive pass but there's no
  126.     // emissive texture.
  127.     if (renderPass == EmissivePass &&
  128.         material->maps[Mesh::EmissiveMap] == InvalidResource)
  129.     {
  130.         return;
  131.     }
  132.     if (group.prim == Mesh::SpriteList)
  133.     {
  134.         glEnable(GL_POINT_SPRITE_ARB);
  135.         glx::glActiveTextureARB(GL_TEXTURE0_ARB);
  136.         glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
  137.         glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
  138.     }
  139.     glDrawElements(GLPrimitiveModes[(int) group.prim],
  140.                    group.nIndices,
  141.                    GL_UNSIGNED_INT,
  142.                    group.indices);
  143.     if (group.prim == Mesh::SpriteList)
  144.     {
  145.         glDisable(GL_POINT_SPRITE_ARB);
  146.         glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
  147.     }
  148. }
  149. FixedFunctionRenderContext::FixedFunctionRenderContext() :
  150.     RenderContext(),
  151.     blendMode(Mesh::InvalidBlend),
  152.     specularOn(false),
  153.     lightingEnabled(true)
  154. {
  155. }
  156. FixedFunctionRenderContext::FixedFunctionRenderContext(const Mesh::Material* _material) :
  157.     RenderContext(_material),
  158.     blendMode(Mesh::InvalidBlend),
  159.     specularOn(false),
  160.     lightingEnabled(true)
  161. {
  162. }
  163. FixedFunctionRenderContext::~FixedFunctionRenderContext()
  164. {
  165.     glDisableClientState(GL_VERTEX_ARRAY);
  166.     glDisableClientState(GL_NORMAL_ARRAY);
  167.     glDisableClientState(GL_COLOR_ARRAY);
  168.     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  169. }
  170. static int blah = 0;
  171. void
  172. FixedFunctionRenderContext::makeCurrent(const Mesh::Material& m)
  173. {
  174.     if (getRenderPass() == PrimaryPass)
  175.     {
  176.         Texture* t = NULL;
  177.         if (m.maps[Mesh::DiffuseMap] != InvalidResource && useTexCoords)
  178.             t = GetTextureManager()->find(m.maps[Mesh::DiffuseMap]);
  179.         if (t == NULL)
  180.         {
  181.             glDisable(GL_TEXTURE_2D);
  182.         }
  183.         else
  184.         {
  185.             glEnable(GL_TEXTURE_2D);
  186.             t->bind();
  187.         }
  188.         Mesh::BlendMode newBlendMode = Mesh::InvalidBlend;
  189.         if (m.opacity != 1.0f ||
  190.             m.blend == Mesh::AdditiveBlend ||
  191.             (t != NULL && t->hasAlpha()))
  192.         {
  193.             newBlendMode = m.blend;
  194.         }
  195.         if (newBlendMode != blendMode)
  196.         {
  197.             blendMode = newBlendMode;
  198.             switch (blendMode)
  199.             {
  200.             case Mesh::NormalBlend:
  201.                 glEnable(GL_BLEND);
  202.                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  203.                 glDepthMask(GL_FALSE);
  204.                 break;
  205.             case Mesh::AdditiveBlend:
  206.                 glEnable(GL_BLEND);
  207.                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  208.                 glDepthMask(GL_FALSE);
  209.                 break;
  210.             case Mesh::PremultipliedAlphaBlend:
  211.                 glEnable(GL_BLEND);
  212.                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  213.                 glDepthMask(GL_FALSE);
  214.                 break;
  215.             default:
  216.                 glDisable(GL_BLEND);
  217.                 glDepthMask(GL_TRUE);
  218.                 break;
  219.             }
  220.         }
  221.         if (useNormals || !lightingEnabled)
  222.         {
  223. #ifdef HDR_COMPRESS
  224.             glColor4f(m.diffuse.red()   * 0.5f,
  225.                       m.diffuse.green() * 0.5f,
  226.                       m.diffuse.blue()  * 0.5f,
  227.                       m.opacity);
  228. #else
  229.             glColor4f(m.diffuse.red(),
  230.                       m.diffuse.green(),
  231.                       m.diffuse.blue(),
  232.                       m.opacity);
  233. #endif
  234.             if (m.specular == Color::Black)
  235.             {
  236.                 float matSpecular[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  237.                 float zero = 0.0f;
  238.                 glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
  239.                 glMaterialfv(GL_FRONT, GL_SHININESS, &zero);
  240.                 specularOn = false;
  241.             }
  242.             else
  243.             {
  244.                 float matSpecular[4] = { m.specular.red(),
  245.                                          m.specular.green(),
  246.                                          m.specular.blue(),
  247.                                          0.0f };
  248.                 glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
  249.                 glMaterialfv(GL_FRONT, GL_SHININESS, &m.specularPower);
  250.                 specularOn = true;
  251.             }
  252.             
  253.             {
  254.                 float matEmissive[4] = { m.emissive.red(),
  255.                                          m.emissive.green(),
  256.                                          m.emissive.blue(),
  257.                                          0.0f };
  258.                 glMaterialfv(GL_FRONT, GL_EMISSION, matEmissive);
  259.             }
  260.         }
  261.         else
  262.         {
  263.             // When lighting without normals, we'll just merge everything
  264.             // into the emissive color. This makes normal-less lighting work
  265.             // more like it does in the GLSL path, though it's not very
  266.             // useful without shadows.
  267.             float matBlack[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  268.             float zero = 0.0f;
  269.             glMaterialfv(GL_FRONT, GL_DIFFUSE, matBlack);
  270.             glMaterialfv(GL_FRONT, GL_SPECULAR, matBlack);
  271.             glMaterialfv(GL_FRONT, GL_SHININESS, &zero);
  272.             {
  273. #ifdef HDR_COMPRESS
  274.                 float matEmissive[4] = { m.emissive.red() + m.diffuse.red() * 0.5f,
  275.                                          m.emissive.green() + m.diffuse.green() * 0.5f,
  276.                                          m.emissive.blue() + m.diffuse.blue() * 0.5f,
  277.                                          m.opacity };
  278. #else
  279.                 float matEmissive[4] = { m.emissive.red() + m.diffuse.red(),
  280.                                          m.emissive.green() + m.diffuse.green(),
  281.                                          m.emissive.blue() + m.diffuse.blue(),
  282.                                          m.opacity };
  283. #endif
  284.                 glMaterialfv(GL_FRONT, GL_EMISSION, matEmissive);
  285.             }
  286.         }
  287.     }
  288.     else if (getRenderPass() == EmissivePass)
  289.     {
  290.         Texture* t = NULL;
  291.         if (m.maps[Mesh::EmissiveMap] != InvalidResource && useTexCoords)
  292.             t = GetTextureManager()->find(m.maps[Mesh::EmissiveMap]);
  293.         if (t == NULL)
  294.         {
  295.             glDisable(GL_TEXTURE_2D);
  296.         }
  297.         else
  298.         {
  299.             glEnable(GL_TEXTURE_2D);
  300.             t->bind();
  301.         }
  302.     }
  303. }
  304. void
  305. FixedFunctionRenderContext::setVertexArrays(const Mesh::VertexDescription& desc, void* vertexData)
  306. {
  307.     // Update the material if normals appear or disappear in the vertex
  308.     // description.
  309.     bool useNormalsNow = (desc.getAttribute(Mesh::Normal).format == Mesh::Float3);
  310.     bool useColorsNow = (desc.getAttribute(Mesh::Color0).format != Mesh::InvalidFormat);
  311.     bool useTexCoordsNow = (desc.getAttribute(Mesh::Texture0).format != Mesh::InvalidFormat);
  312.     if (useNormalsNow != useNormals ||
  313.         useColorsNow != useColors ||
  314.         useTexCoordsNow != useTexCoords)
  315.     {
  316.         useNormals = useNormalsNow;
  317.         useColors = useColorsNow;
  318.         useTexCoords = useTexCoordsNow;
  319.         if (getMaterial() != NULL)
  320.             makeCurrent(*getMaterial());
  321.     }
  322.     setStandardVertexArrays(desc, vertexData);
  323. }
  324. void
  325. FixedFunctionRenderContext::setLighting(bool enabled)
  326. {
  327.     lightingEnabled = enabled;
  328.     if (lightingEnabled)
  329.         glEnable(GL_LIGHTING);
  330.     else
  331.         glDisable(GL_LIGHTING);
  332. }
  333. void
  334. VP_Combiner_RenderContext::setVertexArrays(const Mesh::VertexDescription& desc, void* vertexData)
  335. {
  336.     setStandardVertexArrays(desc, vertexData);
  337.     setExtendedVertexArrays(desc, vertexData);
  338. }
  339. void
  340. VP_FP_RenderContext::setVertexArrays(const Mesh::VertexDescription& desc, void* vertexData)
  341. {
  342.     setStandardVertexArrays(desc, vertexData);
  343.     setExtendedVertexArrays(desc, vertexData);
  344. }
  345. void
  346. setStandardVertexArrays(const Mesh::VertexDescription& desc,
  347.                         void* vertexData)
  348. {
  349.     const Mesh::VertexAttribute& position  = desc.getAttribute(Mesh::Position);
  350.     const Mesh::VertexAttribute& normal    = desc.getAttribute(Mesh::Normal);
  351.     const Mesh::VertexAttribute& color0    = desc.getAttribute(Mesh::Color0);
  352.     const Mesh::VertexAttribute& texCoord0 = desc.getAttribute(Mesh::Texture0);
  353.     // Can't render anything unless we have positions
  354.     if (position.format != Mesh::Float3)
  355.         return;
  356.     // Set up the vertex arrays
  357.     glEnableClientState(GL_VERTEX_ARRAY);
  358.     glVertexPointer(3, GL_FLOAT, desc.stride,
  359.                     reinterpret_cast<char*>(vertexData) + position.offset);
  360.     // Set up the normal array
  361.     switch (normal.format)
  362.     {
  363.     case Mesh::Float3:
  364.         glEnableClientState(GL_NORMAL_ARRAY);
  365.         glNormalPointer(GLComponentTypes[(int) normal.format],
  366.                         desc.stride,
  367.                         reinterpret_cast<char*>(vertexData) + normal.offset);
  368.         break;
  369.     default:
  370.         glDisableClientState(GL_NORMAL_ARRAY);
  371.         break;
  372.     }
  373.     // Set up the color array
  374.     switch (color0.format)
  375.     {
  376.     case Mesh::Float3:
  377.     case Mesh::Float4:
  378.     case Mesh::UByte4:
  379.         glEnableClientState(GL_COLOR_ARRAY);
  380.         glColorPointer(GLComponentCounts[color0.format],
  381.                        GLComponentTypes[color0.format],
  382.                        desc.stride,
  383.                        reinterpret_cast<char*>(vertexData) + color0.offset);
  384.         break;
  385.     default:
  386.         glDisableClientState(GL_COLOR_ARRAY);
  387.         break;
  388.     }
  389.     // Set up the texture coordinate array
  390.     switch (texCoord0.format)
  391.     {
  392.     case Mesh::Float1:
  393.     case Mesh::Float2:
  394.     case Mesh::Float3:
  395.     case Mesh::Float4:
  396.         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  397.         glTexCoordPointer(GLComponentCounts[(int) texCoord0.format],
  398.                           GLComponentTypes[(int) texCoord0.format],
  399.                           desc.stride,
  400.                           reinterpret_cast<char*>(vertexData) + texCoord0.offset);
  401.         break;
  402.     default:
  403.         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  404.         break;
  405.     }
  406. }
  407. void
  408. setExtendedVertexArrays(const Mesh::VertexDescription& desc,
  409.                         const void* vertexData)
  410. {
  411.     const Mesh::VertexAttribute& tangent  = desc.getAttribute(Mesh::Tangent);
  412.     const char* vertices = reinterpret_cast<const char*>(vertexData);
  413.     switch (tangent.format)
  414.     {
  415.     case Mesh::Float3:
  416.         glx::glEnableVertexAttribArrayARB(TangentAttributeIndex);
  417.         glx::glVertexAttribPointerARB(TangentAttributeIndex,
  418.                                       GLComponentCounts[(int) tangent.format],
  419.                                       GLComponentTypes[(int) tangent.format],
  420.                                       GL_FALSE,
  421.                                       desc.stride,
  422.                                       vertices + tangent.offset);
  423.         break;
  424.     default:
  425.         glx::glDisableVertexAttribArrayARB(TangentAttributeIndex);
  426.         break;
  427.     }
  428.     const Mesh::VertexAttribute& pointsize = desc.getAttribute(Mesh::PointSize);
  429.     switch (pointsize.format)
  430.     {
  431.     case Mesh::Float1:
  432.         glx::glEnableVertexAttribArrayARB(PointSizeAttributeIndex);
  433.         glx::glVertexAttribPointerARB(PointSizeAttributeIndex,
  434.                                       GLComponentCounts[(int) pointsize.format],
  435.                                       GLComponentTypes[(int) pointsize.format],
  436.                                       GL_FALSE,
  437.                                       desc.stride,
  438.                                       vertices + pointsize.offset);
  439.         break;
  440.     default:
  441.         glx::glDisableVertexAttribArrayARB(PointSizeAttributeIndex);
  442.         break;
  443.     }
  444. }
  445. /***** GLSL render context ******/
  446. GLSL_RenderContext::GLSL_RenderContext(const LightingState& ls, float _objRadius, const Mat4f& _xform) :
  447.     lightingState(ls),
  448.     atmosphere(NULL),
  449.     blendMode(Mesh::InvalidBlend),
  450.     objRadius(_objRadius),
  451.     xform(_xform),
  452.     lunarLambert(0.0f)
  453. {
  454.     initLightingEnvironment();
  455. }
  456. GLSL_RenderContext::~GLSL_RenderContext()
  457. {
  458.     glDisableClientState(GL_VERTEX_ARRAY);
  459.     glDisableClientState(GL_NORMAL_ARRAY);
  460.     glDisableClientState(GL_COLOR_ARRAY);
  461.     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  462.     glx::glDisableVertexAttribArrayARB(TangentAttributeIndex);
  463.     glx::glDisableVertexAttribArrayARB(PointSizeAttributeIndex);
  464. }
  465. void
  466. GLSL_RenderContext::initLightingEnvironment()
  467. {
  468.     // Set the light and shadow environment, which is constant for the entire model.
  469.     // The material properties will be set per mesh.
  470.     shaderProps.nLights = min(lightingState.nLights, MaxShaderLights);
  471.     // Set the shadow information.
  472.     // Track the total number of shadows; if there are too many, we'll have
  473.     // to fall back to multipass.
  474.     unsigned int totalShadows = 0;
  475.     for (unsigned int li = 0; li < lightingState.nLights; li++)
  476.     {
  477.         if (lightingState.shadows[li] && !lightingState.shadows[li]->empty())
  478.         {
  479.             unsigned int nShadows = (unsigned int) min((size_t) MaxShaderShadows, lightingState.shadows[li]->size());
  480.             shaderProps.setShadowCountForLight(li, nShadows);
  481.             totalShadows += nShadows;
  482.         }
  483.     }
  484. }
  485. void
  486. GLSL_RenderContext::makeCurrent(const Mesh::Material& m)
  487. {
  488.     Texture* textures[4] = { NULL, NULL, NULL, NULL };
  489.     unsigned int nTextures = 0;
  490.     // Set up the textures used by this object
  491.     Texture* baseTex = NULL;
  492.     Texture* bumpTex = NULL;
  493.     Texture* specTex = NULL;
  494.     Texture* emissiveTex = NULL;
  495.     shaderProps.texUsage = ShaderProperties::SharedTextureCoords;
  496.     if (useNormals)
  497.     {
  498.         if (lunarLambert == 0.0f)
  499.             shaderProps.lightModel = ShaderProperties::DiffuseModel;
  500.         else
  501.             shaderProps.lightModel = ShaderProperties::LunarLambertModel;
  502.     }
  503.     else
  504.     {
  505.         // "particle" lighting is the only type that doesn't
  506.         // depend on having a surface normal.
  507.         // Enable alternate particle model when vertex colors are present;
  508.         // eventually, a render context method will enable the particle
  509.         // model.
  510.         if (useColors)
  511.             shaderProps.lightModel = ShaderProperties::ParticleModel;
  512.         else
  513.             shaderProps.lightModel = ShaderProperties::ParticleDiffuseModel;
  514.     }
  515.     if (m.maps[Mesh::DiffuseMap] != InvalidResource && (useTexCoords || usePointSize))
  516.     {
  517.         baseTex = GetTextureManager()->find(m.maps[Mesh::DiffuseMap]);
  518.         if (baseTex != NULL)
  519.         {
  520.             shaderProps.texUsage |= ShaderProperties::DiffuseTexture;
  521.             textures[nTextures++] = baseTex;
  522.         }
  523.     }
  524.     if (m.maps[Mesh::NormalMap] != InvalidResource)
  525.     {
  526.         bumpTex = GetTextureManager()->find(m.maps[Mesh::NormalMap]);
  527.         if (bumpTex != NULL)
  528.         {
  529.             shaderProps.texUsage |= ShaderProperties::NormalTexture;
  530.             if (bumpTex->getFormatOptions() & Texture::DXT5NormalMap)
  531.             {
  532.                 shaderProps.texUsage |= ShaderProperties::CompressedNormalTexture;
  533.             }
  534.             textures[nTextures++] = bumpTex;
  535.         }
  536.     }
  537.     if (m.specular != Color::Black && useNormals)
  538.     {
  539.         shaderProps.lightModel = ShaderProperties::PerPixelSpecularModel;
  540.         specTex = GetTextureManager()->find(m.maps[Mesh::SpecularMap]);
  541.         if (specTex == NULL)
  542.         {
  543.             if (baseTex != NULL)
  544.                 shaderProps.texUsage |= ShaderProperties::SpecularInDiffuseAlpha;
  545.         }
  546.         else
  547.         {
  548.             shaderProps.texUsage |= ShaderProperties::SpecularTexture;
  549.             textures[nTextures++] = specTex;
  550.         }
  551.     }
  552.     if (m.maps[Mesh::EmissiveMap] != InvalidResource)
  553.     {
  554.         emissiveTex = GetTextureManager()->find(m.maps[Mesh::EmissiveMap]);
  555.         if (emissiveTex != NULL)
  556.         {
  557.             shaderProps.texUsage |= ShaderProperties::EmissiveTexture;
  558.             textures[nTextures++] = emissiveTex;
  559.         }
  560.     }
  561.     if (usePointSize)
  562.         shaderProps.texUsage |= ShaderProperties::PointSprite;
  563.     if (useColors)
  564.         shaderProps.texUsage |= ShaderProperties::VertexColors;
  565.     if (atmosphere != NULL)
  566.     {
  567.         // Only use new atmosphere code in OpenGL 2.0 path when new style parameters are defined.
  568.         if (atmosphere->mieScaleHeight > 0.0f)
  569.             shaderProps.texUsage |= ShaderProperties::Scattering;
  570.     }
  571.     // Get a shader for the current rendering configuration
  572.     CelestiaGLProgram* prog = GetShaderManager().getShader(shaderProps);
  573.     if (prog == NULL)
  574.         return;
  575.     prog->use();
  576.     for (unsigned int i = 0; i < nTextures; i++)
  577.     {
  578.         glx::glActiveTextureARB(GL_TEXTURE0_ARB + i);
  579.         glEnable(GL_TEXTURE_2D);
  580.         textures[i]->bind();
  581.     }
  582.     // setLightParameters() expects opacity in the alpha channel of the diffuse color
  583. #ifdef HDR_COMPRESS
  584.     Color diffuse(m.diffuse.red() * 0.5f, m.diffuse.green() * 0.5f, m.diffuse.blue() * 0.5f, m.opacity);
  585. #else
  586.     Color diffuse(m.diffuse.red(), m.diffuse.green(), m.diffuse.blue(), m.opacity);
  587. #endif
  588.     prog->setLightParameters(lightingState, diffuse, m.specular, m.emissive);
  589.     if (shaderProps.shadowCounts != 0)
  590.         prog->setEclipseShadowParameters(lightingState, objRadius, xform);
  591.     // TODO: handle emissive color
  592.     prog->shininess = m.specularPower;
  593.     if (shaderProps.lightModel == ShaderProperties::LunarLambertModel)
  594.     {
  595.         prog->lunarLambert = lunarLambert;
  596.     }
  597.     // Generally, we want to disable depth writes for blend because it
  598.     // makes translucent objects look a bit better (though there are
  599.     // still problems when rendering them without sorting.) However,
  600.     // when scattering atmospheres are enabled, we need to render with
  601.     // depth writes on, otherwise the atmosphere will be drawn over
  602.     // a planet mesh. See SourceForge bug #1855894 for more details.
  603.     bool disableDepthWriteOnBlend = true;
  604.     if (shaderProps.hasScattering())
  605.     {
  606.         prog->setAtmosphereParameters(*atmosphere, objRadius, objRadius);
  607.         disableDepthWriteOnBlend = false;
  608.     }
  609.     if ((shaderProps.texUsage & ShaderProperties::PointSprite) != 0)
  610.     {
  611.         prog->pointScale = getPointScale();
  612.     }
  613.     Mesh::BlendMode newBlendMode = Mesh::InvalidBlend;
  614.     if (m.opacity != 1.0f ||
  615.         m.blend == Mesh::AdditiveBlend ||
  616.         (baseTex != NULL && baseTex->hasAlpha()))
  617.     {
  618.         newBlendMode = m.blend;
  619.     }
  620.     if (newBlendMode != blendMode)
  621.     {
  622.         blendMode = newBlendMode;
  623.         switch (blendMode)
  624.         {
  625.         case Mesh::NormalBlend:
  626.             glEnable(GL_BLEND);
  627.             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  628.             glDepthMask(disableDepthWriteOnBlend ? GL_FALSE : GL_TRUE);
  629.             break;
  630.         case Mesh::AdditiveBlend:
  631.             glEnable(GL_BLEND);
  632.             glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  633.             glDepthMask(disableDepthWriteOnBlend ? GL_FALSE : GL_TRUE);
  634.             break;
  635.         case Mesh::PremultipliedAlphaBlend:
  636.             glEnable(GL_BLEND);
  637.             glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  638.             glDepthMask(disableDepthWriteOnBlend ? GL_FALSE : GL_TRUE);
  639.             break;                
  640.         default:
  641.             glDisable(GL_BLEND);
  642.             glDepthMask(GL_TRUE);
  643.             break;
  644.         }
  645.     }
  646. }
  647. void
  648. GLSL_RenderContext::setVertexArrays(const Mesh::VertexDescription& desc,
  649.                                     void* vertexData)
  650. {
  651.     setStandardVertexArrays(desc, vertexData);
  652.     setExtendedVertexArrays(desc, vertexData);
  653.     // Normally, the shader that will be used depends only on the material.
  654.     // But the presence of point size and normals can also affect the
  655.     // shader, so force an update of the material if those attributes appear
  656.     // or disappear in the new set of vertex arrays.
  657.     bool usePointSizeNow = (desc.getAttribute(Mesh::PointSize).format == Mesh::Float1);
  658.     bool useNormalsNow = (desc.getAttribute(Mesh::Normal).format == Mesh::Float3);
  659.     bool useColorsNow = (desc.getAttribute(Mesh::Color0).format != Mesh::InvalidFormat);
  660.     bool useTexCoordsNow = (desc.getAttribute(Mesh::Texture0).format != Mesh::InvalidFormat);
  661.     if (usePointSizeNow != usePointSize ||
  662.         useNormalsNow   != useNormals   ||
  663.         useColorsNow    != useColors    ||
  664.         useTexCoordsNow != useTexCoords)
  665.     {
  666.         usePointSize = usePointSizeNow;
  667.         useNormals = useNormalsNow;
  668.         useColors = useColorsNow;
  669.         useTexCoords = useTexCoordsNow;
  670.         if (getMaterial() != NULL)
  671.             makeCurrent(*getMaterial());
  672.     }
  673. }
  674. void
  675. GLSL_RenderContext::setAtmosphere(const Atmosphere* _atmosphere)
  676. {
  677.     atmosphere = _atmosphere;
  678. }
  679. // Extended material properties -- currently just lunarLambert term
  680. void
  681. GLSL_RenderContext::setLunarLambert(float l)
  682. {
  683.     lunarLambert = l;
  684. }
  685. /***** GLSL-Unlit render context ******/
  686. GLSLUnlit_RenderContext::GLSLUnlit_RenderContext(float _objRadius) :
  687.     blendMode(Mesh::InvalidBlend),
  688.     objRadius(_objRadius)
  689. {
  690.     initLightingEnvironment();
  691. }
  692. GLSLUnlit_RenderContext::~GLSLUnlit_RenderContext()
  693. {
  694.     glDisableClientState(GL_VERTEX_ARRAY);
  695.     glDisableClientState(GL_NORMAL_ARRAY);
  696.     glDisableClientState(GL_COLOR_ARRAY);
  697.     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  698.     glx::glDisableVertexAttribArrayARB(TangentAttributeIndex);
  699.     glx::glDisableVertexAttribArrayARB(PointSizeAttributeIndex);
  700. }
  701. void
  702. GLSLUnlit_RenderContext::initLightingEnvironment()
  703. {
  704.     // Set the light and shadow environment, which is constant for the entire model.
  705.     // The material properties will be set per mesh.
  706.     shaderProps.nLights = 1;
  707. }
  708. void
  709. GLSLUnlit_RenderContext::makeCurrent(const Mesh::Material& m)
  710. {
  711.     Texture* textures[4] = { NULL, NULL, NULL, NULL };
  712.     unsigned int nTextures = 0;
  713.     // Set up the textures used by this object
  714.     Texture* baseTex = NULL;
  715.     shaderProps.lightModel = ShaderProperties::EmissiveModel;
  716.     shaderProps.texUsage = ShaderProperties::SharedTextureCoords;
  717.     if (m.maps[Mesh::DiffuseMap] != InvalidResource && (useTexCoords || usePointSize))
  718.     {
  719.         baseTex = GetTextureManager()->find(m.maps[Mesh::DiffuseMap]);
  720.         if (baseTex != NULL)
  721.         {
  722.             shaderProps.texUsage |= ShaderProperties::DiffuseTexture;
  723.             textures[nTextures++] = baseTex;
  724.         }
  725.     }
  726.     if (usePointSize)
  727.         shaderProps.texUsage |= ShaderProperties::PointSprite;
  728.     if (useColors)
  729.         shaderProps.texUsage |= ShaderProperties::VertexColors;
  730.     // Get a shader for the current rendering configuration
  731.     CelestiaGLProgram* prog = GetShaderManager().getShader(shaderProps);
  732.     if (prog == NULL)
  733.         return;
  734.     prog->use();
  735.     for (unsigned int i = 0; i < nTextures; i++)
  736.     {
  737.         glx::glActiveTextureARB(GL_TEXTURE0_ARB + i);
  738.         glEnable(GL_TEXTURE_2D);
  739.         textures[i]->bind();
  740.     }
  741. #ifdef HDR_COMPRESS
  742.     prog->lights[0].diffuse = Vec3f(m.diffuse.red()   * 0.5f,
  743.                                     m.diffuse.green() * 0.5f,
  744.                                     m.diffuse.blue()  * 0.5f);
  745. #else
  746.     prog->lights[0].diffuse = Vec3f(m.diffuse.red(),
  747.                                     m.diffuse.green(),
  748.                                     m.diffuse.blue());
  749. #endif
  750.     prog->opacity = m.opacity;
  751.     if ((shaderProps.texUsage & ShaderProperties::PointSprite) != 0)
  752.     {
  753.         prog->pointScale = getPointScale();
  754.     }
  755.     Mesh::BlendMode newBlendMode = Mesh::InvalidBlend;
  756.     if (m.opacity != 1.0f ||
  757.         m.blend == Mesh::AdditiveBlend ||
  758.         (baseTex != NULL && baseTex->hasAlpha()))
  759.     {
  760.         newBlendMode = m.blend;
  761.     }
  762.     if (newBlendMode != blendMode)
  763.     {
  764.         blendMode = newBlendMode;
  765.         switch (blendMode)
  766.         {
  767.         case Mesh::NormalBlend:
  768.             glEnable(GL_BLEND);
  769.             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  770.             glDepthMask(GL_FALSE);
  771.             break;
  772.         case Mesh::AdditiveBlend:
  773.             glEnable(GL_BLEND);
  774.             glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  775.             glDepthMask(GL_FALSE);
  776.             break;
  777.         case Mesh::PremultipliedAlphaBlend:
  778.             glEnable(GL_BLEND);
  779.             glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  780.             glDepthMask(GL_FALSE);
  781.             break;                
  782.         default:
  783.             glDisable(GL_BLEND);
  784.             glDepthMask(GL_TRUE);
  785.             break;
  786.         }
  787.     }
  788. }
  789. void
  790. GLSLUnlit_RenderContext::setVertexArrays(const Mesh::VertexDescription& desc,
  791.                                          void* vertexData)
  792. {
  793.     setStandardVertexArrays(desc, vertexData);
  794.     setExtendedVertexArrays(desc, vertexData);
  795.     // Normally, the shader that will be used depends only on the material.
  796.     // But the presence of point size and normals can also affect the
  797.     // shader, so force an update of the material if those attributes appear
  798.     // or disappear in the new set of vertex arrays.
  799.     bool usePointSizeNow = (desc.getAttribute(Mesh::PointSize).format == Mesh::Float1);
  800.     bool useNormalsNow = (desc.getAttribute(Mesh::Normal).format == Mesh::Float3);
  801.     bool useColorsNow = (desc.getAttribute(Mesh::Color0).format != Mesh::InvalidFormat);
  802.     bool useTexCoordsNow = (desc.getAttribute(Mesh::Texture0).format != Mesh::InvalidFormat);
  803.     if (usePointSizeNow != usePointSize ||
  804.         useNormalsNow   != useNormals   ||
  805.         useColorsNow    != useColors    ||
  806.         useTexCoordsNow != useTexCoords)
  807.     {
  808.         usePointSize = usePointSizeNow;
  809.         useNormals = useNormalsNow;
  810.         useColors = useColorsNow;
  811.         useTexCoords = useTexCoordsNow;
  812.         if (getMaterial() != NULL)
  813.             makeCurrent(*getMaterial());
  814.     }
  815. }