【音视频】SDL窗口显示

发布于:2025-05-01 ⋅ 阅读:(25) ⋅ 点赞:(0)

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、OpenGL
  • 0表示使用软件渲染,也可以改为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); //拷贝纹理到CPU

        SDL_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); //拷贝纹理到CPU

        SDL_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


网站公告

今日签到

点亮在社区的每一天
去签到