2010-10-27 15 views
8

Intento desarrollar un motor de juego en 2D simple y necesito poder dibujar texto, así que decidí usar la famosa biblioteca de tipos de freetype. Mi objetivo actual es representar todos los caracteres de 0 a 255 y almacenar la información adecuada en un objeto de glifo, las posiciones superior e izquierda del personaje, el ancho y el alto, y una textura OpenGL. (En el futuro deseo eliminar 1 textura por glifo, pero antes de comenzar a trabajar en eso necesito que mis personajes se muestren correctamente). Primero tengo todos los caracteres distorsionados pero luego revisé this question y descubrí que tenía que copiar el buffer de mapa de bits en uno nuevo con los tamaños de textura requeridos OpenGL (es decir, una potencia de dos para ancho y alto). A partir de ahí, cada personaje se veía genial, así que probé diferentes tamaños de fuente para ver si todo estaba funcionando bien, adivinen qué ... no lo era, en tamaños de letra pequeños (es decir, < 30) cada carácter con un ancho pequeño ('l', 'i', ';', ':') aparecieron distorsionados.Problema de representación de caracteres con Freetype y OpenGL

http://img17.imageshack.us/img17/2963/helloworld.png

caracteres distorsionados Todos tenían una anchura de 1, que salió a dos, porque esa es la primera potencia de dos, aquí está el código para la prestación de cada personaje.

bool Font::Render(int PixelSize) 
{ 
    if(FT_Set_Pixel_Sizes(mFace, 0, PixelSize) != 0) 
     return false; 

    for(int i = 0; i < 256; ++i) 
    { 
     FT_UInt GlyphIndex; 

     GlyphIndex = FT_Get_Char_Index(mFace, i); 

     if(FT_Load_Glyph(mFace, GlyphIndex, FT_LOAD_RENDER) != 0) 
      return false; 


     int BitmapWidth = mFace->glyph->bitmap.width; 
     int BitmapHeight = mFace->glyph->bitmap.rows; 

     int TextureWidth = NextP2(BitmapWidth); 
     int TextureHeight= NextP2(BitmapHeight); 

     printf("Glyph is %c, BW: %i, BH: %i, TW: %i, TH: %i\n", i, BitmapWidth, BitmapHeight, TextureWidth, TextureHeight); 

     mGlyphs[i].SetAdvance(mFace->glyph->advance.x >> 6); 
     mGlyphs[i].SetLeftTop(mFace->glyph->bitmap_left, mFace->glyph->bitmap_top); 

     GLubyte * TextureBuffer = new GLubyte[ TextureWidth * TextureHeight ]; 

     for(int j = 0; j < TextureHeight; ++j) 
     { 
      for(int i = 0; i < TextureWidth; ++i) 
      { 
       TextureBuffer[ j*TextureWidth + i ] = (j >= BitmapHeight || i >= BitmapWidth ? 0 : mFace->glyph->bitmap.buffer[ j*BitmapWidth + i ]); 
      } 
     } 

     for(int k = 0; k < TextureWidth * TextureHeight; ++k) 
      printf("Buffer is %i\n", TextureBuffer[k]); 

     Texture GlyphTexture; 

     GLuint Handle; 
     glGenTextures(1, &Handle); 

     GlyphTexture.SetHandle(Handle); 
     GlyphTexture.SetWidth(TextureWidth); 
     GlyphTexture.SetHeight(TextureHeight); 

     glBindTexture(GL_TEXTURE_2D, Handle); 

     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 

     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 

     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, TextureWidth, TextureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, TextureBuffer); 

     mGlyphs[i].SetTexture(GlyphTexture); 

     delete [] TextureBuffer; 
    } 

    return true; 
} 

La única solución que pude encontrar fue un poco si la declaración, el cambio de la TextureWidth a 4 si tiene el valor de 2, y de esa manera el texto se ve bien en todos los tamaños de fuente. Pero esto no tiene ningún sentido para mí, ¿por qué OpenGL rechazaría el ancho de 2 texturas? Ah, y he determinado que el problema no está en el buffer, lo imprimí y se ve bien.

¿Puedes pensar en alguna razón por la que esto está sucediendo?

Aquí está el resto del código (extremadamente) desordenado, en caso de que el problema no se encuentre dentro de la función Render.

int NextP2(int Val) 
{ 
    int RVal = 2; 

while(RVal < Val) RVal <<= 1; 

return RVal; 
} 

class Texture 
{ 
    public: 
     void Free() { glDeleteTextures(1, &mHandle); } 

     void SetHandle(GLuint Handle) { mHandle = Handle; } 
     void SetWidth(int Width) { mWidth = Width; } 
     void SetHeight(int Height) { mHeight = Height; } 

