若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108602694

 

前言

  对于Qt应用来说,为了更大的跨平台通用性,使用SDL播放音频,同样也流行使用SDL渲染视频,基本上很大一部分市面上的sdk播放器都是基于sdl的,传入窗口句柄使用sdl渲染。

 

Demo

  循环渲染颜色:
  

  按键渲染颜色:
  
  按键渲染图片:
  

 

SDL渲染流程解析

  基本流程如下:
  

步骤一:初始化子系统

  SDL_Init()初始化视频系统,其他多余的系统不用初始化。

步骤二:创建窗口

  SDL_CreateWindow()创建windows窗口,设置一些常用属性。

步骤三:创建渲染器(与窗口绑定)

  SDL_CreateRenderer()创建渲染器,该渲染器创建时已经与显示的窗口进行了绑定。

步骤四:渲染颜色/渲染图片步骤

  本篇有3个demo,分别为渲染了简单的颜色,同构按键时间渲染不同的颜色,通过按键渲染不同的图片。
  渲染简单的颜色:设置渲染颜色->清空->渲染

// 步骤四:开始渲染-渲染简单的颜色
for(int index = 0; index < 100000; index++)
{
SDL_SetRenderDrawColor(pSDLRenderer,
index/255%255,
index/10%255,
index/20%255,
128);
SDL_RenderClear(pSDLRenderer);
SDL_RenderPresent(pSDLRenderer); SDL_PollEvent(&event);
}

  按键渲染简单的颜色:设置渲染颜色->清空->渲染->按键不同的颜色

// 步骤四:开始渲染-渲染简答的颜色,接受按键输入0~9对应不同的颜色,
// 对键盘事件进行处理
bool out = false;
int r = 0;
int g = 0;
int b = 0;
while(true)
{
SDL_SetRenderDrawColor(pSDLRenderer, r, g, b, 255);
SDL_RenderClear(pSDLRenderer);
SDL_RenderPresent(pSDLRenderer);
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
out = true;
break;
case SDLK_1:
r = 255; g = 0; b = 0;
break;
case SDLK_2:
r = 0; g = 255; b = 0;
break;
case SDLK_3:
r = 0; g = 0; b = 255;
break;
case SDLK_4:
r = 255; g = 255; b = 0;
break;
case SDLK_5:
r = 0; g = 255; b = 255;
break;
case SDLK_6:
r = 255; g = 0; b = 255;
break;
case SDLK_7:
r = 255; g = 255; b = 255;
break;
case SDLK_8:
r = 255; g = 140; b = 0;
break;
case SDLK_9:
r = 0; g = 191; b = 255;
break;
case SDLK_0:
r = 255; g = 215; b = 0;
break;
default:
break;
}
break;
case SDL_QUIT:
out = true;
break;
default:
break;
}
if(out)
{
break;
}
}

  渲染图片:加载图片->创建纹理->清空->复制纹理到渲染->渲染。

// 步骤四:开始渲染-渲染bmp图片,1-2两张图片
SDL_Surface *pSDLSurface = 0;
SDL_Texture *pSDLTexture = 0;
SDL_Surface *pSDLSurface2 = 0;
SDL_Texture *pSDLTexture2 = 0; SDL_Texture *pSDLTextureTemp = 0; // 用于临时存放 bool out = false;
pSDLSurface = SDL_LoadBMP("testBMP/1.bmp");
pSDLTexture = SDL_CreateTextureFromSurface(pSDLRenderer, pSDLSurface);
pSDLSurface2 = SDL_LoadBMP("testBMP/2.bmp");
pSDLTexture2 = SDL_CreateTextureFromSurface(pSDLRenderer, pSDLSurface2); pSDLTextureTemp = pSDLTexture;
while(true)
{ // 清空渲染器
SDL_RenderClear(pSDLRenderer);
// 将问题copy到渲染器上
SDL_RenderCopy(pSDLRenderer, pSDLTextureTemp, 0, 0);
// 显示渲染器内容
SDL_RenderPresent(pSDLRenderer);
// 事件处理
SDL_PollEvent(&event); switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
out = true;
break;
case SDLK_1:
pSDLTextureTemp = pSDLTexture;
break;
case SDLK_2:
pSDLTextureTemp = pSDLTexture2;
break;
default:
break;
}
break;
case SDL_QUIT:
out = true;
break;
default:
break;
}
if(out)
{
break;
}
}

步骤五:销毁渲染器

  SDL_DestroyRenderer();

步骤六:销毁窗口

  SDL_DestroyWindow();

步骤七:退出SDL系统

  SDL_Quit();

 

SDL渲染相关变量

SDL_Window

  用于标识窗口。

SDL_Renderer

  表示呈现状态的结构。

typedef struct SDL_Surface
{
Uint32 flags; /**< Read-only */
SDL_PixelFormat *format; /**< Read-only */
int w, h; /**< Read-only */
int pitch; /**< Read-only */
void *pixels; /**< Read-write */ /** Application data associated with the surface */
void *userdata; /**< Read-write */ /** information needed for surfaces requiring locks */
int locked; /**< Read-only */
void *lock_data; /**< Read-only */ /** clipping information */
SDL_Rect clip_rect; /**< Read-only */ /** info for fast blit mapping to other surfaces */
struct SDL_BlitMap *map; /**< Private */ /** Reference count -- used when freeing surface */
int refcount; /**< Read-mostly */
} SDL_Surface;

SDL_Event

  SDL的事件系统结构体,博大精深,以后兴趣可以仔细研究,按键主要用到了其type,然后键值用到的是其key.keysym.sym。

switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
out = true;
break;
default:
;
}
}

SDL_Surface

  在软件blitting中使用的像素集合,此结构应被视为只读,但像素除外,如果不为空,则包含表面的原始像素数据。

typedef struct SDL_Surface
{
Uint32 flags; /**< Read-only */
SDL_PixelFormat *format; /**< Read-only */
int w, h; /**< Read-only */
int pitch; /**< Read-only */
void *pixels; /**< Read-write */ /** Application data associated with the surface */
void *userdata; /**< Read-write */ /** information needed for surfaces requiring locks */
int locked; /**< Read-only */
void *lock_data; /**< Read-only */ /** clipping information */
SDL_Rect clip_rect; /**< Read-only */ /** info for fast blit mapping to other surfaces */
struct SDL_BlitMap *map; /**< Private */ /** Reference count -- used when freeing surface */
int refcount; /**< Read-mostly */
} SDL_Surface;

SDL_Texture

  纹理,像素数据的一种高效的特定表示。

 

SDL渲染相关函数原型

SDL_Init()

int SDLCALL SDL_Init(Uint32 flags);

  使用此函数初始化SDL库,必须在使用大多数其他SDL函数之前调用它,初始化的时候尽量做到“够用就好”,而不要用SDL_INIT_EVERYTHING。会出现一些不可预知的问题。

  • 参数一:输入初始化的设备
      

SDL_CreateWindow()

SDL_Window * SDL_CreateWindow(const char *title,
int x,
int y,
int w,
int h,
Uint32 flags);

  使用指定的位置、尺寸和标志创建一个窗口。
  前面5个参数都是常用的,第六个参数是窗口的属性,如是否可改变大小等等.

SDL_CreateRenderer()

SDL_Renderer * SDL_CreateRenderer(SDL_Window * window,
int index,
Uint32 flags);

  为窗口创建二维渲染上下文,参数一为我们之前需要渲染的窗口。

SDL_SetRenderDrawColor()

int SDLCALL SDL_SetRenderDrawColor(SDL_Renderer * renderer,
Uint8 r,
Uint8 g,
Uint8 b,
Uint8 a);

  设置用于绘图操作的颜色(矩形、直线和清除)。

SDL_RenderClear()

int SDL_RenderClear(SDL_Renderer * renderer);

  使用绘图颜色清除当前渲染目标。

SDL_RenderPresent()

void SDL_RenderPresent(SDL_Renderer * renderer);

  使用已执行的渲染更新屏幕。

SDL_PollEvent()

int SDL_PollEvent(SDL_Event * event);

  当前挂起事件的轮询。

SDL_LoadBMP()

#define SDL_LoadBMP(file)   SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)
SDL_Surface * SDL_LoadBMP_RW(SDL_RWops * src,
int freesrc);

  从可查找的SDL数据流(内存或文件)加载表面数据。

SDL_CreateTextureFromSurface()

SDL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer * renderer,
SDL_Surface * surface);

  从现有表面创建纹理。

  • 参数一:绑定窗口的渲染器。
  • 参数二:加载文件后的表面数据(加载的图片)。

SDL_RenderCopy()

int SDL_RenderCopy(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_Rect * dstrect);

  将纹理的一部分复制到当前渲染目标。

  • 参数一:应该复制纹理部分的渲染器。
  • 参数二:源纹理
  • 参数三:指向源矩形的指针,设置为0则全部。
  • 参数四:指向目标矩形的指针,设置为0则全部。

SDL_DestroyRenderer()

void SDL_DestroyRenderer(SDL_Renderer * renderer);

  销毁渲染器。

SDL_DestroyWindow()

