本文我們講一下如何使用SDL_Texture將視頻紋理渲染出來。
1. SDL 視頻渲染相關對象
SDL 視頻渲染主要涉及到四個對象:SDL_Window、SDL_Render、SDL_Texture和SDL_Surface。
SDL_Window代表的是窗口的邏輯概念,它是存放在主內存中的一個對象。當我們調用SDL API 創建窗口后,它並不會被顯示出來。
SDL_Render 是渲染器,它也是主存中的一個對象。對Render操作時實際上分為兩個階段:
- 渲染階段。在該階段,用戶可以畫各種圖形渲染到SDL_Surface或SDL_Texture 中;
- 顯示階段。參SDL_Texture為數據,通過OpenGL操作GPU,最終將 SDL_Surfce 或SDL_Texture中的數據輸出到顯示器上。
SDL_Render對象中有一個視頻緩沖區,該緩沖區我們稱之為SDL_Surface,它是按照像素存放圖像的。我們一般把真彩色的像素稱為RGB24數據。也就是說,每一個像素由24位組成,每8位代表一種顏色,像素的最終顏色是由RGB三種顏色混合而成的。
SDL_Texture 與SDL_Surface 相似,也是一種緩沖區。只不過它存放的不是真正的像素數據,而是存放的圖像的描述信息。這些描述信息通過OpenGL、D3D 或 Metal等技術操作GPU,從而繪制出與SDL_Surface一樣的圖形,且效率更高。
2. 使用 SDL_Texute 渲染紋理的步驟
SDL提供了操作SDL_Texture的方法,使用SDL_Texute的基本步驟為:
-
創建一個 SDL_Texture。
-
渲染 Texture
- Destory Texture
3. 使用SDL渲染紋理的核心API
a). 創建 SDL_Texture
SDL_Texture* SDL_CreateTexture(SDL_Renderer* renderer, // 渲染器 Uint32 format, // 渲染數據的格式,如YUV、RGB int access, // Texture 類型,target、stream int w, int h)
下面說明一下重要參數:
format: 指明像素格式,可以是YUV,也可以是RGB
access: 指明Texture的類型。可以是 Stream(視頻),也可以是Target一般的類型。
b). 渲染
int SDL_RenderCopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srcrect, const SDL_Rect* dstrect)
下面說明一下重要參數:
srcrect: 指定 Texture 中要渲染的一部分。如果將 Texture全部輸出,可以設置它為 NULL。
dstrect: 指定輸出的空間大小。
c). 銷毀 SDL_Texture
void SDL_DestroyTexture(SDL_Texture* texture)
紋理渲染實戰:
// SDL.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。 // #include "pch.h" #include <iostream> extern "C" { #include "SDL.h" } int main(int argc, char* argv[]) { SDL_Window *window; SDL_Renderer *renderer; SDL_Texture *texture; SDL_Event event; SDL_Rect r; if (SDL_Init(SDL_INIT_VIDEO) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); return 3; } window = SDL_CreateWindow("SDL_CreateTexture", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1024, 768, SDL_WINDOW_RESIZABLE); r.w = 100; r.h = 50; renderer = SDL_CreateRenderer(window, -1, 0); texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 1024, 768); // 跳來跳去的方塊 while (1) { SDL_PollEvent(&event); if (event.type == SDL_QUIT) break; r.x = rand() % 500; r.y = rand() % 500; SDL_SetRenderTarget(renderer, texture); SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00); SDL_RenderClear(renderer); SDL_RenderDrawRect(renderer, &r); SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0x00); SDL_RenderFillRect(renderer, &r); SDL_SetRenderTarget(renderer, NULL); SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); } SDL_DestroyRenderer(renderer); SDL_Quit(); return 0; }
運行效果: