gpt4 book ai didi

c++ - 渲染文本 - freetype 空白屏幕

转载 作者:行者123 更新时间:2023-11-30 04:15:35 24 4
gpt4 key购买 nike

我正在使用 freetype,为了渲染文本我唯一要做的就是将 ft_bitmap 转换为可以用 opengl 渲染的东西,有人可以解释一下如何做到这一点吗?我正在使用 glfw。按照我尝试这样做的方式,它只会给出一个空白屏幕这是我正在使用的代码:

    #include <exception>
#include <iostream>
#include <string>
#include <glew.h>
#include <GL/glfw.h>
#include <iterator>
#include "../include/TextRenderer.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include <stdexcept>
#include <freetype/ftglyph.h>


using std::runtime_error;
using std::cout;
TextRenderer::TextRenderer(int x, int y, FT_Face Face, std::string s)
{


FT_Set_Char_Size(
Face, /* handle to face object */
0, /* char_width in 1/64th of points */
16*64, /* char_height in 1/64th of points */
0, /* horizontal device resolution */
0 ); /* vertical device resolution */
slot= Face->glyph;

text = s;
setsx(x);
setsy(y);
penX = x;
penY = y;
face = Face;
//shaders
GLuint v = glCreateShader(GL_VERTEX_SHADER) ;
const char* vs = "void main(){ gl_Position = ftransform();}";
glShaderSource(v,1,&vs,NULL);
glCompileShader(v);
GLuint f = glCreateShader(GL_FRAGMENT_SHADER) ;
const char* fs = "uniform sampler2D texture1; void main() { gl_FragColor = texture2D(texture1, gl_TexCoord[0].st); //And that is all we need}";
glShaderSource(f,1,&fs,NULL);
glCompileShader(f);
Program= glCreateProgram();
glAttachShader(Program,v);
glAttachShader(Program,f);
glLinkProgram(Program);


}
void TextRenderer::render()
{
glUseProgram(Program);
FT_UInt glyph_index;
for ( int n = 0; n < text.size(); n++ )
{
/* retrieve glyph index from character code */

glyph_index = FT_Get_Char_Index( face, text[n] );

/* load glyph image into the slot (erase previous one) */
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER );

draw(&face->glyph->bitmap,penX + slot->bitmap_left,penY - slot->bitmap_top );

penX += *(&face->glyph->bitmap.width)+3;
penY += slot->advance.y >> 6; /* not useful for now */
}
}
void TextRenderer::draw(FT_Bitmap * bitmap,float x,float y)
{



GLuint texture [0] ;

glGenTextures(1,texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RED , bitmap->width, bitmap->rows, 0, GL_RED , GL_UNSIGNED_BYTE, bitmap);


// int loc = glGetUniformLocation(Program, "texture1");
// glUniform1i(loc, 0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glEnable(GL_TEXTURE_2D);
int height=bitmap->rows/10;
int width=bitmap->width/10;
glBegin(GL_QUADS);
glTexCoord2f (0.0, 0.0);
glVertex2f(x,y);
glTexCoord2f (1.0, 0.0);
glVertex2f(x+width,y);
glTexCoord2f (1.0, 1.0);
glVertex2f(x+width,y+height);
glTexCoord2f (0.0, 1.0);
glVertex2f(x,y+height);
glEnd();
glDisable(GL_TEXTURE_2D);

}

我正在使用什么来初始化文本渲染器:

FT_Library  library;
FT_Face arial;
FT_Error error = FT_Init_FreeType( &library );
if ( error )
{
throw std::runtime_error("Freetype failed");
}

error = FT_New_Face( library,
"C:/Windows/Fonts/Arial.ttf",
0,
&arial );
if ( error == FT_Err_Unknown_File_Format )
{
throw std::runtime_error("font format not available");
}
else if ( error )
{
throw std::runtime_error("Freetype font failed");
}
TextRenderer t(5,10,arial,"Hello");
t.render();

最佳答案

您的程序中有很多问题是由于不了解您对 OpenGL 或 Freetype 的每次调用的目的而导致的。您应该真正阅读库的文档,而不是将教程相互堆叠。

让我们一个一个地做这个

片段着色器

const char* fs = "uniform sampler2D texture1;
void main() {
gl_FragColor = texture2D(texture1, gl_TexCoord[0].st);
//And that is all we need}";`

此着色器无法编译(您真的应该检查它是否使用 glGetShaderiv 编译,以及它是否与 glGetProgramiv 链接)。如果你缩进正确,那么你会看到你注释掉了最后的 ,因为它在同一行中,在 // 之后。因此,您应该删除评论或使用 \n 结束评论。

此外,对于较新版本的 OpenGL,使用 gl_TexCoord 已被弃用,但如果您使用兼容性配置文件,它仍然有效。

顶点着色器

就像片段着色器一样,使用了已弃用的功能,即 ftransform()

但更大的问题是您在片段着色器中使用了 gl_TexCoord[0] 而没有从顶点着色器传递它。因此,您需要在顶点着色器中添加 gl_TexCoord[0]=gl_MultiTexCoord0; 行。 (您可能已经猜到它也已弃用)

纹理传递

您将指向 bitmap 的指针传递给 glTexImage2Dbitmap 的类型为 FT_Bitmap *,您需要改为传递 bitmap->buffer

你不应该在每一帧为每个字母生成一个新的纹理(尤其是如果你不删除它的话)。您应该只调用一次 glGentextures(您可以将它放在您的 TextRenderer 构造函数中,因为您将所有其他初始化内容都放在那里)。

然后是 GLuint texture [0]; 应该会给你一个编译器错误。如果你真的需要一个只有一个元素的数组,那么语法是 GLuint texture [1];

所以你的最终调用看起来像这样:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap->width, bitmap->rows, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bitmap->buffer);

杂项

int height=bitmap->rows/10;
int width=bitmap->width/10;

这是一个整数除法,如果您的 bitmap->width 值小于 10,您将得到 0 作为结果,这将使您尝试绘制的四边形不可见(高度或宽度为 0)。如果您无法将对象显示在 View 中,您应该将其平移/缩放到 View 中。这也已弃用,但如果您继续使用其他东西,这将使您的窗口具有从 [-100,-100] 到 [100,100](左下角到右上角)的坐标系。

glLoadIdentity();
glScalef(0.01f, 0.01f, 1.0f);

您还缺少从 FreeType 到 OpenGL 的坐标转换,Freetype 使用的坐标系从左上角的 [0,0] 开始,x 是向右的偏移量,而y 是到底部的偏移量。所以如果你只是在 OpenGL 中使用这些坐标,一切都会颠倒过来。

如果您完成了所有操作,您的结果应该如下所示(灰色背景突出显示多边形的开始和结束位置):

glfw Window

至于您的一般方法,重新利用一个纹理并逐个字母绘制重复使用和覆盖相同的纹理似乎是一种低效的方法。最好只分配一个更大的纹理,然后使用 glTexSubImage2D 将字形写入其中。如果自由类型重新渲染字母是一个瓶颈,你也可以在开始时将你需要的所有符号写入一个纹理(例如整个 ASCII 范围),然后将该纹理用作纹理图集。

我的一般建议也是,如果您不是真的想学习 OpenGL,而只是想使用一些跨平台渲染而不用担心低级的东西,我建议您改用渲染框架。

关于c++ - 渲染文本 - freetype 空白屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18213215/

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