allow collection of vertices/indices

this way we need only one draw call for multiple layers
This commit is contained in:
jrkb 2023-04-13 12:54:49 +02:00
parent 26ca2bdf43
commit 604240360e

View file

@ -4,6 +4,7 @@
// but it is still compiled in the "main.cpp" translation unit,
// because both files have mostly the same dependencies (OpenGL, GLM, FreeType).
#include "ofMain.h"
#include "ofUtils.h"
#include <GL/glext.h>
#include <ft2build.h>
@ -57,12 +58,12 @@ class Font {
float x0, y0, x1, y1, x2, y2;
};
struct BufferVertex {
float x, y, u, v;
int32_t bufferIndex;
};
public:
struct BufferVertex {
float x, y, u, v;
int32_t bufferIndex;
};
/// A structure to model a given axis of a variable font.
struct FontVariationAxisParameters {
/// 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){
float originalX = x;