mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +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_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() };
|
||||
QStringList lines = _text.split("\n");
|
||||
int lineOffset = maxHeight;
|
||||
foreach(QString thisLine, lines) {
|
||||
textRenderer->draw(0, lineOffset, qPrintable(thisLine), textColor);
|
||||
lineOffset += maxHeight;
|
||||
}
|
||||
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() };
|
||||
textRenderer->drawString(0, 0, _text, textColor);
|
||||
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
glDisable(GL_CLIP_PLANE1);
|
||||
|
|
|
@ -92,17 +92,7 @@ void TextOverlay::render(RenderArgs* args) {
|
|||
|
||||
float alpha = getAlpha();
|
||||
glm::vec4 textColor = {_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, alpha };
|
||||
QStringList lines = _text.split("\n");
|
||||
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;
|
||||
}
|
||||
textRenderer->draw(x, y, _text, textColor);
|
||||
}
|
||||
|
||||
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
|
||||
#define ROBOTO_REGULAR_SDFF_H
|
||||
|
||||
// http://www.dafont.com/roboto.font
|
||||
|
||||
|
||||
static const unsigned char SDFF_ROBOTO[] = {
|
||||
0x53, 0x44, 0x46, 0x46, 0x02, 0x00, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x6f,
|
||||
0x20, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x00, 0x80, 0x5d,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef TIMELESS_REGULAR_SDFF_H
|
||||
#define TIMELESS_REGULAR_SDFF_H
|
||||
|
||||
// http://www.dafont.com/timeless.font
|
||||
|
||||
static const unsigned char SDFF_TIMELESS[] = {
|
||||
0x53, 0x44, 0x46, 0x46, 0x02, 0x00, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x65,
|
||||
0x73, 0x73, 0x20, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x7d,
|
||||
|
|
|
@ -33,8 +33,9 @@
|
|||
#include "gpu/Stream.h"
|
||||
#include "FontInconsolataMedium.h"
|
||||
#include "FontRoboto.h"
|
||||
#include "FontJackInput.h"
|
||||
#include "FontTimeless.h"
|
||||
#include "FontCourierPrime.h"
|
||||
|
||||
|
||||
|
||||
namespace Shaders {
|
||||
|
@ -95,8 +96,12 @@ void main() {
|
|||
|
||||
// retrieve signed distance
|
||||
float sdf = texture(Font, vTexCoord).r;
|
||||
if (Outline && (sdf > 0.6)) {
|
||||
sdf = 1.0 - sdf;
|
||||
if (Outline) {
|
||||
if (sdf > 0.8) {
|
||||
sdf = 1.0 - sdf;
|
||||
} else {
|
||||
sdf += 0.2;
|
||||
}
|
||||
}
|
||||
// perform adaptive anti-aliasing of the edges
|
||||
// The larger we're rendering, the less anti-aliasing we need
|
||||
|
@ -187,13 +192,15 @@ public:
|
|||
// Initialize the OpenGL structures
|
||||
void setupGL();
|
||||
|
||||
|
||||
glm::vec2 computeExtent(const QString & str) const;
|
||||
|
||||
glm::vec2 drawString(
|
||||
float x, float y,
|
||||
const QString & str,
|
||||
const glm::vec4& color,
|
||||
float scale,
|
||||
TextRenderer::EffectType effectType,
|
||||
float maxWidth);
|
||||
float maxWidth) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -231,7 +238,7 @@ void Font::read(QIODevice & in) {
|
|||
readStream(in, _descent);
|
||||
readStream(in, _spaceWidth);
|
||||
_fontSize = _ascent + _descent;
|
||||
_rowHeight = _fontSize + _descent / 2;
|
||||
_rowHeight = _fontSize + _descent;
|
||||
|
||||
// Read character count
|
||||
uint16_t count;
|
||||
|
@ -360,88 +367,93 @@ void Font::setupGL() {
|
|||
_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(
|
||||
float x, float y,
|
||||
const QString & str,
|
||||
const glm::vec4& color,
|
||||
float scale,
|
||||
TextRenderer::EffectType effectType,
|
||||
float maxWidth) {
|
||||
|
||||
// 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;
|
||||
//}
|
||||
float maxWidth) const {
|
||||
|
||||
// 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, -_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();
|
||||
glm::vec2 advance(0, -_rowHeight - _descent);
|
||||
|
||||
MatrixStack & mv = MatrixStack::modelview();
|
||||
MatrixStack & pr = MatrixStack::projection();
|
||||
// scale the modelview into font units
|
||||
mv.translate(glm::vec2(x, y)).scale(glm::vec3(scale, -scale, scale));
|
||||
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) {
|
||||
_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();
|
||||
// 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.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.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;
|
||||
// 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 += _spaceWidth;
|
||||
}
|
||||
|
||||
_vao->release();
|
||||
_program->release();
|
||||
});
|
||||
_vao->release();
|
||||
_program->release();
|
||||
|
||||
return advance;
|
||||
}
|
||||
|
@ -469,7 +481,7 @@ static QHash<QString, Font*> LOADED_FONTS;
|
|||
Font * loadFont(const QString & family) {
|
||||
if (!LOADED_FONTS.contains(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) {
|
||||
LOADED_FONTS[family] = loadFont(SDFF_INCONSOLATA_MEDIUM);
|
||||
} else if (family == SANS_FONT_FAMILY) {
|
||||
|
@ -497,44 +509,12 @@ TextRenderer::TextRenderer(const Properties& properties) :
|
|||
TextRenderer::~TextRenderer() {
|
||||
}
|
||||
|
||||
|
||||
int TextRenderer::computeWidth(const QChar & ch) const {
|
||||
//return getGlyph(ch).width();
|
||||
return 0;
|
||||
glm::vec2 TextRenderer::computeExtent(const QString & str) const {
|
||||
float scale = (_pointSize / DEFAULT_POINT_SIZE) * 0.25f;
|
||||
return _font->computeExtent(str) * scale;
|
||||
}
|
||||
|
||||
int TextRenderer::computeWidth(const QString & str) const {
|
||||
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 TextRenderer::draw(
|
||||
float x, float y,
|
||||
const QString & str,
|
||||
const glm::vec4& color,
|
||||
|
@ -543,6 +523,15 @@ float TextRenderer::drawString(
|
|||
if (actualColor.r < 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();
|
||||
|
||||
glm::vec2 computeExtent(const QString & str) const;
|
||||
|
||||
// returns the height of the tallest character
|
||||
int calculateHeight(const char * str) const;
|
||||
int calculateHeight(const QString & str) const;
|
||||
//int calculateHeight(const char * str) const;
|
||||
//int calculateHeight(const QString & str) const;
|
||||
|
||||
int computeWidth(char ch) const;
|
||||
int computeWidth(const QChar & ch) const;
|
||||
//int computeWidth(char ch) const;
|
||||
//int computeWidth(const QChar & ch) const;
|
||||
|
||||
int computeWidth(const QString & str) const;
|
||||
int computeWidth(const char * str) const;
|
||||
//int computeWidth(const QString & str) const;
|
||||
//int computeWidth(const char * str) const;
|
||||
|
||||
// also returns the height of the tallest character
|
||||
inline int draw(int x, int y, const char* str,
|
||||
const glm::vec4& color = glm::vec4(-1),
|
||||
float maxWidth = -1
|
||||
) {
|
||||
return drawString(x, y, QString(str), color, maxWidth);
|
||||
}
|
||||
|
||||
float drawString(
|
||||
float draw(
|
||||
float x, float y,
|
||||
const QString & str,
|
||||
const glm::vec4& color = glm::vec4(-1),
|
||||
|
|
|
@ -139,8 +139,8 @@ void QTestWindow::makeCurrent() {
|
|||
m_context->makeCurrent(this);
|
||||
}
|
||||
|
||||
static const wchar_t * EXAMPLE_TEXT = L"Hello 1.0\nline 2\ndescent ggg\nascent ÁÁÁ";
|
||||
static const glm::uvec2 QUAD_OFFSET(10, 20);
|
||||
static const wchar_t * EXAMPLE_TEXT = L"Áy Hello 1.0\nyÁ line 2\nÁy";
|
||||
static const glm::uvec2 QUAD_OFFSET(10, 10);
|
||||
static const glm::vec3 COLORS[4] = {
|
||||
{ 1, 1, 1 },
|
||||
{ 0.5, 1.0, 0.5 },
|
||||
|
@ -183,7 +183,18 @@ void QTestWindow::draw() {
|
|||
}
|
||||
QString str = QString::fromWCharArray(EXAMPLE_TEXT);
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue