Я пытаюсь разработать простой движок для 2D-игр, и мне нужно уметь рисовать текст, поэтому я решил использовать знаменитый freetype. библиотека. Моя текущая цель - визуализировать каждый символ от 0 до 255 и сохранить соответствующую информацию в объекте глифа, верхнем и левом положениях символа, ширине и высоте, а также текстуре OpenGL. (В будущем я хочу убрать по одной текстуре на глиф, но перед тем, как начать работать над этим, мне нужно, чтобы мои символы отображались правильно). Сначала у меня были искажены все символы, но затем я проверил этот вопрос и выяснил, что мне нужно скопировать буфер растрового изображения в новый с требуемыми размерами текстур OpenGL (т.е. степень двойки для ширины и высоты) . С этого момента каждый символ выглядел великолепно, поэтому я пробовал разные размеры шрифта, чтобы проверить, все ли работает нормально, угадайте, что ... не было, на небольших размерах шрифта (т.е.
http://img17.imageshack.us/img17/2963/helloworld.png
Все искаженные символы имели ширину 1, что дало два, потому что это первая степень двойки, вот код для визуализации каждого символа.
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;
}
Единственное решение, которое я смог найти, - это небольшой оператор if, изменение TextureWidth на 4, если оно имеет значение 2, и таким образом текст будет выглядеть нормально при любом размере шрифта. Но для меня это не имеет никакого смысла, почему OpenGL отклоняет ширину в 2 текстуры? О, и я определил, что проблема не в буфере, я распечатал его, и все выглядит нормально.
Можете ли вы придумать причину, по которой это происходит?
Вот остальная часть ( чрезвычайно) запутанный код, на случай, если проблема не в функции рендеринга.
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];
};
Я думаю, что это все, пожалуйста, дайте мне знать, если вы нашли проблему.
С уважением и заранее спасибо,