2

' 'からまでの文字のすべてのビットマップを生成し、'~'それらを 1 つの長いテクスチャに追加しようとしています。それらを固定幅のテクスチャに配置するつもりですが、今のところはコンセプトが機能することを確認したかっただけです。

しかし、私は問題を抱えています。期待されるテクスチャを取得する代わりに、16px フォントに対して以下を取得します。 ここに画像の説明を入力

間違ってコピーしているように見えますが、何をしているように見えても、常に同じ出力が得られるようです。

最後に、コード:

Font.h

#ifndef _FONT_H_
#define _FONT_H_

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <GL/gl.h>

#include <ft2build.h>
#include FT_FREETYPE_H

#include "vector2.h"
#include "math_helper.h"

class Font {
public:
  Font(const std::string font_path, int size);
  ~Font();

  int get_texture() const { return texture_; }

private:
  unsigned int width_, height_, texture_;

  static FT_Library LIBRARY;
  static const char START_CHAR = ' ';
  static const char END_CHAR   = '~';

  static void initialize_library();
};

#endif

フォント.cpp

#include "font.h"

FT_Library Font::LIBRARY = NULL;        

Font::Font(const std::string font_path, int size)
  : width_(64), height_(2), texture_(0) {
  initialize_library();

  FT_Face face = NULL;
  int error = FT_New_Face(Font::LIBRARY, font_path.c_str(), 0, &face);

  if(error == FT_Err_Unknown_File_Format) {
    std::cout << "Error: Unknown file format for font \"" << font_path << "\"" << std::endl;
  } else if(error) {
    std::cout << "Error: Could not open font \"" << font_path << "\"" << std::endl;
  }

  error = FT_Set_Pixel_Sizes(face, 0, size);
  if(error) {
    std::cout << "Error: Could not set pixel size for font \"" << font_path << "\"" << std::endl;
  }

  int num_chars = (END_CHAR - START_CHAR);
  width_ = to_nearest_pow2(num_chars * size);
  height_ = to_nearest_pow2(size);
  std::vector<unsigned char> buffer(width_ * height_, 0);
  Vector2 pen;

  for(char c = START_CHAR; c <= END_CHAR; ++c) {
    error = FT_Load_Char(face, c, FT_LOAD_RENDER);

    if(error) {
      std::cout << "Error: Could not load char \"" << c << "\"" << std::endl;
      continue;
    }

    FT_Bitmap bmp = face->glyph->bitmap;
    int advance = (face->glyph->advance.x >> 6);
    int bitmapWidth = bmp.width; //I have tried pitch, same problem
    int bitmapHeight = bmp.rows;

    for(int h = 0; h < bitmapHeight; ++h) {
      for(int w = 0; w < bitmapWidth; ++w) {
        int index = h * bitmapWidth + pen.x;

        buffer[index + w] = bmp.buffer[w + bitmapWidth * h];
      }
    }

    pen.x += advance;
  }

  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glGenTextures(1, &texture_);
  glBindTexture(GL_TEXTURE_2D, texture_);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width_, height_, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &buffer[0]);

  FT_Done_Face(face);
}

Font::~Font() {
  if(texture_ != 0) {
    glDeleteTextures(1, &texture_);
  }
}

void Font::initialize_library() {
  if(Font::LIBRARY == NULL) {
    if(FT_Init_FreeType(&Font::LIBRARY) != 0) {
      std::cout << "Error: Unable to initialize FreeType Library" << std::endl;
      return;
    }
  }
}

Vector2 は、構築時に 0 に初期化される x フィールドと y フィールドを持つ単純な構造体です。

to_nearest_pow2と定義されている:

template<typename T>
T to_nearest_pow2(const T num) {
  T nearest = 2;

  while((nearest <<= 1) < num);

  return nearest;
}

ああ、これが私がスクリーンに描く方法です(私は正投影を使用しています)

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

  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, test->get_texture());
  glBegin(GL_QUADS);
  glTexCoord2i(0, 0); glVertex2i(0, 0);
  glTexCoord2i(1, 0); glVertex2i(400, 0);
  glTexCoord2i(1, 1); glVertex2i(400, 400);
  glTexCoord2i(0, 1); glVertex2i(0, 400);
  glEnd();

編集

index@shoustonが提案したものに変更したところ、この出力が得られました

ここに画像の説明を入力

4

2 に答える 2

4

出力画像を1000x60のようなものに再スケーリングすると、驚きが得られます。添付したPNGで作成したpaint.netは次のとおりです。

ここに画像の説明を入力してください

最初に明らかなこと。キャラクターは基本的にそこにありますが、何らかの理由であなたはそれらを非常に小さくレンダリングしているだけです(あなたはどのような価値sizeを渡しましたか?)

また、FreeType文字メトリックを処理しようとはしていないので、すべてがうまく整列することを期待しないでください。まだ...

于 2013-03-04T22:59:21.787 に答える
2

問題は、テクスチャ バッファへのインデックスにあります。

int index = h * bitmapWidth + pen.x;

する必要があります

int index = h * width_ + pen.x;

つまり、h にグリフの幅ではなく、テクスチャの全幅を掛けます。

于 2013-03-04T21:33:13.417 に答える