使用OpenGL / GLFW / FreeType绘制文本会生成白色矩形而不是字形

时间:2014-08-17 16:26:00

标签: opengl text glfw freetype2

我正在尝试编写一个函数,该函数将在OpenGL中的某些(x,y)坐标处呈现字符串。这个应用程序只会在2D中渲染事物,这就是为什么我正在以我的方式初始化矩阵模式和正投影。我正在使用GLFW初始化窗口并轮询事件:

int render_loop()
{
    int r;
    GLFWwindow *window;

    int width;
    int height;

    if(!glfwInit())
        return -EINVAL;

    window = glfwCreateWindow(S_WINDOW_W, S_WINDOW_H,
        "My Window", NULL, NULL);

    if(!window)
    {
        glfwTerminate();
        return -EINVAL;
    }

    glfwMakeContextCurrent(window);

    while(!glfwWindowShouldClose(window))
    {
        // Initialize the GL viewport.

        glfwGetFramebufferSize(window, &width, &height);

        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-0.5f, (width - 1) + 0.5f,
            (height - 1) + 0.5f, -0.5f, 0.0f, 1.0f);

        // Draw some text.

        FT_Face font = get_font();

        render_text("f", 5, 5, font);

        // End GL rendering, swap the buffer, and poll for events.

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();

    return 0;
}

这是我渲染文字的功能:

int render_text(const char *t, int x, int y, FT_Face f)
{
    int ret = 0;

    GLuint *textures;

    size_t i;
    size_t length = strlen(t);

    FT_GlyphSlot g = f->glyph;

    // Allocate a texture for each character.

    textures = (GLuint *) malloc(sizeof(GLuint) * length);

    if(textures == NULL)
    {
        ret = -ENOMEM;
        goto done;
    }

    glGenTextures(length, textures);

    // FreeType glyphs are 1-byte greyscale, so we can't use alignment.

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    // Render each character...

    for(i = 0; i < length; ++i)
    {
        // Render this particular character using FreeType.

        if(FT_Load_Char(f, t[i], FT_LOAD_RENDER))
            continue;

        // Make the current glyph's texture active.

        glActiveTexture(textures[i]);
        glEnable(GL_TEXTURE_2D);

        glBindTexture(GL_TEXTURE_2D, textures[i]);

        /*
         * To prevent artifacts when a character is not rendered exactly on
         * pixel boundaries, clamp the texture to edges, and enable linear
         * interpolation.
         */

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);

        // Load the texture.

        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width,
            g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
            g->bitmap.buffer);

        // Render the texture on the screen.

        glBegin(GL_TRIANGLE_STRIP);

            glTexCoord2i(0, 0);
            glVertex2i(x + 0, y + 0);

            glTexCoord2i(g->bitmap.width, 0);
            glVertex2i(x + g->bitmap.width, y + 0);

            glTexCoord2i(0, g->bitmap.rows);
            glVertex2i(x + 0, y + g->bitmap.rows);



            glTexCoord2i(g->bitmap.width, 0);
            glVertex2i(x + g->bitmap.width, y + 0);

            glTexCoord2i(g->bitmap.width, g->bitmap.rows);
            glVertex2i(x + g->bitmap.width, y + g->bitmap.rows);

            glTexCoord2i(0, g->bitmap.rows);
            glVertex2i(x + 0, y + g->bitmap.rows);

        glEnd();
    }

    // Free our textures and we're done.

    glDeleteTextures(length, textures);
    free(textures);
done:
    return ret;
}

结果是我在(5,5)处得到一个白色矩形而不是字符。我认为问题是OpenGL在调用glTexImage2D时错误地解释了alpha数据?但是,我并不完全确定如何正确设置它。

1 个答案:

答案 0 :(得分:2)

21.070 How do texture objects work?

  

纹理对象存储纹理贴图及其相关的纹理参数状态。它们允许通过单次调用glBindTexture()在纹理之间切换。

     

...

     

以下函数影响和存储纹理对象中的状态:glTexImage *(),glTexSubImage *(),glCopyTexImage *(),glCopyTexSubImage *(), glTexParameter *()和glPrioritizeTextures() 。由于用于构建mipmap金字塔的GLU例程最终调用glTexImage *(),因此它们也会影响纹理对象状态。值得注意的是,此列表中没有glTexEnv *()和glTexGen *();它们不会在纹理对象中存储状态。

因此,GL_TEXTURE_MIN_FILTER / GL_TEXTURE_MAG_FILTER状态与纹理对象一起存储。

你在之前设置它们你有一个真正的纹理对象绑定所以你所做的就是对象纹理对象0。不是很有帮助。

所有新创建的纹理都将为GL_NEAREST_MIPMAP_LINEAR设置默认GL_TEXTURE_MIN_FILTER。但是你没有提供任何mipmap。这会导致您看到白色incomplete textures

解决方案:在 glTexParameter()之后将glBindTexture()电话移至