将freetype位图复制到opengl纹理时出现问题 [英] Problems copying freetype bitmap to opengl texture

查看:253
本文介绍了将freetype位图复制到opengl纹理时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图为'''〜'生成字符的所有位图,然后添加它们到一个长的纹理。我打算把它们放在一个固定宽度的纹理,但现在我只是想确保这个概念将工作。

I'm trying to generate all the bitmaps for characters from ' ' to '~' and add them to one long texture. I intend to position them in a fixed width texture but for now I just wanted to make sure the concept would work.

但我有问题。不是得到预期的纹理我只是得到下面的一个16像素的字体:

But I am having problems. Instead of getting the expected texture I just get the below for a 16px font:

它看起来像我复制它错了,但不管我似乎总是得到相同的输出。

It looks to me as if I'm copying it wrong but no matter what I seem to do I seem to always get the same output.

最后,代码:

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

Font.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只是一个简单的结构其中x和y字段在构造时被初始化为0.

Vector2 is just a simple struct with an x and y field that are initialized to 0 on construction.

to_nearest_pow2 定义为:

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

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

  return nearest;
}

哦,这是我如何绘制到屏幕)

Oh and here's how I am drawing it to screen (I am using orthographic projection)

  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();

编辑

我改变了索引到@shouston建议的,现在我得到这个输出

I changed index to what was suggested by @shouston and now I get this output

推荐答案

将输出图像重新调整为像1000x60这样的大小,你会得到一个惊喜。这是你用附加的PNG做的paint.net。

Rescale your output image to something like 1000x60, and you'll get a surprise. Here's what paint.net made of the PNG you attached.

明显的事情。字符基本上是在那里,但由于某种原因,你只是把它们变得非常小( size 的值 c>你通过了吗?)

Obvious things first. The characters are basically there, but for some reason you;'re just rendering them very small (what value of size did you pass?)

此外,你不是要处理任何freetype字符度量,所以不要指望他们所有排队。但... ...

Also, you're not trying to handle any of the freetype character metrics, so don't expect them to all line up nicely. yet...

这篇关于将freetype位图复制到opengl纹理时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