0

SDL_ttf を使用して OpenGL でテキストをレンダリングする基本的なプログラムを作成しようとしています。この 2 つを連携させる方法について、約 12 の質問が回答されているのを見てきましたが、そのほとんどすべてが、私が使用しているものと似たコードを提供しています。しかし、私が経験しているボラティリティに関連する質問は見たことがありません。

とても奇妙です。特定のフォント、特定のポイント サイズ、特定の出力文字列を使用している場合、プログラムは機能し、完全に出力されます。それ以外の場合、プログラムは実行されますが、テキストの表面がゴミとして出てきます。また、プログラムがすぐにクラッシュする場合もあります。

たとえば、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();

}

必要に応じて追加の詳細を提供できるよう最善を尽くします。

4

1 に答える 1

0

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 のサイズを変更して 2 の累乗次元にする方法とその方法の例を確認してください。適切な OpenGL テクスチャ座標にマップします。

于 2014-01-03T05:49:20.937 に答える