void SDL_DestroyWindow(SDL_Window * window);

  销毁窗口。

SDL_Quit()

void SDL_Quit(void);

  此函数用于清除所有初始化的子系统。在所有退出条件后调用它。

 

Demo源码

void SDLManager::testRenderWindow()
{
int ret = 0;
SDL_Window *pSDLWindow = 0;
SDL_Renderer *pSDLRenderer = 0;
SDL_Event event; // 步骤一:初始化视频子系统
ret = SDL_Init(SDL_INIT_VIDEO);
if(ret)
{
LOG << "Failed";
return;
}
// 步骤二:创建窗口,支持opengl、大小可变
pSDLWindow = SDL_CreateWindow("SDL Widget",
0,
0,
800,
480,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if(!pSDLWindow)
{
LOG << "Failed";
return;
}
// 步骤三:基于窗口创建渲染器
pSDLRenderer = SDL_CreateRenderer(pSDLWindow, -1, 0);
if(!pSDLRenderer)
{
LOG << "Failed";
return;
} #if 0
// 步骤四:开始渲染-渲染简单的颜色
for(int index = 0; index < 100000; index++)
{
SDL_SetRenderDrawColor(pSDLRenderer,
index/255%255,
index/10%255,
index/20%255, 128);
SDL_RenderClear(pSDLRenderer);
SDL_RenderPresent(pSDLRenderer); SDL_PollEvent(&event);
}
#endif #if 0
// 步骤四:开始渲染-渲染简答的颜色,接受按键输入0~9对应不同的颜色,
// 对键盘事件进行处理
bool out = false;
int r = 0;
int g = 0;
int b = 0;
while(true)
{
SDL_SetRenderDrawColor(pSDLRenderer, r, g, b, 255);
SDL_RenderClear(pSDLRenderer);
SDL_RenderPresent(pSDLRenderer);
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
out = true;
break;
case SDLK_1:
r = 255; g = 0; b = 0;
break;
case SDLK_2:
r = 0; g = 255; b = 0;
break;
case SDLK_3:
r = 0; g = 0; b = 255;
break;
case SDLK_4:
r = 255; g = 255; b = 0;
break;
case SDLK_5:
r = 0; g = 255; b = 255;
break;
case SDLK_6:
r = 255; g = 0; b = 255;
break;
case SDLK_7:
r = 255; g = 255; b = 255;
break;
case SDLK_8:
r = 255; g = 140; b = 0;
break;
case SDLK_9:
r = 0; g = 191; b = 255;
break;
case SDLK_0:
r = 255; g = 215; b = 0;
break;
default:
break;
}
break;
case SDL_QUIT:
out = true;
break;
default:
break;
}
if(out)
{
break;
}
}
#endif #if 1
// 步骤四:开始渲染-渲染bmp图片,1-2两张图片
SDL_Surface *pSDLSurface = 0;
SDL_Texture *pSDLTexture = 0;
SDL_Surface *pSDLSurface2 = 0;
SDL_Texture *pSDLTexture2 = 0; SDL_Texture *pSDLTextureTemp = 0; // 用于临时存放 bool out = false;
pSDLSurface = SDL_LoadBMP("testBMP/1.bmp");
pSDLTexture = SDL_CreateTextureFromSurface(pSDLRenderer, pSDLSurface);
pSDLSurface2 = SDL_LoadBMP("testBMP/2.bmp");
pSDLTexture2 = SDL_CreateTextureFromSurface(pSDLRenderer, pSDLSurface2); pSDLTextureTemp = pSDLTexture;
while(true)
{ // 清空渲染器
SDL_RenderClear(pSDLRenderer);
// 将问题copy到渲染器上
SDL_RenderCopy(pSDLRenderer, pSDLTextureTemp, 0, 0);
// 显示渲染器内容
SDL_RenderPresent(pSDLRenderer);
// 事件处理
SDL_PollEvent(&event); switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
out = true;
break;
case SDLK_1:
pSDLTextureTemp = pSDLTexture;
break;
case SDLK_2:
pSDLTextureTemp = pSDLTexture2;
break;
default:
break;
}
break;
case SDL_QUIT:
out = true;
break;
default:
break;
}
if(out)
{
break;
}
}
#endif
// 步骤五:销毁渲染器
SDL_DestroyRenderer(pSDLRenderer);
// 步骤六:销毁窗口
SDL_DestroyWindow(pSDLWindow);
// 步骤七:退出SDL
SDL_Quit();
}
 

工程模板:对应版本号v1.2.0

  对应版本号v1.2.0:按键渲染颜色和BMP图片

 
 

