OpenGL font rendering using Freetype2

匿名 (未验证) 提交于 2019-12-03 01:58:03

问题:

I'm trying to render a freetype font using OpenGL, following the example posted at http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_02.

I've been able to generate a texture atlas from the font, creating shaders and creating quads. What I seem to get stuck at is passing the texture to the shader and/or getting the correct UVs for my quads. Been struggling for a good while now and really need the help.

The following is the struct I use to create my texture atlas.

struct FontCharacter     {         float advanceX;         float advanceY;          float bitmapWidth;         float bitmapHeight;          float bitmapLeft;         float bitmapTop;          float uvOffsetX;         float uvOffsetY;     };      struct FontTextureAtlas     {         GLuint texture;         GLuint textureUniform;          int width;         int height;          FontCharacter characters[128];          FontTextureAtlas(FT_Face face, int h, GLuint tUniform)         {             FT_Set_Pixel_Sizes(face, 0, h);             FT_GlyphSlot glyphSlot = face->glyph;              int roww = 0;             int rowh = 0;             width = 0;             height = 0;              memset(characters, 0, sizeof(FontCharacter));              for (int i = 32; i bitmap.width + 1 >= MAX_WIDTH)                 {                     width = std::fmax(width, roww);                     height += rowh;                     roww = 0;                     rowh = 0;                 }                  roww += glyphSlot->bitmap.width + 1;                 rowh = std::fmax(rowh, glyphSlot->bitmap.rows);             }              width = std::fmax(width, roww);             height += rowh;              glGenTextures(1, &texture);              if (glGetError() != GL_NO_ERROR)             {                 std::cout bitmap.width + 1 >= MAX_WIDTH)                  {                     oy += rowh;                     rowh = 0;                     ox = 0;                 }                  glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, glyphSlot->bitmap.width, glyphSlot->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, glyphSlot->bitmap.buffer);                  if (glGetError() != GL_NO_ERROR)                 {                     std::cout advance.x >> 6;                 characters[i].advanceY = glyphSlot->advance.y >> 6;                  characters[i].bitmapWidth = glyphSlot->bitmap.width;                 characters[i].bitmapHeight = glyphSlot->bitmap.rows;                  characters[i].bitmapLeft = glyphSlot->bitmap_left;                 characters[i].bitmapTop = glyphSlot->bitmap_top;                  characters[i].uvOffsetX = ox / (float)width;                 characters[i].uvOffsetY = oy / (float)height;                  rowh = std::fmax(rowh, glyphSlot->bitmap.rows);                 ox += glyphSlot->bitmap.width + 1;             }              std::cout 

Local variables and function heads used in the renderer

class RenderCore {     FT_Library library;             FT_Face face;             FontTextureAtlas* a48;             FontTextureAtlas* a24;             FontTextureAtlas* a12;             GLuint vbo;             GLuint vao;             GLuint m_posUV;             GLuint m_colorIN;             GLuint m_texture;              int InitFT();             void RenderText(const char* text, FontTextureAtlas* atlas, float x, float y, float sx, float sy); } 

This is where I load my fonts.

