2012-02-08 21:43:38 +01:00
|
|
|
/* Copyright (C) 2012 Wildfire Games.
|
2011-08-27 16:31:24 +02:00
|
|
|
* This file is part of 0 A.D.
|
|
|
|
*
|
|
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 0 A.D. is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precompiled.h"
|
|
|
|
|
|
|
|
#include "ShaderProgram.h"
|
|
|
|
|
2012-04-03 20:44:46 +02:00
|
|
|
#include "graphics/ShaderDefines.h"
|
2012-02-08 21:43:38 +01:00
|
|
|
#include "graphics/TextureManager.h"
|
2011-08-27 16:31:24 +02:00
|
|
|
#include "lib/res/graphics/ogl_tex.h"
|
2012-01-30 01:27:23 +01:00
|
|
|
#include "maths/Matrix3D.h"
|
2011-08-27 16:31:24 +02:00
|
|
|
#include "maths/Vector3D.h"
|
|
|
|
#include "ps/CLogger.h"
|
|
|
|
#include "ps/Overlay.h"
|
2012-02-08 21:43:38 +01:00
|
|
|
#include "renderer/Renderer.h"
|
2011-08-27 16:31:24 +02:00
|
|
|
|
2012-02-12 14:20:49 +01:00
|
|
|
#if !CONFIG2_GLES
|
|
|
|
|
2011-08-27 16:31:24 +02:00
|
|
|
/**
|
|
|
|
* CShaderProgramFFP allows rendering code to use the shader-based API
|
|
|
|
* even if the 'shader' is actually implemented with the fixed-function
|
|
|
|
* pipeline instead of anything programmable.
|
|
|
|
*
|
|
|
|
* Currently we just hard-code a number of FFP programs as subclasses of this.
|
|
|
|
* If we have lots, it might be nicer to abstract out the common functionality
|
|
|
|
* and load these from text files or something.
|
|
|
|
*/
|
|
|
|
class CShaderProgramFFP : public CShaderProgram
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP(int streamflags) :
|
|
|
|
CShaderProgram(streamflags)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~CShaderProgramFFP()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Reload()
|
|
|
|
{
|
|
|
|
m_IsValid = true;
|
|
|
|
}
|
|
|
|
|
2012-04-08 17:55:06 +02:00
|
|
|
int GetUniformIndex(CStrIntern id)
|
2011-08-27 16:31:24 +02:00
|
|
|
{
|
2012-04-08 17:55:06 +02:00
|
|
|
std::map<CStrIntern, int>::iterator it = m_UniformIndexes.find(id);
|
2011-08-27 16:31:24 +02:00
|
|
|
if (it == m_UniformIndexes.end())
|
|
|
|
return -1;
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
2012-04-03 20:44:46 +02:00
|
|
|
virtual Binding GetTextureBinding(uniform_id_t id)
|
2011-08-27 16:31:24 +02:00
|
|
|
{
|
2012-04-08 17:55:06 +02:00
|
|
|
int index = GetUniformIndex(CStrIntern(id));
|
2012-04-03 20:44:46 +02:00
|
|
|
if (index == -1)
|
|
|
|
return Binding();
|
|
|
|
else
|
|
|
|
return Binding((int)GL_TEXTURE_2D, index);
|
2011-08-27 16:31:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void BindTexture(texture_id_t id, Handle tex)
|
|
|
|
{
|
2012-04-08 17:55:06 +02:00
|
|
|
int index = GetUniformIndex(CStrIntern(id));
|
2011-08-27 16:31:24 +02:00
|
|
|
if (index != -1)
|
|
|
|
ogl_tex_bind(tex, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void BindTexture(texture_id_t id, GLuint tex)
|
|
|
|
{
|
2012-04-08 17:55:06 +02:00
|
|
|
int index = GetUniformIndex(CStrIntern(id));
|
2011-08-27 16:31:24 +02:00
|
|
|
if (index != -1)
|
|
|
|
{
|
|
|
|
pglActiveTextureARB((int)(GL_TEXTURE0+index));
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-03 20:44:46 +02:00
|
|
|
virtual void BindTexture(Binding id, Handle tex)
|
2012-01-30 01:27:23 +01:00
|
|
|
{
|
2012-04-03 20:44:46 +02:00
|
|
|
int index = id.second;
|
|
|
|
if (index != -1)
|
|
|
|
ogl_tex_bind(tex, index);
|
2012-01-30 01:27:23 +01:00
|
|
|
}
|
|
|
|
|
2011-08-27 16:31:24 +02:00
|
|
|
virtual Binding GetUniformBinding(uniform_id_t id)
|
2012-04-08 17:55:06 +02:00
|
|
|
{
|
|
|
|
return Binding(-1, GetUniformIndex(CStrIntern(id)));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Binding GetUniformBinding(CStrIntern id)
|
2011-08-27 16:31:24 +02:00
|
|
|
{
|
|
|
|
return Binding(-1, GetUniformIndex(id));
|
|
|
|
}
|
|
|
|
|
2012-02-08 21:43:38 +01:00
|
|
|
virtual void Uniform(Binding UNUSED(id), float UNUSED(v0), float UNUSED(v1), float UNUSED(v2), float UNUSED(v3))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding UNUSED(id), const CMatrix3D& UNUSED(v))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-04-12 16:10:02 +02:00
|
|
|
virtual void Uniform(Binding UNUSED(id), size_t UNUSED(count), const CMatrix3D* UNUSED(v))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-08-27 16:31:24 +02:00
|
|
|
protected:
|
2012-04-08 17:55:06 +02:00
|
|
|
std::map<CStrIntern, int> m_UniformIndexes;
|
|
|
|
|
|
|
|
void SetUniformIndex(const char* id, int value)
|
|
|
|
{
|
|
|
|
m_UniformIndexes[CStrIntern(id)] = value;
|
|
|
|
}
|
2011-08-27 16:31:24 +02:00
|
|
|
};
|
|
|
|
|
2012-01-30 01:27:23 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-02-13 15:02:14 +01:00
|
|
|
/**
|
|
|
|
* A shader that does nothing but provide a shader-compatible interface to
|
|
|
|
* fixed-function features, for compatibility with existing fixed-function
|
|
|
|
* code that isn't fully ported to the shader API.
|
|
|
|
*/
|
|
|
|
class CShaderProgramFFP_Dummy : public CShaderProgramFFP
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_Dummy() :
|
|
|
|
CShaderProgramFFP(0)
|
|
|
|
{
|
2012-03-20 14:32:30 +01:00
|
|
|
// Texture units, for when this shader is used with terrain:
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("baseTex", 0);
|
2012-02-13 15:02:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
BindClientStates();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
|
|
|
UnbindClientStates();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2011-08-27 16:31:24 +02:00
|
|
|
class CShaderProgramFFP_OverlayLine : public CShaderProgramFFP
|
|
|
|
{
|
|
|
|
// Uniforms
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
ID_losTransform,
|
|
|
|
ID_objectColor
|
|
|
|
};
|
|
|
|
|
2011-12-10 08:07:04 +01:00
|
|
|
bool m_IgnoreLos;
|
2012-04-22 06:04:02 +02:00
|
|
|
bool m_UseObjectColor;
|
2011-12-10 08:07:04 +01:00
|
|
|
|
2011-08-27 16:31:24 +02:00
|
|
|
public:
|
2012-04-03 20:44:46 +02:00
|
|
|
CShaderProgramFFP_OverlayLine(const CShaderDefines& defines) :
|
2012-04-22 06:04:02 +02:00
|
|
|
CShaderProgramFFP(0) // will be set manually in initializer below
|
2011-08-27 16:31:24 +02:00
|
|
|
{
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("losTransform", ID_losTransform);
|
|
|
|
SetUniformIndex("objectColor", ID_objectColor);
|
2011-08-27 16:31:24 +02:00
|
|
|
|
|
|
|
// Texture units:
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("baseTex", 0);
|
|
|
|
SetUniformIndex("maskTex", 1);
|
|
|
|
SetUniformIndex("losTex", 2);
|
2011-12-10 08:07:04 +01:00
|
|
|
|
2012-04-03 20:44:46 +02:00
|
|
|
m_IgnoreLos = (defines.GetInt("IGNORE_LOS") != 0);
|
2012-04-22 06:04:02 +02:00
|
|
|
m_UseObjectColor = (defines.GetInt("USE_OBJECTCOLOR") != 0);
|
|
|
|
|
|
|
|
m_StreamFlags = STREAM_POS | STREAM_UV0 | STREAM_UV1;
|
|
|
|
if (!m_UseObjectColor)
|
|
|
|
m_StreamFlags |= STREAM_COLOR;
|
2011-12-10 08:07:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsIgnoreLos()
|
|
|
|
{
|
|
|
|
return m_IgnoreLos;
|
2011-08-27 16:31:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
|
|
|
|
{
|
2012-01-29 02:22:22 +01:00
|
|
|
if (id.second == ID_losTransform)
|
2011-08-27 16:31:24 +02:00
|
|
|
{
|
|
|
|
pglActiveTextureARB(GL_TEXTURE2);
|
|
|
|
GLfloat texgenS1[4] = { v0, 0, 0, v1 };
|
|
|
|
GLfloat texgenT1[4] = { 0, 0, v0, v1 };
|
|
|
|
glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS1);
|
|
|
|
glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT1);
|
|
|
|
}
|
2012-01-29 02:22:22 +01:00
|
|
|
else if (id.second == ID_objectColor)
|
2011-08-27 16:31:24 +02:00
|
|
|
{
|
|
|
|
float c[] = { v0, v1, v2, v3 };
|
|
|
|
pglActiveTextureARB(GL_TEXTURE1);
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, c);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug_warn(L"Invalid id");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding UNUSED(id), const CMatrix3D& UNUSED(v))
|
|
|
|
{
|
|
|
|
debug_warn(L"Not implemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
// RGB channels:
|
2012-04-22 06:04:02 +02:00
|
|
|
// Unit 0: Sample base texture
|
|
|
|
// Unit 1: Sample mask texture; interpolate with [objectColor or vertexColor] and base, depending on USE_OBJECTCOLOR
|
2011-12-10 08:07:04 +01:00
|
|
|
// Unit 2: (Load LOS texture; multiply) if not #IGNORE_LOS, pass through otherwise
|
2011-08-27 16:31:24 +02:00
|
|
|
// Alpha channel:
|
2012-04-22 06:04:02 +02:00
|
|
|
// Unit 0: Sample base texture
|
2011-08-27 16:31:24 +02:00
|
|
|
// Unit 1: Multiply by objectColor
|
|
|
|
// Unit 2: Pass through
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
|
2012-04-22 06:04:02 +02:00
|
|
|
// Sample base texture RGB
|
2011-08-27 16:31:24 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
|
|
|
2012-04-22 06:04:02 +02:00
|
|
|
// Sample base texture Alpha
|
2011-08-27 16:31:24 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
|
|
|
|
2011-12-10 08:07:04 +01:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
2011-08-27 16:31:24 +02:00
|
|
|
pglActiveTextureARB(GL_TEXTURE1);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
|
2012-04-22 06:04:02 +02:00
|
|
|
// RGB: interpolate component-wise between [objectColor or vertexColor] and base using mask:
|
|
|
|
// a0 * a2 + a1 * (1 - a2)
|
|
|
|
// Overridden implementation of Uniform() sets GL_TEXTURE_ENV_COLOR to objectColor, which
|
|
|
|
// is referenced as GL_CONSTANT (see spec)
|
2011-08-27 16:31:24 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
|
2012-04-22 06:04:02 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, m_UseObjectColor ? GL_CONSTANT : GL_PRIMARY_COLOR);
|
2011-08-27 16:31:24 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
|
|
|
|
|
2012-04-22 06:04:02 +02:00
|
|
|
// ALPHA: Multiply base alpha with [objectColor or vertexColor] alpha
|
2011-08-27 16:31:24 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
|
2012-04-22 06:04:02 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, m_UseObjectColor ? GL_CONSTANT : GL_PRIMARY_COLOR);
|
2011-08-27 16:31:24 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
|
|
|
|
|
2011-12-10 08:07:04 +01:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
2011-08-27 16:31:24 +02:00
|
|
|
pglActiveTextureARB(GL_TEXTURE2);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
|
2011-12-10 08:07:04 +01:00
|
|
|
bool ignoreLos = IsIgnoreLos();
|
|
|
|
if (ignoreLos)
|
|
|
|
{
|
|
|
|
// RGB pass through
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-04-22 06:04:02 +02:00
|
|
|
// Multiply RGB result up till now with LoS texture alpha channel
|
2011-12-10 08:07:04 +01:00
|
|
|
glEnable(GL_TEXTURE_GEN_S);
|
|
|
|
glEnable(GL_TEXTURE_GEN_T);
|
|
|
|
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
|
|
|
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
2012-04-22 06:04:02 +02:00
|
|
|
// Overridden implementation of Uniform() sets GL_OBJECT_PLANE values
|
2011-12-10 08:07:04 +01:00
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
|
|
|
|
}
|
2011-08-27 16:31:24 +02:00
|
|
|
|
2011-12-10 08:07:04 +01:00
|
|
|
// alpha pass through
|
2011-08-27 16:31:24 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
2012-02-09 18:55:25 +01:00
|
|
|
|
|
|
|
BindClientStates();
|
2011-08-27 16:31:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
2012-02-09 18:55:25 +01:00
|
|
|
UnbindClientStates();
|
|
|
|
|
2011-08-27 16:31:24 +02:00
|
|
|
pglActiveTextureARB(GL_TEXTURE2);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_GEN_S);
|
|
|
|
glDisable(GL_TEXTURE_GEN_T);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE1);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-01-30 01:27:23 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class CShaderProgramFFP_GuiText : public CShaderProgramFFP
|
|
|
|
{
|
|
|
|
// Uniforms
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
ID_transform,
|
|
|
|
ID_colorMul
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_GuiText() :
|
|
|
|
CShaderProgramFFP(STREAM_POS | STREAM_UV0)
|
|
|
|
{
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("transform", ID_transform);
|
|
|
|
SetUniformIndex("colorMul", ID_colorMul);
|
2012-01-30 01:27:23 +01:00
|
|
|
|
|
|
|
// Texture units:
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("tex", 0);
|
2012-01-30 01:27:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
|
|
|
|
{
|
|
|
|
if (id.second == ID_colorMul)
|
|
|
|
glColor4f(v0, v1, v2, v3);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding id, const CMatrix3D& v)
|
|
|
|
{
|
|
|
|
if (id.second == ID_transform)
|
|
|
|
glLoadMatrixf(&v._11);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
2012-02-09 18:55:25 +01:00
|
|
|
|
|
|
|
BindClientStates();
|
2012-01-30 01:27:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
2012-02-09 18:55:25 +01:00
|
|
|
UnbindClientStates();
|
|
|
|
|
2012-01-30 01:27:23 +01:00
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-02-08 21:43:38 +01:00
|
|
|
class CShaderProgramFFP_Gui_Base : public CShaderProgramFFP
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
// Uniforms
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
ID_transform,
|
|
|
|
ID_color
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_Gui_Base(int streamflags) :
|
|
|
|
CShaderProgramFFP(streamflags)
|
|
|
|
{
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("transform", ID_transform);
|
|
|
|
SetUniformIndex("color", ID_color);
|
2012-02-08 21:43:38 +01:00
|
|
|
|
|
|
|
// Texture units:
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("tex", 0);
|
2012-02-08 21:43:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding id, const CMatrix3D& v)
|
|
|
|
{
|
|
|
|
if (id.second == ID_transform)
|
|
|
|
glLoadMatrixf(&v._11);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
2012-02-09 18:55:25 +01:00
|
|
|
|
|
|
|
BindClientStates();
|
2012-02-08 21:43:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
2012-02-09 18:55:25 +01:00
|
|
|
UnbindClientStates();
|
|
|
|
|
2012-02-08 21:43:38 +01:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CShaderProgramFFP_GuiBasic : public CShaderProgramFFP_Gui_Base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_GuiBasic() :
|
|
|
|
CShaderProgramFFP_Gui_Base(STREAM_POS | STREAM_UV0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
CShaderProgramFFP_Gui_Base::Bind();
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
CShaderProgramFFP_Gui_Base::Unbind();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CShaderProgramFFP_GuiAdd : public CShaderProgramFFP_Gui_Base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_GuiAdd() :
|
|
|
|
CShaderProgramFFP_Gui_Base(STREAM_POS | STREAM_UV0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
|
|
|
|
{
|
|
|
|
if (id.second == ID_color)
|
|
|
|
glColor4f(v0, v1, v2, v3);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
CShaderProgramFFP_Gui_Base::Bind();
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
|
|
|
glColor4f(1.f, 1.f, 1.f, 1.f);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
CShaderProgramFFP_Gui_Base::Unbind();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CShaderProgramFFP_GuiGrayscale : public CShaderProgramFFP_Gui_Base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_GuiGrayscale() :
|
|
|
|
CShaderProgramFFP_Gui_Base(STREAM_POS | STREAM_UV0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
CShaderProgramFFP_Gui_Base::Bind();
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
For the main conversion, use GL_DOT3_RGB, which is defined as
|
|
|
|
L = 4 * ((Arg0r - 0.5) * (Arg1r - 0.5)+
|
|
|
|
(Arg0g - 0.5) * (Arg1g - 0.5)+
|
|
|
|
(Arg0b - 0.5) * (Arg1b - 0.5))
|
|
|
|
where each of the RGB components is given the value 'L'.
|
|
|
|
|
|
|
|
Use the magical luminance formula
|
|
|
|
L = 0.3R + 0.59G + 0.11B
|
|
|
|
to calculate the greyscale value.
|
|
|
|
|
|
|
|
But to work around the annoying "Arg0-0.5", we need to calculate
|
|
|
|
Arg0+0.5. But we also need to scale it into the range 0.5-1.0, else
|
|
|
|
Arg0>0.5 will be clamped to 1.0. So use GL_INTERPOLATE, which outputs:
|
|
|
|
A0 * A2 + A1 * (1 - A2)
|
|
|
|
and set A2 = 0.5, A1 = 1.0, and A0 = texture (i.e. interpolating halfway
|
|
|
|
between the texture and {1,1,1}) giving
|
|
|
|
A0/2 + 0.5
|
|
|
|
and use that as Arg0.
|
|
|
|
|
|
|
|
So L = 4*(A0/2 * (Arg1-.5))
|
|
|
|
= 2 (Rx+Gy+Bz) (where Arg1 = {x+0.5, y+0.5, z+0.5})
|
|
|
|
= 2x R + 2y G + 2z B
|
|
|
|
= 0.3R + 0.59G + 0.11B
|
|
|
|
so e.g. 2y = 0.59 = 2(Arg1g-0.5) => Arg1g = 0.59/2+0.5
|
|
|
|
which fortunately doesn't get clamped.
|
|
|
|
|
|
|
|
So, just implement that:
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const float GreyscaleDotColor[4] = {
|
|
|
|
0.3f / 2.f + 0.5f,
|
|
|
|
0.59f / 2.f + 0.5f,
|
|
|
|
0.11f / 2.f + 0.5f,
|
|
|
|
1.0f
|
|
|
|
};
|
|
|
|
static const float GreyscaleInterpColor0[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
|
|
static const float GreyscaleInterpColor1[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GreyscaleInterpColor0);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
|
|
|
|
|
|
|
glColor4fv(GreyscaleInterpColor1);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE1);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
|
|
|
|
|
|
|
|
// GL_DOT3_RGB requires GL_(EXT|ARB)_texture_env_dot3.
|
|
|
|
// We currently don't bother implementing a fallback because it's
|
|
|
|
// only lacking on Riva-class HW, but at least want the rest of the
|
|
|
|
// game to run there without errors. Therefore, squelch the
|
|
|
|
// OpenGL error that's raised if they aren't actually present.
|
|
|
|
// Note: higher-level code checks for this extension, but
|
|
|
|
// allows users the choice of continuing even if not present.
|
|
|
|
ogl_SquelchError(GL_INVALID_ENUM);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GreyscaleDotColor);
|
|
|
|
|
|
|
|
// To activate the second texture unit, we have to have some kind
|
|
|
|
// of texture bound into it, but we don't actually use the texture data,
|
|
|
|
// so bind a dummy texture
|
|
|
|
g_Renderer.GetTextureManager().GetErrorTexture()->Bind(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
|
|
|
glColor4f(1.f, 1.f, 1.f, 1.f);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE1);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
CShaderProgramFFP_Gui_Base::Unbind();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CShaderProgramFFP_GuiSolid : public CShaderProgramFFP_Gui_Base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_GuiSolid() :
|
|
|
|
CShaderProgramFFP_Gui_Base(STREAM_POS)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
|
|
|
|
{
|
|
|
|
if (id.second == ID_color)
|
|
|
|
glColor4f(v0, v1, v2, v3);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
CShaderProgramFFP_Gui_Base::Bind();
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-04-03 20:44:46 +02:00
|
|
|
/**
|
|
|
|
* Common functionality for model rendering in the fixed renderpath.
|
|
|
|
*/
|
|
|
|
class CShaderProgramFFP_Model_Base : public CShaderProgramFFP
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
// Uniforms
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
ID_transform,
|
|
|
|
ID_objectColor,
|
|
|
|
ID_playerColor
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_Model_Base(const CShaderDefines& defines, int streamflags)
|
|
|
|
: CShaderProgramFFP(streamflags)
|
|
|
|
{
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("transform", ID_transform);
|
2012-04-03 20:44:46 +02:00
|
|
|
|
|
|
|
if (defines.GetInt("USE_OBJECTCOLOR"))
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("objectColor", ID_objectColor);
|
2012-04-03 20:44:46 +02:00
|
|
|
|
|
|
|
if (defines.GetInt("USE_PLAYERCOLOR"))
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("playerColor", ID_playerColor);
|
2012-04-03 20:44:46 +02:00
|
|
|
|
|
|
|
// Texture units:
|
2012-04-08 17:55:06 +02:00
|
|
|
SetUniformIndex("baseTex", 0);
|
2012-04-03 20:44:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding id, const CMatrix3D& v)
|
|
|
|
{
|
|
|
|
if (id.second == ID_transform)
|
|
|
|
glLoadMatrixf(&v._11);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
|
|
|
|
BindClientStates();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
|
|
|
UnbindClientStates();
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Basic non-recolored diffuse-textured model rendering.
|
|
|
|
*/
|
|
|
|
class CShaderProgramFFP_Model : public CShaderProgramFFP_Model_Base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_Model(const CShaderDefines& defines)
|
|
|
|
: CShaderProgramFFP_Model_Base(defines, STREAM_POS | STREAM_COLOR | STREAM_UV0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
// Set up texture environment for base pass - modulate texture and vertex color
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
|
|
|
|
|
|
|
// Copy alpha channel from texture
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
|
|
|
|
|
|
|
// The vertex color is scaled by 0.5 to permit overbrightness without clamping.
|
|
|
|
// We therefore need to scale by 2.0 after the modulation, and before any
|
|
|
|
// further clamping, to get the right color.
|
|
|
|
float scale2[] = { 2.0f, 2.0f, 2.0f };
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale2);
|
|
|
|
|
|
|
|
CShaderProgramFFP_Model_Base::Bind();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
|
|
|
CShaderProgramFFP_Model_Base::Unbind();
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
|
|
|
|
// Revert the scaling to default
|
|
|
|
float scale1[] = { 1.0f, 1.0f, 1.0f };
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Player-coloring diffuse-textured model rendering.
|
|
|
|
*/
|
|
|
|
class CShaderProgramFFP_ModelColor : public CShaderProgramFFP_Model_Base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_ModelColor(const CShaderDefines& defines)
|
|
|
|
: CShaderProgramFFP_Model_Base(defines, STREAM_POS | STREAM_COLOR | STREAM_UV0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
|
|
|
|
{
|
|
|
|
if (id.second == ID_objectColor || id.second == ID_playerColor)
|
|
|
|
{
|
|
|
|
// (Player color and object color are mutually exclusive)
|
|
|
|
float color[] = { v0, v1, v2, v3 };
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
// Player color uses a single pass with three texture environments
|
|
|
|
// Note: This uses ARB_texture_env_crossbar (which is checked in GameSetup),
|
|
|
|
// and it requires MAX_TEXTURE_IMAGE_UNITS >= 3 (which only excludes GF2MX/GF4MX)
|
|
|
|
//
|
|
|
|
// We calculate: Result = Color*Texture*(PlayerColor*(1-Texture.a) + 1.0*Texture.a)
|
|
|
|
// Algebra gives us:
|
|
|
|
// Result = (1 - ((1 - PlayerColor) * (1 - Texture.a)))*Texture*Color
|
|
|
|
|
|
|
|
// TexEnv #0
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_ONE_MINUS_SRC_COLOR);
|
|
|
|
|
|
|
|
// Don't care about alpha; set it to something harmless
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
|
|
|
|
|
|
|
// TexEnv #1
|
|
|
|
pglActiveTextureARB(GL_TEXTURE1);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
|
|
|
|
|
|
|
// Don't care about alpha; set it to something harmless
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
|
|
|
|
|
|
|
// TexEnv #2
|
|
|
|
pglActiveTextureARB(GL_TEXTURE2);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
|
|
|
|
|
|
|
// Don't care about alpha; set it to something harmless
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
|
|
|
|
|
|
|
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
|
|
|
|
|
|
|
|
// Scale colors at the end of all the computation (see CShaderProgramFFP_Model::Bind)
|
|
|
|
float scale[] = { 2.0f, 2.0f, 2.0f };
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale);
|
|
|
|
|
|
|
|
// Need to bind some kind of texture to enable the texture units.
|
|
|
|
// Unit 0 has baseTex, but the others need a texture.
|
|
|
|
g_Renderer.GetTextureManager().GetErrorTexture()->Bind(1);
|
|
|
|
g_Renderer.GetTextureManager().GetErrorTexture()->Bind(2);
|
|
|
|
|
|
|
|
CShaderProgramFFP_Model_Base::Bind();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Unbind()
|
|
|
|
{
|
|
|
|
CShaderProgramFFP_Model_Base::Unbind();
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE2);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
float scale[] = { 1.0f, 1.0f, 1.0f };
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_RGB_SCALE, scale);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE1);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Optionally-player-colored untextured model rendering.
|
|
|
|
*/
|
|
|
|
class CShaderProgramFFP_ModelSolid : public CShaderProgramFFP_Model_Base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_ModelSolid(const CShaderDefines& defines)
|
|
|
|
: CShaderProgramFFP_Model_Base(defines, STREAM_POS)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
|
|
|
|
{
|
|
|
|
if (id.second == ID_playerColor)
|
|
|
|
{
|
|
|
|
float color[] = { v0, v1, v2, v3 };
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
|
|
|
|
|
|
|
CShaderProgramFFP_Model_Base::Bind();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Plain unlit texture model rendering, for e.g. alpha-blended shadow casters.
|
|
|
|
*/
|
|
|
|
class CShaderProgramFFP_ModelSolidTex : public CShaderProgramFFP_Model_Base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CShaderProgramFFP_ModelSolidTex(const CShaderDefines& defines)
|
|
|
|
: CShaderProgramFFP_Model_Base(defines, STREAM_POS | STREAM_UV0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Bind()
|
|
|
|
{
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
|
|
|
|
|
|
CShaderProgramFFP_Model_Base::Bind();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/*static*/ CShaderProgram* CShaderProgram::ConstructFFP(const std::string& id, const CShaderDefines& defines)
|
2011-08-27 16:31:24 +02:00
|
|
|
{
|
2012-02-13 15:02:14 +01:00
|
|
|
if (id == "dummy")
|
|
|
|
return new CShaderProgramFFP_Dummy();
|
2011-08-27 16:31:24 +02:00
|
|
|
if (id == "overlayline")
|
2011-12-10 08:07:04 +01:00
|
|
|
return new CShaderProgramFFP_OverlayLine(defines);
|
2012-01-30 01:27:23 +01:00
|
|
|
if (id == "gui_text")
|
|
|
|
return new CShaderProgramFFP_GuiText();
|
2012-02-08 21:43:38 +01:00
|
|
|
if (id == "gui_basic")
|
|
|
|
return new CShaderProgramFFP_GuiBasic();
|
|
|
|
if (id == "gui_add")
|
|
|
|
return new CShaderProgramFFP_GuiAdd();
|
|
|
|
if (id == "gui_grayscale")
|
|
|
|
return new CShaderProgramFFP_GuiGrayscale();
|
|
|
|
if (id == "gui_solid")
|
|
|
|
return new CShaderProgramFFP_GuiSolid();
|
2012-02-12 14:20:49 +01:00
|
|
|
if (id == "solid")
|
|
|
|
return new CShaderProgramFFP_GuiSolid(); // works for non-GUI objects too
|
2012-04-03 20:44:46 +02:00
|
|
|
if (id == "model")
|
|
|
|
return new CShaderProgramFFP_Model(defines);
|
|
|
|
if (id == "model_color")
|
|
|
|
return new CShaderProgramFFP_ModelColor(defines);
|
|
|
|
if (id == "model_solid")
|
|
|
|
return new CShaderProgramFFP_ModelSolid(defines);
|
|
|
|
if (id == "model_solid_tex")
|
|
|
|
return new CShaderProgramFFP_ModelSolidTex(defines);
|
2012-02-12 14:20:49 +01:00
|
|
|
|
2012-02-12 14:26:57 +01:00
|
|
|
LOGERROR(L"CShaderProgram::ConstructFFP: '%hs': Invalid id", id.c_str());
|
|
|
|
debug_warn(L"CShaderProgram::ConstructFFP: Invalid id");
|
2012-02-12 14:20:49 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
2011-08-27 16:31:24 +02:00
|
|
|
|
2012-02-12 14:20:49 +01:00
|
|
|
#else // CONFIG2_GLES
|
|
|
|
|
2012-04-03 20:44:46 +02:00
|
|
|
/*static*/ CShaderProgram* CShaderProgram::ConstructFFP(const std::string& UNUSED(id), const CShaderDefines& UNUSED(defines))
|
2012-02-12 14:20:49 +01:00
|
|
|
{
|
2012-02-12 14:26:57 +01:00
|
|
|
debug_warn(L"CShaderProgram::ConstructFFP: FFP not supported on this device");
|
2011-08-27 16:31:24 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-02-12 14:20:49 +01:00
|
|
|
|
|
|
|
#endif // CONFIG2_GLES
|