SDL开发笔记(三):使用SDL渲染窗口颜色和图片的更多相关文章

  1. SDL开发笔记(二):音频基础介绍、使用SDL播放音频

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  2. 【C语言探索之旅】 第三部分第一课:SDL开发游戏之安装SDL

    内容简介 1.课程大纲 2.第三部分第一课: SDL开发游戏之安装SDL 3.第三部分第二课预告: SDL开发游戏之创建窗口和画布 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会 ...

  3. Django开发笔记三

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.基于类的方式重写登录:views.py: from ...

  4. RBL开发笔记三

    2014-08-26 20:06:24 今天就是在开发这个EPOLL来处理网络事件 封装较为健壮的EPOLL模型来处理基本的网络IO 1) 超时这个主题先没有弄 在开发EPOLL包括select/po ...

  5. Vue-cli开发笔记三----------引入外部插件

    (一)绝对路径直接引入: (1)主入口页面index.html中头部script标签引入: <script type="text/javascript" src=" ...

  6. 钉钉开发笔记(三)MySQL的配置

    最近在编写web的过程中,经常需要与后台工作人员互动.由于比较麻烦.没有效率. 就果断的请教了,公司的后台大牛,学习下数据库的一些简单操作,现在就把利用MySQL连接服务器, 进行可视化操作的简单步骤 ...

  7. openwrt开发笔记三:uci移植及API调用

    1.uci编译安装.移植 安装依赖 libubox #安装cmake sudo apt-get install cmake #下载依赖库libubox git clone http://git.nbd ...

  8. 【转】Android开发笔记(序)写在前面的目录

    原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经 ...

  9. Django开发笔记六

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.登录功能完善 登录成功应该是重定向到首页,而不是转发 ...

  10. Django开发笔记五

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.页面继承 定义base.html: <!DOC ...

随机推荐

  1. [转帖]AMD Zen CPU 架构以及不同CPU性能大PK

    https://plantegg.github.io/2021/08/13/AMD_Zen_CPU%E6%9E%B6%E6%9E%84/ 前言 本文先介绍AMD Zen 架构,结合前一篇文章<C ...

  2. 【JS 逆向百例】XHR 断点调试,Steam 登录逆向

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标 目标:Steam ...

  3. 【Jmeter】基础介绍-详细

    最近做压测时使用到Jmeter,为什么用它,之前也做过部分压测,不是很系统,使用的是Apache Bench,虽然效率高,但是功能比较简单,不太适合本次压测场景,另外Jmeter能更好的利用压测机的多 ...

  4. 6.1 Windows驱动开发:内核枚举SSDT表基址

    SSDT表(System Service Descriptor Table)是Windows操作系统内核中的关键组成部分,负责存储系统服务调用的相关信息.具体而言,SSDT表包含了系统调用的函数地址以 ...

  5. C/C++ 通用ShellCode的编写与调用

    首先,我们的ShellCode代码需要自定位,因为我们的代码并不是一个完整的EXE可执行程序,他没有导入表无法定位到当前系统中每个函数的虚拟地址,所以我们直接获取到Kernel32.dll的基地址,里 ...

  6. centOS系统 迁移docker镜像及数据文件到指定目录

    话说我今天正在快乐的敲代码,突然看到IDE报警磁盘空间不足了,du -h 查看了一下磁盘占用情况,发现是自己的docker镜像全部放/var/lib/docker目录下 这个系统磁盘给根目录只分配了5 ...

  7. 基于.NET的机械运动模拟应用开发

    1 简介 机械运动在物理学中,把一个物体相对于另一个物体位置的变化称作为机械运动,简称运动.机械运动是指一个物体相对于其他物体的位置发生改变,是自然界中最简单,最基本的运动形态. 自然界中一切物体都在 ...

  8. AIX6.1系统NTP同步配置

    前言   当AIX系统的本地时间与时间服务器授出的标准时间误差大于±1000秒时.xntpd服务将无法同步时间并变得无法正常工作,请进行ntp配置前,先修改AIX系统的本地时间,尽量和时间服务器的标准 ...

  9. 【可观测性系列】 Opentelemetry 介绍

    作者简介:大家好,我是蓝胖子 ️博客首页:博客园主页蓝胖子的编程梦 每日一句:人生的烦恼,多在于明白的太多,而做的太少 大家好,我是蓝胖子,随着微服务的流行,服务的可观测性概念被越来越多人提及到,究竟 ...

  10. 201871010111-刘佳华 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

    实验三 软件工程结对项目 ========== 时间:2021-4-1 项目 内容 课程班级博客链接 课程链接 这个作业要求链接 作业要求 我的课程学习目标 1.了解软件工程过程中结对项目的开发流程 ...