SDL tilemap 渲染很慢
SDL tilemap rendering quite slow
我正在使用 SDL 编写一个显示相当大的图块地图(大约 240*240 个图块)的模拟。由于我对 SDL 库还很陌生,所以我真的无法判断渲染超过 50,000 个图块时相当慢的性能是否真的正常。每个图块始终可见,大约 4*4 像素大。目前它通过 2d 数组迭代每一帧并渲染每个单独的图块,这给了我大约 40fps,太慢了,无法真正将任何游戏逻辑放在系统后面。
我试图找到一些替代系统,比如只更新更新的图块,但人们总是评论说这是一种不好的做法,渲染器应该每帧都清理等等。
Here a picture of the map
所以我基本上想问问是否有比每帧渲染每个图块更高效的系统。
编辑: 下面是我使用的简单渲染方法
void World::DirtyBiomeDraw(Graphics *graphics) {
if(_biomeTexture == NULL) {
_biomeTexture = graphics->loadImage("assets/biome_sprites.png");
printf("Biome texture loaded.\n");
}
for(int i = 0; i < globals::WORLD_WIDTH; i++) {
for(int l = 0; l < globals::WORLD_HEIGHT; l++) {
SDL_Rect srect;
srect.h = globals::SPRITE_SIZE;
srect.w = globals::SPRITE_SIZE;
if(sites[l][i].biome > 0) {
srect.y = 0;
srect.x = (globals::SPRITE_SIZE * sites[l][i].biome) - globals::SPRITE_SIZE;
}
else {
srect.y = globals::SPRITE_SIZE;
srect.x = globals::SPRITE_SIZE * fabs(sites[l][i].biome);
}
SDL_Rect drect = {i * globals::SPRITE_SIZE * globals::SPRITE_SCALE, l * globals::SPRITE_SIZE * globals::SPRITE_SCALE,
globals::SPRITE_SIZE * globals::SPRITE_SCALE, globals::SPRITE_SIZE * globals::SPRITE_SCALE};
graphics->blitOnRenderer(_biomeTexture, &srect, &drect);
}
}
}
所以在这种情况下,每个瓷砖都称为 "site",这是因为它们还存储湿度、温度等信息。
每个站点在生成过程中都分配了一个生物群落,每个生物群落基本上都是一个 ID,每个陆地生物群落的 ID 都大于 0,每个水域 ID 都为 0 或更低。
这让我可以将每个按 ID 排序的生物群系精灵放入 "biome_sprites.png" 图像中。所有的地精基本上都在第一排,而所有的水瓦都在第二排。这样我就不必手动将精灵分配给生物群落,并且该方法可以通过将图块大小(基本上是宽度)与生物群落相乘来自行完成。
这是 biome ID table from my SDD/GDD and the actual spritesheet.
图形 class 中的 blitOnRenderer 方法基本上只是运行 SDL_RenderCopy 将纹理 bliting 到渲染器上。
void Graphics::blitOnRenderer(SDL_Texture *texture, SDL_Rect
*sourceRectangle, SDL_Rect *destinationRectangle) {
SDL_RenderCopy(this->_renderer, texture, sourceRectangle, destinationRectangle);
}
在游戏循环中,每一帧都会调用 RenderClear 和 RenderPresent。
我真的希望我解释得通俗易懂,想问什么就问什么,我就是在向你们寻求帮助,所以我至少可以合作 :D
向 SDL2 开发人员咨询 SDL_RenderCopy()
的多项目版本(类似于现有的 SDL_RenderDrawLines()
/SDL_RenderDrawPoints()
/SDL_RenderDrawRects()
函数)and/or batched SDL_Renderer 个后端。
现在你正在尝试 slam 至少 240*240 = 57000 次绘制调用到 GPU 的喉咙;在任何给定的 16 毫秒内,您通常只能指望 1000-4000 次绘制调用。
或者切换到 OpenGL 并自己进行批处理。
我正在使用 SDL 编写一个显示相当大的图块地图(大约 240*240 个图块)的模拟。由于我对 SDL 库还很陌生,所以我真的无法判断渲染超过 50,000 个图块时相当慢的性能是否真的正常。每个图块始终可见,大约 4*4 像素大。目前它通过 2d 数组迭代每一帧并渲染每个单独的图块,这给了我大约 40fps,太慢了,无法真正将任何游戏逻辑放在系统后面。
我试图找到一些替代系统,比如只更新更新的图块,但人们总是评论说这是一种不好的做法,渲染器应该每帧都清理等等。
Here a picture of the map
所以我基本上想问问是否有比每帧渲染每个图块更高效的系统。
编辑: 下面是我使用的简单渲染方法
void World::DirtyBiomeDraw(Graphics *graphics) {
if(_biomeTexture == NULL) {
_biomeTexture = graphics->loadImage("assets/biome_sprites.png");
printf("Biome texture loaded.\n");
}
for(int i = 0; i < globals::WORLD_WIDTH; i++) {
for(int l = 0; l < globals::WORLD_HEIGHT; l++) {
SDL_Rect srect;
srect.h = globals::SPRITE_SIZE;
srect.w = globals::SPRITE_SIZE;
if(sites[l][i].biome > 0) {
srect.y = 0;
srect.x = (globals::SPRITE_SIZE * sites[l][i].biome) - globals::SPRITE_SIZE;
}
else {
srect.y = globals::SPRITE_SIZE;
srect.x = globals::SPRITE_SIZE * fabs(sites[l][i].biome);
}
SDL_Rect drect = {i * globals::SPRITE_SIZE * globals::SPRITE_SCALE, l * globals::SPRITE_SIZE * globals::SPRITE_SCALE,
globals::SPRITE_SIZE * globals::SPRITE_SCALE, globals::SPRITE_SIZE * globals::SPRITE_SCALE};
graphics->blitOnRenderer(_biomeTexture, &srect, &drect);
}
}
}
所以在这种情况下,每个瓷砖都称为 "site",这是因为它们还存储湿度、温度等信息。
每个站点在生成过程中都分配了一个生物群落,每个生物群落基本上都是一个 ID,每个陆地生物群落的 ID 都大于 0,每个水域 ID 都为 0 或更低。
这让我可以将每个按 ID 排序的生物群系精灵放入 "biome_sprites.png" 图像中。所有的地精基本上都在第一排,而所有的水瓦都在第二排。这样我就不必手动将精灵分配给生物群落,并且该方法可以通过将图块大小(基本上是宽度)与生物群落相乘来自行完成。
这是 biome ID table from my SDD/GDD and the actual spritesheet.
图形 class 中的 blitOnRenderer 方法基本上只是运行 SDL_RenderCopy 将纹理 bliting 到渲染器上。
void Graphics::blitOnRenderer(SDL_Texture *texture, SDL_Rect
*sourceRectangle, SDL_Rect *destinationRectangle) {
SDL_RenderCopy(this->_renderer, texture, sourceRectangle, destinationRectangle);
}
在游戏循环中,每一帧都会调用 RenderClear 和 RenderPresent。
我真的希望我解释得通俗易懂,想问什么就问什么,我就是在向你们寻求帮助,所以我至少可以合作 :D
向 SDL2 开发人员咨询 SDL_RenderCopy()
的多项目版本(类似于现有的 SDL_RenderDrawLines()
/SDL_RenderDrawPoints()
/SDL_RenderDrawRects()
函数)and/or batched SDL_Renderer 个后端。
现在你正在尝试 slam 至少 240*240 = 57000 次绘制调用到 GPU 的喉咙;在任何给定的 16 毫秒内,您通常只能指望 1000-4000 次绘制调用。
或者切换到 OpenGL 并自己进行批处理。