SDL2 面向对象包装器; 1000+ Virtual Function 调用一个框架;有什么办法可以优化这个吗?
SDL2 Object Oriented Wrapper; 1000+ Virtual Function calls a frame; Is there any way to optimize this?
我正在为 SDL2 编写一个面向对象的包装器。我决定制作 2 classes:一个 Sprite class 和一个 Rectangle Class。我使用了一些多态性,所以我不必为每个可绘制对象重载 draw
函数。我有一个基础 class Drawable
,它具有纯虚拟函数 draw
.
现在Sprite
和Rect
继承Drawable
并定义了draw
函数以适应class的风格。现在,当我必须在屏幕上绘制很多东西时,我会使用指向 Drawable
的指针,然后调用 draw
方法。这种情况每秒发生 1000 多次。
如果我看一下我的 CPU 使用率,大约是 10%。我知道每秒绘制 60 次 1000 多个 Sprites 会阻碍我的 CPU 使用,但我认为不会有这么多。
现在,我的问题是:有什么办法可以优化这个吗?也许去掉纯虚函数,重载函数?
我的代码(我尽量缩短):
Sprite::Draw声明
void Draw() override;
Sprite::Draw函数
void Sprite::Draw() {
// rect is SDL_Rect
rect.x = rect.x - window->getCamera().getCoords().x;
rect.y = rect.y - window->getCamera().getCoords().y;
SDL_RenderCopyEx(window->renderer, texture, NULL, &rect, 0, NULL, flip);
}
调用Sprite::Draw
的Function
void Window::Draw(Drawable *d) {
d->Draw();
}
绘图循环
// 1024 grass Sprites
for (int i = 0; i < 1024; i++) {
mainWindow.Draw(&grass[i]); // Calls Window::Draw
}
正如我之前所说,它占用了我 CPU 使用量的大约 10%。我有一个 AMD 6300 和一个 NVIDIA GTX 750Ti。我正在使用 Microsoft Visual Studio Express 2013。
可执行文件名称是OBA.exe
能否将这些草精灵的纹理压缩成一个纹理贴图,然后绘制其中的一部分(第三个参数,srcrect -- https://wiki.libsdl.org/SDL_RenderCopyEx)?
我猜你没有 1024 种独特的草纹理,而是一些重复的纹理。将它们全部组合成一个图像并将其加载为草纹理。
你的精灵 class 然后只需要定义一个 SDL_Rect
它用来绘制纹理的哪一部分。
示例纹理:
假设您的精灵使用纹理 0,则 srcrect
将是 0,0,32,32。绘制它只是将一个参数添加到您的 RenderCopy 调用中。
SDL_RenderCopyEx(window->renderer, texture, &srcrect, &rect, 0, NULL, flip);
这应该会提高绘制大量精灵的性能。此外,您只能在相机视图中绘制精灵。
我修复了它,我所做的只是绘制当前在相机视图中的精灵。 SDL_LogCritical 被调用如此之多的原因是每次 SDL_RenderCopyEx 调用都会调用 SDL_LogCritical 以及其他 SDL 函数。但是通过绘制用户可以看到的内容,我将 CPU 使用率降低到大约 0.1%
我正在为 SDL2 编写一个面向对象的包装器。我决定制作 2 classes:一个 Sprite class 和一个 Rectangle Class。我使用了一些多态性,所以我不必为每个可绘制对象重载 draw
函数。我有一个基础 class Drawable
,它具有纯虚拟函数 draw
.
现在Sprite
和Rect
继承Drawable
并定义了draw
函数以适应class的风格。现在,当我必须在屏幕上绘制很多东西时,我会使用指向 Drawable
的指针,然后调用 draw
方法。这种情况每秒发生 1000 多次。
如果我看一下我的 CPU 使用率,大约是 10%。我知道每秒绘制 60 次 1000 多个 Sprites 会阻碍我的 CPU 使用,但我认为不会有这么多。
现在,我的问题是:有什么办法可以优化这个吗?也许去掉纯虚函数,重载函数?
我的代码(我尽量缩短):
Sprite::Draw声明
void Draw() override;
Sprite::Draw函数
void Sprite::Draw() {
// rect is SDL_Rect
rect.x = rect.x - window->getCamera().getCoords().x;
rect.y = rect.y - window->getCamera().getCoords().y;
SDL_RenderCopyEx(window->renderer, texture, NULL, &rect, 0, NULL, flip);
}
调用Sprite::Draw
的Functionvoid Window::Draw(Drawable *d) {
d->Draw();
}
绘图循环
// 1024 grass Sprites
for (int i = 0; i < 1024; i++) {
mainWindow.Draw(&grass[i]); // Calls Window::Draw
}
正如我之前所说,它占用了我 CPU 使用量的大约 10%。我有一个 AMD 6300 和一个 NVIDIA GTX 750Ti。我正在使用 Microsoft Visual Studio Express 2013。
可执行文件名称是OBA.exe
能否将这些草精灵的纹理压缩成一个纹理贴图,然后绘制其中的一部分(第三个参数,srcrect -- https://wiki.libsdl.org/SDL_RenderCopyEx)?
我猜你没有 1024 种独特的草纹理,而是一些重复的纹理。将它们全部组合成一个图像并将其加载为草纹理。
你的精灵 class 然后只需要定义一个 SDL_Rect
它用来绘制纹理的哪一部分。
示例纹理:
假设您的精灵使用纹理 0,则 srcrect
将是 0,0,32,32。绘制它只是将一个参数添加到您的 RenderCopy 调用中。
SDL_RenderCopyEx(window->renderer, texture, &srcrect, &rect, 0, NULL, flip);
这应该会提高绘制大量精灵的性能。此外,您只能在相机视图中绘制精灵。
我修复了它,我所做的只是绘制当前在相机视图中的精灵。 SDL_LogCritical 被调用如此之多的原因是每次 SDL_RenderCopyEx 调用都会调用 SDL_LogCritical 以及其他 SDL 函数。但是通过绘制用户可以看到的内容,我将 CPU 使用率降低到大约 0.1%