我一直在努力学习如何使用带有C(而不是C ++)的SDL库,并且最近发现我遇到的所有错误的原因是我正在查看SDL1教程,而不是SDL2教程。我已经发现SDL2已经从SDL1中实现了许多抽象层(据我所知),这似乎是不可能绕过的。
具体而言,在SDL1中,在屏幕上绘制一组像素是通过以下方式完成的:
定义表面 - 找到像素的rgb值 - 在表面上绘制像素 - 在屏幕上绘制表面
在SDL2中,它似乎完成了:定义窗口 - 为窗口创建渲染器 - 创建曲面 - 查找像素的rgb值 - 将像素绘制到曲面 - 将曲面转换为纹理 - 将纹理发送到渲染器 - 重绘窗口
虽然我理解如果除了原始像素数据之外还有其他东西,纹理可以是一种更简单的方法,特别是如果有多个数据源,在特定情况下我想用它(单个)窗口程序,其中原始像素数据是唯一将被绘制的东西)窗口,渲染器和纹理之间的区别只是毫无意义的抽象。此外,似乎在大多数情况下,来自图像的数据将被加载到SDL_Surface类,然后必须将其转换为纹理,从而添加更多不必要的抽象。
除了恢复旧版SDL之外,还有什么方法可以避免这种情况吗?
答案 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_Surface
和SDL_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;
}