LCOV - code coverage report
Current view: top level - source/graphics - ShaderProgramFFP.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 0 585 0.0 %
Date: 2021-04-16 20:41:45 Functions: 0 59 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2021 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "ShaderProgram.h"
      21             : 
      22             : #include "graphics/ShaderDefines.h"
      23             : #include "graphics/TextureManager.h"
      24             : #include "lib/res/graphics/ogl_tex.h"
      25             : #include "maths/Matrix3D.h"
      26             : #include "maths/Vector3D.h"
      27             : #include "ps/CLogger.h"
      28             : #include "renderer/Renderer.h"
      29             : 
      30             : #if !CONFIG2_GLES
      31             : 
      32             : /**
      33             :  * CShaderProgramFFP allows rendering code to use the shader-based API
      34             :  * even if the 'shader' is actually implemented with the fixed-function
      35             :  * pipeline instead of anything programmable.
      36             :  *
      37             :  * Currently we just hard-code a number of FFP programs as subclasses of this.
      38             :  * If we have lots, it might be nicer to abstract out the common functionality
      39             :  * and load these from text files or something.
      40             :  */
      41             : class CShaderProgramFFP : public CShaderProgram
      42             : {
      43             : public:
      44           0 :     CShaderProgramFFP(int streamflags) :
      45           0 :         CShaderProgram(streamflags)
      46             :     {
      47             :     }
      48             : 
      49           0 :     ~CShaderProgramFFP()
      50           0 :     {
      51           0 :     }
      52           0 : 
      53           0 :     virtual void Reload()
      54           0 :     {
      55           0 :         m_IsValid = true;
      56           0 :     }
      57           0 : 
      58             :     int GetUniformIndex(CStrIntern id)
      59           0 :     {
      60             :         std::map<CStrIntern, int>::iterator it = m_UniformIndexes.find(id);
      61           0 :         if (it == m_UniformIndexes.end())
      62           0 :             return -1;
      63             :         return it->second;
      64             :     }
      65             : 
      66           0 :     virtual Binding GetTextureBinding(uniform_id_t id)
      67           0 :     {
      68             :         int index = GetUniformIndex(CStrIntern(id));
      69           0 :         if (index == -1)
      70             :             return Binding();
      71             :         else
      72           0 :             return Binding((int)GL_TEXTURE_2D, index);
      73             :     }
      74           0 : 
      75           0 :     virtual void BindTexture(texture_id_t id, Handle tex)
      76           0 :     {
      77             :         int index = GetUniformIndex(CStrIntern(id));
      78           0 :         if (index != -1)
      79             :             ogl_tex_bind(tex, index);
      80             :     }
      81           0 : 
      82             :     virtual void BindTexture(texture_id_t id, GLuint tex)
      83           0 :     {
      84           0 :         int index = GetUniformIndex(CStrIntern(id));
      85           0 :         if (index != -1)
      86           0 :         {
      87             :             pglActiveTextureARB((int)(GL_TEXTURE0+index));
      88           0 :             glBindTexture(GL_TEXTURE_2D, tex);
      89             :         }
      90           0 :     }
      91           0 : 
      92             :     virtual void BindTexture(Binding id, Handle tex)
      93           0 :     {
      94           0 :         int index = id.second;
      95             :         if (index != -1)
      96           0 :             ogl_tex_bind(tex, index);
      97             :     }
      98           0 : 
      99             :     virtual Binding GetUniformBinding(uniform_id_t id)
     100           0 :     {
     101           0 :         return Binding(-1, GetUniformIndex(id));
     102           0 :     }
     103           0 : 
     104             :     virtual void Uniform(Binding UNUSED(id), float UNUSED(v0), float UNUSED(v1), float UNUSED(v2), float UNUSED(v3))
     105           0 :     {
     106             :     }
     107           0 : 
     108             :     virtual void Uniform(Binding UNUSED(id), const CMatrix3D& UNUSED(v))
     109             :     {
     110           0 :     }
     111             : 
     112           0 :     virtual void Uniform(Binding UNUSED(id), size_t UNUSED(count), const CMatrix3D* UNUSED(v))
     113             :     {
     114           0 :     }
     115             : 
     116           0 :     virtual void Uniform(Binding UNUSED(id), size_t UNUSED(count), const float* UNUSED(v))
     117             :     {
     118           0 :     }
     119             : 
     120           0 :     virtual std::vector<VfsPath> GetFileDependencies() const
     121             :     {
     122           0 :         return {};
     123             :     }
     124           0 : 
     125             : protected:
     126           0 :     std::map<CStrIntern, int> m_UniformIndexes;
     127             : 
     128           0 :     void SetUniformIndex(const char* id, int value)
     129             :     {
     130             :         m_UniformIndexes[CStrIntern(id)] = value;
     131             :     }
     132             : };
     133             : 
     134             : //////////////////////////////////////////////////////////////////////////
     135             : 
     136           0 : /**
     137             :  * A shader that does nothing but provide a shader-compatible interface to
     138             :  * fixed-function features, for compatibility with existing fixed-function
     139             :  * code that isn't fully ported to the shader API.
     140             :  */
     141             : class CShaderProgramFFP_Dummy : public CShaderProgramFFP
     142             : {
     143             : public:
     144             :     CShaderProgramFFP_Dummy() :
     145             :         CShaderProgramFFP(0)
     146             :     {
     147             :         // Texture units, for when this shader is used with terrain:
     148             :         SetUniformIndex("baseTex", 0);
     149             :     }
     150           0 : 
     151           0 :     virtual void Bind()
     152             :     {
     153             :         BindClientStates();
     154           0 :     }
     155           0 : 
     156             :     virtual void Unbind()
     157           0 :     {
     158             :         UnbindClientStates();
     159           0 :     }
     160           0 : };
     161             : 
     162           0 : //////////////////////////////////////////////////////////////////////////
     163             : 
     164           0 : class CShaderProgramFFP_OverlayLine : public CShaderProgramFFP
     165           0 : {
     166             :     // Uniforms
     167             :     enum
     168             :     {
     169             :         ID_losTransform,
     170             :         ID_objectColor
     171             :     };
     172             : 
     173             :     bool m_IgnoreLos;
     174             :     bool m_UseObjectColor;
     175             : 
     176             : public:
     177             :     CShaderProgramFFP_OverlayLine(const CShaderDefines& defines) :
     178             :         CShaderProgramFFP(0) // will be set manually in initializer below
     179             :     {
     180             :         SetUniformIndex("losTransform", ID_losTransform);
     181             :         SetUniformIndex("objectColor", ID_objectColor);
     182             : 
     183           0 :         // Texture units:
     184           0 :         SetUniformIndex("baseTex", 0);
     185             :         SetUniformIndex("maskTex", 1);
     186           0 :         SetUniformIndex("losTex", 2);
     187           0 : 
     188             :         m_IgnoreLos = (defines.GetInt("IGNORE_LOS") != 0);
     189             :         m_UseObjectColor = (defines.GetInt("USE_OBJECTCOLOR") != 0);
     190           0 : 
     191           0 :         m_StreamFlags = STREAM_POS | STREAM_UV0 | STREAM_UV1;
     192           0 :         if (!m_UseObjectColor)
     193             :             m_StreamFlags |= STREAM_COLOR;
     194           0 :     }
     195           0 : 
     196             :     bool IsIgnoreLos()
     197           0 :     {
     198           0 :         return m_IgnoreLos;
     199           0 :     }
     200           0 : 
     201             :     virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
     202           0 :     {
     203             :         if (id.second == ID_losTransform)
     204           0 :         {
     205             :             pglActiveTextureARB(GL_TEXTURE2);
     206             :             GLfloat texgenS1[4] = { v0, 0, 0, v1 };
     207           0 :             GLfloat texgenT1[4] = { 0, 0, v0, v1 };
     208             :             glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS1);
     209           0 :             glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT1);
     210             :         }
     211           0 :         else if (id.second == ID_objectColor)
     212           0 :         {
     213           0 :             float c[] = { v0, v1, v2, v3 };
     214           0 :             pglActiveTextureARB(GL_TEXTURE1);
     215           0 :             glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, c);
     216             :         }
     217           0 :         else
     218             :         {
     219           0 :             debug_warn(L"Invalid id");
     220           0 :         }
     221           0 :     }
     222             : 
     223             :     virtual void Uniform(Binding UNUSED(id), const CMatrix3D& UNUSED(v))
     224             :     {
     225           0 :         debug_warn(L"Not implemented");
     226             :     }
     227           0 : 
     228             :     virtual void Bind()
     229           0 :     {
     230             :         // RGB channels:
     231           0 :         //   Unit 0: Sample base texture
     232           0 :         //   Unit 1: Sample mask texture; interpolate with [objectColor or vertexColor] and base, depending on USE_OBJECTCOLOR
     233             :         //   Unit 2: (Load LOS texture; multiply) if not #IGNORE_LOS, pass through otherwise
     234           0 :         // Alpha channel:
     235             :         //   Unit 0: Sample base texture
     236             :         //   Unit 1: Multiply by objectColor
     237             :         //   Unit 2: Pass through
     238             : 
     239             :         pglActiveTextureARB(GL_TEXTURE0);
     240             :         glEnable(GL_TEXTURE_2D);
     241             :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     242             : 
     243             :         // Sample base texture RGB
     244             :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
     245           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
     246           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     247           0 : 
     248             :         // Sample base texture Alpha
     249             :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     250           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
     251           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     252           0 : 
     253             :         // -----------------------------------------------------------------------------
     254             : 
     255           0 :         pglActiveTextureARB(GL_TEXTURE1);
     256           0 :         glEnable(GL_TEXTURE_2D);
     257           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     258             : 
     259             :         // RGB: interpolate component-wise between [objectColor or vertexColor] and base using mask:
     260             :         //   a0 * a2 + a1 * (1 - a2)
     261           0 :         // Overridden implementation of Uniform() sets GL_TEXTURE_ENV_COLOR to objectColor, which
     262           0 :         // is referenced as GL_CONSTANT (see spec)
     263           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
     264             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, m_UseObjectColor ? GL_CONSTANT : GL_PRIMARY_COLOR);
     265             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     266             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
     267             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
     268             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
     269           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
     270           0 : 
     271           0 :         // ALPHA: Multiply base alpha with [objectColor or vertexColor] alpha
     272           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
     273           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, m_UseObjectColor ? GL_CONSTANT : GL_PRIMARY_COLOR);
     274           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     275           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS);
     276             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
     277             : 
     278           0 :         // -----------------------------------------------------------------------------
     279           0 : 
     280           0 :         pglActiveTextureARB(GL_TEXTURE2);
     281           0 :         glEnable(GL_TEXTURE_2D);
     282           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     283             : 
     284             :         bool ignoreLos = IsIgnoreLos();
     285             :         if (ignoreLos)
     286           0 :         {
     287           0 :             // RGB pass through
     288           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
     289             :             glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
     290           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     291           0 :         }
     292             :         else
     293             :         {
     294           0 :             // Multiply RGB result up till now with LoS texture alpha channel
     295           0 :             glEnable(GL_TEXTURE_GEN_S);
     296           0 :             glEnable(GL_TEXTURE_GEN_T);
     297             :             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
     298             :             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
     299             :             // Overridden implementation of Uniform() sets GL_OBJECT_PLANE values
     300             : 
     301           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     302           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
     303           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     304           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
     305             :             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
     306             :         }
     307           0 : 
     308           0 :         // alpha pass through
     309           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     310           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
     311           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     312             : 
     313             :         BindClientStates();
     314             :     }
     315           0 : 
     316           0 :     virtual void Unbind()
     317           0 :     {
     318             :         UnbindClientStates();
     319           0 : 
     320           0 :         pglActiveTextureARB(GL_TEXTURE2);
     321             :         glDisable(GL_TEXTURE_2D);
     322           0 : 
     323             :         glDisable(GL_TEXTURE_GEN_S);
     324           0 :         glDisable(GL_TEXTURE_GEN_T);
     325             : 
     326           0 :         pglActiveTextureARB(GL_TEXTURE1);
     327           0 :         glDisable(GL_TEXTURE_2D);
     328             : 
     329           0 :         pglActiveTextureARB(GL_TEXTURE0);
     330           0 :         glDisable(GL_TEXTURE_2D);
     331             :     }
     332           0 : };
     333           0 : 
     334             : //////////////////////////////////////////////////////////////////////////
     335           0 : 
     336           0 : class CShaderProgramFFP_GuiText : public CShaderProgramFFP
     337           0 : {
     338             :     // Uniforms
     339             :     enum
     340             :     {
     341             :         ID_transform,
     342             :         ID_colorMul
     343             :     };
     344             : 
     345             : public:
     346             :     CShaderProgramFFP_GuiText() :
     347             :         CShaderProgramFFP(STREAM_POS | STREAM_UV0)
     348             :     {
     349             :         SetUniformIndex("transform", ID_transform);
     350             :         SetUniformIndex("colorMul", ID_colorMul);
     351             : 
     352           0 :         // Texture units:
     353           0 :         SetUniformIndex("tex", 0);
     354             :     }
     355           0 : 
     356           0 :     virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
     357             :     {
     358             :         if (id.second == ID_colorMul)
     359           0 :             glColor4f(v0, v1, v2, v3);
     360           0 :     }
     361             : 
     362           0 :     virtual void Uniform(Binding id, const CMatrix3D& v)
     363             :     {
     364           0 :         if (id.second == ID_transform)
     365           0 :             glLoadMatrixf(&v._11);
     366           0 :     }
     367             : 
     368           0 :     virtual void Bind()
     369             :     {
     370           0 :         glMatrixMode(GL_PROJECTION);
     371           0 :         glPushMatrix();
     372           0 :         glLoadIdentity();
     373             :         glMatrixMode(GL_MODELVIEW);
     374           0 :         glPushMatrix();
     375             : 
     376           0 :         pglActiveTextureARB(GL_TEXTURE0);
     377           0 :         glEnable(GL_TEXTURE_2D);
     378           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
     379           0 : 
     380           0 :         BindClientStates();
     381             :     }
     382           0 : 
     383           0 :     virtual void Unbind()
     384           0 :     {
     385             :         UnbindClientStates();
     386           0 : 
     387           0 :         pglActiveTextureARB(GL_TEXTURE0);
     388             :         glDisable(GL_TEXTURE_2D);
     389           0 : 
     390             :         glMatrixMode(GL_PROJECTION);
     391           0 :         glPopMatrix();
     392             :         glMatrixMode(GL_MODELVIEW);
     393           0 :         glPopMatrix();
     394           0 :     }
     395             : };
     396           0 : 
     397           0 : //////////////////////////////////////////////////////////////////////////
     398           0 : 
     399           0 : class CShaderProgramFFP_Gui_Base : public CShaderProgramFFP
     400           0 : {
     401             : protected:
     402             :     // Uniforms
     403             :     enum
     404             :     {
     405             :         ID_transform,
     406             :         ID_color
     407             :     };
     408             : 
     409             : public:
     410             :     CShaderProgramFFP_Gui_Base(int streamflags) :
     411             :         CShaderProgramFFP(streamflags)
     412             :     {
     413             :         SetUniformIndex("transform", ID_transform);
     414             :         SetUniformIndex("color", ID_color);
     415             : 
     416           0 :         // Texture units:
     417           0 :         SetUniformIndex("tex", 0);
     418             :     }
     419           0 : 
     420           0 :     virtual void Uniform(Binding id, const CMatrix3D& v)
     421             :     {
     422             :         if (id.second == ID_transform)
     423           0 :             glLoadMatrixf(&v._11);
     424           0 :     }
     425             : 
     426           0 :     virtual void Bind()
     427             :     {
     428           0 :         glMatrixMode(GL_PROJECTION);
     429           0 :         glPushMatrix();
     430           0 :         glLoadIdentity();
     431             :         glMatrixMode(GL_MODELVIEW);
     432           0 :         glPushMatrix();
     433             : 
     434           0 :         BindClientStates();
     435           0 :     }
     436           0 : 
     437           0 :     virtual void Unbind()
     438           0 :     {
     439             :         UnbindClientStates();
     440           0 : 
     441           0 :         glMatrixMode(GL_PROJECTION);
     442             :         glPopMatrix();
     443           0 :         glMatrixMode(GL_MODELVIEW);
     444             :         glPopMatrix();
     445           0 :     }
     446             : };
     447           0 : 
     448           0 : class CShaderProgramFFP_GuiMinimap : public CShaderProgramFFP
     449           0 : {
     450           0 : protected:
     451           0 :     CShaderDefines m_Defines;
     452             :     // Uniforms
     453             :     enum
     454             :     {
     455             :         ID_transform,
     456             :         ID_textureTransform,
     457             :         ID_color,
     458             :         ID_pointSize,
     459             :     };
     460             : public:
     461             :     CShaderProgramFFP_GuiMinimap(const CShaderDefines& defines) :
     462             :         CShaderProgramFFP(0) // We set the streamflags later, during initialization.
     463             :     {
     464             :         m_Defines = defines;
     465             :         SetUniformIndex("transform", ID_transform);
     466             :         SetUniformIndex("textureTransform", ID_textureTransform);
     467           0 :         SetUniformIndex("color", ID_color);
     468           0 :         SetUniformIndex("pointSize", ID_pointSize);
     469             : 
     470           0 :         if (m_Defines.GetInt("MINIMAP_BASE") || m_Defines.GetInt("MINIMAP_LOS"))
     471           0 :         {
     472           0 :             SetUniformIndex("baseTex", 0);
     473           0 :             m_StreamFlags = STREAM_POS | STREAM_UV0;
     474           0 :         }
     475             :         else if (m_Defines.GetInt("MINIMAP_POINT"))
     476           0 :             m_StreamFlags = STREAM_POS | STREAM_COLOR;
     477             :         else
     478           0 :             m_StreamFlags = STREAM_POS;
     479           0 :     }
     480             : 
     481           0 :     virtual void Uniform(Binding id, const CMatrix3D& v)
     482           0 :     {
     483             :         if (id.second == ID_textureTransform)
     484           0 :         {
     485           0 :             glMatrixMode(GL_TEXTURE);
     486             :             glLoadMatrixf(&v._11);
     487           0 :         }
     488             :         else if (id.second == ID_transform)
     489           0 :         {
     490             :             glMatrixMode(GL_MODELVIEW);
     491           0 :             glLoadMatrixf(&v._11);
     492           0 :         }
     493             :     }
     494           0 : 
     495             :     virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
     496           0 :     {
     497           0 :         if (id.second == ID_color)
     498             :             glColor4f(v0, v1, v2, v3);
     499           0 :         else if (id.second == ID_pointSize)
     500             :             glPointSize(v0);
     501           0 :     }
     502             : 
     503           0 :     virtual void Bind()
     504           0 :     {
     505           0 :         // Setup matrix environment
     506           0 :         glMatrixMode(GL_PROJECTION);
     507           0 :         glPushMatrix();
     508             :         glLoadIdentity();
     509           0 :         glMatrixMode(GL_MODELVIEW);
     510             :         glPushMatrix();
     511             :         glLoadIdentity();
     512           0 :         glMatrixMode(GL_TEXTURE);
     513           0 :         glPushMatrix();
     514           0 :         glLoadIdentity();
     515           0 : 
     516           0 :         BindClientStates();
     517           0 : 
     518           0 :         // Setup texture environment
     519           0 :         if (m_Defines.GetInt("MINIMAP_BASE"))
     520           0 :         {
     521             :             pglActiveTextureARB(GL_TEXTURE0);
     522           0 :             glEnable(GL_TEXTURE_2D);
     523             :             glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     524             :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     525           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     526             :         }
     527           0 :         else if (m_Defines.GetInt("MINIMAP_LOS"))
     528           0 :         {
     529           0 :             pglActiveTextureARB(GL_TEXTURE0);
     530           0 :             glEnable(GL_TEXTURE_2D);
     531           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     532             :             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
     533           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
     534             :             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     535           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     536           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
     537           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
     538           0 :             glColor3f(0.0f, 0.0f, 0.0f);
     539           0 :         }
     540           0 :         else if (m_Defines.GetInt("MINIMAP_POINT"))
     541           0 :         {
     542           0 :             pglActiveTextureARB(GL_TEXTURE0);
     543           0 :             glDisable(GL_TEXTURE_2D);
     544           0 :             glEnableClientState(GL_VERTEX_ARRAY);
     545             :             glEnableClientState(GL_COLOR_ARRAY);
     546           0 :         }
     547             :         else if (m_Defines.GetInt("MINIMAP_LINE"))
     548           0 :         {
     549           0 :             // JoshuaJB 13.7.2014: This doesn't seem to do anything on my drivers.
     550           0 :             glEnable(GL_LINE_SMOOTH);
     551           0 :         }
     552             :     }
     553           0 : 
     554             :     virtual void Unbind()
     555             :     {
     556           0 :         // Reset texture environment
     557             :         if (m_Defines.GetInt("MINIMAP_POINT"))
     558           0 :         {
     559             :             pglActiveTextureARB(GL_TEXTURE0);
     560           0 :             glEnable(GL_TEXTURE_2D);
     561             :             glDisableClientState(GL_VERTEX_ARRAY);
     562             :             glDisableClientState(GL_COLOR_ARRAY);
     563           0 :         }
     564             :         else if (m_Defines.GetInt("MINIMAP_LINE"))
     565           0 :         {
     566           0 :             glDisable(GL_LINE_SMOOTH);
     567           0 :         }
     568           0 : 
     569             :         UnbindClientStates();
     570           0 : 
     571             :         // Clear matrix stack
     572           0 :         glMatrixMode(GL_TEXTURE);
     573             :         glPopMatrix();
     574             :         glMatrixMode(GL_PROJECTION);
     575           0 :         glPopMatrix();
     576             :         glMatrixMode(GL_MODELVIEW);
     577             :         glPopMatrix();
     578           0 :     }
     579           0 : };
     580           0 : 
     581           0 : class CShaderProgramFFP_GuiBasic : public CShaderProgramFFP_Gui_Base
     582           0 : {
     583           0 : public:
     584           0 :     CShaderProgramFFP_GuiBasic() :
     585             :         CShaderProgramFFP_Gui_Base(STREAM_POS | STREAM_UV0)
     586             :     {
     587             :     }
     588             : 
     589             :     virtual void Bind()
     590           0 :     {
     591           0 :         CShaderProgramFFP_Gui_Base::Bind();
     592             : 
     593             :         pglActiveTextureARB(GL_TEXTURE0);
     594             :         glEnable(GL_TEXTURE_2D);
     595           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     596             :     }
     597           0 : 
     598             :     virtual void Unbind()
     599           0 :     {
     600           0 :         pglActiveTextureARB(GL_TEXTURE0);
     601           0 :         glDisable(GL_TEXTURE_2D);
     602           0 : 
     603             :         CShaderProgramFFP_Gui_Base::Unbind();
     604           0 :     }
     605             : };
     606           0 : 
     607           0 : class CShaderProgramFFP_GuiAdd : public CShaderProgramFFP_Gui_Base
     608             : {
     609           0 : public:
     610           0 :     using CShaderProgramFFP_Gui_Base::Uniform;
     611             : 
     612             :     CShaderProgramFFP_GuiAdd() :
     613             :         CShaderProgramFFP_Gui_Base(STREAM_POS | STREAM_UV0)
     614             :     {
     615             :     }
     616             : 
     617             :     virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
     618           0 :     {
     619           0 :         if (id.second == ID_color)
     620             :             glColor4f(v0, v1, v2, v3);
     621             :     }
     622             : 
     623           0 :     virtual void Bind()
     624             :     {
     625           0 :         CShaderProgramFFP_Gui_Base::Bind();
     626           0 : 
     627           0 :         pglActiveTextureARB(GL_TEXTURE0);
     628             :         glEnable(GL_TEXTURE_2D);
     629           0 : 
     630             :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     631           0 : 
     632             :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
     633           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
     634           0 : 
     635             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
     636           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
     637             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
     638           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
     639           0 : 
     640             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
     641           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
     642           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
     643           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
     644           0 :     }
     645             : 
     646           0 :     virtual void Unbind()
     647           0 :     {
     648           0 :         glColor4f(1.f, 1.f, 1.f, 1.f);
     649           0 : 
     650           0 :         pglActiveTextureARB(GL_TEXTURE0);
     651             :         glDisable(GL_TEXTURE_2D);
     652           0 : 
     653             :         CShaderProgramFFP_Gui_Base::Unbind();
     654           0 :     }
     655             : };
     656           0 : 
     657           0 : class CShaderProgramFFP_GuiGrayscale : public CShaderProgramFFP_Gui_Base
     658             : {
     659           0 : public:
     660           0 :     CShaderProgramFFP_GuiGrayscale() :
     661             :         CShaderProgramFFP_Gui_Base(STREAM_POS | STREAM_UV0)
     662             :     {
     663             :     }
     664             : 
     665             :     virtual void Bind()
     666           0 :     {
     667           0 :         CShaderProgramFFP_Gui_Base::Bind();
     668             : 
     669             :         /*
     670             : 
     671           0 :         For the main conversion, use GL_DOT3_RGB, which is defined as
     672             :             L = 4 * ((Arg0r - 0.5) * (Arg1r - 0.5)+
     673           0 :                      (Arg0g - 0.5) * (Arg1g - 0.5)+
     674             :                      (Arg0b - 0.5) * (Arg1b - 0.5))
     675             :         where each of the RGB components is given the value 'L'.
     676             : 
     677             :         Use the magical luminance formula
     678             :             L = 0.3R + 0.59G + 0.11B
     679             :         to calculate the greyscale value.
     680             : 
     681             :         But to work around the annoying "Arg0-0.5", we need to calculate
     682             :         Arg0+0.5. But we also need to scale it into the range 0.5-1.0, else
     683             :         Arg0>0.5 will be clamped to 1.0. So use GL_INTERPOLATE, which outputs:
     684             :             A0 * A2 + A1 * (1 - A2)
     685             :         and set A2 = 0.5, A1 = 1.0, and A0 = texture (i.e. interpolating halfway
     686             :         between the texture and {1,1,1}) giving
     687             :             A0/2 + 0.5
     688             :         and use that as Arg0.
     689             : 
     690             :         So L = 4*(A0/2 * (Arg1-.5))
     691             :              = 2 (Rx+Gy+Bz)      (where Arg1 = {x+0.5, y+0.5, z+0.5})
     692             :              = 2x R + 2y G + 2z B
     693             :              = 0.3R + 0.59G + 0.11B
     694             :         so e.g. 2y = 0.59 = 2(Arg1g-0.5) => Arg1g = 0.59/2+0.5
     695             :         which fortunately doesn't get clamped.
     696             : 
     697             :         So, just implement that:
     698             : 
     699             :         */
     700             : 
     701             :         static const float GreyscaleDotColor[4] = {
     702             :             0.3f / 2.f + 0.5f,
     703             :             0.59f / 2.f + 0.5f,
     704             :             0.11f / 2.f + 0.5f,
     705             :             1.0f
     706             :         };
     707           0 :         static const float GreyscaleInterpColor0[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
     708             :         static const float GreyscaleInterpColor1[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
     709             : 
     710             :         pglActiveTextureARB(GL_TEXTURE0);
     711             :         glEnable(GL_TEXTURE_2D);
     712             : 
     713           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     714           0 : 
     715             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
     716           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
     717           0 : 
     718             :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
     719           0 : 
     720             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
     721           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
     722           0 :         glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GreyscaleInterpColor0);
     723             : 
     724           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS);
     725             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
     726           0 : 
     727           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
     728           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
     729             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
     730           0 : 
     731           0 :         glColor4fv(GreyscaleInterpColor1);
     732             : 
     733           0 :         pglActiveTextureARB(GL_TEXTURE1);
     734           0 :         glEnable(GL_TEXTURE_2D);
     735           0 : 
     736             :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     737           0 : 
     738             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
     739           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
     740           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
     741             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
     742           0 : 
     743             :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
     744           0 : 
     745           0 :         // GL_DOT3_RGB requires GL_(EXT|ARB)_texture_env_dot3.
     746           0 :         // We currently don't bother implementing a fallback because it's
     747           0 :         // only lacking on Riva-class HW, but at least want the rest of the
     748             :         // game to run there without errors. Therefore, squelch the
     749           0 :         // OpenGL error that's raised if they aren't actually present.
     750             :         // Note: higher-level code checks for this extension, but
     751             :         // allows users the choice of continuing even if not present.
     752             :         ogl_SquelchError(GL_INVALID_ENUM);
     753             : 
     754             :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
     755             : 
     756             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
     757             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
     758           0 :         glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GreyscaleDotColor);
     759             : 
     760           0 :         // To activate the second texture unit, we have to have some kind
     761             :         // of texture bound into it, but we don't actually use the texture data,
     762           0 :         // so bind a dummy texture
     763           0 :         g_Renderer.GetTextureManager().GetErrorTexture()->Bind(1);
     764           0 :     }
     765             : 
     766             :     virtual void Unbind()
     767             :     {
     768             :         glColor4f(1.f, 1.f, 1.f, 1.f);
     769           0 : 
     770           0 :         pglActiveTextureARB(GL_TEXTURE1);
     771             :         glDisable(GL_TEXTURE_2D);
     772           0 : 
     773             :         pglActiveTextureARB(GL_TEXTURE0);
     774           0 :         glDisable(GL_TEXTURE_2D);
     775             : 
     776           0 :         CShaderProgramFFP_Gui_Base::Unbind();
     777           0 :     }
     778             : };
     779           0 : 
     780           0 : class CShaderProgramFFP_GuiSolid : public CShaderProgramFFP_Gui_Base
     781             : {
     782           0 : public:
     783           0 :     using CShaderProgramFFP_Gui_Base::Uniform;
     784             : 
     785             :     CShaderProgramFFP_GuiSolid() :
     786             :         CShaderProgramFFP_Gui_Base(STREAM_POS)
     787             :     {
     788             :     }
     789             : 
     790             :     virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
     791           0 :     {
     792           0 :         if (id.second == ID_color)
     793             :             glColor4f(v0, v1, v2, v3);
     794             :     }
     795             : 
     796           0 :     virtual void Bind()
     797             :     {
     798           0 :         CShaderProgramFFP_Gui_Base::Bind();
     799           0 : 
     800           0 :         pglActiveTextureARB(GL_TEXTURE0);
     801             :         glDisable(GL_TEXTURE_2D);
     802           0 :     }
     803             : };
     804           0 : 
     805             : //////////////////////////////////////////////////////////////////////////
     806           0 : 
     807           0 : /**
     808           0 :  * Common functionality for model rendering in the fixed renderpath.
     809             :  */
     810             : class CShaderProgramFFP_Model_Base : public CShaderProgramFFP
     811             : {
     812             : protected:
     813             :     // Uniforms
     814             :     enum
     815             :     {
     816             :         ID_transform,
     817             :         ID_objectColor,
     818             :         ID_playerColor,
     819             :         ID_losTransform
     820             :     };
     821             : 
     822             :     bool m_IgnoreLos;
     823             : 
     824             : public:
     825             :     CShaderProgramFFP_Model_Base(const CShaderDefines& defines, int streamflags)
     826             :         : CShaderProgramFFP(streamflags)
     827             :     {
     828             :         SetUniformIndex("transform", ID_transform);
     829             :         SetUniformIndex("losTransform", ID_losTransform);
     830             : 
     831           0 :         if (defines.GetInt("USE_OBJECTCOLOR"))
     832           0 :             SetUniformIndex("objectColor", ID_objectColor);
     833             : 
     834           0 :         if (defines.GetInt("USE_PLAYERCOLOR"))
     835           0 :             SetUniformIndex("playerColor", ID_playerColor);
     836             : 
     837           0 :         m_IgnoreLos = (defines.GetInt("IGNORE_LOS") != 0);
     838           0 : 
     839             :         // Texture units:
     840           0 :         SetUniformIndex("baseTex", 0);
     841           0 :         SetUniformIndex("losTex", 3);
     842             :     }
     843           0 : 
     844             :     virtual void Uniform(Binding id, const CMatrix3D& v)
     845             :     {
     846           0 :         if (id.second == ID_transform)
     847           0 :             glLoadMatrixf(&v._11);
     848           0 :     }
     849             : 
     850           0 :     virtual void Uniform(Binding id, float v0, float v1, float UNUSED(v2), float UNUSED(v3))
     851             :     {
     852           0 :         if (id.second == ID_losTransform)
     853           0 :         {
     854           0 :             pglActiveTextureARB(GL_TEXTURE3);
     855             :             GLfloat texgenS1[4] = { v0, 0, 0, v1 };
     856           0 :             GLfloat texgenT1[4] = { 0, 0, v0, v1 };
     857             :             glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS1);
     858           0 :             glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT1);
     859             :         }
     860           0 :     }
     861           0 : 
     862           0 :     virtual void Bind()
     863           0 :     {
     864           0 :         glMatrixMode(GL_PROJECTION);
     865             :         glPushMatrix();
     866           0 :         glLoadIdentity();
     867             :         glMatrixMode(GL_MODELVIEW);
     868           0 :         glPushMatrix();
     869             : 
     870           0 :         // -----------------------------------------------------------------------------
     871           0 : 
     872           0 :         pglActiveTextureARB(GL_TEXTURE3);
     873           0 :         glEnable(GL_TEXTURE_2D);
     874           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     875             : 
     876             :         if (m_IgnoreLos)
     877             :         {
     878           0 :             // RGB pass through
     879           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
     880           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
     881             :             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     882           0 :         }
     883             :         else
     884             :         {
     885           0 :             // Multiply RGB result up till now with LoS texture alpha channel
     886           0 :             glEnable(GL_TEXTURE_GEN_S);
     887           0 :             glEnable(GL_TEXTURE_GEN_T);
     888             :             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
     889             :             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
     890             :             // Overridden implementation of Uniform() sets GL_OBJECT_PLANE values
     891             : 
     892           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     893           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
     894           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     895           0 :             glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
     896             :             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
     897             :         }
     898           0 : 
     899           0 :         // alpha pass through
     900           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     901           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
     902           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     903             : 
     904             :         // -----------------------------------------------------------------------------
     905             : 
     906           0 :         BindClientStates();
     907           0 :     }
     908           0 : 
     909             :     virtual void Unbind()
     910             :     {
     911             :         UnbindClientStates();
     912           0 : 
     913           0 :         pglActiveTextureARB(GL_TEXTURE3);
     914             :         glDisable(GL_TEXTURE_2D);
     915           0 : 
     916             :         glDisable(GL_TEXTURE_GEN_S);
     917           0 :         glDisable(GL_TEXTURE_GEN_T);
     918             : 
     919           0 :         pglActiveTextureARB(GL_TEXTURE0);
     920           0 : 
     921             :         glMatrixMode(GL_PROJECTION);
     922           0 :         glPopMatrix();
     923           0 :         glMatrixMode(GL_MODELVIEW);
     924             :         glPopMatrix();
     925           0 :     }
     926             : };
     927           0 : 
     928           0 : /**
     929           0 :  * Basic non-recolored diffuse-textured model rendering.
     930           0 :  */
     931           0 : class CShaderProgramFFP_Model : public CShaderProgramFFP_Model_Base
     932             : {
     933             : public:
     934             :     CShaderProgramFFP_Model(const CShaderDefines& defines)
     935             :         : CShaderProgramFFP_Model_Base(defines, STREAM_POS | STREAM_COLOR | STREAM_UV0)
     936             :     {
     937             :     }
     938             : 
     939             :     virtual void Bind()
     940             :     {
     941           0 :         // Set up texture environment for base pass - modulate texture and vertex color
     942             :         pglActiveTextureARB(GL_TEXTURE0);
     943             :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     944             :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
     945           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
     946             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
     947             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
     948           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
     949           0 : 
     950           0 :         // Copy alpha channel from texture
     951           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
     952           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
     953           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
     954           0 : 
     955             :         // The vertex color is scaled by 0.5 to permit overbrightness without clamping.
     956             :         // We therefore need to scale by 2.0 after the modulation, and before any
     957           0 :         // further clamping, to get the right color.
     958           0 :         float scale2[] = { 2.0f, 2.0f, 2.0f };
     959           0 :         glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale2);
     960             : 
     961             :         CShaderProgramFFP_Model_Base::Bind();
     962             :     }
     963             : 
     964           0 :     virtual void Unbind()
     965           0 :     {
     966             :         CShaderProgramFFP_Model_Base::Unbind();
     967           0 : 
     968           0 :         pglActiveTextureARB(GL_TEXTURE0);
     969             : 
     970           0 :         // Revert the scaling to default
     971             :         float scale1[] = { 1.0f, 1.0f, 1.0f };
     972           0 :         glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale1);
     973             :     }
     974           0 : };
     975             : 
     976             : /**
     977           0 :  * Player-coloring diffuse-textured model rendering.
     978           0 :  */
     979           0 : class CShaderProgramFFP_ModelColor : public CShaderProgramFFP_Model_Base
     980             : {
     981             : public:
     982             :     CShaderProgramFFP_ModelColor(const CShaderDefines& defines)
     983             :         : CShaderProgramFFP_Model_Base(defines, STREAM_POS | STREAM_COLOR | STREAM_UV0)
     984             :     {
     985             :     }
     986             : 
     987             :     virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
     988             :     {
     989           0 :         if (id.second == ID_objectColor || id.second == ID_playerColor)
     990             :         {
     991             :             // (Player color and object color are mutually exclusive)
     992             :             float color[] = { v0, v1, v2, v3 };
     993           0 :             glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
     994             :         }
     995           0 :     }
     996             : 
     997             :     virtual void Bind()
     998           0 :     {
     999           0 :         // Player color uses a single pass with three texture environments
    1000             :         // Note: This uses ARB_texture_env_crossbar (which is checked in GameSetup),
    1001           0 :         // and it requires MAX_TEXTURE_IMAGE_UNITS >= 3 (which only excludes GF2MX/GF4MX)
    1002             :         //
    1003           0 :         // We calculate: Result = Color*Texture*(PlayerColor*(1-Texture.a) + 1.0*Texture.a)
    1004             :         // Algebra gives us:
    1005             :         // Result = (1 - ((1 - PlayerColor) * (1 - Texture.a)))*Texture*Color
    1006             : 
    1007             :         // TexEnv #0
    1008             :         pglActiveTextureARB(GL_TEXTURE0);
    1009             :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    1010             :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
    1011             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
    1012             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_ALPHA);
    1013             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
    1014           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_ONE_MINUS_SRC_COLOR);
    1015           0 : 
    1016           0 :         // Don't care about alpha; set it to something harmless
    1017           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
    1018           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
    1019           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
    1020           0 : 
    1021             :         // TexEnv #1
    1022             :         pglActiveTextureARB(GL_TEXTURE1);
    1023           0 :         glEnable(GL_TEXTURE_2D);
    1024           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    1025           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
    1026             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
    1027             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
    1028           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
    1029           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
    1030           0 : 
    1031           0 :         // Don't care about alpha; set it to something harmless
    1032           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
    1033           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
    1034           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
    1035           0 : 
    1036             :         // TexEnv #2
    1037             :         pglActiveTextureARB(GL_TEXTURE2);
    1038           0 :         glEnable(GL_TEXTURE_2D);
    1039           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    1040           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
    1041             :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
    1042             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
    1043           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0);
    1044           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
    1045           0 : 
    1046           0 :         // Don't care about alpha; set it to something harmless
    1047           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
    1048           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
    1049           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
    1050           0 : 
    1051             :         float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    1052             :         glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
    1053           0 : 
    1054           0 :         // Scale colors at the end of all the computation (see CShaderProgramFFP_Model::Bind)
    1055           0 :         float scale[] = { 2.0f, 2.0f, 2.0f };
    1056             :         glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale);
    1057           0 : 
    1058           0 :         // Need to bind some kind of texture to enable the texture units.
    1059             :         // Unit 0 has baseTex, but the others need a texture.
    1060             :         g_Renderer.GetTextureManager().GetErrorTexture()->Bind(1);
    1061           0 :         g_Renderer.GetTextureManager().GetErrorTexture()->Bind(2);
    1062           0 : 
    1063             :         CShaderProgramFFP_Model_Base::Bind();
    1064             :     }
    1065             : 
    1066           0 :     virtual void Unbind()
    1067           0 :     {
    1068             :         CShaderProgramFFP_Model_Base::Unbind();
    1069           0 : 
    1070           0 :         pglActiveTextureARB(GL_TEXTURE2);
    1071             :         glDisable(GL_TEXTURE_2D);
    1072           0 : 
    1073             :         float scale[] = { 1.0f, 1.0f, 1.0f };
    1074           0 :         glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale);
    1075             : 
    1076           0 :         pglActiveTextureARB(GL_TEXTURE1);
    1077           0 :         glDisable(GL_TEXTURE_2D);
    1078             : 
    1079           0 :         pglActiveTextureARB(GL_TEXTURE0);
    1080           0 :     }
    1081             : };
    1082           0 : 
    1083           0 : /**
    1084             :  * Optionally-player-colored untextured model rendering.
    1085           0 :  */
    1086           0 : class CShaderProgramFFP_ModelSolid : public CShaderProgramFFP_Model_Base
    1087             : {
    1088             : public:
    1089             :     CShaderProgramFFP_ModelSolid(const CShaderDefines& defines)
    1090             :         : CShaderProgramFFP_Model_Base(defines, STREAM_POS)
    1091             :     {
    1092             :     }
    1093             : 
    1094             :     virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
    1095             :     {
    1096           0 :         if (id.second == ID_playerColor)
    1097             :         {
    1098             :             float color[] = { v0, v1, v2, v3 };
    1099             :             glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
    1100           0 :         }
    1101             :     }
    1102           0 : 
    1103             :     virtual void Bind()
    1104           0 :     {
    1105           0 :         float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    1106             :         glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
    1107           0 : 
    1108             :         pglActiveTextureARB(GL_TEXTURE0);
    1109           0 :         glEnable(GL_TEXTURE_2D);
    1110             :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    1111           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
    1112           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT);
    1113             :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
    1114           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
    1115           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);
    1116           0 :         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
    1117           0 : 
    1118           0 :         CShaderProgramFFP_Model_Base::Bind();
    1119           0 :     }
    1120           0 : };
    1121           0 : 
    1122           0 : /**
    1123             :  * Plain unlit texture model rendering, for e.g. alpha-blended shadow casters.
    1124           0 :  */
    1125           0 : class CShaderProgramFFP_ModelSolidTex : public CShaderProgramFFP_Model_Base
    1126             : {
    1127             : public:
    1128             :     CShaderProgramFFP_ModelSolidTex(const CShaderDefines& defines)
    1129             :         : CShaderProgramFFP_Model_Base(defines, STREAM_POS | STREAM_UV0)
    1130             :     {
    1131             :     }
    1132             : 
    1133             :     virtual void Bind()
    1134             :     {
    1135           0 :         pglActiveTextureARB(GL_TEXTURE0);
    1136             :         glEnable(GL_TEXTURE_2D);
    1137             :         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    1138             : 
    1139           0 :         CShaderProgramFFP_Model_Base::Bind();
    1140             :     }
    1141           0 : };
    1142           0 : 
    1143           0 : //////////////////////////////////////////////////////////////////////////
    1144             : 
    1145           0 : /*static*/ CShaderProgram* CShaderProgram::ConstructFFP(const std::string& id, const CShaderDefines& defines)
    1146           0 : {
    1147             :     LOGWARNING("CShaderProgram::ConstructFFP: '%s': fixed pipeline is going to be removed soon, don't use its programs", id.c_str());
    1148             :     if (id == "dummy")
    1149             :         return new CShaderProgramFFP_Dummy();
    1150             :     if (id == "overlayline")
    1151           0 :         return new CShaderProgramFFP_OverlayLine(defines);
    1152             :     if (id == "gui_text")
    1153           0 :         return new CShaderProgramFFP_GuiText();
    1154           0 :     if (id == "gui_basic")
    1155           0 :         return new CShaderProgramFFP_GuiBasic();
    1156           0 :     if (id == "gui_add")
    1157           0 :         return new CShaderProgramFFP_GuiAdd();
    1158           0 :     if (id == "gui_grayscale")
    1159           0 :         return new CShaderProgramFFP_GuiGrayscale();
    1160           0 :     if (id == "gui_solid")
    1161           0 :         return new CShaderProgramFFP_GuiSolid();
    1162           0 :     if (id == "minimap")
    1163           0 :         return new CShaderProgramFFP_GuiMinimap(defines);
    1164           0 :     if (id == "solid")
    1165           0 :         return new CShaderProgramFFP_GuiSolid(); // works for non-GUI objects too
    1166           0 :     if (id == "model")
    1167           0 :         return new CShaderProgramFFP_Model(defines);
    1168           0 :     if (id == "model_color")
    1169           0 :         return new CShaderProgramFFP_ModelColor(defines);
    1170           0 :     if (id == "model_solid")
    1171           0 :         return new CShaderProgramFFP_ModelSolid(defines);
    1172           0 :     if (id == "model_solid_tex")
    1173           0 :         return new CShaderProgramFFP_ModelSolidTex(defines);
    1174           0 : 
    1175           0 :     LOGERROR("CShaderProgram::ConstructFFP: '%s': Invalid id", id.c_str());
    1176           0 :     debug_warn(L"CShaderProgram::ConstructFFP: Invalid id");
    1177           0 :     return NULL;
    1178           0 : }
    1179           0 : 
    1180             : #else // CONFIG2_GLES
    1181           0 : 
    1182           0 : /*static*/ CShaderProgram* CShaderProgram::ConstructFFP(const std::string& UNUSED(id), const CShaderDefines& UNUSED(defines))
    1183             : {
    1184             :     debug_warn(L"CShaderProgram::ConstructFFP: FFP not supported on this device");
    1185             :     return NULL;
    1186             : }
    1187             : 
    1188             : #endif // CONFIG2_GLES

Generated by: LCOV version 1.13