我一直在尝试学习如何将 SDL 库与 C(不是 C++)一起使用,最近发现我遇到的所有错误的原因是我正在查看 SDL1 教程,而不是 SDL2 教程。从那以后,我发现 SDL2 实现了许多 SDL1 中没有(据我所知)的抽象层,这些抽象层似乎无法绕过。
具体来说,在 SDL1 中,在屏幕上绘制一组像素是通过以下方式完成的:
定义表面 - 找到像素的 rgb 值 - 在表面上绘制像素 - 在屏幕上绘制表面
在 SDL2 中,它似乎是通过以下方式完成的:
定义窗口 - 为窗口创建渲染器 - 创建表面 - 查找像素的 rgb 值 - 将像素绘制到表面 - 将表面转换为纹理 - 将纹理发送到渲染器 - 重绘窗口
虽然我明白如果涉及原始像素数据以外的其他东西,纹理可以成为一种更简单的处理方式,特别是如果有多个数据源,在特定情况下,我想将它用于(单个窗口程序哪些原始像素数据是唯一会被绘制的东西)窗口、渲染器和纹理之间的区别只是毫无意义的抽象。此外,似乎在大多数情况下,来自图像的数据将加载到 SDL_Surface 类,然后必须将其转换为纹理,从而增加更多不必要的抽象。
除了恢复到旧版本的 SDL 之外,还有什么办法可以规避这个问题?
最佳答案
当我开始使用 SDL2 时,我分享了完全相同的想法。
首先,可能不清楚,因为你没有探索很多 SDL2,但即使你不想做 OGL/DX,这些额外的层即使是纯 2D 和像素处理也是有用的。
例如,SDL_RenderCopyEx
可以在动态旋转和调整其大小的同时渲染表面。在 SDL1 中,您需要使用第三方库或编写您自己的 rotozoom 算法来实现相同的目标。
另一个有用的功能是您可以轻松渲染图元。例如,有一个优化的 SDL_RenderDrawLine
方法,在 SDL1 中,您需要构建自己的方法,该方法将创建一个表面、浏览和 blit 像素信息,并将线 blit 返回到您的整个表面。
我相信你会在给定的时间内发现许多其他方法,例如颜色调制。
下一点是您认为 SDL1 更底层和“现实”,而 SDL2 添加了一些附加层。事实上,现代图形卡的工作方式与 SDL2 相同。通常,您不会在内存中存储巨大的位图( SDL_Surface
是原始数据),也不会将其他一些表面 blit 到它然后将其发送到图形卡。显卡正在考虑纹理。
现在如果你仍然想绕过这些“附加层”,你仍然可以通过隔离纹理渲染过程。我认为最简洁的方法是创建一个你想要 blit 的表面的链表:
struct SurfaceElement {
SDL_Surface* s;
SDL_Rect clip;
SDL_Rect position;
struct SurfaceElement * next;
};
typedef struct SurfaceElement SurfaceElement;
void ProcessingLoop() {
SurfaceElement *surfacesList = (SurfaceElement *)malloc(sizeof(SurfaceElement));
// Create surfaces, work on surfaces
// When you're done with a surface, add it to the list:
surfacesList = AddToBlitList(yourSurface, yourClipPos, yourBlitPos, surfacesList);
// When everything is okay and you're ready to blit:
TextureBlittingProcess(surfacesList, renderer);
}
SurfaceElement* AddToBlitList(SDL_Surface *s, SDL_Rect clip, SDL_Rect position, SurfaceElement *head) {
SurfaceElement *current = (SurfaceElement*)malloc(sizeof(SurfaceElement));
current->s = s;
current->clip = clip;
current->position = position;
current->next = head;
return current;
}
void TextureBlittingProcess(SurfaceElement *surfacesList, SDL_Renderer *renderer) {
while (surfaceList) {
SDL_Texture *t = SDL_CreateTextureFromSurface(renderer, surfaceList->s)
SDL_RenderCopy(renderer, t, &(surfaceList->clip), &(surfaceList->position));
surfaceList = surfaceList->next;
}
}
最后,如果您真的没有看到使用这些纹理的意义,如果您不一定要对纹理进行 blit 而只是对其像素进行操作,那么 SDL 可能不适合您。您应该阅读有关 Matlab 或脚本语言(例如 Python 或 Caml)的信息。
关于C SDL2- 是否有可能消除一些抽象层?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33459049/