allow collection of vertices/indices
this way we need only one draw call for multiple layers
This commit is contained in:
parent
26ca2bdf43
commit
604240360e
1 changed files with 97 additions and 5 deletions
|
@ -4,6 +4,7 @@
|
||||||
// but it is still compiled in the "main.cpp" translation unit,
|
// but it is still compiled in the "main.cpp" translation unit,
|
||||||
// because both files have mostly the same dependencies (OpenGL, GLM, FreeType).
|
// because both files have mostly the same dependencies (OpenGL, GLM, FreeType).
|
||||||
#include "ofMain.h"
|
#include "ofMain.h"
|
||||||
|
#include "ofUtils.h"
|
||||||
|
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
|
@ -57,12 +58,12 @@ class Font {
|
||||||
float x0, y0, x1, y1, x2, y2;
|
float x0, y0, x1, y1, x2, y2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BufferVertex {
|
|
||||||
float x, y, u, v;
|
|
||||||
int32_t bufferIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct BufferVertex {
|
||||||
|
float x, y, u, v;
|
||||||
|
int32_t bufferIndex;
|
||||||
|
};
|
||||||
|
|
||||||
/// A structure to model a given axis of a variable font.
|
/// A structure to model a given axis of a variable font.
|
||||||
struct FontVariationAxisParameters {
|
struct FontVariationAxisParameters {
|
||||||
/// The name of the variation axis.
|
/// The name of the variation axis.
|
||||||
|
@ -700,6 +701,97 @@ class Font {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void collectVerticesAndIndices(const glm::vec3 & position,
|
||||||
|
const std::string & text,
|
||||||
|
std::vector <BufferVertex> & vertices,
|
||||||
|
std::vector <int32_t> & indices,
|
||||||
|
const bool vFlip = false,
|
||||||
|
const float fontSize_px = 42){
|
||||||
|
float x = position.x;
|
||||||
|
float y = position.y;
|
||||||
|
float originalX = x;
|
||||||
|
|
||||||
|
FT_UInt previous = 0;
|
||||||
|
for(const char * textIt = text.c_str(); *textIt != '\0';){
|
||||||
|
float letterFontSize_px = fontSize_px; // can be individual
|
||||||
|
uint32_t charcode = decodeCharcode(&textIt);
|
||||||
|
|
||||||
|
if(charcode == '\r'){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(charcode == '\n'){
|
||||||
|
x = originalX;
|
||||||
|
y -= (float)face->height / (float)face->units_per_EM * worldSize;
|
||||||
|
if(hinting){
|
||||||
|
y = std::round(y);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto glyphIt = glyphs.find(charcode);
|
||||||
|
Glyph & glyph = (glyphIt == glyphs.end()) ? glyphs[0] : glyphIt->second;
|
||||||
|
|
||||||
|
if(previous != 0 && glyph.index != 0){
|
||||||
|
FT_Vector kerning;
|
||||||
|
FT_Error error = FT_Get_Kerning(face, previous, glyph.index, kerningMode, &kerning);
|
||||||
|
if(!error){
|
||||||
|
x += (float)kerning.x / emSize * worldSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not emit quad for empty glyphs (whitespace).
|
||||||
|
if(glyph.curveCount){
|
||||||
|
FT_Pos d = (FT_Pos)(emSize * dilation);
|
||||||
|
|
||||||
|
float u0 = (float)(glyph.bearingX - d) / emSize;
|
||||||
|
float v0 = (float)(glyph.bearingY - glyph.height - d) / emSize;
|
||||||
|
float u1 = (float)(glyph.bearingX + glyph.width + d) / emSize;
|
||||||
|
float v1 = (float)(glyph.bearingY + d) / emSize;
|
||||||
|
|
||||||
|
|
||||||
|
float x0 = x + u0 * worldSize * letterFontSize_px;
|
||||||
|
float y0 = y + v0 * worldSize * letterFontSize_px;
|
||||||
|
float x1 = x + u1 * worldSize * letterFontSize_px;
|
||||||
|
float y1 = y + v1 * worldSize * letterFontSize_px;
|
||||||
|
|
||||||
|
if(vFlip){
|
||||||
|
float _v = v0;
|
||||||
|
v0 = v1;
|
||||||
|
v1 = _v;
|
||||||
|
|
||||||
|
y0 = y - v0 * worldSize * letterFontSize_px;
|
||||||
|
y1 = y - v1 * worldSize * letterFontSize_px;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t base = static_cast <int32_t>(vertices.size());
|
||||||
|
vertices.push_back(BufferVertex{x0, y0, u0, v0, glyph.bufferIndex});
|
||||||
|
vertices.push_back(BufferVertex{x1, y0, u1, v0, glyph.bufferIndex});
|
||||||
|
vertices.push_back(BufferVertex{x1, y1, u1, v1, glyph.bufferIndex});
|
||||||
|
vertices.push_back(BufferVertex{x0, y1, u0, v1, glyph.bufferIndex});
|
||||||
|
|
||||||
|
indices.insert(indices.end(), {base, base + 1, base + 2, base + 2, base + 3, base});
|
||||||
|
}
|
||||||
|
|
||||||
|
x += ((float)glyph.advance * letterFontSize_px) / emSize * worldSize;
|
||||||
|
previous = glyph.index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(const std::vector <BufferVertex> & vertices,
|
||||||
|
const std::vector <int32_t> & indices){
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(BufferVertex) * vertices.size(), vertices.data(), GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int32_t) * indices.size(), indices.data(), GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
void draw(float x, float y, float z, const std::string & text, bool vFlip = false, float fontSize_px = 42){
|
void draw(float x, float y, float z, const std::string & text, bool vFlip = false, float fontSize_px = 42){
|
||||||
float originalX = x;
|
float originalX = x;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue