【问题标题】:SDL_ttf and OpenGL are outputting seemingly random garbage and crashesSDL_ttf 和 OpenGL 正在输出看似随机的垃圾和崩溃
【发布时间】:2013-12-27 02:43:53
【问题描述】:

我正在尝试编写一个基本程序来使用 SDL_ttf 在 OpenGL 中呈现文本。我已经看到了十几个关于如何让两者协同工作的问题,几乎所有这些问题都提供了与我正在使用的代码相似的代码。但是,我没有看到任何与我正在经历的波动有关的问题。

这很奇怪。如果我使用特定字体、特定点大小和特定输出字符串,那么程序可以完美运行并输出。在其他情况下,程序将运行,但文本表面显示为垃圾。在其他情况下,程序会立即崩溃。

例如,如果我调用 TTF_OpenFont( "font1.ttf" , 28 ),然后使用 "Testing" 作为输出字符串调用 TTF_RenderUTF8_Blended(),它会崩溃。但是我尝试了很多东西,得到了非常令人不安的结果。

-如果我删除“g”并尝试输出“Testin”,那么程序将按预期工作并输出。 O_o

-如果我尝试输出“Test”,我会得到垃圾。

-如果我尝试输出“Tst”,程序可以工作。 o_O

-如果我尝试输出“tst”,程序就会崩溃。

此外,当我尝试不同的字体和磅值时,我会因使用不同的字符串而出现垃圾或崩溃。

对 SDL_ttf 函数的所有错误检查都恢复正常。

换句话说,据我所知,唯一决定程序是否工作的因素是我传递给 SDL_ttf 函数的字符串。我完全不知道为什么会这样(字体目录绝对准确)。我只能假设我忽略了某种明显的内存泄漏或其他东西。

话虽如此,这是我的初始化代码:

bool Init() {

if( SDL_Init(SDL_INIT_EVERYTHING) < 0 )
    return false;

//SDL_Surface* display_surface is declared outside of this function
if( (display_surface = SDL_SetVideoMode(640 , 480 , 32 , SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER | SDL_OPENGL)) == NULL )
    return false;

SDL_GL_SetAttribute(SDL_GL_RED_SIZE,            8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,          8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,           8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,          8);

SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,          16);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,         32);

SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE,      8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE,    8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE,     8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE,    8);

SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,  1);

SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES,  2);

glClearColor(0, 0, 0, 0);
glClearDepth(1.0f);

glViewport(0, 0, 640, 480);

glMatrixMode( GL_PROJECTION );
glLoadIdentity();

glOrtho(0 ,640 ,480 ,0 ,1 ,-1);

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

//TTF_Font* test_font is declared outside of this function
test_font = TTF_OpenFont( "font1.ttf" , 28 ); 

SDL_Color text_color = { 255 , 255 , 255 };

//SDL_Surface* text_surface is declared outside of this function
text_surface = TTF_RenderUTF8_Blended( test_font, "Testing" , text_color );

//force powers of 2
int w_pow2 = 1;
int h_pow2 = 1;
while( w_pow2 < text_surface->w )
    w_pow2 *= 2;
while( h_pow2 < text_surface->h )
    h_pow2 *= 2;
text_surface->w = w_pow2;
text_surface->h = h_pow2;

GLuint color_format;

if ( text_surface->format->BytesPerPixel == 4 ) {
    if (text_surface->format->Rmask == 0x000000ff) 
        color_format = GL_RGBA;
    else 
        color_format = GL_BGRA;
    } 
else if ( text_surface->format->BytesPerPixel == 3 ) {
    if ( text_surface->format->Rmask == 0x000000ff) 
        color_format = GL_RGB;
    else 
        color_format = GL_BGR;
    } 

glGenTextures( 1 , &texture ); //GLuint texture is declared outside of this function
glBindTexture( GL_TEXTURE_2D , texture );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D , 0 , text_surface->format->BytesPerPixel , text_surface->w , text_surface->h , 0 , color_format , GL_UNSIGNED_BYTE , text_surface->pixels ); 

return true;

}

我的渲染代码:

void Draw() {

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA );

glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D , texture );

glBegin( GL_QUADS );
    glTexCoord2f( 0.0 , 0.0 );
    glVertex2f( 0.0 , 0.0 );

    glTexCoord2f( 1.0 , 0.0 );
    glVertex2f( text_surface->w , 0.0 );

    glTexCoord2f( 1.0 , 1.0 );
    glVertex2f( text_surface->w , text_surface->h );

    glTexCoord2f( 0.0 , 1.0 );
    glVertex2f( 0.0 , text_surface->h );
glEnd();

glDisable( GL_TEXTURE_2D );
glDisable( GL_BLEND );

SDL_GL_SwapBuffers();

}

还有我的清理工作:

void Cleanup() {

glDeleteTextures( 1 , &texture );

SDL_FreeSurface( text_surface ); 

TTF_CloseFont( test_font ); 

TTF_Quit();

SDL_Quit();

}

我将尽我所能提供尽可能多的其他详细信息。

【问题讨论】:

  • 你能用调试器找出崩溃的地方吗?
  • 当我通过调试器运行它时它不会崩溃,它只会输出如果我正常运行程序会崩溃的字符串的垃圾像素。如果重要的话,我正在使用 dev c++。
  • 调用TTF_OpenFont( "font1.ttf" , 28 )时,运行目录下是否存在font1.ttf?
  • @cup 确实如此。我认为opengl如何尝试读取sdl表面数据导致访问冲突。但如果是这样的话,我不知道为什么调试器不抱怨它。关于我如何格式化 opengl 纹理有什么问题吗?

标签: c++ string opengl sdl sdl-ttf


【解决方案1】:

TTF_RenderUTF8_Blended() 根据 TrueType 渲染器决定绘制文本的方式生成任意大小的 SDL_Surface (text_surface)。稍后,您的代码会单方面重新调整 text_surface 的宽度和高度变量的大小,而不会实际更改图像数据(存储在“像素”中)以反映更改后的尺寸。这将导致 glTexImage2D() 将不相关的程序变量数据读取为图像数据(最好的情况)和/或非法的内存访问(最坏的情况)。

查看https://github.com/gpcz/OpenGL-SDL-Code-Warehouse/blob/master/SDLGLTexture.cpp 中的 SDLGL_LoadTextureFromFileBestFit() 示例,了解如何调整 SDL_Surface 的大小以具有二维的幂以及如何将其映射到正确的 OpenGL 纹理坐标。

【讨论】:

  • 啊,当然。应该早点意识到这一点。现在可以工作了。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-13
相关资源
最近更新 更多