SDL2常用函數&結構分析:SDL_Texture&SDL_CreateTexture&SDL_UpdateTexture

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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章