     inline GLuint Handle() const { return mHandle; } 
     inline int Width() const { return mWidth; } 
     inline int Height() const { return mHeight; } 
    private: 
     GLuint mHandle; 
     int mWidth; 
     int mHeight; 
}; 

class Glyph 
{ 
    public: 

     void SetAdvance(int Advance) { mAdvance = Advance; } 
     void SetLeftTop(int Left, int Top) { mLeft = Left; mTop = Top; } 
     void SetTexture(Texture texture) { mTexture = texture; } 

     Texture & GetTexture() { return mTexture; } 
     int GetAdvance() const { return mAdvance; } 
     int GetLeft() const { return mLeft; } 
     int GetTop() const { return mTop; } 

    private: 
     int mAdvance; 
     int mLeft; 
     int mTop; 
     Texture mTexture; 

}; 

class Font 
{ 
    public: 
     ~Font() { for(int i = 0; i < 256; ++i) mGlyphs[i].GetTexture().Free(); } 
     bool Load(const std::string & File); 
     bool Render(int PixelSize); 

     Glyph & GetGlyph(unsigned char CharCode) { return mGlyphs[CharCode]; } 

    private: 
     FT_Face mFace; 
     Glyph mGlyphs[256]; 

}; 

creo que eso es todo, por favor, hágamelo saber si usted ha encontrado el problema.

Saludos y gracias de antemano,

+0

¿Ha intentado ejecutar esto en una computadora diferente? Puede ser un problema con el controlador. –

+0

No, no lo he intentado y lo volveré a publicar más tarde. ¡Gracias por la idea! :) – Carlos

Respuesta

0

Es probable que se encontró con un problema de la textura y embalaje.

Los píxeles representados en un borde de su textura 'sangran' hacia el otro lado en OpenGls intentan colocar la textura en mosaico. correctamente. Si estoy en lo cierto, cambiando los parámetros que envolver a

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 

debe hacer OpenGL abrazadera su textura en sus bordes, y sacar sus pequeñas texturas correctamente.

actualización

he encontrado algo en un tutorial page:

Si los mapas de bits de una pequeña fuente no están alineados con los píxeles de la pantalla, interpolación bilineal causará artefactos. Una solución fácil para esto es cambiar el método de interpolación de GL_LINEAR a GL_NEAREST, aunque este puede conducir a artefactos adicionales en el caso de texto girado.(Si la rotación texto es importante para usted, es posible que desee para tratar diciendo a OpenGL muestra súper de mapas de bits fuente más grandes.)

+0

Me temo que no funcionó. Todo permanece igual. ¿Revisaste la pantalla de impresión? Eso no parece una textura de mosaico para mí. Parecen valores de píxel aleatorios y no tengo idea de por qué aparecen allí, porque ni siquiera se supone que el búfer sea tan grande. Esto es realmente frustrante ... ¡simplemente no tiene ningún sentido! ¿Por qué los caracteres de ancho pequeño fallarían mientras que otros no tendrían ningún problema? He revisado mi código una y otra vez, y nada parece estar mal, el mapa de bits se procesó correctamente y también lo está mi TextureBuffer ... ¿Alguna otra idea? – Carlos

+0

En realidad, me había topado con ese tutorial mientras buscaba una solución a este problema, el cambio a GL_NEAREST no hizo nada ... pero gracias por su tiempo :) – Carlos

0

Prepárese para apoyar> 256 caracteres (Eso es historia) y derecha abajo flujo de texto izquierda a izquierda e izquierda a derecha, así como flujo descendente.

Solo una sugerencia de tema diferente para hablantes de inglés.

+0

Gracias, pero no apunto a la compatibilidad con Unicode En el momento. Se supone que es un pequeño proyecto elaborado en casa, no una biblioteca de renderizado de texto de propósito general. :) – Carlos

15

Apuesto a que me encontré con exactamente el mismo problema con freetype y OpenGL la semana pasada.

OpenGL por defecto es considerar que las filas de datos de textura están alineadas en límites de 4 bytes. Esto causa problemas cuando el ancho de la textura se vuelve 2 o 1, que son tamaños válidos de potencia de 2.

¿Fijar la alineación de filas a los límites de 1 byte soluciona el problema? Usando

glPixelStore(GL_UNPACK_ALIGNMENT, 1) 

HTH

+0

¡Funcionó perfectamente! ¡Muchas gracias! – Carlos

+8

Para no dejar que esta pregunta 'no haya sido respondida' quizás debería '' aceptar 'esta respuesta :) – rotoglup

0

Uso Freetype con la UCI. Freetype solo no puede representar los glifos correctamente. Use la UCI para eso.

Cuestiones relacionadas