Я нахожусь в процессе написания небольшой игры для обучения рендерингу OpenGL, поскольку это одна из вещей, которой я еще не занимался.Я использовал SDL раньше, и эта та же самая функция, хотя она по-прежнему работала плохо, работала не так сильно, как сейчас.
По сути, в моей игре пока что мало что происходит, только некоторые базовые движенияи фоновый рисунок.Когда я переключился на OpenGL, кажется, что он way слишком быстро.Число моих кадров в секунду превышает 2000, и эта функция потребляет большую часть вычислительной мощности.
Что интересно, программа в своей версии SDL использует 100% ЦП, но работает без сбоев, в то время как версия OpenGL использует только около 40% - 60% ЦП, но, кажется, нагружает мою видеокарту таким образом, что весь мой рабочий стол перестает отвечать на запросы.Плохо.
Это не слишком сложная функция, она создает фоновый тайл 1024x1024 в соответствии с координатами X и Y игрока, чтобы создать впечатление движения, в то время как само изображение игрока остается заблокированным в центре.Поскольку это небольшая плитка для большого экрана, я должен рендерить ее несколько раз, чтобы соединить плитки вместе для получения полного фона.Два цикла for в приведенном ниже коде повторяются вместе 12 раз, поэтому я понимаю, почему это неэффективно при вызове 2000 раз в секунду.
Итак, чтобы перейти к сути, это злодей:
void render_background(game_t *game)
{
int bgw;
int bgh;
int x, y;
glBindTexture(GL_TEXTURE_2D, game->art_background);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &bgw);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &bgh);
glBegin(GL_QUADS);
/*
* Start one background tile too early and end one too late
* so the player can not outrun the background
*/
for (x = -bgw; x < root->w + bgw; x += bgw)
{
for (y = -bgh; y < root->h + bgh; y += bgh)
{
/* Offsets */
int ox = x + (int)game->player->x % bgw;
int oy = y + (int)game->player->y % bgh;
/* Top Left */
glTexCoord2f(0, 0);
glVertex3f(ox, oy, 0);
/* Top Right */
glTexCoord2f(1, 0);
glVertex3f(ox + bgw, oy, 0);
/* Bottom Right */
glTexCoord2f(1, 1);
glVertex3f(ox + bgw, oy + bgh, 0);
/* Bottom Left */
glTexCoord2f(0, 1);
glVertex3f(ox, oy + bgh, 0);
}
}
glEnd();
}
Если я искусственно ограничиваю скорость, набрав SDL_Delay(1)
в игровом цикле, я урежу FPS до ~ 660 ± 20, я не получу «перебор производительности».Но я сомневаюсь, что это правильный путь для этого.
Ради завершения, это мои общие функции рендеринга и игрового цикла:
void game_main()
{
long current_ticks = 0;
long elapsed_ticks;
long last_ticks = SDL_GetTicks();
game_t game;
object_t player;
if (init_game(&game) != 0)
return;
init_player(&player);
game.player = &player;
/* game_init() */
while (!game.quit)
{
/* Update number of ticks since last loop */
current_ticks = SDL_GetTicks();
elapsed_ticks = current_ticks - last_ticks;
last_ticks = current_ticks;
game_handle_inputs(elapsed_ticks, &game);
game_update(elapsed_ticks, &game);
game_render(elapsed_ticks, &game);
/* Lagging stops if I enable this */
/* SDL_Delay(1); */
}
cleanup_game(&game);
return;
}
void game_render(long elapsed_ticks, game_t *game)
{
game->tick_counter += elapsed_ticks;
if (game->tick_counter >= 1000)
{
game->fps = game->frame_counter;
game->tick_counter = 0;
game->frame_counter = 0;
printf("FPS: %d\n", game->fps);
}
render_background(game);
render_objects(game);
SDL_GL_SwapBuffers();
game->frame_counter++;
return;
}
Согласно профилированию gprof,даже когда я ограничиваю выполнение с помощью SDL_Delay()
, оно все равно тратит около 50% времени на рендеринг моего фона.