首页 文章

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

提问于
浏览
4

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

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

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

在SDL2中,它似乎完成了:

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

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

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

2 回答

  • 2

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

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


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

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

    还有很多其他的方法,我相信你会在给定的时间内发现,比如颜色调制 .


    下一点是您认为SDL1更低级别且'realistic'并且SDL2添加了一些额外的层 . 实际上,现代图形卡用于SDL2 . 通常,您不会在内存中存储大的位图( SDL_Surface s是原始数据),您不要将其他表面与其相关联,然后将其发送到图形卡 . 图形卡正在考虑纹理 .


    现在,如果你仍想绕过这些“附加层”,你仍然可以通过隔离纹理渲染过程来实现 . 我认为实现这一目标的最简洁方法是创建一个想要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)的内容 .

  • 0

    grab 你的窗口 SDL_Surface 通过 SDL_GetWindowSurface()SDL_BlitSurface() 到它的心脏's content. Don' t当你完成blitting以将更新的帧缓冲区推回到操作系统时忘记 SDL_UpdateWindowSurface() .

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

    #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;
    }
    

相关问题