gpt4 book ai didi

使用 Freetype2 进行 OpenGL 字体渲染

转载 作者:行者123 更新时间:2023-12-03 04:22:09 27 4
gpt4 key购买 nike

我正在尝试使用 OpenGL 渲染 freetype 字体,遵循 http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_02 上发布的示例.

我已经能够从字体生成纹理图集,创建着色器并创建四边形。我似乎陷入的困境是将纹理传递给着色器和/或为我的四边形获取正确的 UV。现在已经挣扎了很长一段时间,确实需要帮助。

以下是我用来创建纹理图集的结构。

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 < 128; i++)
{
if (FT_Load_Char(face, i, FT_LOAD_RENDER))
{
std::cout << "Loading character %c failed\n", i;
continue;
}

if (roww + glyphSlot->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 << "glGenTextures failed\n";
}

glActiveTexture(GL_TEXTURE0 + texture);

if (glGetError() != GL_NO_ERROR)
{
std::cout << "glActiveTexture failed\n";
}

glBindTexture(GL_TEXTURE_2D, texture);

if (glGetError() != GL_NO_ERROR)
{
std::cout << "glBindTexture failed\n";
}

glUniform1i(tUniform, 0);
textureUniform = tUniform;

glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, 0);

if (glGetError() != GL_NO_ERROR)
{
std::cout << "glTexImage2D failed\n";
}

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

if (glGetError() != GL_NO_ERROR)
{
std::cout << "glPixelStorei failed\n";
}

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

if (glGetError() != GL_NO_ERROR)
{
std::cout << "glTexParameteri failed\n";
}

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

if (glGetError() != GL_NO_ERROR)
{
std::cout << "glTexParameteri failed\n";
}

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

if (glGetError() != GL_NO_ERROR)
{
std::cout << "glTexParameteri failed\n";
}

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

if (glGetError() != GL_NO_ERROR)
{
std::cout << "glTexParameteri failed\n";
}


int ox = 0;
int oy = 0;

rowh = 0;

for (int i = 32; i < 128; i++)
{
if (FT_Load_Char(face, i, FT_LOAD_RENDER))
{
std::cout << "Loading character %c failed\n", i;
continue;
}

if (ox + glyphSlot->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 << "BORKED AGAIN\n";
}

characters[i].advanceX = glyphSlot->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 << "Generated a " << width << "x " << height << " (" << width * height / 1024 << " kb) texture atlas.\n";
}

~FontTextureAtlas()
{
glDeleteTextures(1, &texture);
}

渲染器中使用的局部变量和函数头

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

这是我加载字体的地方。

int RenderCore::InitFT()
{
if (FT_Init_FreeType(&library))
{
std::cout << "Could not Initialize freetype library.\n";
return 0;
}

/* Load a font */
if (FT_New_Face(library, "assets/Fonts/arialbd.ttf", 0, &face))
{
std::cout << "Could not open font assets/Fonts/DentonBeta2.ttf\n";
return 0;
}

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

渲染功能。

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<glm::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();
}

顶点着色器

#version 440

in vec4 pos_uv;
out vec2 uv;

void main()
{
gl_Position = vec4(pos_uv.xy, 0, 1);
uv = pos_uv.zw;
}

片段着色器

#version 440

in vec2 uv;
uniform sampler2D texture;
uniform vec4 inputColor;

out vec4 color;

void main()
{
color = vec4(inputColor.rgb, texture2D(texture, uv).a);
}

使用 gDebugger,我可以看到纹理图集已正确生成,并且 VBO 看起来也很好。结果只是屏幕上出现一堆方 block ,我真的不知道为什么。我认为可能是将纹理传递给着色器时出现问题,除了 alpha channel 之外的所有 channel 都是空的并且 alpha 始终为 1。

最佳答案

设法解决问题,而不是glActiveTexture(GL_TEXTURE0 +texture);它应该只是 glActiveTexture(GL_TEXTURE0);

我假设 glActiveTexture 绑定(bind)到程序中的特定索引,而不是所有纹理。

关于使用 Freetype2 进行 OpenGL 字体渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20271331/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com