我一直在尝试学习如何将 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/

10-16 04:57