繁体   English   中英

将SDL_TTF文本呈现到openGL Red Square而不是文本上

[英]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_texturedrawText合并到一个可以正确显示文本的函数中。 那是代码:

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. 大大减慢速度

(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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM