【音视频】SDL窗口显示
SDL视频显示函数简介
- SDL_Init(): 初始化SDL系统
- SDL_CreateWindow():创建窗口SDL_Window
- SDL_CreateRenderer():创建渲染器SDL_Renderer
- SDL_CreateTexture():创建纹理SDL_Texture
- SDL_UpdateTexture(): 设置纹理的数据
- SDL_RenderCopy():将纹理的数据拷贝给渲染器
- SDL_RenderPresent():显示
- SDL_Delay(): 工具函数,用于延时
- SDL_Quit(): 退出SDL系统
SDL数据结构简介
- SDL_Window 代表了一个“窗口”
- SDL_Renderer 代表了一个“渲染器”
- SDL_Texture 代表了一个“纹理”
- SDL_Rect 一个简单的矩形结构
存储RGB和存储纹理的区别:
比如一个从左到右由红色渐变到蓝色的矩形,用存储RGB的话就需要把矩形中每个点的具体颜色值存储下来;而纹理只是一些描述信息,比如记
录了矩形的大小、起始颜色、终止颜色等信息,显卡可以通过这些信息推算出矩形块的详细信息。
所以相对于存储RGB而已,存储纹理占用的内存要少的多。
SDL子系统(subsystem):
SDL将功能分成下列数个子系统(subsystem):
SDL_INIT_TIMER:
定时器SDL_INIT_AUDIO:
音频SDL_INIT_VIDEO:
视频SDL_INIT_JOYSTICK:
摇杆SDL_INIT_HAPTIC:
触摸屏SDL_INIT_GAMECONTROLLER:
游戏控制器SDL_INIT_EVENTS:
事件SDL_INIT_EVERYTHING:
包含上述所有选项SDL_INIT_TIMER:
定时器SDL_INIT_AUDIO:
音频SDL_INIT_VIDEO:
视频SDL_INIT_JOYSTICK:
摇杆SDL_INIT_HAPTIC:
触摸屏SDL_INIT_GAMECONTROLLER:
游戏控制器SDL_INIT_EVENTS:
事件SDL_INIT_EVERYTHING:
包含上述所有选项
实现效果
实现流程
引入头文件
这个头文件是SDL
的核心
#include <SDL.h>
需要取消main
的宏,因为在SDL.h
中定义了:
#define main SDL_main
因此,需要取消这个宏,因为我们下面用到的main
是作为主函数使用
开启SDL
视频模块功能
核心模块有很多,这里就用到视频这一块,因此开启这个即可
SDL_Init(SDL_INIT_VIDEO);//初始化函数,可以确定希望激活的子系统
创建一个窗口
这里可以指定窗口的标题、窗口的出现位置,SDL_WINDOWPOS_UNDEFINED
表示默认在窗口中心,设置的窗口大小为640x480
。
同时:
SDL_WINDOW_OPENGL
:启用 OpenGL 支持,便于复杂图形渲染SDL_WINDOW_RESIZABLE
:允许用户调整窗口大小
SDL_Window *window = NULL;
window = SDL_CreateWindow("SDL-Window",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);// 创建窗口
创建失败返回0
if (!window){return -1;
}
创建一个渲染器
创建一个渲染器,用于渲染纹理。这里将这个渲染器与窗口进行绑定。
-1
表示选择默认渲染驱动,如 Direct3D、OpenGL0
表示使用软件渲染,也可以改为SDL_RENDERER_ACCELERATED
使用硬件渲染
SDL_Renderer *renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, 0);//基于窗口创建渲染器
创建失败返回0
if (!render){return -1;
}
创建一个纹理
创建一个纹理,用于渲染器的输入,并将这个纹理绑定在之前创建的渲染器上。
SDL_PIXELFORMAT_RGBA8888
:32 位像素格式,包含透明通道(A)SDL_TEXTUREACCESS_TARGET
:指定纹理为渲染目标,支持离屏绘制
SDL_Texture *texture = NULL;
texture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET,640,480); //创建纹理
创建失败返回0
if (!renderer)
{return -1;
}
创建一个矩形
创建一个矩形,设置矩形的大小
SDL_Rect rect; // 长方形,原点在左上角
rect.w = 50; //方块大小
rect.h = 50;
开始绘制
我们这里绘制300
帧后结束
int show_count = 0;while (run){rect.x = rand() % 600;rect.y = rand() % 400;SDL_SetRenderTarget(renderer, texture); // 设置渲染目标为纹理SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // 纹理背景为宏色SDL_RenderClear(renderer); //清屏SDL_RenderDrawRect(renderer, &rect); //绘制一个长方形SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255); //长方形为白色SDL_RenderFillRect(renderer, &rect);SDL_SetRenderTarget(renderer, NULL); //恢复默认,渲染目标为窗口SDL_RenderCopy(renderer, texture, NULL, NULL); //拷贝纹理到CPUSDL_RenderPresent(renderer); //输出到目标窗口上SDL_Delay(300);if(show_count++ > 30){run = 0; // 不跑了}}
- 设置矩形的出现位置在窗口的随机位置
rect.x = rand() % 600;
rect.y = rand() % 400;
- 设置渲染目标为纹理,并且设置纹理的背景颜色为红色,每一帧都需要清屏
SDL_SetRenderTarget(renderer, texture); // 设置渲染目标为纹理
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // 纹理背景为黑色
SDL_RenderClear(renderer); //清屏
- 绘制矩形,设置矩形的颜色为白色
SDL_RenderDrawRect(renderer, &rect); //绘制一个长方形
SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255); //长方形为白色
SDL_RenderFillRect(renderer, &rect);
- 渲染器解绑纹理
SDL_SetRenderTarget(renderer, NULL); //恢复默认,渲染目标为窗口
- 拷贝纹理到
CPU
,并且呈现在窗口上
SDL_RenderCopy(renderer, texture, NULL, NULL); //拷贝纹理到CPU
SDL_RenderPresent(renderer); //输出到目标窗口上
- 延迟
300ms
,防止速度过快
SDL_Delay(300);
释放内存
程序结束的时候需要释放相关内存,比如窗口、渲染器、纹理等内存
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
最后,执行退出释放所有的SDL
子系统资源
SDL_Quit();
整体代码
main.c
#include <stdio.h>
#include <SDL.h>
#undef main
int main()
{int run = 1;SDL_Window *window = NULL;SDL_Renderer *renderer = NULL;SDL_Texture *texture = NULL;SDL_Rect rect; // 长方形,原点在左上角rect.w = 50; //方块大小rect.h = 50;SDL_Init(SDL_INIT_VIDEO);//初始化函数,可以确定希望激活的子系统window = SDL_CreateWindow("SDL-Window",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);// 创建窗口if (!window){return -1;}renderer = SDL_CreateRenderer(window, -1, 0);//基于窗口创建渲染器if (!renderer){return -1;}texture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET,640,480); //创建纹理if (!texture){return -1;}int show_count = 0;while (run){rect.x = rand() % 600;rect.y = rand() % 400;SDL_SetRenderTarget(renderer, texture); // 设置渲染目标为纹理SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // 纹理背景为红色SDL_RenderClear(renderer); //清屏SDL_RenderDrawRect(renderer, &rect); //绘制一个长方形SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255); //长方形为白色SDL_RenderFillRect(renderer, &rect);SDL_SetRenderTarget(renderer, NULL); //恢复默认,渲染目标为窗口SDL_RenderCopy(renderer, texture, NULL, NULL); //拷贝纹理到CPUSDL_RenderPresent(renderer); //输出到目标窗口上SDL_Delay(300);if(show_count++ > 30){run = 0; // 不跑了}}SDL_DestroyTexture(texture);SDL_DestroyRenderer(renderer);SDL_DestroyWindow(window); //销毁窗口SDL_Quit();return 0;
}
更多资料:https://github.com/0voice