SDL_Texture
SDL_Texture
是計算機圖形圖像中,如何在屏幕上顯示圖像的一個數據的抽象。中文也已翻譯爲紋理。這種概念在OpenGL中也有出現。對於SDL_Texture
本身來說,它包含了顯示驅動用於顯示的特定數據結構。
SDL_Texture
的創建一半通過SDL_CreateTexture
創建,創建一次後,可以重複使用,通過SDL_UpdateTexture
函數更新數據。
SDL_CreateTexture
函數原型:
SDL_Texture* SDL_CreateTexture(SDL_Renderer* renderer,
Uint32 format,
int access,
int w,
int h)
函數功能:使用此函數可爲渲染器上下文創建紋理。
參數列表:
參數 | 釋義 |
---|---|
renderer | 渲染器上下文 |
format | 渲染的像素格式,支持的格式,在 SDL_PixelFormatEnum中,詳情見渲染器支持的像素格式 |
access | 紋理訪問模式,定義在 SDL_TextureAccess中; 詳見紋理訪問模式 |
w | 紋理的寬度(以像素爲單位) |
h | 紋理的高度(以像素爲單位) |
返回值:返回渲染器上下文的紋理。
渲染器支持的像素格式:
SDL_PIXELFORMAT_UNKNOWN | |
---|---|
SDL_PIXELFORMAT_RGB332 | |
SDL_PIXELFORMAT_RGB444 | |
SDL_PIXELFORMAT_RGB555 | |
SDL_PIXELFORMAT_ARGB1555 | |
SDL_PIXELFORMAT_RGBA5551 | |
SDL_PIXELFORMAT_ABGR1555 | |
SDL_PIXELFORMAT_BGRA5551 | |
SDL_PIXELFORMAT_RGB565 | |
SDL_PIXELFORMAT_RGBA32 | 當前平臺的RGBA字節數組顏色的別名(>= SDL 2.0.5) |
SDL_PIXELFORMAT_ARGB32 | 當前平臺的ARGB字節數組顏色數據的別名(>= SDL 2.0.5) |
SDL_PIXELFORMAT_YV12 | 平面模式: Y + V + U (3 planes) |
SDL_PIXELFORMAT_IYUV | 平面模式: Y + U + V (3 planes) |
SDL_PIXELFORMAT_YUY2 | 打包模式: Y0+U0+Y1+V0 (1 plane) |
SDL_PIXELFORMAT_UYVY | 打包模式: U0+Y0+V0+Y1 (1 plane) |
SDL_PIXELFORMAT_YVYU | 打包模式: Y0+V0+Y1+U0 (1 plane) |
SDL_PIXELFORMAT_NV12 | 打包模式: Y + U/V 交錯 (2 planes) (>= SDL 2.0.4) |
SDL_PIXELFORMAT_NV21 | 打包模式: Y + V/U 交錯 (2 planes) (>= SDL 2.0.4) |
紋理訪問模式:
訪問模式 | 含義 |
---|---|
SDL_TEXTUREACCESS_STATIC | 變化很少,不可鎖定 |
SDL_TEXTUREACCESS_STREAMING | 經常變化,可鎖定 |
SDL_TEXTUREACCESS_TARGET | 可以用作渲染目標 |
SDL_UpdateTexture
函數原型:
int SDL_UpdateTexture(SDL_Texture* texture,
const SDL_Rect* rect,
const void* pixels,
int pitch)
函數功能:使用新的像素數據更新給定的紋理矩形。也就是說,可以固定刷新紋理的某一分部區域。
參數列表:
參數 | 含義 |
---|---|
texture | the texture to update |
rect | 用SDL_Rect結構表達紋理中需要更新數據的區域, 如果爲NULL則更新整個紋理 |
pixels | 紋理格式的原始像素數據,格式通常在創建紋理的函數中指定 |
pitch | 一行像素數據中的字節數,包括行之間的填充。字節數通常由紋理的格式決定 |
這裏需要解釋一下pitch的計算方式,以一幀尺寸爲960x540,格式爲SDL_PIXELFORMAT_IYUV爲例,計算
pitch :
SDL_PIXELFORMAT_IYUV,也就是IYUV類型,也稱爲YUV420p、I420,它在內存中的存儲格式爲三平面存儲。
即:第一個平面960個字節的位置存Y分量,第二個平面480個字節存U分量,第三個平面480個字節存V分量。而這個函數中的pitch所說的一行數像素數據中的字節數,其實指的是第一個平面的長度(字節爲單位),也就是960字節,雖然和寬度在數學上相等,但它們所表達的意思是不一樣的,
另外,這是一個相當慢的函數,旨在用於不經常更改的靜態紋理。
如果要經常更新紋理,則最好將紋理創建爲流式傳輸並使用下面SDL_LockTexture
鎖定函數。 雖然此功能適用於流式紋理,但出於優化原因,如果之後鎖定紋理,則可能無法獲得像素。
SDL_LockTexture:鎖定紋理
SDL_UnlockTexture:解鎖紋理
返回值:
成功時返回0或失敗時返回負錯誤代碼
#include <iostream>
#include <SDL.h>
#include <SDL2/SDL_image.h>
using namespace std;
const int WIDTH = 960, HEIGHT = 540;
int main() {
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
cout << "SDL could not initialized with error: " << SDL_GetError() << endl;
return -1;
}
SDL_Window *window = SDL_CreateWindow("Hello SDL world!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
WIDTH, HEIGHT, SDL_WINDOW_ALLOW_HIGHDPI);
if (NULL == window) {
cout << "SDL could not create window with error: " << SDL_GetError() << endl;
return -1;
}
if (!(IMG_Init(IMG_INIT_JPG) & IMG_INIT_JPG)) {
cout << "SDL_image could not init with error: " << IMG_GetError() << endl;
return -1;
}
FILE* pFile = fopen("little_prince_i420_960x540.yuv", "rb");
if (pFile == NULL) {
cerr << "little_prince_i420_960x540.yuv open failed" << endl;
}
unsigned char *m_yuv_data;
int frameSize = HEIGHT * WIDTH * 12 / 8;
m_yuv_data = (unsigned char*)malloc(frameSize * sizeof(unsigned char));
fread(m_yuv_data, 1, frameSize, pFile);
fclose(pFile);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); // 創建渲染器
// 創建紋理
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);
if (texture != NULL) {
SDL_Event windowEvent;
while (true) {
if (SDL_PollEvent(&windowEvent)) {
if (SDL_QUIT == windowEvent.type) {
cout << "SDL quit!!" << endl;
break;
}
}
SDL_UpdateTexture(texture, NULL, m_yuv_data, WIDTH); // 更新紋理
SDL_RenderClear(renderer); // 清除渲染器
SDL_RenderCopy(renderer, texture, NULL, NULL); // 拷貝紋理到渲染器
SDL_RenderPresent(renderer); // 渲染
}
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
}