C++
SDL调用OPENGL渲染图像
  • By刘立博
  • 2021-01-02 16:04:11
  • 1218人已阅读

程序流程设计

使用SDL渲染一副图像需要以下9个步骤,需要调用8个SDL函数

函数介绍

 

初始化子系统 SDL_Init

flags为需要初始化的设备

 

其函数定义如下:

flags支持以下参数:

SDL_INIT_TIMER : 定时器
SDL_INIT_AUDIO : 音频
SDL_INIT_VIDEO : 视频
SDL_INIT_JOYSTICK : 手柄
SDL_INIT_HAPTIC : 触屏
SDL_INIT_GAMECONTROLLER : 游戏控制器
SDL_INIT_EVENTS : 事件
SDL_INIT_SENSOR : 传感器
SDL_INIT_NOPARACHUTE : 忽略
SDL_INIT_EVERYTHING : 全部

 

创建窗体 SDL_CreateWindow

 

其函数定义如下:

分别传入标题、x坐标、y坐标、宽、高和flags

flags支持以下参数:

SDL_WINDOW_FULLSCREEN : 全屏
SDL_WINDOW_OPENGL : 窗体使用OPENGL
SDL_WINDOW_SHOWN : 窗体可见
SDL_WINDOW_HIDDEN : 窗体不可见
SDL_WINDOW_BORDERLESS : 窗体无边框
SDL_WINDOW_RESIZABLE : 窗体尺寸可变
SDL_WINDOW_MINIMIZED : 窗体最小化
SDL_WINDOW_MAXIMIZED : 窗体最大化
SDL_WINDOW_INPUT_GRABBED : 窗体获得输入焦点
SDL_WINDOW_INPUT_FOCUS : 窗体强制输入
SDL_WINDOW_MOUSE_FOCUS : 窗体获取鼠标焦点
SDL_WINDOW_FOREIGN : 窗体不由SDL创建
SDL_WINDOW_ALLOW_HIGHDPI : 窗体支持高DPI
SDL_WINDOW_MOUSE_CAPTURE : 窗体捕获鼠标
SDL_WINDOW_ALWAYS_ON_TOP : 窗体置顶
SDL_WINDOW_SKIP_TASKBAR : 窗体无任务栏
SDL_WINDOW_UTILITY : 窗体公用
SDL_WINDOW_TOOLTIP :工具栏窗体
SDL_WINDOW_POPUP_MENU: 弹出菜单窗体
SDL_WINDOW_VULKAN : 窗体使用VULKAN

创建渲染器 SDL_CreateRenderer

 

其函数定义如下:

分别传入窗体对象、渲染设备索引(-1 为使用第一个设备)、以及flags

flags支持以下参数:

SDL_RENDERER_SOFTWARE : 软件渲染
SDL_RENDERER_ACCELERATED : 硬件加速
SDL_RENDERER_PRESENTVSYNC : 刷新率同步
SDL_RENDERER_TARGETTEXTURE : 支持渲染材质

 

创建材质 SDL_CreateTexture

 

其函数定义如下:

分别传入渲染器、材质格式、材质选项、宽度、高度

其中材质格式用于描述材质数据,我们使用ARGB888

材质选项支持以下值:

SDL_TEXTUREACCESS_STATIC : 静态材质
SDL_TEXTUREACCESS_STREAMING : 流材质
SDL_TEXTUREACCESS_TARGET : 材质直接渲染

 

更新材质数据 SDL_UpdateTexture

 

其函数定义如下:

 

材质指针、要更新的位置(NULL为全部更新)、材质数据、数据长度

渲染器加载材质 SDL_RenderCopy

 

其函数定义如下:

渲染器指针、材质指针、源区域(NULL为全部)、目标区域

输出 SDL_RenderPresent

传入渲染器指针即可

 

其函数定义如下:

程序代码

假设我们需要使用OPENGL渲染一幅1280X720的绿色图片

#include <iostream>
#include <sdl/SDL.h>

using namespace std;
#pragma comment(lib,"SDL2.lib")
#undef main

int main(int argc, char* argv[])
{
	int winWidth = 1280;
	int winHeight = 720;

	//SDL初始化
	if (SDL_Init(SDL_INIT_VIDEO))
	{
		cout << SDL_GetError() << endl;
		return -1;
	}

	//创建窗体
	SDL_Window*  window = SDL_CreateWindow(
		"test SDL",
		SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED,
		winWidth,
		winHeight,
		SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
	);

	if (!window)
	{
		cout << SDL_GetError() << endl;
		return -1;
	}

	//创建渲染器
	SDL_Renderer* renderer = SDL_CreateRenderer(
		window,
		-1,
		SDL_RENDERER_ACCELERATED
	);
	if (!renderer)
	{
		cout << SDL_GetError() << endl;
		return -1;
	}

	//创建材质
	SDL_Texture* texture = SDL_CreateTexture(
		renderer,
		SDL_PIXELFORMAT_ARGB8888,
		SDL_TEXTUREACCESS_STREAMING,
		winWidth,
		winHeight
	);
	if (!texture)
	{
		cout << SDL_GetError() << endl;
		return -1;
	}

	//构造材质数据
	shared_ptr<unsigned char> argb(new unsigned char[winWidth * winHeight * 4]);

	unsigned char* argbData = argb.get();

	for (int h = 0; h < winHeight; h++)
	{
		int b = h * winWidth * 4;
		for (int w = 0; w < winWidth*4; w += 4)
		{
			argbData[b + w] = 0;
			argbData[b + w +1] = 255;
			argbData[b + w + 2] = 0;
			argbData[b + w + 3] = 0;
		}
	}

	//更新材质
	SDL_UpdateTexture(texture, NULL, argbData, winWidth * 4);

	//清屏
	SDL_RenderClear(renderer);

	SDL_Rect rect;
	rect.x = 0;
	rect.y = 0;
	rect.w = winWidth;
	rect.h = winHeight;
	
	//渲染器加载材质
	SDL_RenderCopy(
		renderer,
		texture,
		NULL,
		&rect
	);

	//输出
	SDL_RenderPresent(renderer);

	getchar();

	return 0;
}

运行结果