C SDL2-是否可以消除一些抽象层?

时间:2015-11-01 03:56:01

标签: c sdl sdl-2

我一直在努力学习如何使用带有C(而不是C ++)的SDL库,并且最近发现我遇到的所有错误的原因是我正在查看SDL1教程,而不是SDL2教程。我已经发现SDL2已经从SDL1中实现了许多抽象层(据我所知),这似乎是不可能绕过的。

具体而言,在SDL1中,在屏幕上绘制一组像素是通过以下方式完成的:

定义表面 - 找到像素的rgb值 - 在表面上绘制像素 - 在屏幕上绘制表面

在SDL2中,它似乎完成了:

定义窗口 - 为窗口创建渲染器 - 创建曲面 - 查找像素的rgb值 - 将像素绘制到曲面 - 将曲面转换为纹理 - 将纹理发送到渲染器 - 重绘窗口

虽然我理解如果除了原始像素数据之外还有其他东西,纹理可以是一种更简单的方法,特别是如果有多个数据源,在特定情况下我想用它(单个)窗口程序,其中原始像素数据是唯一将被绘制的东西)窗口,渲染器和纹理之间的区别只是毫无意义的抽象。此外,似乎在大多数情况下,来自图像的数据将被加载到SDL_Surface类,然后必须将其转换为纹理,从而添加更多不必要的抽象。

除了恢复旧版SDL之外,还有什么方法可以避免这种情况吗?

2 个答案:

答案 0 :(得分:2)

当我开始使用SDL2时,我的想法完全相同。

首先,它可能不清楚,因为你没有探索过很多SDL2,但即使你不想做OGL / DX,这些附加层也很有用,即使是普通的2D和像素处理。

例如,SDL_RenderCopyEx可以在旋转时渲染曲面并在运行时调整其大小。在SDL1中,您需要使用第三方库或编写自己的rotozoom算法来实现相同的目标。

另一个有用的功能是您可以轻松渲染基元。例如,有一个优化的SDL_RenderDrawLine方法,在SDL1中你需要构建自己的方法,这将创建一个表面,浏览和blit像素信息,然后将线条回到你的整个表面。 / p>

我确信您会在给定时间内发现许多其他方法,例如色彩调制。

下一点是您认为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等脚本语言。

答案 1 :(得分:0)

通过SDL_SurfaceSDL_GetWindowSurface()抓住窗口的SDL_BlitSurface(),使之成为您内心的内容。在完成将更新后的帧缓冲区推回操作系统后,请不要忘记SDL_UpdateWindowSurface()

usage example上有一个the SDL_GetWindowSurface() wiki page

#include "SDL.h" // include SDL header

int main(int argc, char* argv[])
{
    SDL_Surface *screen; // even with SDL2, we can still bring ancient code back
    SDL_Window *window;
    SDL_Surface *image;

    SDL_Init(SDL_INIT_VIDEO); // init video

    // create the window like normal
    window = SDL_CreateWindow("SDL2 Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);

    // but instead of creating a renderer, we can draw directly to the screen
    screen = SDL_GetWindowSurface(window);

    // let's just show some classic code for reference
    image = SDL_LoadBMP("box.bmp"); // loads image
    SDL_BlitSurface(image, NULL, screen, NULL); // blit it to the screen
    SDL_FreeSurface(image);

    // this works just like SDL_Flip() in SDL 1.2
    SDL_UpdateWindowSurface(window);

    // show image for 2 seconds
    SDL_Delay(2000);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}