0

我一直在尝试在我的引擎中采用TrueType OpenGL 教程。当我编译并运行他们的示例时,一切正常,但是当我尝试将代码重写到我的引擎中时,我不断遇到分段错误。然后我尝试将他们的代码复制粘贴到我的 Utils 头文件中,但它不起作用。我已经用 cout 进行了一些调试,似乎错误发生在我的渲染方法中。我将首先发布渲染方法,然后是所有其他与 TrueType 相关的函数。如果你需要问我什么,请随意。

渲染方法

void Util::Font::render(const char *text, Atlas *a, float x, float y, float sx, float sy)
{
glUseProgram(shaderID);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

const uint8_t *p;

/* Use the texture containing the atlas */
glBindTexture(GL_TEXTURE_2D, a->tex);
glUniform1i(samplerID, 0);

/* Set up the VBO for our vertex data */
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);

point coords[6 * strlen(text)];
int c = 0;

/* Loop through all characters */
for (p = (const uint8_t *)text; *p; p++) {
    /* Calculate the vertex and texture coordinates */
    float x2 = x + a->c[*p].bl * sx;
    float y2 = -y - a->c[*p].bt * sy;
    float w = a->c[*p].bw * sx;
    float h = a->c[*p].bh * sy;

    /* Advance the cursor to the start of the next character */
    x += a->c[*p].ax * sx;
    y += a->c[*p].ay * sy;

    /* Skip glyphs that have no pixels */
    if (!w || !h)
        continue;

    coords[c++] = (point) {
    x2, -y2, a->c[*p].tx, a->c[*p].ty};
    coords[c++] = (point) {
    x2 + w, -y2, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty};
    coords[c++] = (point) {
    x2, -y2 - h, a->c[*p].tx, a->c[*p].ty + a->c[*p].bh / a->h};
    coords[c++] = (point) {
    x2 + w, -y2, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty};
    coords[c++] = (point) {
    x2, -y2 - h, a->c[*p].tx, a->c[*p].ty + a->c[*p].bh / a->h};
    coords[c++] = (point) {
    x2 + w, -y2 - h, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty + a->c[*p].bh / a->h};
}

/* Draw all the character on the screen in one go */
glBufferData(GL_ARRAY_BUFFER, sizeof coords, coords, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, c);

glDisableVertexAttribArray(0);


}

字体初始化

bool Util::Font::init()
{
if (FT_Init_FreeType(&ft))
{
    std::cout << "Failed to load Freetype!" << std::endl;
    return false;
}

if (FT_New_Face(ft, "res/fonts/Ubuntu-R.ttf", 0 , &face))
{
    std::cout << "Failed to load font file!" << std::endl;
    return false;
}

shaderID = Util::Shader::loadShaders("res/shaders/font.vert", "res/shaders/font.frag");

samplerID = glGetUniformLocation(shaderID, "textureSampler");
colorID = glGetUniformLocation(shaderID, "color");

glGenBuffers(1, &vertexBufferID);

font12px = new Atlas(face, 12);
font24px = new Atlas(face, 24);
font48px = new Atlas(face, 48);

return true;
}

Utils.h 中的字体头

namespace Font {

    static FT_Library ft;
    static FT_Face face;
    static GLuint shaderID;
    static GLuint samplerID;
    static GLuint colorID;
    static GLuint vertexBufferID;
    static GLuint coordID;

    bool init();

    struct point {
        GLfloat x;
        GLfloat y;
        GLfloat s;
        GLfloat t;

    };

    struct Atlas {
GLuint tex;     // texture object

int w;          // width of texture in pixels
int h;          // height of texture in pixels

struct {
    float ax;   // advance.x
    float ay;   // advance.y

    float bw;   // bitmap.width;
    float bh;   // bitmap.height;

    float bl;   // bitmap_left;
    float bt;   // bitmap_top;

    float tx;   // x offset of glyph in texture coordinates
    float ty;   // y offset of glyph in texture coordinates
} c[128];       // character information

 Atlas(FT_Face face, int height) {
    FT_Set_Pixel_Sizes(face, 0, height);
    FT_GlyphSlot g = face->glyph;

    int roww = 0;
    int rowh = 0;
     w = 0;
     h = 0;

     memset(c, 0, sizeof c);

    /* Find minimum size for a texture holding all visible ASCII characters */
    for (int i = 32; i < 128; i++) {
        if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
            fprintf(stderr, "Loading character %c failed!\n", i);
            continue;
        }
        if (roww + g->bitmap.width + 1 >= 1024) {
            w = std::max(w, roww);
            h += rowh;
            roww = 0;
            rowh = 0;
        }
        roww += g->bitmap.width + 1;
        rowh = std::max(rowh, g->bitmap.rows);
    }

    w = std::max(w, roww);
    h += rowh;

    /* Create a texture that will be used to hold all ASCII glyphs */
    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glUniform1i(samplerID, 0);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);

    /* We require 1 byte alignment when uploading texture data */
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    /* Clamping to edges is important to prevent artifacts when scaling */
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    /* Linear filtering usually looks best for text */
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    /* Paste all glyph bitmaps into the texture, remembering the offset */
    int ox = 0;
    int oy = 0;

    rowh = 0;

    for (int i = 32; i < 128; i++) {
        if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
            fprintf(stderr, "Loading character %c failed!\n", i);
            continue;
        }

        if (ox + g->bitmap.width + 1 >= 1024) {
            oy += rowh;
            rowh = 0;
            ox = 0;
        }

        glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
        c[i].ax = g->advance.x >> 6;
        c[i].ay = g->advance.y >> 6;

        c[i].bw = g->bitmap.width;
        c[i].bh = g->bitmap.rows;

        c[i].bl = g->bitmap_left;
        c[i].bt = g->bitmap_top;

        c[i].tx = ox / (float)w;
        c[i].ty = oy / (float)h;

        rowh = std::max(rowh, g->bitmap.rows);
        ox += g->bitmap.width + 1;
    }

    fprintf(stderr, "Generated a %d x %d (%d kb) texture atlas\n", w, h, w * h / 1024);
}

~Atlas() {
    glDeleteTextures(1, &tex);
}
};

    static Atlas *font48px;
    static Atlas *font24px;
    static Atlas *font12px;

    void render(const char *text, Atlas *atlas, float x, float y, float sx, float sy);
}
4

0 回答 0