[英]rendering SDL_TTF text onto openGL Red Square instead of text
我一直在尝试在Windows XP,VS2010上使用SDL和SDL_TTF库将文本呈现到openGL窗口上。
版本:
SDL版本1.2.14
SDL TTF开发版本1.2.10
openGL(版本至少为2-3岁)。
我已经使用SDL / SDL_image成功创建了一个openGL窗口,并且可以毫无问题地在其上渲染线条/多边形。
但是,移到文本上似乎我的当前程序存在一些缺陷,在此处尝试此代码时得到以下结果
对于那些不愿意在此处粘贴信箱的人,仅是关键代码段:
void drawText(char * text) {
glLoadIdentity();
SDL_Color clrFg = {0,0,255,0}; // set colour to blue (or 'red' for BGRA)
SDL_Surface *sText = TTF_RenderUTF8_Blended( fntCourier, text, clrFg );
GLuint * texture = create_texture(sText);
glBindTexture(GL_TEXTURE_2D, *texture);
// draw a polygon and map the texture to it, may be the source of error
glBegin(GL_QUADS); {
glTexCoord2i(0, 0); glVertex3f(0, 0, 0);
glTexCoord2i(1, 0); glVertex3f(0 + sText->w, 0, 0);
glTexCoord2i(1, 1); glVertex3f(0 + sText->w, 0 + sText->h, 0);
glTexCoord2i(0, 1); glVertex3f(0, 0 + sText->h, 0);
} glEnd();
// free the surface and texture, removing this code has no effect
SDL_FreeSurface( sText );
glDeleteTextures( 1, texture );
}
段2:
// create GLTexture out of SDL_Surface
GLuint * create_texture(SDL_Surface *surface) {
GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// The SDL_Surface appears to have BGR_A formatting, however this ends up with a
// white rectangle no matter which colour i set in the previous code.
int Mode = GL_RGB;
if(surface->format->BytesPerPixel == 4) {
Mode = GL_RGBA;
}
glTexImage2D(GL_TEXTURE_2D, 0, Mode, surface->w, surface->h, 0, Mode,
GL_UNSIGNED_BYTE, surface->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return &texture;
}
我是否缺少明显的代码?
感谢您在此问题上的任何帮助。
我已经尝试学习openGL和SDL已有3天了,所以请原谅我的任何错误信息。
编辑:
我注意到使用
TTF_RenderUTF8_Shaded
TTF_RenderUTF8_Solid
抛出一个空指针异常,这意味着实际的文本呈现函数中存在错误(我怀疑),我不知道这意味着TTF_RenderUTF8_Blended
返回一个红色正方形,但我怀疑所有麻烦都取决于此。
我认为问题出在每次在屏幕上绘制文本时必须调用的glEnable(GL_TEXTURE_2D)
和glDisable(GL_TEXTURE_2D)
函数,而且SDL和GL表面之间的颜色转换可能不正确。 我将create_texture
和drawText
合并到一个可以正确显示文本的函数中。 那是代码:
void drawText(char * text, TTF_Font* tmpfont) {
SDL_Rect area;
SDL_Color clrFg = {0,0,255,0};
SDL_Surface *sText = SDL_DisplayFormatAlpha(TTF_RenderUTF8_Blended( tmpfont, text, clrFg ));
area.x = 0;area.y = 0;area.w = sText->w;area.h = sText->h;
SDL_Surface* temp = SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCALPHA,sText->w,sText->h,32,0x000000ff,0x0000ff00,0x00ff0000,0x000000ff);
SDL_BlitSurface(sText, &area, temp, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sText->w, sText->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS); {
glTexCoord2d(0, 0); glVertex3f(0, 0, 0);
glTexCoord2d(1, 0); glVertex3f(0 + sText->w, 0, 0);
glTexCoord2d(1, 1); glVertex3f(0 + sText->w, 0 + sText->h, 0);
glTexCoord2d(0, 1); glVertex3f(0, 0 + sText->h, 0);
} glEnd();
glDisable(GL_TEXTURE_2D);
SDL_FreeSurface( sText );
SDL_FreeSurface( temp );
}
我正在初始化OpenGL,如下所示:
int Init(){
glClearColor( 0.1, 0.2, 0.2, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, 600, 300, 0, -1, 1 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if( glGetError() != GL_NO_ERROR ){
return false;
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
}
好的,我终于花了时间通过编译器放置您的代码。 最重要的是,使用-Werror
编译, -Werror
使警告变为错误
GLuint * create_texture(SDL_Surface *surface) {
GLuint texture = 0;
/*...*/
return &texture;
}
我没有首先看到它,因为这类似于C编码器101,这是非常意外的: 您不得返回指向局部变量的指针! 。 一旦函数超出范围,返回的指针将仅指向废话。 为什么根本不返回指针? 只需返回一个整数:
GLuint create_texture(SDL_Surface *surface) {
GLuint texture = 0;
/*...*/
return texture;
}
因此,您以后也不会删除纹理。 您将其上载到OpenGL,但随后失去了对其的引用。
您的代码 但是,您对纹理的使用不是最佳的。 他们以这种方式进行操作,每次要绘制文本时都会重新创建一个全新的纹理。 如果在动画循环中发生这种情况,您将 glEnable(GL_TEXTURE_2D)
,这就是为什么您看不到任何纹理效果的原因。
(1)可以通过不生成新的纹理名称来解决,每次重绘
(2)可以通过仅在文本更改时上载新的纹理数据并且不使用glTexImage2D而是使用glTexSubImage2D(当然,如果纹理的尺寸更改,它必须是glTexImage2D)来上载新的纹理数据。
您应该确保使用的是GL_REPLACE或GL_MODULATE纹理环境模式。 如果使用GL_DECAL或GL_BLEND,则最终在红色四边形上显示红色文本。
我认为您应该只添加glEnable(GL_BLEND),因为文本表面的代码为TTF_RenderUTF8_Blended(fntCourier,text,clrFg),并且您必须启用opengl的混合功能。
在上一篇文章中,该函数的内存泄漏,并且程序在一段时间后崩溃了……我通过分离纹理加载和显示来改进了此功能:
必须在SDL循环之前调用第一个函数,它将文本字符串加载到内存中:
每个加载的字符串必须具有不同的txtNum参数
GLuint texture[100];
SDL_Rect area[100];
void Load_string(char * text, SDL_Color clr, int txtNum, const char* file, int ptsize){
TTF_Font* tmpfont;
tmpfont = TTF_OpenFont(file, ptsize);
SDL_Surface *sText = SDL_DisplayFormatAlpha(TTF_RenderUTF8_Solid( tmpfont, text, clr ));
area[txtNum].x = 0;area[txtNum].y = 0;area[txtNum].w = sText->w;area[txtNum].h = sText->h;
glGenTextures(1, &texture[txtNum]);
glBindTexture(GL_TEXTURE_2D, texture[txtNum]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, sText->w, sText->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, sText->pixels);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
SDL_FreeSurface( sText );
TTF_CloseFont(tmpfont);
}
第二个显示字符串,必须在SDL循环中调用:
void drawText(float coords[3], int txtNum) {
glBindTexture(GL_TEXTURE_2D, texture[txtNum]);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS); {
glTexCoord2f(0, 0); glVertex3f(coords[0], coords[1], coords[2]);
glTexCoord2f(1, 0); glVertex3f(coords[0] + area[txtNum].w, coords[1], coords[2]);
glTexCoord2f(1, 1); glVertex3f(coords[0] + area[txtNum].w, coords[1] + area[txtNum].h, coords[2]);
glTexCoord2f(0, 1); glVertex3f(coords[0], coords[1] + area[txtNum].h, coords[2]);
} glEnd();
glDisable(GL_TEXTURE_2D);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.