mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 19:50:38 +02:00
Working on the text renderer
This commit is contained in:
parent
5d9aee16cb
commit
6cfb51283e
9 changed files with 31893 additions and 11040 deletions
|
@ -124,13 +124,8 @@ void Text3DOverlay::render(RenderArgs* args) {
|
||||||
enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y);
|
enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y);
|
||||||
enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y);
|
enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y);
|
||||||
|
|
||||||
glm::vec4 textColor = {_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() };
|
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() };
|
||||||
QStringList lines = _text.split("\n");
|
textRenderer->drawString(0, 0, _text, textColor);
|
||||||
int lineOffset = maxHeight;
|
|
||||||
foreach(QString thisLine, lines) {
|
|
||||||
textRenderer->draw(0, lineOffset, qPrintable(thisLine), textColor);
|
|
||||||
lineOffset += maxHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
glDisable(GL_CLIP_PLANE0);
|
glDisable(GL_CLIP_PLANE0);
|
||||||
glDisable(GL_CLIP_PLANE1);
|
glDisable(GL_CLIP_PLANE1);
|
||||||
|
|
|
@ -92,17 +92,7 @@ void TextOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
float alpha = getAlpha();
|
float alpha = getAlpha();
|
||||||
glm::vec4 textColor = {_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, alpha };
|
glm::vec4 textColor = {_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, alpha };
|
||||||
QStringList lines = _text.split("\n");
|
textRenderer->draw(x, y, _text, textColor);
|
||||||
int lineOffset = 0;
|
|
||||||
foreach(QString thisLine, lines) {
|
|
||||||
if (lineOffset == 0) {
|
|
||||||
lineOffset = textRenderer->calculateHeight(qPrintable(thisLine));
|
|
||||||
}
|
|
||||||
lineOffset += textRenderer->draw(x, y + lineOffset, qPrintable(thisLine), textColor);
|
|
||||||
|
|
||||||
const int lineGap = 2;
|
|
||||||
lineOffset += lineGap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextOverlay::setProperties(const QScriptValue& properties) {
|
void TextOverlay::setProperties(const QScriptValue& properties) {
|
||||||
|
|
31760
libraries/render-utils/src/FontCourierPrime.h
Normal file
31760
libraries/render-utils/src/FontCourierPrime.h
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,9 @@
|
||||||
#ifndef ROBOTO_REGULAR_SDFF_H
|
#ifndef ROBOTO_REGULAR_SDFF_H
|
||||||
#define ROBOTO_REGULAR_SDFF_H
|
#define ROBOTO_REGULAR_SDFF_H
|
||||||
|
|
||||||
|
// http://www.dafont.com/roboto.font
|
||||||
|
|
||||||
|
|
||||||
static const unsigned char SDFF_ROBOTO[] = {
|
static const unsigned char SDFF_ROBOTO[] = {
|
||||||
0x53, 0x44, 0x46, 0x46, 0x02, 0x00, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x6f,
|
0x53, 0x44, 0x46, 0x46, 0x02, 0x00, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x6f,
|
||||||
0x20, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x00, 0x80, 0x5d,
|
0x20, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x00, 0x80, 0x5d,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef TIMELESS_REGULAR_SDFF_H
|
#ifndef TIMELESS_REGULAR_SDFF_H
|
||||||
#define TIMELESS_REGULAR_SDFF_H
|
#define TIMELESS_REGULAR_SDFF_H
|
||||||
|
|
||||||
|
// http://www.dafont.com/timeless.font
|
||||||
|
|
||||||
static const unsigned char SDFF_TIMELESS[] = {
|
static const unsigned char SDFF_TIMELESS[] = {
|
||||||
0x53, 0x44, 0x46, 0x46, 0x02, 0x00, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x65,
|
0x53, 0x44, 0x46, 0x46, 0x02, 0x00, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x65,
|
||||||
0x73, 0x73, 0x20, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x7d,
|
0x73, 0x73, 0x20, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x7d,
|
||||||
|
|
|
@ -33,8 +33,9 @@
|
||||||
#include "gpu/Stream.h"
|
#include "gpu/Stream.h"
|
||||||
#include "FontInconsolataMedium.h"
|
#include "FontInconsolataMedium.h"
|
||||||
#include "FontRoboto.h"
|
#include "FontRoboto.h"
|
||||||
#include "FontJackInput.h"
|
|
||||||
#include "FontTimeless.h"
|
#include "FontTimeless.h"
|
||||||
|
#include "FontCourierPrime.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace Shaders {
|
namespace Shaders {
|
||||||
|
@ -95,8 +96,12 @@ void main() {
|
||||||
|
|
||||||
// retrieve signed distance
|
// retrieve signed distance
|
||||||
float sdf = texture(Font, vTexCoord).r;
|
float sdf = texture(Font, vTexCoord).r;
|
||||||
if (Outline && (sdf > 0.6)) {
|
if (Outline) {
|
||||||
sdf = 1.0 - sdf;
|
if (sdf > 0.8) {
|
||||||
|
sdf = 1.0 - sdf;
|
||||||
|
} else {
|
||||||
|
sdf += 0.2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// perform adaptive anti-aliasing of the edges
|
// perform adaptive anti-aliasing of the edges
|
||||||
// The larger we're rendering, the less anti-aliasing we need
|
// The larger we're rendering, the less anti-aliasing we need
|
||||||
|
@ -187,13 +192,15 @@ public:
|
||||||
// Initialize the OpenGL structures
|
// Initialize the OpenGL structures
|
||||||
void setupGL();
|
void setupGL();
|
||||||
|
|
||||||
|
|
||||||
|
glm::vec2 computeExtent(const QString & str) const;
|
||||||
|
|
||||||
glm::vec2 drawString(
|
glm::vec2 drawString(
|
||||||
float x, float y,
|
float x, float y,
|
||||||
const QString & str,
|
const QString & str,
|
||||||
const glm::vec4& color,
|
const glm::vec4& color,
|
||||||
float scale,
|
|
||||||
TextRenderer::EffectType effectType,
|
TextRenderer::EffectType effectType,
|
||||||
float maxWidth);
|
float maxWidth) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -231,7 +238,7 @@ void Font::read(QIODevice & in) {
|
||||||
readStream(in, _descent);
|
readStream(in, _descent);
|
||||||
readStream(in, _spaceWidth);
|
readStream(in, _spaceWidth);
|
||||||
_fontSize = _ascent + _descent;
|
_fontSize = _ascent + _descent;
|
||||||
_rowHeight = _fontSize + _descent / 2;
|
_rowHeight = _fontSize + _descent;
|
||||||
|
|
||||||
// Read character count
|
// Read character count
|
||||||
uint16_t count;
|
uint16_t count;
|
||||||
|
@ -360,88 +367,93 @@ void Font::setupGL() {
|
||||||
_vao->release();
|
_vao->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec2 Font::computeExtent(const QString & str) const {
|
||||||
|
glm::vec2 advance(0, _rowHeight - _descent);
|
||||||
|
float maxX = 0;
|
||||||
|
foreach(QString token, str.split(" ")) {
|
||||||
|
foreach(QChar c, token) {
|
||||||
|
if (QChar('\n') == c) {
|
||||||
|
maxX = std::max(advance.x, maxX);
|
||||||
|
advance.x = 0;
|
||||||
|
advance.y += _rowHeight;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!_glyphs.contains(c)) {
|
||||||
|
c = QChar('?');
|
||||||
|
}
|
||||||
|
const Glyph & m = _glyphs[c];
|
||||||
|
advance.x += m.d;
|
||||||
|
}
|
||||||
|
advance.x += _spaceWidth;
|
||||||
|
}
|
||||||
|
return glm::vec2(maxX, advance.y);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec2 Font::drawString(
|
glm::vec2 Font::drawString(
|
||||||
float x, float y,
|
float x, float y,
|
||||||
const QString & str,
|
const QString & str,
|
||||||
const glm::vec4& color,
|
const glm::vec4& color,
|
||||||
float scale,
|
|
||||||
TextRenderer::EffectType effectType,
|
TextRenderer::EffectType effectType,
|
||||||
float maxWidth) {
|
float maxWidth) const {
|
||||||
|
|
||||||
// This is a hand made scale intended to match the previous scale of text in the application
|
|
||||||
//float scale = 0.25f; // DTP_TO_METERS;
|
|
||||||
//if (fontSize > 0.0) {
|
|
||||||
// scale *= fontSize / _fontSize;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//bool wrap = false; // (maxWidth == maxWidth);
|
|
||||||
//if (wrap) {
|
|
||||||
// maxWidth /= scale;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Stores how far we've moved from the start of the string, in DTP units
|
// Stores how far we've moved from the start of the string, in DTP units
|
||||||
static const float SPACE_ADVANCE = getGlyph('J').d;
|
glm::vec2 advance(0, -_rowHeight - _descent);
|
||||||
glm::vec2 advance(0, -_ascent);
|
|
||||||
MatrixStack::withGlMatrices([&] {
|
|
||||||
// Fetch the matrices out of GL
|
|
||||||
_program->bind();
|
|
||||||
_program->setUniformValue("Color", color.r, color.g, color.b, color.a);
|
|
||||||
_program->setUniformValue("Projection", fromGlm(MatrixStack::projection().top()));
|
|
||||||
if (effectType == TextRenderer::OUTLINE_EFFECT) {
|
|
||||||
_program->setUniformValue("Outline", true);
|
|
||||||
}
|
|
||||||
_texture->bind();
|
|
||||||
_vao->bind();
|
|
||||||
|
|
||||||
MatrixStack & mv = MatrixStack::modelview();
|
_program->bind();
|
||||||
MatrixStack & pr = MatrixStack::projection();
|
_program->setUniformValue("Color", color.r, color.g, color.b, color.a);
|
||||||
// scale the modelview into font units
|
_program->setUniformValue("Projection", fromGlm(MatrixStack::projection().top()));
|
||||||
mv.translate(glm::vec2(x, y)).scale(glm::vec3(scale, -scale, scale));
|
if (effectType == TextRenderer::OUTLINE_EFFECT) {
|
||||||
mv.translate(glm::vec3(0, _ascent, 0));
|
_program->setUniformValue("Outline", true);
|
||||||
foreach(QString token, str.split(" ")) {
|
}
|
||||||
// float tokenWidth = measureWidth(token, fontSize);
|
_texture->bind();
|
||||||
// if (wrap && 0 != advance.x && (advance.x + tokenWidth) > maxWidth) {
|
_vao->bind();
|
||||||
|
|
||||||
|
MatrixStack & mv = MatrixStack::modelview();
|
||||||
|
// scale the modelview into font units
|
||||||
|
mv.translate(glm::vec3(0, _ascent, 0));
|
||||||
|
foreach(QString token, str.split(" ")) {
|
||||||
|
// float tokenWidth = measureWidth(token, fontSize);
|
||||||
|
// if (wrap && 0 != advance.x && (advance.x + tokenWidth) > maxWidth) {
|
||||||
|
// advance.x = 0;
|
||||||
|
// advance.y -= _rowHeight;
|
||||||
|
// }
|
||||||
|
|
||||||
|
foreach(QChar c, token) {
|
||||||
|
if (QChar('\n') == c) {
|
||||||
|
advance.x = 0;
|
||||||
|
advance.y -= _rowHeight;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glyphs.contains(c)) {
|
||||||
|
c = QChar('?');
|
||||||
|
}
|
||||||
|
|
||||||
|
// get metrics for this character to speed up measurements
|
||||||
|
const Glyph & m = _glyphs[c];
|
||||||
|
//if (wrap && ((advance.x + m.d) > maxWidth)) {
|
||||||
// advance.x = 0;
|
// advance.x = 0;
|
||||||
// advance.y -= _rowHeight;
|
// advance.y -= _rowHeight;
|
||||||
// }
|
//}
|
||||||
|
|
||||||
foreach(QChar c, token) {
|
// We create an offset vec2 to hold the local offset of this character
|
||||||
if (QChar('\n') == c) {
|
// This includes compensating for the inverted Y axis of the font
|
||||||
advance.x = 0;
|
// coordinates
|
||||||
advance.y -= _rowHeight;
|
glm::vec2 offset(advance);
|
||||||
continue;
|
offset.y -= m.size.y;
|
||||||
}
|
// Bind the new position
|
||||||
|
mv.withPush([&] {
|
||||||
if (!_glyphs.contains(c)) {
|
mv.translate(offset);
|
||||||
c = QChar('?');
|
_program->setUniformValue("ModelView", fromGlm(mv.top()));
|
||||||
}
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)(m.indexOffset));
|
||||||
|
});
|
||||||
// get metrics for this character to speed up measurements
|
advance.x += m.d;//+ m.offset.x;// font->getAdvance(m, mFontSize);
|
||||||
const Glyph & m = _glyphs[c];
|
|
||||||
//if (wrap && ((advance.x + m.d) > maxWidth)) {
|
|
||||||
// advance.x = 0;
|
|
||||||
// advance.y -= _rowHeight;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// We create an offset vec2 to hold the local offset of this character
|
|
||||||
// This includes compensating for the inverted Y axis of the font
|
|
||||||
// coordinates
|
|
||||||
glm::vec2 offset(advance);
|
|
||||||
offset.y -= m.size.y;
|
|
||||||
// Bind the new position
|
|
||||||
mv.withPush([&] {
|
|
||||||
mv.translate(offset);
|
|
||||||
_program->setUniformValue("ModelView", fromGlm(mv.top()));
|
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)(m.indexOffset));
|
|
||||||
});
|
|
||||||
advance.x += m.d;//+ m.offset.x;// font->getAdvance(m, mFontSize);
|
|
||||||
}
|
|
||||||
advance.x += SPACE_ADVANCE;
|
|
||||||
}
|
}
|
||||||
|
advance.x += _spaceWidth;
|
||||||
|
}
|
||||||
|
|
||||||
_vao->release();
|
_vao->release();
|
||||||
_program->release();
|
_program->release();
|
||||||
});
|
|
||||||
|
|
||||||
return advance;
|
return advance;
|
||||||
}
|
}
|
||||||
|
@ -469,7 +481,7 @@ static QHash<QString, Font*> LOADED_FONTS;
|
||||||
Font * loadFont(const QString & family) {
|
Font * loadFont(const QString & family) {
|
||||||
if (!LOADED_FONTS.contains(family)) {
|
if (!LOADED_FONTS.contains(family)) {
|
||||||
if (family == MONO_FONT_FAMILY) {
|
if (family == MONO_FONT_FAMILY) {
|
||||||
LOADED_FONTS[family] = loadFont(SDFF_JACKINPUT);
|
LOADED_FONTS[family] = loadFont(SDFF_COURIER_PRIME);
|
||||||
} else if (family == INCONSOLATA_FONT_FAMILY) {
|
} else if (family == INCONSOLATA_FONT_FAMILY) {
|
||||||
LOADED_FONTS[family] = loadFont(SDFF_INCONSOLATA_MEDIUM);
|
LOADED_FONTS[family] = loadFont(SDFF_INCONSOLATA_MEDIUM);
|
||||||
} else if (family == SANS_FONT_FAMILY) {
|
} else if (family == SANS_FONT_FAMILY) {
|
||||||
|
@ -497,44 +509,12 @@ TextRenderer::TextRenderer(const Properties& properties) :
|
||||||
TextRenderer::~TextRenderer() {
|
TextRenderer::~TextRenderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec2 TextRenderer::computeExtent(const QString & str) const {
|
||||||
int TextRenderer::computeWidth(const QChar & ch) const {
|
float scale = (_pointSize / DEFAULT_POINT_SIZE) * 0.25f;
|
||||||
//return getGlyph(ch).width();
|
return _font->computeExtent(str) * scale;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextRenderer::computeWidth(const QString & str) const {
|
float TextRenderer::draw(
|
||||||
int width = 0;
|
|
||||||
foreach(QChar c, str) {
|
|
||||||
width += computeWidth(c);
|
|
||||||
}
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TextRenderer::computeWidth(const char * str) const {
|
|
||||||
int width = 0;
|
|
||||||
while (*str) {
|
|
||||||
width += computeWidth(*str++);
|
|
||||||
}
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TextRenderer::computeWidth(char ch) const {
|
|
||||||
return computeWidth(QChar(ch));
|
|
||||||
}
|
|
||||||
|
|
||||||
int TextRenderer::calculateHeight(const char* str) const {
|
|
||||||
int maxHeight = 0;
|
|
||||||
//for (const char* ch = str; *ch != 0; ch++) {
|
|
||||||
// const Glyph& glyph = getGlyph(*ch);
|
|
||||||
// if (glyph.bounds().height() > maxHeight) {
|
|
||||||
// maxHeight = glyph.bounds().height();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
return maxHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
float TextRenderer::drawString(
|
|
||||||
float x, float y,
|
float x, float y,
|
||||||
const QString & str,
|
const QString & str,
|
||||||
const glm::vec4& color,
|
const glm::vec4& color,
|
||||||
|
@ -543,6 +523,15 @@ float TextRenderer::drawString(
|
||||||
if (actualColor.r < 0) {
|
if (actualColor.r < 0) {
|
||||||
actualColor = glm::vec4(_color.redF(), _color.greenF(), _color.blueF(), 1.0);
|
actualColor = glm::vec4(_color.redF(), _color.greenF(), _color.blueF(), 1.0);
|
||||||
}
|
}
|
||||||
return _font->drawString(x, y, str, actualColor, (_pointSize / DEFAULT_POINT_SIZE) * 0.25f, _effectType, maxWidth).x;
|
|
||||||
|
float scale = (_pointSize / DEFAULT_POINT_SIZE) * 0.25f;
|
||||||
|
glm::vec2 result;
|
||||||
|
MatrixStack::withGlMatrices([&] {
|
||||||
|
MatrixStack & mv = MatrixStack::modelview();
|
||||||
|
// scale the modelview into font units
|
||||||
|
mv.translate(glm::vec2(x, y)).scale(glm::vec3(scale, -scale, scale));
|
||||||
|
result = _font->drawString(x, y, str, actualColor, _effectType, maxWidth);
|
||||||
|
});
|
||||||
|
return result.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,25 +65,20 @@ public:
|
||||||
|
|
||||||
~TextRenderer();
|
~TextRenderer();
|
||||||
|
|
||||||
|
glm::vec2 computeExtent(const QString & str) const;
|
||||||
|
|
||||||
// returns the height of the tallest character
|
// returns the height of the tallest character
|
||||||
int calculateHeight(const char * str) const;
|
//int calculateHeight(const char * str) const;
|
||||||
int calculateHeight(const QString & str) const;
|
//int calculateHeight(const QString & str) const;
|
||||||
|
|
||||||
int computeWidth(char ch) const;
|
//int computeWidth(char ch) const;
|
||||||
int computeWidth(const QChar & ch) const;
|
//int computeWidth(const QChar & ch) const;
|
||||||
|
|
||||||
int computeWidth(const QString & str) const;
|
//int computeWidth(const QString & str) const;
|
||||||
int computeWidth(const char * str) const;
|
//int computeWidth(const char * str) const;
|
||||||
|
|
||||||
// also returns the height of the tallest character
|
// also returns the height of the tallest character
|
||||||
inline int draw(int x, int y, const char* str,
|
float draw(
|
||||||
const glm::vec4& color = glm::vec4(-1),
|
|
||||||
float maxWidth = -1
|
|
||||||
) {
|
|
||||||
return drawString(x, y, QString(str), color, maxWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
float drawString(
|
|
||||||
float x, float y,
|
float x, float y,
|
||||||
const QString & str,
|
const QString & str,
|
||||||
const glm::vec4& color = glm::vec4(-1),
|
const glm::vec4& color = glm::vec4(-1),
|
||||||
|
|
|
@ -139,8 +139,8 @@ void QTestWindow::makeCurrent() {
|
||||||
m_context->makeCurrent(this);
|
m_context->makeCurrent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const wchar_t * EXAMPLE_TEXT = L"Hello 1.0\nline 2\ndescent ggg\nascent ÁÁÁ";
|
static const wchar_t * EXAMPLE_TEXT = L"Áy Hello 1.0\nyÁ line 2\nÁy";
|
||||||
static const glm::uvec2 QUAD_OFFSET(10, 20);
|
static const glm::uvec2 QUAD_OFFSET(10, 10);
|
||||||
static const glm::vec3 COLORS[4] = {
|
static const glm::vec3 COLORS[4] = {
|
||||||
{ 1, 1, 1 },
|
{ 1, 1, 1 },
|
||||||
{ 0.5, 1.0, 0.5 },
|
{ 0.5, 1.0, 0.5 },
|
||||||
|
@ -183,7 +183,18 @@ void QTestWindow::draw() {
|
||||||
}
|
}
|
||||||
QString str = QString::fromWCharArray(EXAMPLE_TEXT);
|
QString str = QString::fromWCharArray(EXAMPLE_TEXT);
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
_textRenderer[i]->drawString(offsets[i].x, offsets[i].y, str, glm::vec4(COLORS[i], 1.0f));
|
glm::vec2 bounds = _textRenderer[i]->computeExtent(str);
|
||||||
|
glPushMatrix(); {
|
||||||
|
glTranslatef(offsets[i].x, offsets[i].y, 0);
|
||||||
|
glColor3f(0, 0, 0);
|
||||||
|
glBegin(GL_QUADS); {
|
||||||
|
glVertex2f(0, 0);
|
||||||
|
glVertex2f(0, bounds.y);
|
||||||
|
glVertex2f(bounds.x, bounds.y);
|
||||||
|
glVertex2f(bounds.x, 0);
|
||||||
|
} glEnd();
|
||||||
|
} glPopMatrix();
|
||||||
|
_textRenderer[i]->draw(offsets[i].x, offsets[i].y, str, glm::vec4(COLORS[i], 1.0f));
|
||||||
}
|
}
|
||||||
m_context->swapBuffers(this);
|
m_context->swapBuffers(this);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue