mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 13:23:56 -07:00
Move GUI renderer towards using shader infrastructure.
Remove support for unused GUI sprite effects. Use vertex arrays for bounding box rendering. This was SVN commit r11039.
This commit is contained in:
parent
bbded2db91
commit
1f5b8f1c9a
12 changed files with 396 additions and 457 deletions
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -19,11 +19,13 @@
|
|||
|
||||
#include "ShaderProgram.h"
|
||||
|
||||
#include "graphics/TextureManager.h"
|
||||
#include "lib/res/graphics/ogl_tex.h"
|
||||
#include "maths/Matrix3D.h"
|
||||
#include "maths/Vector3D.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/Overlay.h"
|
||||
#include "renderer/Renderer.h"
|
||||
|
||||
/**
|
||||
* CShaderProgramFFP allows rendering code to use the shader-based API
|
||||
|
|
@ -93,6 +95,14 @@ public:
|
|||
return Binding(-1, GetUniformIndex(id));
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
std::map<CStr, int> m_UniformIndexes;
|
||||
};
|
||||
|
|
@ -267,8 +277,6 @@ class CShaderProgramFFP_GuiText : public CShaderProgramFFP
|
|||
ID_colorMul
|
||||
};
|
||||
|
||||
bool m_IgnoreLos;
|
||||
|
||||
public:
|
||||
CShaderProgramFFP_GuiText() :
|
||||
CShaderProgramFFP(STREAM_POS | STREAM_UV0)
|
||||
|
|
@ -283,17 +291,13 @@ public:
|
|||
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()
|
||||
|
|
@ -323,12 +327,287 @@ public:
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CShaderProgramFFP_Gui_Base : public CShaderProgramFFP
|
||||
{
|
||||
protected:
|
||||
// Uniforms
|
||||
enum
|
||||
{
|
||||
ID_transform,
|
||||
ID_color
|
||||
};
|
||||
|
||||
public:
|
||||
CShaderProgramFFP_Gui_Base(int streamflags) :
|
||||
CShaderProgramFFP(streamflags)
|
||||
{
|
||||
m_UniformIndexes["transform"] = ID_transform;
|
||||
m_UniformIndexes["color"] = ID_color;
|
||||
|
||||
// Texture units:
|
||||
m_UniformIndexes["tex"] = 0;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
virtual void Unbind()
|
||||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*static*/ CShaderProgram* CShaderProgram::ConstructFFP(const std::string& id, const std::map<CStr, CStr>& defines)
|
||||
{
|
||||
if (id == "overlayline")
|
||||
return new CShaderProgramFFP_OverlayLine(defines);
|
||||
if (id == "gui_text")
|
||||
return new CShaderProgramFFP_GuiText();
|
||||
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();
|
||||
|
||||
LOGERROR(L"CShaderProgram::ConstructFFP: Invalid id '%hs'", id.c_str());
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -1573,8 +1573,6 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
|
|||
image.m_WrapMode = GL_MIRRORED_REPEAT;
|
||||
else if (attr_value == L"clamp_to_edge")
|
||||
image.m_WrapMode = GL_CLAMP_TO_EDGE;
|
||||
else if (attr_value == L"clamp_to_border")
|
||||
image.m_WrapMode = GL_CLAMP_TO_BORDER;
|
||||
else
|
||||
LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
|
||||
}
|
||||
|
|
@ -1656,28 +1654,18 @@ void CGUI::Xeromyces_ReadEffects(XMBElement Element, CXeromyces* pFile, SGUIImag
|
|||
CStr attr_name (pFile->GetAttributeString(attr.Name));
|
||||
CStrW attr_value (attr.Value.FromUTF8());
|
||||
|
||||
#define COLOR(xml, mem, alpha) \
|
||||
if (attr_name == xml) \
|
||||
{ \
|
||||
CColor color; \
|
||||
if (!GUI<int>::ParseColor(attr_value, color, alpha)) \
|
||||
LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str()); \
|
||||
else effects.m_##mem = color; \
|
||||
} \
|
||||
if (attr_name == "add_color")
|
||||
{
|
||||
CColor color;
|
||||
if (!GUI<int>::ParseColor(attr_value, color, 0.f))
|
||||
LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
|
||||
else effects.m_AddColor = color;
|
||||
}
|
||||
else if (attr_name == "grayscale")
|
||||
{
|
||||
effects.m_Greyscale = true;
|
||||
}
|
||||
else
|
||||
|
||||
|
||||
#define BOOL(xml, mem) \
|
||||
if (attr_name == xml) \
|
||||
{ \
|
||||
effects.m_##mem = true; \
|
||||
} \
|
||||
else
|
||||
|
||||
COLOR("add_color", AddColor, 0.f)
|
||||
COLOR("multiply_color", MultiplyColor, 255.f)
|
||||
BOOL("grayscale", Greyscale)
|
||||
|
||||
{
|
||||
debug_warn(L"Invalid data - DTD shouldn't allow this");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ struct SGUIImageEffects
|
|||
{
|
||||
SGUIImageEffects() : m_Greyscale(false) {}
|
||||
CColor m_AddColor;
|
||||
CColor m_MultiplyColor;
|
||||
bool m_Greyscale;
|
||||
};
|
||||
|
||||
|
|
@ -116,7 +115,7 @@ struct SGUIImage
|
|||
bool m_RoundCoordinates;
|
||||
|
||||
/**
|
||||
* Texture wrapping mode (GL_REPEAT, GL_CLAMP_TO_BORDER, etc)
|
||||
* Texture wrapping mode (GL_REPEAT, GL_CLAMP_TO_EDGE, etc)
|
||||
*/
|
||||
GLint m_WrapMode;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "GUIRenderer.h"
|
||||
|
||||
#include "graphics/ShaderManager.h"
|
||||
#include "graphics/TextureManager.h"
|
||||
#include "gui/GUIutil.h"
|
||||
#include "lib/ogl.h"
|
||||
|
|
@ -33,24 +34,10 @@
|
|||
using namespace GUIRenderer;
|
||||
|
||||
|
||||
void DrawCalls::clear()
|
||||
{
|
||||
for (iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
delete it->m_Effects;
|
||||
}
|
||||
std::vector<SDrawCall>::clear();
|
||||
}
|
||||
|
||||
DrawCalls::DrawCalls()
|
||||
{
|
||||
}
|
||||
|
||||
DrawCalls::~DrawCalls()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// DrawCalls needs to be copyable, so it can be used in other copyable types.
|
||||
// But actually copying data is hard, since we'd need to avoid losing track of
|
||||
// who owns various pointers, so instead we just return an empty list.
|
||||
|
|
@ -69,293 +56,6 @@ const DrawCalls& DrawCalls::operator=(const DrawCalls&)
|
|||
}
|
||||
|
||||
|
||||
|
||||
// Implementations of graphical effects:
|
||||
|
||||
|
||||
const GLint TexScale1[3] = { 1, 1, 1 };
|
||||
const GLint TexScale2[3] = { 2, 2, 2 };
|
||||
const GLint TexScale4[3] = { 4, 4, 4 };
|
||||
|
||||
class Effect_AddColor : public IGLState
|
||||
{
|
||||
// Uses GL_COMBINE and GL_ADD/GL_SUBTRACT/GL_ADD_SIGNED, to allow
|
||||
// addition/subtraction of colors.
|
||||
|
||||
public:
|
||||
Effect_AddColor(CColor c)
|
||||
{
|
||||
// If everything's in [0,1], use GL_ADD
|
||||
#define RANGE(lo,hi) c.r >= lo && c.r <= hi && c.g >= lo && c.g <= hi && c.b >= lo && c.b <= hi && c.a >= lo && c.a <= hi
|
||||
if (RANGE(0.f, 1.f))
|
||||
{
|
||||
m_Color = c;
|
||||
m_Method = ADD_NORMAL;
|
||||
}
|
||||
// If it's in [-1, 0] use GL_SUBTRACT
|
||||
else if (RANGE(-1.f, 0.f))
|
||||
{
|
||||
m_Color = CColor(-c.r, -c.g, -c.b, -c.a);
|
||||
m_Method = ADD_SUBTRACT;
|
||||
}
|
||||
// If it's in [-0.5, 0.5] use GL_ADD_SIGNED
|
||||
else if (RANGE(-0.5f, 0.5f))
|
||||
{
|
||||
m_Color = CColor(c.r+0.5f, c.g+0.5f, c.b+0.5f, c.a+0.5f);
|
||||
m_Method = ADD_SIGNED;
|
||||
}
|
||||
// Otherwise, complain.
|
||||
else
|
||||
{
|
||||
LOGWARNING(L"add_color effect has some components above 127 and some below -127 - colours will be clamped");
|
||||
m_Color = CColor(c.r+0.5f, c.g+0.5f, c.b+0.5f, c.a+0.5f);
|
||||
m_Method = ADD_SIGNED;
|
||||
}
|
||||
}
|
||||
|
||||
~Effect_AddColor() {}
|
||||
|
||||
void Set(const CTexturePtr& tex)
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glColor4fv(m_Color.FloatArray());
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
if (m_Method == ADD_NORMAL)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
|
||||
}
|
||||
else
|
||||
if (m_Method == ADD_SUBTRACT)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_SUBTRACT);
|
||||
}
|
||||
else // if (m_Method == ADD_SIGNED)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD_SIGNED);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD_SIGNED);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
tex->Bind();
|
||||
}
|
||||
|
||||
void Unset()
|
||||
{
|
||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||
}
|
||||
|
||||
private:
|
||||
CColor m_Color;
|
||||
enum { ADD_NORMAL, ADD_SUBTRACT, ADD_SIGNED, ADD_SIGNED_DOUBLED } m_Method;
|
||||
};
|
||||
|
||||
class Effect_MultiplyColor : public IGLState
|
||||
{
|
||||
// Uses GL_MODULATE to do the multiplication; but since all colours are
|
||||
// clamped to the range [0,1], it uses GL_RGB_SCALE to allow images to be
|
||||
// multiplied by [0,4]. Alpha is assumed to always be [0,1].
|
||||
public:
|
||||
Effect_MultiplyColor(CColor c)
|
||||
{
|
||||
if (c.r <= 1.f && c.g <= 1.f && c.b <= 1.f)
|
||||
{
|
||||
m_Color = c;
|
||||
m_Scale = 1;
|
||||
}
|
||||
else if (c.r <= 2.f && c.g <= 2.f && c.b <= 2.f)
|
||||
{
|
||||
m_Color = CColor(c.r/2.f, c.g/2.f, c.b/2.f, c.a);
|
||||
m_Scale = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c.r <= 4.f && c.g <= 4.f && c.b <= 4.f)
|
||||
;
|
||||
else
|
||||
// Oops - trying to multiply by >4
|
||||
LOGWARNING(L"multiply_color effect has a component >1020 - colours will be clamped");
|
||||
|
||||
m_Color = CColor(c.r/4.f, c.g/4.f, c.b/4.f, c.a);
|
||||
m_Scale = 4;
|
||||
}
|
||||
}
|
||||
~Effect_MultiplyColor() {}
|
||||
void Set(const CTexturePtr& tex)
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glColor4fv(m_Color.FloatArray());
|
||||
|
||||
if (m_Scale == 1)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Duplicate the effect of GL_MODULATE, but using GL_COMBINE
|
||||
// so that GL_RGB_SCALE will work.
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, 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_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);
|
||||
|
||||
if (m_Scale == 2)
|
||||
glTexEnviv(GL_TEXTURE_ENV, GL_RGB_SCALE, TexScale2);
|
||||
else if (m_Scale == 4)
|
||||
glTexEnviv(GL_TEXTURE_ENV, GL_RGB_SCALE, TexScale4);
|
||||
}
|
||||
|
||||
tex->Bind();
|
||||
}
|
||||
void Unset()
|
||||
{
|
||||
if (m_Scale != 1)
|
||||
glTexEnviv(GL_TEXTURE_ENV, GL_RGB_SCALE, TexScale1);
|
||||
|
||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||
}
|
||||
private:
|
||||
CColor m_Color;
|
||||
int m_Scale;
|
||||
};
|
||||
|
||||
#define X(n) (n##f/2.0f + 0.5f)
|
||||
const float GreyscaleDotColor[4] = { X(0.3), X(0.59), X(0.11), 1.0f };
|
||||
#undef X
|
||||
const float GreyscaleInterpColor0[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
const float GreyscaleInterpColor1[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
||||
|
||||
class Effect_Greyscale : public IGLState
|
||||
{
|
||||
public:
|
||||
~Effect_Greyscale() {}
|
||||
void Set(const CTexturePtr& tex)
|
||||
{
|
||||
/*
|
||||
|
||||
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:
|
||||
|
||||
*/
|
||||
|
||||
// TODO: Render all greyscale objects at the same time, to reduce
|
||||
// the number of times the following code is called - it looks like
|
||||
// a rather worrying amount of work for rendering a single button...
|
||||
|
||||
// Texture unit 0:
|
||||
|
||||
tex->Bind(0);
|
||||
|
||||
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);
|
||||
|
||||
// Texture unit 1:
|
||||
|
||||
tex->Bind(1);
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
void Unset()
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Functions to perform drawing-related actions:
|
||||
|
||||
void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, const CStr& SpriteName, const CRect &Size, int CellID, std::map<CStr, CGUISprite> &Sprites)
|
||||
{
|
||||
// This is called only when something has changed (like the size of the
|
||||
|
|
@ -485,37 +185,34 @@ void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, const CStr& SpriteName,
|
|||
Call.m_BackColor = cit->m_BackColor;
|
||||
Call.m_BorderColor = cit->m_Border ? cit->m_BorderColor : CColor();
|
||||
Call.m_DeltaZ = cit->m_DeltaZ;
|
||||
|
||||
if (cit->m_Effects)
|
||||
|
||||
if (!Call.m_HasTexture)
|
||||
{
|
||||
Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect("shader:fixed:gui_solid");
|
||||
}
|
||||
else if (cit->m_Effects)
|
||||
{
|
||||
if (cit->m_Effects->m_AddColor != CColor())
|
||||
{
|
||||
Call.m_Effects = new Effect_AddColor(cit->m_Effects->m_AddColor);
|
||||
Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect("shader:fixed:gui_add");
|
||||
Call.m_ShaderColorParameter = cit->m_Effects->m_AddColor;
|
||||
// Always enable blending if something's being subtracted from
|
||||
// the alpha channel
|
||||
if (cit->m_Effects->m_AddColor.a < 0.f)
|
||||
Call.m_EnableBlending = true;
|
||||
}
|
||||
else if (cit->m_Effects->m_MultiplyColor != CColor())
|
||||
{
|
||||
Call.m_Effects = new Effect_MultiplyColor(cit->m_Effects->m_MultiplyColor);
|
||||
// Always enable blending if the alpha channel is being multiplied
|
||||
if (cit->m_Effects->m_AddColor.a != 1.f)
|
||||
Call.m_EnableBlending = true;
|
||||
}
|
||||
else if (cit->m_Effects->m_Greyscale)
|
||||
{
|
||||
Call.m_Effects = new Effect_Greyscale;
|
||||
Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect("shader:fixed:gui_grayscale");
|
||||
}
|
||||
else /* Slight confusion - why no effects? */
|
||||
{
|
||||
Call.m_Effects = NULL;
|
||||
Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect("shader:fixed:gui_basic");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Call.m_Effects = NULL;
|
||||
Call.m_Shader = g_Renderer.GetShaderManager().LoadEffect("shader:fixed:gui_basic");
|
||||
}
|
||||
|
||||
Calls.push_back(Call);
|
||||
|
|
@ -598,33 +295,31 @@ void GUIRenderer::Draw(DrawCalls &Calls, float Z)
|
|||
{
|
||||
// Called every frame, to draw the object (based on cached calculations)
|
||||
|
||||
glPushMatrix();
|
||||
// TODO: batching by shader/texture/etc would be nice
|
||||
|
||||
CMatrix3D matrix = GetDefaultGuiMatrix();
|
||||
matrix.Translate(0, 0, Z);
|
||||
glLoadMatrixf(&matrix._11);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
// Set LOD bias so mipmapped textures are prettier
|
||||
#if CONFIG2_GLES
|
||||
#warning TODO: implement GUI LOD bias for GLES
|
||||
#else
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -1.f);
|
||||
#endif
|
||||
|
||||
// Iterate through each DrawCall, and execute whatever drawing code is being called
|
||||
for (DrawCalls::const_iterator cit = Calls.begin(); cit != Calls.end(); ++cit)
|
||||
{
|
||||
if (cit->m_HasTexture)
|
||||
{
|
||||
// TODO: Handle the GL state in a nicer way
|
||||
cit->m_Shader->BeginPass(0);
|
||||
CShaderProgramPtr shader = cit->m_Shader->GetShader(0);
|
||||
shader->Uniform("transform", matrix);
|
||||
shader->Uniform("color", cit->m_ShaderColorParameter);
|
||||
shader->BindTexture("tex", cit->m_Texture);
|
||||
|
||||
if (cit->m_Effects)
|
||||
cit->m_Effects->Set(cit->m_Texture);
|
||||
else
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
cit->m_Texture->Bind();
|
||||
}
|
||||
|
||||
if (cit->m_EnableBlending || cit->m_Texture->HasAlpha()) // (shouldn't call HasAlpha before Bind)
|
||||
if (cit->m_EnableBlending || cit->m_Texture->HasAlpha()) // (shouldn't call HasAlpha before BindTexture)
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
|
@ -648,25 +343,27 @@ void GUIRenderer::Draw(DrawCalls &Calls, float Z)
|
|||
glBegin(GL_QUADS);
|
||||
|
||||
glTexCoord2f(TexCoords.left, TexCoords.bottom);
|
||||
glVertex3f(Verts.left, Verts.bottom, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.left, Verts.bottom, Z + cit->m_DeltaZ);
|
||||
|
||||
glTexCoord2f(TexCoords.right, TexCoords.bottom);
|
||||
glVertex3f(Verts.right, Verts.bottom, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right, Verts.bottom, Z + cit->m_DeltaZ);
|
||||
|
||||
glTexCoord2f(TexCoords.right, TexCoords.top);
|
||||
glVertex3f(Verts.right, Verts.top, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right, Verts.top, Z + cit->m_DeltaZ);
|
||||
|
||||
glTexCoord2f(TexCoords.left, TexCoords.top);
|
||||
glVertex3f(Verts.left, Verts.top, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.left, Verts.top, Z + cit->m_DeltaZ);
|
||||
|
||||
glEnd();
|
||||
|
||||
if (cit->m_Effects)
|
||||
cit->m_Effects->Unset();
|
||||
cit->m_Shader->EndPass(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
cit->m_Shader->BeginPass(0);
|
||||
CShaderProgramPtr shader = cit->m_Shader->GetShader(0);
|
||||
shader->Uniform("transform", matrix);
|
||||
shader->Uniform("color", cit->m_BackColor);
|
||||
|
||||
if (cit->m_EnableBlending)
|
||||
{
|
||||
|
|
@ -674,8 +371,6 @@ void GUIRenderer::Draw(DrawCalls &Calls, float Z)
|
|||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
glColor4fv(cit->m_BackColor.FloatArray());
|
||||
|
||||
// Ensure the quad has the correct winding order
|
||||
CRect Verts = cit->m_Vertices;
|
||||
if (Verts.right < Verts.left)
|
||||
|
|
@ -684,29 +379,32 @@ void GUIRenderer::Draw(DrawCalls &Calls, float Z)
|
|||
std::swap(Verts.bottom, Verts.top);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(Verts.left, Verts.bottom, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right, Verts.bottom, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right, Verts.top, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.left, Verts.top, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.left, Verts.bottom, Z + cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right, Verts.bottom, Z + cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right, Verts.top, Z + cit->m_DeltaZ);
|
||||
glVertex3f(Verts.left, Verts.top, Z + cit->m_DeltaZ);
|
||||
glEnd();
|
||||
|
||||
|
||||
if (cit->m_BorderColor != CColor())
|
||||
{
|
||||
glColor4fv(cit->m_BorderColor.FloatArray());
|
||||
shader->Uniform("color", cit->m_BorderColor);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3f(Verts.left + 0.5f, Verts.top + 0.5f, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right - 0.5f, Verts.top + 0.5f, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right - 0.5f, Verts.bottom - 0.5f, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.left + 0.5f, Verts.bottom - 0.5f, cit->m_DeltaZ);
|
||||
glVertex3f(Verts.left + 0.5f, Verts.top + 0.5f, Z + cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right - 0.5f, Verts.top + 0.5f, Z + cit->m_DeltaZ);
|
||||
glVertex3f(Verts.right - 0.5f, Verts.bottom - 0.5f, Z + cit->m_DeltaZ);
|
||||
glVertex3f(Verts.left + 0.5f, Verts.bottom - 0.5f, Z + cit->m_DeltaZ);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
cit->m_Shader->EndPass(0);
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
#if CONFIG2_GLES
|
||||
#warning TODO: implement GUI LOD bias for GLES
|
||||
#else
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.f);
|
||||
|
||||
glPopMatrix();
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2010 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#ifndef GUIRenderer_h
|
||||
#define GUIRenderer_h
|
||||
|
||||
#include "graphics/ShaderTechnique.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "lib/res/handle.h"
|
||||
#include "ps/Overlay.h"
|
||||
|
|
@ -39,7 +40,7 @@ namespace GUIRenderer
|
|||
|
||||
struct SDrawCall
|
||||
{
|
||||
SDrawCall(const SGUIImage* image) : m_Image(image), m_Effects(NULL) {}
|
||||
SDrawCall(const SGUIImage* image) : m_Image(image) {}
|
||||
CRect ComputeTexCoords() const;
|
||||
|
||||
const SGUIImage* m_Image;
|
||||
|
|
@ -52,7 +53,8 @@ namespace GUIRenderer
|
|||
|
||||
bool m_EnableBlending;
|
||||
|
||||
IGLState* m_Effects;
|
||||
CShaderTechniquePtr m_Shader;
|
||||
CColor m_ShaderColorParameter;
|
||||
|
||||
CRect m_Vertices;
|
||||
float m_DeltaZ;
|
||||
|
|
@ -64,9 +66,7 @@ namespace GUIRenderer
|
|||
class DrawCalls : public std::vector<SDrawCall>
|
||||
{
|
||||
public:
|
||||
void clear();
|
||||
DrawCalls();
|
||||
~DrawCalls();
|
||||
// Copy/assignment results in an empty list, not an actual copy
|
||||
DrawCalls(const DrawCalls&);
|
||||
const DrawCalls& operator=(const DrawCalls&);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -25,7 +25,7 @@ GUI utilities
|
|||
#include "maths/Matrix3D.h"
|
||||
#include "ps/Parser.h"
|
||||
|
||||
extern int g_yres;
|
||||
extern int g_xres, g_yres;
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
|
|
@ -256,6 +256,11 @@ CMatrix3D GetDefaultGuiMatrix()
|
|||
m.SetIdentity();
|
||||
m.Scale(1.0f, -1.f, 1.0f);
|
||||
m.Translate(0.0f, (float)g_yres, -1000.0f);
|
||||
|
||||
CMatrix3D proj;
|
||||
proj.SetOrtho(0.f, (float)g_xres, 0.f, (float)g_yres, -1.f, 1000.f);
|
||||
m = proj * m;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class CMatrix3D;
|
|||
template <typename T>
|
||||
bool __ParseString(const CStrW& Value, T &tOutput);
|
||||
|
||||
// Matrix with (0,0) in top-left of screen
|
||||
// Model-view-projection matrix with (0,0) in top-left of screen
|
||||
CMatrix3D GetDefaultGuiMatrix();
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -299,6 +299,10 @@ void CMiniMap::Draw()
|
|||
RebuildTerrainTexture();
|
||||
}
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
CMatrix3D matrix = GetDefaultGuiMatrix();
|
||||
glLoadMatrixf(&matrix._11);
|
||||
|
|
@ -421,6 +425,10 @@ void CMiniMap::Draw()
|
|||
|
||||
glPopMatrix();
|
||||
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
// Reset everything back to normal
|
||||
|
|
|
|||
|
|
@ -237,35 +237,35 @@ void CBoundingBoxAligned::Expand(float amount)
|
|||
// Render the bounding box
|
||||
void CBoundingBoxAligned::Render() const
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0); glVertex3f(m_Data[0].X, m_Data[0].Y, m_Data[0].Z);
|
||||
glTexCoord2f(1, 0); glVertex3f(m_Data[1].X, m_Data[0].Y, m_Data[0].Z);
|
||||
glTexCoord2f(1, 1); glVertex3f(m_Data[1].X, m_Data[1].Y, m_Data[0].Z);
|
||||
glTexCoord2f(0, 1); glVertex3f(m_Data[0].X, m_Data[1].Y, m_Data[0].Z);
|
||||
std::vector<float> data;
|
||||
|
||||
glTexCoord2f(0, 0); glVertex3f(m_Data[0].X, m_Data[0].Y, m_Data[0].Z);
|
||||
glTexCoord2f(1, 0); glVertex3f(m_Data[0].X, m_Data[1].Y, m_Data[0].Z);
|
||||
glTexCoord2f(1, 1); glVertex3f(m_Data[0].X, m_Data[1].Y, m_Data[1].Z);
|
||||
glTexCoord2f(0, 1); glVertex3f(m_Data[0].X, m_Data[0].Y, m_Data[1].Z);
|
||||
#define ADD_FACE(x, y, z) \
|
||||
ADD_PT(0, 0, x, y, z); ADD_PT(1, 0, x, y, z); ADD_PT(1, 1, x, y, z); \
|
||||
ADD_PT(1, 1, x, y, z); ADD_PT(0, 1, x, y, z); ADD_PT(0, 0, x, y, z);
|
||||
#define ADD_PT(u_, v_, x, y, z) \
|
||||
STMT(int u = u_; int v = v_; \
|
||||
data.push_back(u); \
|
||||
data.push_back(v); \
|
||||
data.push_back(m_Data[x].X); \
|
||||
data.push_back(m_Data[y].Y); \
|
||||
data.push_back(m_Data[z].Z); \
|
||||
)
|
||||
|
||||
glTexCoord2f(0, 0); glVertex3f(m_Data[0].X, m_Data[0].Y, m_Data[1].Z);
|
||||
glTexCoord2f(1, 0); glVertex3f(m_Data[1].X, m_Data[0].Y, m_Data[1].Z);
|
||||
glTexCoord2f(1, 1); glVertex3f(m_Data[1].X, m_Data[0].Y, m_Data[0].Z);
|
||||
glTexCoord2f(0, 1); glVertex3f(m_Data[0].X, m_Data[0].Y, m_Data[0].Z);
|
||||
ADD_FACE(u, v, 0);
|
||||
ADD_FACE(0, u, v);
|
||||
ADD_FACE(u, 0, 1-v);
|
||||
ADD_FACE(u, 1-v, 1);
|
||||
ADD_FACE(1, u, 1-v);
|
||||
ADD_FACE(u, 1, v);
|
||||
|
||||
glTexCoord2f(0, 0); glVertex3f(m_Data[0].X, m_Data[1].Y, m_Data[1].Z);
|
||||
glTexCoord2f(1, 0); glVertex3f(m_Data[1].X, m_Data[1].Y, m_Data[1].Z);
|
||||
glTexCoord2f(1, 1); glVertex3f(m_Data[1].X, m_Data[0].Y, m_Data[1].Z);
|
||||
glTexCoord2f(0, 1); glVertex3f(m_Data[0].X, m_Data[0].Y, m_Data[1].Z);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), &data[0]);
|
||||
glVertexPointer(3, GL_FLOAT, 5*sizeof(float), &data[2]);
|
||||
|
||||
glTexCoord2f(0, 0); glVertex3f(m_Data[1].X, m_Data[0].Y, m_Data[1].Z);
|
||||
glTexCoord2f(1, 0); glVertex3f(m_Data[1].X, m_Data[1].Y, m_Data[1].Z);
|
||||
glTexCoord2f(1, 1); glVertex3f(m_Data[1].X, m_Data[1].Y, m_Data[0].Z);
|
||||
glTexCoord2f(0, 1); glVertex3f(m_Data[1].X, m_Data[0].Y, m_Data[0].Z);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6*6);
|
||||
|
||||
glTexCoord2f(0, 0); glVertex3f(m_Data[0].X, m_Data[1].Y, m_Data[0].Z);
|
||||
glTexCoord2f(1, 0); glVertex3f(m_Data[1].X, m_Data[1].Y, m_Data[0].Z);
|
||||
glTexCoord2f(1, 1); glVertex3f(m_Data[1].X, m_Data[1].Y, m_Data[1].Z);
|
||||
glTexCoord2f(0, 1); glVertex3f(m_Data[0].X, m_Data[1].Y, m_Data[1].Z);
|
||||
glEnd();
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -301,36 +301,4 @@ void CBrush::Intersect(const CFrustum& frustum, CBrush& result) const
|
|||
}
|
||||
|
||||
ENSURE(prev == &result);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Dump the faces to OpenGL
|
||||
void CBrush::Render() const
|
||||
{
|
||||
size_t firstInFace = no_vertex;
|
||||
|
||||
for(size_t i = 0; i < m_Faces.size(); ++i)
|
||||
{
|
||||
if (firstInFace == no_vertex)
|
||||
{
|
||||
glBegin(GL_POLYGON);
|
||||
firstInFace = m_Faces[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
const CVector3D& vertex = m_Vertices[m_Faces[i]];
|
||||
|
||||
glVertex3fv(&vertex.X);
|
||||
|
||||
if (firstInFace == m_Faces[i])
|
||||
{
|
||||
glEnd();
|
||||
firstInFace = no_vertex;
|
||||
}
|
||||
}
|
||||
|
||||
ENSURE(firstInFace == no_vertex);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -75,14 +75,6 @@ public:
|
|||
*/
|
||||
void Intersect(const CFrustum& frustum, CBrush& result) const;
|
||||
|
||||
/**
|
||||
* Render: Renders the brush as OpenGL polygons.
|
||||
*
|
||||
* @note the winding of the brush faces is undefined (i.e. it is undefined which
|
||||
* sides of the faces are the front faces)
|
||||
*/
|
||||
void Render() const;
|
||||
|
||||
private:
|
||||
static const size_t no_vertex = ~0u;
|
||||
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ void ParticleRenderer::RenderParticles(bool solidColor)
|
|||
emitter->RenderArray();
|
||||
}
|
||||
|
||||
CVertexBuffer::Unbind();
|
||||
|
||||
pglBlendEquationEXT(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue