SDL2第三篇。
接下來(lái)就看下如何使用SDL如何通過(guò)SDL_Texture在窗口繪制圖像。
先了解幾個(gè)紋理渲染相關(guān)API:
創(chuàng)建紋理
SDL_Texture* SDL_CreateTexture(SDL_Renderer * renderer,
Uint32 format,
int access,
int w, int h);
format: 像素格式,YUV或RGB
access: 指明Texture的類(lèi)型。可以是 Stream(視頻),也可以是Target一般的類(lèi)型。
銷(xiāo)毀紋理
void SDL_DestroyTexture(SDL_Texture* texture)
渲染目標(biāo)
//將渲染目標(biāo)定為紋理
int SDL_SetRenderTarget(SDL_Renderer *renderer,
SDL_Texture *texture);
紋理拷貝
//會(huì)將紋理拷貝到顯卡上去,顯卡會(huì)計(jì)算出最終圖形并渲染到窗口中
int SDL_RenderCopy(SDL_Renderer* renderer,
SDL_Texture* texture,
const SDL_Rect* srcrect,
const SDL_Rect* dstrect)
srcrect: 指定 Texture 中要渲染的一部分。如果將 Texture全部輸出,可以設(shè)置它為 NULL。
dstrect: 指定輸出的空間大小。
簡(jiǎn)單示例
在前面Demo的基礎(chǔ)上做了一定修改,簡(jiǎn)單實(shí)現(xiàn)一個(gè)正方形在界面中隨機(jī)顯示。
#include <stdio.h>
#include <SDL2/SDL.h>
int WinMain() {
int quit = 1;
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *sdlTexture = NULL;
SDL_Event event;
SDL_Rect rect; // 長(zhǎng)方形,原點(diǎn)在左上角
rect.w = 50;
rect.h = 50;
SDL_Init(SDL_INIT_VIDEO);//初始化函數(shù),可以確定希望激活的子系統(tǒng)
window = SDL_CreateWindow("My First Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);// 創(chuàng)建窗口
if (!window) {
return -1;
}
renderer = SDL_CreateRenderer(window, -1, 0);//基于窗口創(chuàng)建渲染器
if (!renderer) {
return -1;
}
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); //設(shè)置渲染器顏色
// SDL_RenderClear(renderer); //用指定的顏色清空緩沖區(qū)
// SDL_RenderPresent(renderer); //將緩沖區(qū)中的內(nèi)容輸出到目標(biāo)窗口上
sdlTexture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_TARGET,
640,
480); //創(chuàng)建紋理
if (!sdlTexture) {
return -1;
}
while (quit) {
SDL_PollEvent(&event); // SDL_WaitEvent在這里就不太適合,只有在事件發(fā)生時(shí)才會(huì)觸發(fā),其余時(shí)間都是阻塞狀態(tài)
switch (event.type) {
case SDL_QUIT:
SDL_Log("quit");
quit = 0;
break;
default:
SDL_Log("event type:%d", event.type);
}
rect.x = rand() % 600;
rect.y = rand() % 400;
SDL_SetRenderTarget(renderer, sdlTexture); // 設(shè)置渲染目標(biāo)為紋理
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); // 紋理背景為黑色
SDL_RenderClear(renderer); //清屏
SDL_RenderDrawRect(renderer, &rect); //繪制一個(gè)長(zhǎng)方形
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); //長(zhǎng)方形為白色
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderTarget(renderer, NULL); //恢復(fù)默認(rèn),渲染目標(biāo)為窗口
SDL_RenderCopy(renderer, sdlTexture, NULL, NULL); //拷貝紋理到CPU
SDL_RenderPresent(renderer); //輸出到目標(biāo)窗口上
}
SDL_DestroyTexture(sdlTexture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window); //銷(xiāo)毀窗口
SDL_Quit();
return 0;
}
上面這個(gè)Demo就是最簡(jiǎn)單的紋理渲染流程。
接下來(lái)再認(rèn)識(shí)兩個(gè)API:
更新紋理
//兩個(gè)API功能相同,但是SDL_UpdateYUVTexture直接將Y、U、V分量傳入,可以減少CPU計(jì)算量,更快一些
int SDL_UpdateTexture(SDL_Texture * texture, //想要更新的紋理
const SDL_Rect * rect, //更新的像素矩形,傳NULL則表示為整個(gè)紋理
const void *pixels, //像素?cái)?shù)據(jù)
int pitch);//一行像素?cái)?shù)據(jù)的字節(jié)數(shù)
int SDL_UpdateYUVTexture(SDL_Texture * texture,
const SDL_Rect * rect,
const Uint8 *Yplane, int Ypitch,
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch);
這兩個(gè)API將會(huì)在視頻播放中發(fā)揮重要作用,下一篇博客將會(huì)結(jié)合FFmpeg實(shí)現(xiàn)一個(gè)簡(jiǎn)易的視頻播放器。