int RenderCore::InitFT() {     if (FT_Init_FreeType(&library))     {         std::cout CreateProgram("Text");     m_shaderManager->LoadShader("shaders/Text.vertex", "TextVS", GL_VERTEX_SHADER);     m_shaderManager->LoadShader("shaders/Text.fragment", "TextFS", GL_FRAGMENT_SHADER);     m_shaderManager->AttachShader("TextVS", "Text");     m_shaderManager->AttachShader("TextFS", "Text");     m_shaderManager->LinkProgram("Text");     m_shaderManager->UseProgram("Text");     m_shaderManager->UseProgram("Text");      m_colorIN = m_shaderManager->GetUniformLocation("Text", "inputColor");     m_texture = m_shaderManager->GetUniformLocation("Text", "texture");       // Create the vertex buffer object     glGenBuffers(1, &vbo);     glGenVertexArrays(1, &vao);     /* Create texture atlasses for several font sizes */     a48 = new FontTextureAtlas(face, 48, m_texture);     a24 = new FontTextureAtlas(face, 24, m_texture);     a12 = new FontTextureAtlas(face, 12, m_texture); } 

Rendering function.

void RenderCore::RenderText(const char* text, FontTextureAtlas* atlas, float x, float y, float sx, float sy)     {         m_shaderManager->UseProgram("Text");          const unsigned char* p;          std::vector<:vec4> coords;          int c = 0;          for (p = (const unsigned char*)text; *p; p++)         {             float x2 = x + atlas->characters[*p].bitmapLeft * sx;             float y2 = -y - atlas->characters[*p].bitmapTop * sy;             float w = atlas->characters[*p].bitmapWidth * sx;             float h = atlas->characters[*p].bitmapHeight * sy;              x += atlas->characters[*p].advanceX * sx;             y += atlas->characters[*p].advanceY * sy;              if (!w || !h)                 continue;               coords.push_back(                 glm::vec4(                 x2,                 -y2,                 atlas->characters[*p].uvOffsetX,                 atlas->characters[*p].uvOffsetY)                 );               coords.push_back(                 glm::vec4(                 x2 + w,                 -y2,                 atlas->characters[*p].uvOffsetX + atlas->characters[*p].bitmapWidth / atlas->width,                 atlas->characters[*p].uvOffsetY)                 );                coords.push_back(                 glm::vec4(                 x2,                 -y2 - h,                 atlas->characters[*p].uvOffsetX,                 atlas->characters[*p].uvOffsetY + atlas->characters[*p].bitmapHeight / atlas->height)                 );                coords.push_back(                 glm::vec4(                 x2 + w,                 -y2,                 atlas->characters[*p].uvOffsetX + atlas->characters[*p].bitmapWidth / atlas->width,                 atlas->characters[*p].uvOffsetY)                 );               coords.push_back(                 glm::vec4(                 x2,                 -y2 - h,                 atlas->characters[*p].uvOffsetX,                 atlas->characters[*p].uvOffsetY + atlas->characters[*p].bitmapHeight / atlas->height)                 );               coords.push_back(                 glm::vec4(                 x2 + w,                 -y2 - h,                 atlas->characters[*p].uvOffsetX + atlas->characters[*p].bitmapWidth / atlas->width,                 atlas->characters[*p].uvOffsetY + atlas->characters[*p].bitmapHeight / atlas->height)                 );         }          glEnable(GL_BLEND);         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);          glActiveTexture(GL_TEXTURE0 + atlas->texture);         glUniform1i(atlas->textureUniform, 0);         glBindTexture(GL_TEXTURE_2D, atlas->texture);          m_shaderManager->SetUniform(1, glm::vec4(0, 0, 1, 1), m_colorIN);          glBindBuffer(GL_ARRAY_BUFFER, vbo);         glBufferData(GL_ARRAY_BUFFER, coords.size() * sizeof(glm::vec4), coords.data(), GL_DYNAMIC_DRAW);          //Generate VAO         glBindVertexArray(vao);          //Position         glEnableVertexAttribArray(0);         glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (void*)0);          glBindVertexArray(vao);         glDrawArrays(GL_TRIANGLE_STRIP, 0, coords.size());          glDisableVertexAttribArray(0);         m_shaderManager->ResetProgram();     } 

Vertex shader

#version 440  in vec4 pos_uv; out vec2 uv;  void main() {     gl_Position = vec4(pos_uv.xy, 0, 1);     uv = pos_uv.zw; } 

Fragment shader

#version 440      in vec2 uv;     uniform sampler2D texture;     uniform vec4 inputColor;      out vec4 color;      void main()     {         color = vec4(inputColor.rgb, texture2D(texture, uv).a);     } 

Using gDebugger I can see the texture atlas having been generated properly and the VBO seems fine as well. The result is just a bunch of squares on screen however and I really have no idea why. I think it might be a problem with passing the texture to the shader, all channels except the alpha channel is empty and the alpha is always 1.

回答1:

Managed to solve the problem, instead of glActiveTexture(GL_TEXTURE0 + texture); it should have only been glActiveTexture(GL_TEXTURE0);

I'm assuming glActiveTexture binds to a specific index within a program and not for all textures.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!