SDL_ttf и OpenGL выводят, казалось бы, случайный мусор и сбои

Я пытаюсь написать базовую программу для визуализации текста в OpenGL с использованием SDL_ttf. Я видел около дюжины вопросов о том, как заставить их работать вместе, почти все из которых содержат код, похожий на тот, который я использую. Однако я не видел вопросов, связанных с волатильностью, которую я испытываю.

Это очень странно Если я использую определенный шрифт, с определенным размером точки, с определенной строкой вывода, то программа работает и выводит отлично. В других случаях программа будет работать, но текстовая поверхность выглядит как мусор. А в других случаях программа вылетает сразу.

Например, если я вызываю TTF_OpenFont («font1.ttf», 28), а затем вызываю TTF_RenderUTF8_Blended () с «Testing» в качестве выходной строки, происходит сбой. Но я попробовал кучу вещей и получил очень тревожные результаты.

-Если я удаляю «g» и пытаюсь вывести «Testin», то программа работает и выводит как положено. O_o

-Если я пытаюсь вывести «Test», я получаю мусор.

-Если я пытаюсь вывести «Tst», программа работает. о_О

-Если я пытаюсь вывести «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();

}

Я сделаю все возможное, чтобы предоставить как можно больше дополнительных деталей.

0

Решение

TTF_RenderUTF8_Blended () генерирует SDL_Surface (text_surface) произвольного размера на основе того, как средство визуализации TrueType решает построить текст. Позже ваш код в одностороннем порядке изменяет размеры переменных ширины и высоты text_surface, фактически не изменяя данные изображения (хранящиеся в «пикселях»), чтобы отразить измененные размеры. Это приведет к тому, что glTexImage2D () будет считывать несвязанные данные программных переменных как данные изображения (в лучшем случае) и / или недопустимые обращения к памяти (в худшем случае).

Проверьте SDLGL_LoadTextureFromFileBestFit () из https://github.com/gpcz/OpenGL-SDL-Code-Warehouse/blob/master/SDLGLTexture.cpp для примера того, как изменить размер SDL_Surface, чтобы иметь размеры степени два, и как сопоставить его с правильными координатами текстуры OpenGL.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]