SDL2紋理渲染

SDL2第三篇。git

SDL2入門github

SDL2事件處理函數

接下來就看下如何使用SDL如何經過SDL_Texture在窗口繪製圖像。post

先了解幾個紋理渲染相關API:ui

建立紋理

SDL_Texture* SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h);
複製代碼

format: 像素格式,YUV或RGBspa

access: 指明Texture的類型。能夠是 Stream(視頻),也能夠是Target通常的類型。code

銷燬紋理

void SDL_DestroyTexture(SDL_Texture* texture) 複製代碼

渲染目標

//將渲染目標定爲紋理
int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture);
複製代碼

紋理拷貝

//會將紋理拷貝到顯卡上去,顯卡會計算出最終圖形並渲染到窗口中
int SDL_RenderCopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srcrect, const SDL_Rect* dstrect) 複製代碼

srcrect: 指定 Texture 中要渲染的一部分。若是將 Texture所有輸出,能夠設置它爲 NULL。orm

dstrect: 指定輸出的空間大小。視頻

簡單示例

在前面Demo的基礎上作了必定修改,簡單實現一個正方形在界面中隨機顯示。事件

#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; // 長方形,原點在左上角
    rect.w = 50;
    rect.h = 50;

    SDL_Init(SDL_INIT_VIDEO);//初始化函數,能夠肯定但願激活的子系統

    window = SDL_CreateWindow("My First Window",
                              SDL_WINDOWPOS_UNDEFINED,
                              SDL_WINDOWPOS_UNDEFINED,
                              640,
                              480,
                              SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);// 建立窗口

    if (!window) {
        return -1;
    }
    renderer = SDL_CreateRenderer(window, -1, 0);//基於窗口建立渲染器
    if (!renderer) {
        return -1;
    }
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); //設置渲染器顏色
// SDL_RenderClear(renderer); //用指定的顏色清空緩衝區
// SDL_RenderPresent(renderer); //將緩衝區中的內容輸出到目標窗口上

    sdlTexture = SDL_CreateTexture(renderer,
                                   SDL_PIXELFORMAT_RGBA8888,
                                   SDL_TEXTUREACCESS_TARGET,
                                   640,
                                   480); //建立紋理

    if (!sdlTexture) {
        return -1;
    }

    while (quit) {
        SDL_PollEvent(&event); // SDL_WaitEvent在這裏就不太適合,只有在事件發生時纔會觸發,其他時間都是阻塞狀態
        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); // 設置渲染目標爲紋理
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); // 紋理背景爲黑色
        SDL_RenderClear(renderer); //清屏

        SDL_RenderDrawRect(renderer, &rect); //繪製一個長方形
        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); //長方形爲白色
        SDL_RenderFillRect(renderer, &rect);

        SDL_SetRenderTarget(renderer, NULL); //恢復默認,渲染目標爲窗口
        SDL_RenderCopy(renderer, sdlTexture, NULL, NULL); //拷貝紋理到CPU

        SDL_RenderPresent(renderer); //輸出到目標窗口上
    }

    SDL_DestroyTexture(sdlTexture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window); //銷燬窗口
    SDL_Quit();
    return 0;
}
複製代碼

上面這個Demo就是最簡單的紋理渲染流程。

接下來再認識兩個API:

更新紋理

//兩個API功能相同,可是SDL_UpdateYUVTexture直接將Y、U、V份量傳入,能夠減小CPU計算量,更快一些

int SDL_UpdateTexture(SDL_Texture * texture, //想要更新的紋理 const SDL_Rect * rect, //更新的像素矩形,傳NULL則表示爲整個紋理 const void *pixels, //像素數據 int pitch);//一行像素數據的字節數

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);
複製代碼

這兩個API將會在視頻播放中發揮重要做用,下一篇博客將會結合FFmpeg實現一個簡易的視頻播放器。

相關文章
相關標籤/搜索