2010-10-27 7 views
8

Tôi đang cố gắng phát triển một công cụ trò chơi 2D đơn giản và tôi cần có khả năng vẽ văn bản, vì vậy tôi quyết định sử dụng thư viện freetype nổi tiếng. Mục tiêu hiện tại của tôi là hiển thị mọi ký tự từ 0 đến 255 và lưu trữ thông tin thích hợp trong đối tượng glyph, vị trí trên cùng và bên trái của ký tự, chiều rộng và chiều cao và kết cấu OpenGL. (Trong tương lai tôi muốn loại bỏ có 1 texture cho mỗi glyph, nhưng trước khi bắt đầu làm việc trên đó tôi cần các ký tự của mình hiển thị chính xác). Đầu tiên tôi có tất cả các nhân vật bị cắt xén nhưng sau đó tôi đã kiểm tra this question và đã tìm ra rằng tôi phải sao chép bộ đệm bitmap vào bộ đệm mới với kích thước kết cấu OpenGL yêu cầu (nghĩa là sức mạnh của cả hai chiều rộng và chiều cao). Từ đó trở đi, mọi nhân vật đều trông rất tuyệt, vì vậy tôi đã thử các kích thước phông chữ khác nhau để xem mọi thứ có hoạt động tốt không, đoán xem ... nó không phải là cỡ chữ nhỏ (tức là < 30). 'l', 'i', ';', ':') xuất hiện bị cắt xén.Các ký tự kết xuất vấn đề với Freetype và OpenGL

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

nhân vật Tất cả bị bóp méo có chiều rộng 1, mà ra đến hai, bởi vì đó chính là sức mạnh đầu tiên của hai, đây là đoạn code để hiển thị mỗi nhân vật.

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; 
} 

Giải pháp duy nhất tôi có thể tìm thấy là một chút nếu tuyên bố, thay đổi TextureWidth thành 4 nếu nó có giá trị là 2 và cách văn bản trông đẹp mắt ở mọi kích thước phông chữ. Nhưng điều này không có ý nghĩa gì với tôi, tại sao OpenGL sẽ từ chối chiều rộng của 2 họa tiết? Oh, và tôi đã xác định rằng vấn đề không nằm trong bộ đệm, tôi in nó ra và nó trông rất ổn.

Bạn có thể nghĩ ra bất kỳ lý do nào tại sao điều này xảy ra không?

Đây là phần còn lại của mã cực kỳ lộn xộn, trong trường hợp vấn đề không nằm trong hàm 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]; 

}; 

Tôi nghĩ đó là về mọi thứ, vui lòng cho tôi biết nếu bạn đã tìm thấy sự cố.

Trân trọng và cảm ơn trước,

+0

Bạn đã thử chạy trên một máy tính khác? Nó có thể là một vấn đề trình điều khiển. –

+0

Không, tôi chưa, tôi sẽ thử và đăng lại sau. Cảm ơn ý tưởng! :) – Carlos

Trả lời

0

Có thể bạn đã gặp phải vấn đề về kết cấu.

Các pixel được hiển thị trên một đường viền của kết cấu của bạn 'chảy máu' sang phía bên kia trong OpenGls sẽ cố gắng tô kết cấu. đúng. Nếu tôi đúng, thay đổi bạn gói thông số để

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

nên OpenGL kẹp kết cấu tại các cạnh của nó, và vẽ kết cấu nhỏ của bạn một cách chính xác.

Cập nhật

tôi tìm thấy một cái gì đó trên một tutorial page:

Nếu bitmap một phông chữ nhỏ của không phù hợp với các điểm ảnh màn hình, Bilinear suy sẽ gây hiện vật. Một sửa chữa dễ dàng cho việc này là để thay đổi phương thức nội suy từ GL_LINEAR thành GL_NEAREST, mặc dù điều này có thể dẫn đến hiện vật bổ sung trong trường hợp văn bản được xoay.(Nếu quay văn bản là quan trọng với bạn, bạn có thể muốn thử nói OpenGL để siêu mẫu từ bitmap font chữ lớn hơn.)

+0

Tôi sợ điều đó không hiệu quả. Mọi thứ vẫn như cũ. Bạn đã kiểm tra màn hình in chưa? Điều đó không giống như một kết cấu lát gạch ở tất cả cho tôi. Chúng có vẻ giống như các giá trị pixel ngẫu nhiên và tôi không biết tại sao chúng lại xuất hiện ở đó, bởi vì ngay cả bộ đệm cũng không đáng kể. Điều này thực sự bực bội ... nó không có ý nghĩa gì cả! Tại sao các ký tự có chiều rộng nhỏ lại thất bại trong khi những ký tự khác không có vấn đề gì cả? Tôi đã được thông qua mã của tôi hơn và hơn, và không có gì có vẻ sai, bitmap được trả lại một cách chính xác và do đó là TextureBuffer của tôi ... Bất kỳ suy nghĩ khác? – Carlos

+0

Trên thực tế, tôi đã vấp phải hướng dẫn đó trong khi tìm kiếm giải pháp cho vấn đề này, thay đổi thành GL_NEAREST không làm bất cứ điều gì ... nhưng cảm ơn thời gian của bạn :) – Carlos

0

Chuẩn bị cho mình để hỗ trợ> 256 ký tự (Đó là lịch sử) và right dòng văn bản từ trái sang trái và phải cũng như luồng đầu dòng.

Chỉ là gợi ý chủ đề khác cho người nói tiếng Anh.

+0

Cảm ơn, nhưng tôi không hướng đến hỗ trợ Unicode tại thời điểm này. Điều này được cho là một dự án nhỏ do nhà sản xuất, không phải là thư viện kết xuất văn bản có mục đích chung. :) – Carlos

15

Tôi đặt cược Tôi tình cờ gặp chính xác cùng một vấn đề với freetype và OpenGL tuần trước.

Mặc định OpenGL là xem xét rằng các hàng dữ liệu kết cấu được căn chỉnh trên ranh giới 4 byte. Điều này gây ra vấn đề khi chiều rộng kết cấu trở thành 2 hoặc 1 là kích thước power-of-2 hợp lệ.

Việc đặt liên kết hàng thành ranh giới 1 byte có khắc phục được sự cố của bạn không? Sử dụng

glPixelStore(GL_UNPACK_ALIGNMENT, 1) 

HTH

+0

Nó hoạt động hoàn hảo! Cảm ơn nhiều! – Carlos

+8

Vì vậy, để không cho câu hỏi này 'chưa được trả lời', bạn có lẽ nên 'chấp nhận' câu trả lời này :) – rotoglup

0

Sử dụng freetype với ICU. Freetype một mình không thể render glyphs đúng cách. Sử dụng ICU cho điều đó.