Jump to content
  • Advertisement
Sign in to follow this  
Yezzy

OpenGL Problems rendering text with FreeType.

This topic is 3962 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I'm mucking around with FreeType trying to render some text. The problem is my code is producing garbage somewhere along the line and I can't figure out what it is, certain characters will render fine in some instances but the vast majority of what is rendered is garbage. Here's a picture to demonstrate: http://www.flickr.com/photos/15915212@N00/2241260330/. I'm trying this out on my Mac because my XP box has been MIA for a while now, however I'm sure the problem lies in the following function(rest of the code is provided below as well). Credit to NeHe for most of this code was copied from tutorial #43.
void renderString(const char *filename, const char *string, const size_t length, int pixel_size) {
    int i, width, height;
    FT_Library library;
    FT_Face face;
    FT_Glyph glyph;
    FT_BitmapGlyph bitmap_glyph;
    FT_Bitmap bitmap;
    GLuint *textures;

    FT_Init_FreeType(&library);
    FT_New_Face(library, filename, 0, &face);
    FT_Set_Char_Size(face, pixel_size * 64, pixel_size * 64, DPI, DPI);

    textures = calloc(length, sizeof(GLuint));
    glGenTextures(length, textures);

    glfwGetWindowSize(&width, &height);
    glTranslatef(0, height / 2, 0);

    for (i = 0; i < length; ++i) {
        FT_Load_Glyph(face, FT_Get_Char_Index(face, string), FT_LOAD_DEFAULT);
        FT_Get_Glyph(face->glyph, &glyph);
        FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
        bitmap_glyph = (FT_BitmapGlyph)glyph;
        bitmap = bitmap_glyph->bitmap;

        int width = npo2(bitmap.width);
        int height = npo2(bitmap.rows);
        float x = (float)bitmap.width / (float)width;
        float y = (float)bitmap.rows / (float)height;

        glBindTexture(GL_TEXTURE_2D, textures);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);

        glPushMatrix();
        glTranslatef(0, bitmap_glyph->top - bitmap.rows, 0);
        glBindTexture(GL_TEXTURE_2D, textures);
        glBegin(GL_QUADS);
            glTexCoord2f(0, 0); glVertex2f(0, bitmap.rows);
            glTexCoord2f(0, y); glVertex2f(0, 0);
            glTexCoord2f(x, y); glVertex2f(bitmap.width, 0);
            glTexCoord2f(x, 0); glVertex2f(bitmap.width, bitmap.rows);
        glEnd();
        glPopMatrix();
        glTranslatef(glyph->advance.x / 65536, 0, 0);
        FT_Done_Glyph(glyph);
    }

    glfwSwapBuffers();
    glDeleteTextures(length, textures);
    free(textures);

    FT_Done_Face(face);
    FT_Done_FreeType(library);
}

Just a note, I'm using GLFW.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_OUTLINE_H
#include FT_TRIGONOMETRY_H

#include <GL/glfw.h>

#define DPI 72
#define FONT_PATH "/Library/Fonts/Chalkboard.ttf"

/* gcc glfont.c -o glfont -lfreetype -lglfw -framework Carbon -framework AGL -framework OpenGL */

void initGL();
int npo2(int x);
void renderString(const char *filename, const char *string, const size_t length, int pixel_size);

int main(int argc, char **argv) {
    const char *string = argc >= 2 ? argv[1] : "abcdefghijklmnopqrstuvwxyz0123456789";
    const size_t length = strlen(string);

    glfwInit();
    glfwOpenWindow(800, 600, 8, 8, 8, 8, 24, 0, GLFW_WINDOW);
    glfwSetWindowTitle("FreeType + OpenGL Font Test.");
    glfwEnable(GLFW_STICKY_KEYS);
    initGL();
    renderString(FONT_PATH, string, length, 40);

    int running;
    do {
        running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED);
        glfwWaitEvents();
        glfwSleep(0.1);
    } while (running);

    glfwTerminate();

    return EXIT_SUCCESS;
}

void initGL() {
    int width, height;
    glfwGetWindowSize(&width, &height);

    glViewport(0, 0, width, height);

    glClearColor(0, 0.67f, 0.67f, 0);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, width, 0, height);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

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

/* calculate the next power of 2 for x. */
int npo2(int x) {
    int result = 1;
    while (result < x) {
        result *= 2;
    }
    return result;
}

If anyone can lend a pair of eyes it would be much appreciated. Thanks.

Share this post


Link to post
Share on other sites
Advertisement
It is because you're trying to load the glyph bitmap with size for example 23x24, but you're telling opengl the buffer is acually in power-of-two dimensions (32x32). The correct way is to first set the size of empty texture:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);

then use glTexSubImage to load the glyph as only part of the texture:

glPixelStorei(GL_UNPACK_ALIGNMENT,1); // no alignment
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width, bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!