diff --git a/binaries/data/mods/public/shaders/effects/gui_text.xml b/binaries/data/mods/public/shaders/effects/gui_text.xml
new file mode 100644
index 0000000000..cc2f8f36db
--- /dev/null
+++ b/binaries/data/mods/public/shaders/effects/gui_text.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/binaries/data/mods/public/shaders/gui_text.fs b/binaries/data/mods/public/shaders/gui_text.fs
new file mode 100644
index 0000000000..0333ee3de0
--- /dev/null
+++ b/binaries/data/mods/public/shaders/gui_text.fs
@@ -0,0 +1,10 @@
+uniform vec4 colorAdd;
+uniform vec4 colorMul;
+uniform sampler2D tex;
+
+varying vec2 v_texcoord;
+
+void main()
+{
+ gl_FragColor = (texture2D(tex, v_texcoord) + colorAdd) * colorMul;
+}
diff --git a/binaries/data/mods/public/shaders/gui_text.vs b/binaries/data/mods/public/shaders/gui_text.vs
new file mode 100644
index 0000000000..a27db1f8f8
--- /dev/null
+++ b/binaries/data/mods/public/shaders/gui_text.vs
@@ -0,0 +1,9 @@
+uniform mat4 transform;
+
+varying vec2 v_texcoord;
+
+void main()
+{
+ gl_Position = transform * gl_Vertex;
+ v_texcoord = gl_MultiTexCoord0.xy;
+}
diff --git a/binaries/data/mods/public/shaders/gui_text.xml b/binaries/data/mods/public/shaders/gui_text.xml
new file mode 100644
index 0000000000..dd125a9b13
--- /dev/null
+++ b/binaries/data/mods/public/shaders/gui_text.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/graphics/ShaderManager.cpp b/source/graphics/ShaderManager.cpp
index 566fc5a5f2..4a2638eca1 100644
--- a/source/graphics/ShaderManager.cpp
+++ b/source/graphics/ShaderManager.cpp
@@ -212,6 +212,41 @@ bool CShaderManager::NewProgram(const char* name, const std::map& ba
return true;
}
+static GLenum ParseBlendFunc(const CStr& str)
+{
+ if (str == "zero")
+ return GL_ZERO;
+ if (str == "one")
+ return GL_ONE;
+ if (str == "src_color")
+ return GL_SRC_COLOR;
+ if (str == "one_minus_src_color")
+ return GL_ONE_MINUS_SRC_COLOR;
+ if (str == "dst_color")
+ return GL_DST_COLOR;
+ if (str == "one_minus_dst_color")
+ return GL_ONE_MINUS_DST_COLOR;
+ if (str == "src_alpha")
+ return GL_SRC_ALPHA;
+ if (str == "one_minus_src_alpha")
+ return GL_ONE_MINUS_SRC_ALPHA;
+ if (str == "dst_alpha")
+ return GL_DST_ALPHA;
+ if (str == "one_minus_dst_alpha")
+ return GL_ONE_MINUS_DST_ALPHA;
+ if (str == "constant_color")
+ return GL_CONSTANT_COLOR;
+ if (str == "one_minus_constant_color")
+ return GL_ONE_MINUS_CONSTANT_COLOR;
+ if (str == "constant_alpha")
+ return GL_CONSTANT_ALPHA;
+ if (str == "one_minus_constant_alpha")
+ return GL_ONE_MINUS_CONSTANT_ALPHA;
+ if (str == "src_alpha_saturate")
+ return GL_SRC_ALPHA_SATURATE;
+ return GL_ZERO;
+}
+
CShaderTechnique CShaderManager::LoadEffect(const char* name, const std::map& baseDefines)
{
PROFILE2("loading effect");
@@ -229,8 +264,11 @@ CShaderTechnique CShaderManager::LoadEffect(const char* name, const std::map
#include "graphics/ShaderProgram.h"
+#include "graphics/ShaderTechnique.h"
#if USE_SHADER_XML_VALIDATION
# include "ps/XML/RelaxNG.h"
@@ -31,8 +32,6 @@
#include
-class CShaderTechnique;
-
/**
* Shader manager: loads and caches shader programs.
*/
@@ -48,7 +47,7 @@ public:
* @param defines key/value set of preprocessor definitions
* @return loaded program, or null pointer on error
*/
- CShaderProgramPtr LoadProgram(const char* name, const std::map& defines);
+ CShaderProgramPtr LoadProgram(const char* name, const std::map& defines = std::map());
/**
* Load a shader effect.
@@ -57,7 +56,7 @@ public:
* @param defines key/value set of preprocessor definitions
* @return loaded technique, or empty technique on error
*/
- CShaderTechnique LoadEffect(const char* name, const std::map& defines);
+ CShaderTechnique LoadEffect(const char* name, const std::map& defines = std::map());
private:
bool NewProgram(const char* name, const std::map& defines, CShaderProgramPtr& program);
diff --git a/source/graphics/ShaderProgram.cpp b/source/graphics/ShaderProgram.cpp
index 24f536f245..59d6c4618e 100644
--- a/source/graphics/ShaderProgram.cpp
+++ b/source/graphics/ShaderProgram.cpp
@@ -173,6 +173,11 @@ public:
}
}
+ virtual int GetTextureUnit(texture_id_t id)
+ {
+ return GetUniformFragmentIndex(id);
+ }
+
virtual Binding GetUniformBinding(uniform_id_t id)
{
return Binding(GetUniformVertexIndex(id), GetUniformFragmentIndex(id));
@@ -438,6 +443,15 @@ public:
glBindTexture(it->second.first, tex);
}
+ virtual int GetTextureUnit(texture_id_t id)
+ {
+ std::map >::iterator it = m_Samplers.find(id);
+ if (it == m_Samplers.end())
+ return -1;
+
+ return it->second.second;
+ }
+
virtual Binding GetUniformBinding(uniform_id_t id)
{
int loc = GetUniformLocation(id);
diff --git a/source/graphics/ShaderProgram.h b/source/graphics/ShaderProgram.h
index 6baed6ce85..56e12af62f 100644
--- a/source/graphics/ShaderProgram.h
+++ b/source/graphics/ShaderProgram.h
@@ -149,6 +149,8 @@ public:
virtual void BindTexture(texture_id_t id, GLuint tex) = 0;
+ virtual int GetTextureUnit(texture_id_t) = 0;
+
virtual Binding GetUniformBinding(uniform_id_t id) = 0;
// Uniform-setting methods that subclasses must define:
diff --git a/source/graphics/ShaderProgramFFP.cpp b/source/graphics/ShaderProgramFFP.cpp
index 0a816d63cc..913853ddd4 100644
--- a/source/graphics/ShaderProgramFFP.cpp
+++ b/source/graphics/ShaderProgramFFP.cpp
@@ -20,6 +20,7 @@
#include "ShaderProgram.h"
#include "lib/res/graphics/ogl_tex.h"
+#include "maths/Matrix3D.h"
#include "maths/Vector3D.h"
#include "ps/CLogger.h"
#include "ps/Overlay.h"
@@ -82,6 +83,11 @@ public:
}
}
+ virtual int GetTextureUnit(texture_id_t id)
+ {
+ return GetUniformIndex(id);
+ }
+
virtual Binding GetUniformBinding(uniform_id_t id)
{
return Binding(-1, GetUniformIndex(id));
@@ -91,6 +97,8 @@ protected:
std::map m_UniformIndexes;
};
+//////////////////////////////////////////////////////////////////////////
+
class CShaderProgramFFP_OverlayLine : public CShaderProgramFFP
{
// Uniforms
@@ -248,10 +256,79 @@ public:
}
};
+//////////////////////////////////////////////////////////////////////////
+
+class CShaderProgramFFP_GuiText : public CShaderProgramFFP
+{
+ // Uniforms
+ enum
+ {
+ ID_transform,
+ ID_colorMul
+ };
+
+ bool m_IgnoreLos;
+
+public:
+ CShaderProgramFFP_GuiText() :
+ CShaderProgramFFP(STREAM_POS | STREAM_UV0)
+ {
+ m_UniformIndexes["transform"] = ID_transform;
+ m_UniformIndexes["colorMul"] = ID_colorMul;
+
+ // Texture units:
+ m_UniformIndexes["tex"] = 0;
+ }
+
+ 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);
+ }
+
+ virtual void Unbind()
+ {
+ pglActiveTextureARB(GL_TEXTURE0);
+ glDisable(GL_TEXTURE_2D);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+
/*static*/ CShaderProgram* CShaderProgram::ConstructFFP(const std::string& id, const std::map& defines)
{
if (id == "overlayline")
return new CShaderProgramFFP_OverlayLine(defines);
+ if (id == "gui_text")
+ return new CShaderProgramFFP_GuiText();
LOGERROR(L"CShaderProgram::ConstructFFP: Invalid id '%hs'", id.c_str());
return NULL;
diff --git a/source/graphics/ShaderTechnique.cpp b/source/graphics/ShaderTechnique.cpp
index 0a57a49527..24b7bf6337 100644
--- a/source/graphics/ShaderTechnique.cpp
+++ b/source/graphics/ShaderTechnique.cpp
@@ -146,5 +146,4 @@ CShaderProgramPtr CShaderTechnique::GetShader(int pass)
{
ENSURE(0 <= pass && pass < (int)m_Passes.size());
return m_Passes[pass].GetShader();
-
}
diff --git a/source/graphics/TextRenderer.cpp b/source/graphics/TextRenderer.cpp
index 68b11d516f..1b8588c710 100644
--- a/source/graphics/TextRenderer.cpp
+++ b/source/graphics/TextRenderer.cpp
@@ -23,9 +23,10 @@
#include "lib/res/graphics/unifont.h"
#include "ps/Font.h"
-extern int g_yres;
+extern int g_xres, g_yres;
-CTextRenderer::CTextRenderer()
+CTextRenderer::CTextRenderer(const CShaderProgramPtr& shader) :
+ m_Shader(shader)
{
ResetTransform();
Color(CColor(1.0f, 1.0f, 1.0f, 1.0f));
@@ -37,6 +38,10 @@ void CTextRenderer::ResetTransform()
m_Transform.SetIdentity();
m_Transform.Scale(1.0f, -1.f, 1.0f);
m_Transform.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_Transform = proj * m_Transform;
}
CMatrix3D CTextRenderer::GetTransform()
@@ -101,16 +106,24 @@ void CTextRenderer::Render()
{
SBatch& batch = m_Batches[i];
- batch.font->Bind();
+ int unit = m_Shader->GetTextureUnit("tex");
+ if (unit == -1) // just in case the shader doesn't use the sampler
+ continue;
- glPushMatrix();
- glLoadMatrixf(&batch.transform._11);
+ batch.font->Bind(unit);
- glColor4fv(batch.color.FloatArray());
-
- glwprintf(L"%ls", batch.text.c_str());
+ m_Shader->Uniform("transform", batch.transform);
- glPopMatrix();
+ // ALPHA-only textures will have .rgb sampled as 0, so we need to
+ // replace it with white (but not affect RGBA textures)
+ if (batch.font->HasRGB())
+ m_Shader->Uniform("colorAdd", CColor(0.0f, 0.0f, 0.0f, 0.0f));
+ else
+ m_Shader->Uniform("colorAdd", CColor(1.0f, 1.0f, 1.0f, 0.0f));
+
+ m_Shader->Uniform("colorMul", batch.color);
+
+ unifont_render(batch.text.c_str());
}
m_Batches.clear();
diff --git a/source/graphics/TextRenderer.h b/source/graphics/TextRenderer.h
index 22394601a2..394010c617 100644
--- a/source/graphics/TextRenderer.h
+++ b/source/graphics/TextRenderer.h
@@ -18,6 +18,7 @@
#ifndef INCLUDED_TEXTRENDERER
#define INCLUDED_TEXTRENDERER
+#include "graphics/ShaderProgram.h"
#include "maths/Matrix3D.h"
#include "ps/CStr.h"
#include "ps/Overlay.h"
@@ -27,7 +28,7 @@ class CFont;
class CTextRenderer
{
public:
- CTextRenderer();
+ CTextRenderer(const CShaderProgramPtr& shader);
void ResetTransform();
CMatrix3D GetTransform();
@@ -51,6 +52,8 @@ private:
std::wstring text;
};
+ CShaderProgramPtr m_Shader;
+
CMatrix3D m_Transform;
CColor m_Color;
diff --git a/source/gui/CGUI.cpp b/source/gui/CGUI.cpp
index 9628cada66..5e063f8a6e 100644
--- a/source/gui/CGUI.cpp
+++ b/source/gui/CGUI.cpp
@@ -43,6 +43,7 @@ CGUI
#include "MiniMap.h"
#include "scripting/JSInterface_GUITypes.h"
+#include "graphics/ShaderManager.h"
#include "graphics/TextRenderer.h"
#include "lib/input.h"
#include "lib/bits.h"
@@ -57,6 +58,7 @@ CGUI
#include "ps/Profile.h"
#include "ps/Pyrogenesis.h"
#include "ps/XML/Xeromyces.h"
+#include "renderer/Renderer.h"
#include "scripting/ScriptingHost.h"
#include "scriptinterface/ScriptInterface.h"
@@ -902,18 +904,9 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
void CGUI::DrawText(SGUIText &Text, const CColor &DefaultColor,
const CPos &pos, const float &z, const CRect &clipping)
{
- // TODO Gee: All these really necessary? Some
- // are defaults and if you changed them
- // the opposite value at the end of the functions,
- // some things won't be drawn correctly.
- glEnable(GL_TEXTURE_2D);
- glDisable(GL_CULL_FACE);
+ CShaderTechnique tech = g_Renderer.GetShaderManager().LoadEffect("gui_text");
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- glDisable(GL_ALPHA_TEST);
-
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ tech.BeginPass(0);
if (clipping != CRect())
{
@@ -921,7 +914,7 @@ void CGUI::DrawText(SGUIText &Text, const CColor &DefaultColor,
glScissor(clipping.left, g_yres - clipping.bottom, clipping.GetWidth(), clipping.GetHeight());
}
- CTextRenderer textRenderer;
+ CTextRenderer textRenderer(tech.GetShader(0));
for (std::vector::const_iterator it = Text.m_TextCalls.begin();
it != Text.m_TextCalls.end();
@@ -952,7 +945,7 @@ void CGUI::DrawText(SGUIText &Text, const CColor &DefaultColor,
if (clipping != CRect())
glDisable(GL_SCISSOR_TEST);
- glDisable(GL_TEXTURE_2D);
+ tech.EndPass(0);
}
bool CGUI::GetPreDefinedColor(const CStr& name, CColor &Output)
diff --git a/source/gui/CInput.cpp b/source/gui/CInput.cpp
index 2ca034b4e6..9a56c81603 100644
--- a/source/gui/CInput.cpp
+++ b/source/gui/CInput.cpp
@@ -24,6 +24,7 @@ CInput
#include "CInput.h"
#include "CGUIScrollBarVertical.h"
+#include "graphics/ShaderManager.h"
#include "graphics/TextRenderer.h"
#include "lib/ogl.h"
#include "lib/res/graphics/unifont.h"
@@ -32,6 +33,7 @@ CInput
#include "ps/Font.h"
#include "ps/Globals.h"
#include "ps/Hotkey.h"
+#include "renderer/Renderer.h"
#include
@@ -1078,7 +1080,9 @@ void CInput::Draw()
float h = (float)font.GetHeight();
float ls = (float)font.GetLineSpacing();
- CTextRenderer textRenderer;
+ CShaderTechnique tech = g_Renderer.GetShaderManager().LoadEffect("gui_text");
+
+ CTextRenderer textRenderer(tech.GetShader(0));
textRenderer.Font(font_name);
// Set the Z to somewhat more, so we can draw a selected area between the
@@ -1243,13 +1247,7 @@ void CInput::Draw()
// Setup initial color (then it might change and change back, when drawing selected area)
textRenderer.Color(color);
- // Setup state for text rendering
-
- glEnable(GL_TEXTURE_2D);
- glDisable(GL_CULL_FACE);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ tech.BeginPass(0);
bool using_selected_color = false;
@@ -1351,7 +1349,7 @@ void CInput::Draw()
if (cliparea != CRect())
glDisable(GL_SCISSOR_TEST);
- glDisable(GL_TEXTURE_2D);
+ tech.EndPass(0);
}
}
diff --git a/source/gui/GUIRenderer.cpp b/source/gui/GUIRenderer.cpp
index 4b18ddc50a..a3c46be799 100644
--- a/source/gui/GUIRenderer.cpp
+++ b/source/gui/GUIRenderer.cpp
@@ -634,18 +634,18 @@ void GUIRenderer::Draw(DrawCalls &Calls, float Z)
glBegin(GL_QUADS);
- glTexCoord2f(TexCoords.right, TexCoords.bottom);
- glVertex3f(cit->m_Vertices.right, cit->m_Vertices.bottom, cit->m_DeltaZ);
-
glTexCoord2f(TexCoords.left, TexCoords.bottom);
glVertex3f(cit->m_Vertices.left, cit->m_Vertices.bottom, cit->m_DeltaZ);
- glTexCoord2f(TexCoords.left, TexCoords.top);
- glVertex3f(cit->m_Vertices.left, cit->m_Vertices.top, cit->m_DeltaZ);
+ glTexCoord2f(TexCoords.right, TexCoords.bottom);
+ glVertex3f(cit->m_Vertices.right, cit->m_Vertices.bottom, cit->m_DeltaZ);
glTexCoord2f(TexCoords.right, TexCoords.top);
glVertex3f(cit->m_Vertices.right, cit->m_Vertices.top, cit->m_DeltaZ);
+ glTexCoord2f(TexCoords.left, TexCoords.top);
+ glVertex3f(cit->m_Vertices.left, cit->m_Vertices.top, cit->m_DeltaZ);
+
glEnd();
if (cit->m_Effects)
@@ -664,10 +664,10 @@ void GUIRenderer::Draw(DrawCalls &Calls, float Z)
glColor4fv(cit->m_BackColor.FloatArray());
glBegin(GL_QUADS);
- glVertex3f(cit->m_Vertices.right, cit->m_Vertices.bottom, cit->m_DeltaZ);
glVertex3f(cit->m_Vertices.left, cit->m_Vertices.bottom, cit->m_DeltaZ);
- glVertex3f(cit->m_Vertices.left, cit->m_Vertices.top, cit->m_DeltaZ);
+ glVertex3f(cit->m_Vertices.right, cit->m_Vertices.bottom, cit->m_DeltaZ);
glVertex3f(cit->m_Vertices.right, cit->m_Vertices.top, cit->m_DeltaZ);
+ glVertex3f(cit->m_Vertices.left, cit->m_Vertices.top, cit->m_DeltaZ);
glEnd();
diff --git a/source/lib/res/graphics/unifont.cpp b/source/lib/res/graphics/unifont.cpp
index 913fe671e0..726b48f9f1 100644
--- a/source/lib/res/graphics/unifont.cpp
+++ b/source/lib/res/graphics/unifont.cpp
@@ -50,6 +50,8 @@ struct UniFont
{
Handle ht; // Handle to font texture
+ bool HasRGB; // true if RGBA, false if ALPHA
+
glyphmap* glyphs;
int LineSpacing;
@@ -102,9 +104,15 @@ static Status UniFont_reload(UniFont* f, const PIVFS& vfs, const VfsPath& basena
std::string Format;
FNTStream >> Format;
if (Format == "rgba")
+ {
+ f->HasRGB = true;
fmt_ovr = GL_RGBA;
+ }
else if (Format == "a")
+ {
+ f->HasRGB = false;
fmt_ovr = GL_ALPHA;
+ }
else
debug_warn(L"Invalid .fnt format string");
}
@@ -214,11 +222,11 @@ Status unifont_unload(Handle& h)
}
-Status unifont_bind(const Handle h)
+Status unifont_bind(const Handle h, size_t unit)
{
H_DEREF(h, UniFont, f);
- ogl_tex_bind(f->ht);
+ ogl_tex_bind(f->ht, unit);
BoundGlyphs = f->glyphs;
return INFO::OK;
@@ -239,6 +247,15 @@ int unifont_height(const Handle h)
}
+bool unifont_has_rgb(const Handle h)
+{
+ UniFont* const f = H_USER_DATA(h, UniFont);
+ if(!f)
+ return false;
+ return f->HasRGB;
+}
+
+
int unifont_character_width(const Handle h, wchar_t c)
{
H_DEREF(h, UniFont, f);
@@ -270,10 +287,19 @@ void glvwprintf(const wchar_t* fmt, va_list args)
// Make sure there's always null termination
buf[buf_size-1] = 0;
+ int advance = 0;
+ unifont_render(buf, &advance);
+
+ // Move into position for subsequent prints
+ glTranslatef((float)advance, 0, 0);
+}
+
+void unifont_render(const wchar_t* str, int* advance)
+{
ENSURE(BoundGlyphs != NULL); // You always need to bind something first
// Count the number of characters
- size_t len = wcslen(buf);
+ size_t len = wcslen(str);
// 0 glyphs -> nothing to do (avoid BoundsChecker warning)
if (!len)
@@ -281,11 +307,11 @@ void glvwprintf(const wchar_t* fmt, va_list args)
t2f_v2i* vertexes = new t2f_v2i[len*4];
- i32 x = 0;
+ i16 x = 0;
for (size_t i = 0; i < len; ++i)
{
- glyphmap::iterator it = BoundGlyphs->find(buf[i]);
+ glyphmap::iterator it = BoundGlyphs->find(str[i]);
if (it == BoundGlyphs->end())
it = BoundGlyphs->find(0xFFFD); // Use the missing glyph symbol
@@ -295,24 +321,24 @@ void glvwprintf(const wchar_t* fmt, va_list args)
const GlyphData& g = it->second;
- vertexes[i*4].u = g.u0;
+ vertexes[i*4].u = g.u1;
vertexes[i*4].v = g.v0;
- vertexes[i*4].x = g.x0 + x;
+ vertexes[i*4].x = g.x1 + x;
vertexes[i*4].y = g.y0;
- vertexes[i*4+1].u = g.u1;
+ vertexes[i*4+1].u = g.u0;
vertexes[i*4+1].v = g.v0;
- vertexes[i*4+1].x = g.x1 + x;
+ vertexes[i*4+1].x = g.x0 + x;
vertexes[i*4+1].y = g.y0;
- vertexes[i*4+2].u = g.u1;
+ vertexes[i*4+2].u = g.u0;
vertexes[i*4+2].v = g.v1;
- vertexes[i*4+2].x = g.x1 + x;
+ vertexes[i*4+2].x = g.x0 + x;
vertexes[i*4+2].y = g.y1;
- vertexes[i*4+3].u = g.u0;
+ vertexes[i*4+3].u = g.u1;
vertexes[i*4+3].v = g.v1;
- vertexes[i*4+3].x = g.x0 + x;
+ vertexes[i*4+3].x = g.x1 + x;
vertexes[i*4+3].y = g.y1;
x += g.xadvance;
@@ -335,11 +361,11 @@ void glvwprintf(const wchar_t* fmt, va_list args)
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
ogl_WarnIfError();
-
- // Move into position for subsequent prints
- glTranslatef((float)x, 0, 0);
#endif
+ if (advance)
+ *advance = x;
+
delete[] vertexes;
}
diff --git a/source/lib/res/graphics/unifont.h b/source/lib/res/graphics/unifont.h
index bdf5ce26dd..bd8fd6740b 100644
--- a/source/lib/res/graphics/unifont.h
+++ b/source/lib/res/graphics/unifont.h
@@ -53,7 +53,7 @@ extern Status unifont_unload(Handle& h);
*
* Must be called before any glwprintf().
**/
-extern Status unifont_bind(Handle h);
+extern Status unifont_bind(Handle h, size_t unit);
/**
* Output text at current OpenGL modelview pos.
@@ -79,6 +79,11 @@ extern void glwprintf(const wchar_t* fmt, ...) WPRINTF_ARGS(1);
**/
extern void glvwprintf(const wchar_t* fmt, va_list args) VWPRINTF_ARGS(1);
+/**
+ * Output text, and return advance distance (if @p advance not NULL).
+ */
+extern void unifont_render(const wchar_t* str, int* advance = NULL);
+
/**
* Determine pixel extents of a string.
*
@@ -92,6 +97,11 @@ extern void glvwprintf(const wchar_t* fmt, va_list args) VWPRINTF_ARGS(1);
**/
Status unifont_stringsize(const Handle h, const wchar_t* text, int& width, int& height);
+/**
+ * @return whether the font is an RGBA texture, not an ALPHA texture.
+ **/
+bool unifont_has_rgb(const Handle h);
+
/**
* @return height [pixels] of the font.
**/
diff --git a/source/maths/Matrix3D.cpp b/source/maths/Matrix3D.cpp
index 8e38024553..f6ebbfcd7d 100644
--- a/source/maths/Matrix3D.cpp
+++ b/source/maths/Matrix3D.cpp
@@ -44,6 +44,17 @@ void CMatrix3D::SetZero ()
_41=0.0f; _42=0.0f; _43=0.0f; _44=0.0f;
}
+void CMatrix3D::SetOrtho (float l, float r, float b, float t, float n, float f)
+{
+ // Based on OpenGL spec
+ *this = CMatrix3D(
+ 2/(r-l), 0, 0, -(r+l)/(r-l),
+ 0, 2/(t-b), 0, -(t+b)/(t-b),
+ 0, 0, -2/(f-n), -(f+n)/(f-n),
+ 0, 0, 0, 1
+ );
+}
+
//The following clear the matrix and set the
//rotation of each of the 3 axes
diff --git a/source/maths/Matrix3D.h b/source/maths/Matrix3D.h
index 7e6855d318..ed9a2840ec 100644
--- a/source/maths/Matrix3D.h
+++ b/source/maths/Matrix3D.h
@@ -177,6 +177,8 @@ public:
void SetIdentity();
// set this matrix to the zero matrix
void SetZero();
+ // set this matrix to the orthogonal projection matrix (as with glOrtho)
+ void SetOrtho(float l, float r, float b, float t, float n, float f);
// concatenate arbitrary matrix onto this matrix
void Concatenate(const CMatrix3D& m)
diff --git a/source/ps/Font.cpp b/source/ps/Font.cpp
index 844be17260..0a15fe9b54 100644
--- a/source/ps/Font.cpp
+++ b/source/ps/Font.cpp
@@ -48,9 +48,14 @@ CFont::~CFont()
unifont_unload(h);
}
-void CFont::Bind()
+void CFont::Bind(size_t unit)
{
- unifont_bind(h);
+ unifont_bind(h, unit);
+}
+
+bool CFont::HasRGB()
+{
+ return unifont_has_rgb(h);
}
int CFont::GetLineSpacing()
diff --git a/source/ps/Font.h b/source/ps/Font.h
index 32055c0e29..016cfc92ff 100644
--- a/source/ps/Font.h
+++ b/source/ps/Font.h
@@ -38,7 +38,8 @@ public:
CFont(const CStrW& name);
~CFont();
- void Bind();
+ void Bind(size_t unit = 0);
+ bool HasRGB();
int GetLineSpacing();
int GetHeight();
int GetCharacterWidth(wchar_t c);
diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp
index f252c0367b..8e335eee32 100644
--- a/source/ps/GameSetup/GameSetup.cpp
+++ b/source/ps/GameSetup/GameSetup.cpp
@@ -226,7 +226,6 @@ void Render()
// set up overlay mode
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
- glDisable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
diff --git a/source/ps/ProfileViewer.cpp b/source/ps/ProfileViewer.cpp
index 0d673e3a4a..24377e4fd4 100644
--- a/source/ps/ProfileViewer.cpp
+++ b/source/ps/ProfileViewer.cpp
@@ -188,10 +188,10 @@ void CProfileViewer::RenderProfile()
glDisable(GL_TEXTURE_2D);
glColor4ub(0,0,0,128);
glBegin(GL_QUADS);
- glVertex2i(0, g_yres);
glVertex2i(estimate_width, g_yres);
- glVertex2i(estimate_width, g_yres-estimate_height);
+ glVertex2i(0, g_yres);
glVertex2i(0, g_yres-estimate_height);
+ glVertex2i(estimate_width, g_yres-estimate_height);
glEnd();
glEnable(GL_TEXTURE_2D);
diff --git a/source/renderer/OverlayRenderer.cpp b/source/renderer/OverlayRenderer.cpp
index b33c6a7904..53d6b59ce2 100644
--- a/source/renderer/OverlayRenderer.cpp
+++ b/source/renderer/OverlayRenderer.cpp
@@ -209,7 +209,7 @@ void OverlayRenderer::RenderOverlaysAfterWater()
CLOSTexture& los = g_Renderer.GetScene().GetLOSTexture();
CShaderManager& shaderManager = g_Renderer.GetShaderManager();
- CShaderProgramPtr shaderTexLineNormal(shaderManager.LoadProgram(shaderName, std::map()));
+ CShaderProgramPtr shaderTexLineNormal(shaderManager.LoadProgram(shaderName));
CShaderProgramPtr shaderTexLineAlwaysVisible(shaderManager.LoadProgram(shaderName, defAlwaysVisible));
// ----------------------------------------------------------------------------------------
diff --git a/source/renderer/ParticleRenderer.cpp b/source/renderer/ParticleRenderer.cpp
index 1aa7b95459..ccbf3ff346 100644
--- a/source/renderer/ParticleRenderer.cpp
+++ b/source/renderer/ParticleRenderer.cpp
@@ -86,10 +86,8 @@ void ParticleRenderer::PrepareForRendering()
// RenderParticles will never be called so it's safe to leave the shaders as null
if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
{
- typedef std::map Defines;
- Defines defNull;
- m->shader = g_Renderer.GetShaderManager().LoadProgram("particle", defNull);
- m->shaderSolid = g_Renderer.GetShaderManager().LoadProgram("particle_solid", defNull);
+ m->shader = g_Renderer.GetShaderManager().LoadProgram("particle");
+ m->shaderSolid = g_Renderer.GetShaderManager().LoadProgram("particle_solid");
}
}
diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp
index 493cd636df..72a78b06cc 100644
--- a/source/renderer/Renderer.cpp
+++ b/source/renderer/Renderer.cpp
@@ -50,7 +50,6 @@
#include "graphics/ModelDef.h"
#include "graphics/ParticleManager.h"
#include "graphics/ShaderManager.h"
-#include "graphics/ShaderTechnique.h"
#include "graphics/Terrain.h"
#include "graphics/Texture.h"
#include "graphics/TextureManager.h"