SDL開發筆記(三):使用SDL渲染窗口顏色和圖片


若該文為原創文章,未經允許不得轉載
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108602694

 

前言

  對於Qt應用來說,為了更大的跨平台通用性,使用SDL播放音頻,同樣也流行使用SDL渲染視頻,基本上很大一部分市面上的sdk播放器都是基於sdl的,傳入窗口句柄使用sdl渲染。

 

Demo

  循環渲染顏色:
  
在這里插入圖片描述
  按鍵渲染顏色:
  在這里插入圖片描述
  按鍵渲染圖片:
  在這里插入圖片描述

 

SDL渲染流程解析

  基本流程如下:
  在這里插入圖片描述

步驟一:初始化子系統

  SDL_Init()初始化視頻系統,其他多余的系統不用初始化。

步驟二:創建窗口

  SDL_CreateWindow()創建windows窗口,設置一些常用屬性。

步驟三:創建渲染器(與窗口綁定)

  SDL_CreateRenderer()創建渲染器,該渲染器創建時已經與顯示的窗口進行了綁定。

步驟四:渲染顏色/渲染圖片步驟

  本篇有3個demo,分別為渲染了簡單的顏色,同構按鍵時間渲染不同的顏色,通過按鍵渲染不同的圖片。
  渲染簡單的顏色:設置渲染顏色->清空->渲染

// 步驟四:開始渲染-渲染簡單的顏色
for(int index = 0; index < 100000; index++)
{
    SDL_SetRenderDrawColor(pSDLRenderer, 
                           index/255%255, 
                           index/10%255, 
                           index/20%255, 
                           128);
    SDL_RenderClear(pSDLRenderer);
    SDL_RenderPresent(pSDLRenderer);

    SDL_PollEvent(&event);
}

  按鍵渲染簡單的顏色:設置渲染顏色->清空->渲染->按鍵不同的顏色

// 步驟四:開始渲染-渲染簡答的顏色,接受按鍵輸入0~9對應不同的顏色,
// 對鍵盤事件進行處理
bool out = false;
int r = 0;
int g = 0;
int b = 0;
while(true)
{
    SDL_SetRenderDrawColor(pSDLRenderer, r, g, b, 255);
    SDL_RenderClear(pSDLRenderer);
    SDL_RenderPresent(pSDLRenderer);
    SDL_PollEvent(&event);
    switch (event.type)
    {
    case SDL_KEYDOWN:
        switch (event.key.keysym.sym)
        {
        case SDLK_ESCAPE:
            out = true;
            break;
        case SDLK_1:
            r = 255; g = 0; b = 0;
            break;
        case SDLK_2:
            r = 0; g = 255; b = 0;
            break;
        case SDLK_3:
            r = 0; g = 0; b = 255;
            break;
        case SDLK_4:
            r = 255; g = 255; b = 0;
            break;
        case SDLK_5:
            r = 0; g = 255; b = 255;
            break;
        case SDLK_6:
            r = 255; g = 0; b = 255;
            break;
        case SDLK_7:
            r = 255; g = 255; b = 255;
            break;
        case SDLK_8:
            r = 255; g = 140; b = 0;
            break;
        case SDLK_9:
            r = 0; g = 191; b = 255;
            break;
        case SDLK_0:
            r = 255; g = 215; b = 0;
            break;
        default:
            break;
        }
        break;
    case SDL_QUIT:
        out = true;
        break;
    default:
        break;
    }
    if(out)
    {
        break;
    }
}

  渲染圖片:加載圖片->創建紋理->清空->復制紋理到渲染->渲染。

// 步驟四:開始渲染-渲染bmp圖片,1-2兩張圖片
SDL_Surface *pSDLSurface = 0;
SDL_Texture *pSDLTexture = 0;
SDL_Surface *pSDLSurface2 = 0;
SDL_Texture *pSDLTexture2 = 0;

SDL_Texture *pSDLTextureTemp = 0;       // 用於臨時存放

bool out = false;
pSDLSurface = SDL_LoadBMP("testBMP/1.bmp");
pSDLTexture = SDL_CreateTextureFromSurface(pSDLRenderer, pSDLSurface);
pSDLSurface2 = SDL_LoadBMP("testBMP/2.bmp");
pSDLTexture2 = SDL_CreateTextureFromSurface(pSDLRenderer, pSDLSurface2);

pSDLTextureTemp = pSDLTexture;
while(true)
{

    // 清空渲染器
    SDL_RenderClear(pSDLRenderer);
    // 將問題copy到渲染器上
    SDL_RenderCopy(pSDLRenderer, pSDLTextureTemp, 0, 0);
    // 顯示渲染器內容
    SDL_RenderPresent(pSDLRenderer);
    // 事件處理
    SDL_PollEvent(&event);

    switch (event.type)
    {
    case SDL_KEYDOWN:
        switch (event.key.keysym.sym)
        {
        case SDLK_ESCAPE:
            out = true;
            break;
        case SDLK_1:
            pSDLTextureTemp = pSDLTexture;
            break;
        case SDLK_2:
            pSDLTextureTemp = pSDLTexture2;
            break;
        default:
            break;
        }
        break;
    case SDL_QUIT:
        out = true;
        break;
    default:
        break;
    }
    if(out)
    {
        break;
    }
} 

步驟五:銷毀渲染器

  SDL_DestroyRenderer();

步驟六:銷毀窗口

  SDL_DestroyWindow();

步驟七:退出SDL系統

  SDL_Quit();

 

SDL渲染相關變量

SDL_Window

  用於標識窗口。

SDL_Renderer

  表示呈現狀態的結構。

typedef struct SDL_Surface
{
    Uint32 flags;               /**< Read-only */
    SDL_PixelFormat *format;    /**< Read-only */
    int w, h;                   /**< Read-only */
    int pitch;                  /**< Read-only */
    void *pixels;               /**< Read-write */

    /** Application data associated with the surface */
    void *userdata;             /**< Read-write */

    /** information needed for surfaces requiring locks */
    int locked;                 /**< Read-only */
    void *lock_data;            /**< Read-only */

    /** clipping information */
    SDL_Rect clip_rect;         /**< Read-only */

    /** info for fast blit mapping to other surfaces */
    struct SDL_BlitMap *map;    /**< Private */

    /** Reference count -- used when freeing surface */
    int refcount;               /**< Read-mostly */
} SDL_Surface;

SDL_Event

  SDL的事件系統結構體,博大精深,以后興趣可以仔細研究,按鍵主要用到了其type,然后鍵值用到的是其key.keysym.sym。

switch (event.type)
{
case SDL_KEYDOWN:
    switch (event.key.keysym.sym)
    {
    case SDLK_ESCAPE:
        out = true;
        break;
    default:
        ;
    }
}

SDL_Surface

  在軟件blitting中使用的像素集合,此結構應被視為只讀,但像素除外,如果不為空,則包含表面的原始像素數據。

typedef struct SDL_Surface
{
    Uint32 flags;               /**< Read-only */
    SDL_PixelFormat *format;    /**< Read-only */
    int w, h;                   /**< Read-only */
    int pitch;                  /**< Read-only */
    void *pixels;               /**< Read-write */

    /** Application data associated with the surface */
    void *userdata;             /**< Read-write */

    /** information needed for surfaces requiring locks */
    int locked;                 /**< Read-only */
    void *lock_data;            /**< Read-only */

    /** clipping information */
    SDL_Rect clip_rect;         /**< Read-only */

    /** info for fast blit mapping to other surfaces */
    struct SDL_BlitMap *map;    /**< Private */

    /** Reference count -- used when freeing surface */
    int refcount;               /**< Read-mostly */
} SDL_Surface;

SDL_Texture

  紋理,像素數據的一種高效的特定表示。

 

SDL渲染相關函數原型

SDL_Init()

int SDLCALL SDL_Init(Uint32 flags);

  使用此函數初始化SDL庫,必須在使用大多數其他SDL函數之前調用它,初始化的時候盡量做到“夠用就好”,而不要用SDL_INIT_EVERYTHING。會出現一些不可預知的問題。

  • 參數一:輸入初始化的設備
      在這里插入圖片描述

SDL_CreateWindow()

SDL_Window * SDL_CreateWindow(const char *title,
                              int x,
                              int y,
                              int w,
                              int h,
                              Uint32 flags);

  使用指定的位置、尺寸和標志創建一個窗口。
  前面5個參數都是常用的,第六個參數是窗口的屬性,如是否可改變大小等等.

SDL_CreateRenderer()

SDL_Renderer * SDL_CreateRenderer(SDL_Window * window,
                                  int index,
                                  Uint32 flags);

  為窗口創建二維渲染上下文,參數一為我們之前需要渲染的窗口。

SDL_SetRenderDrawColor()

int SDLCALL SDL_SetRenderDrawColor(SDL_Renderer * renderer,
                                   Uint8 r,
                                   Uint8 g,
                                   Uint8 b,
                                   Uint8 a);

  設置用於繪圖操作的顏色(矩形、直線和清除)。

SDL_RenderClear()

int SDL_RenderClear(SDL_Renderer * renderer);

  使用繪圖顏色清除當前渲染目標。

SDL_RenderPresent()

void SDL_RenderPresent(SDL_Renderer * renderer);

  使用已執行的渲染更新屏幕。

SDL_PollEvent()

int SDL_PollEvent(SDL_Event * event);

  當前掛起事件的輪詢。

SDL_LoadBMP()

#define SDL_LoadBMP(file)   SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)
SDL_Surface * SDL_LoadBMP_RW(SDL_RWops * src,
                             int freesrc);

  從可查找的SDL數據流(內存或文件)加載表面數據。

SDL_CreateTextureFromSurface()

SDL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer * renderer,
                                           SDL_Surface * surface);

  從現有表面創建紋理。

  • 參數一:綁定窗口的渲染器。
  • 參數二:加載文件后的表面數據(加載的圖片)。

SDL_RenderCopy()

int SDL_RenderCopy(SDL_Renderer * renderer,
                   SDL_Texture * texture,
                   const SDL_Rect * srcrect,
                   const SDL_Rect * dstrect);

  將紋理的一部分復制到當前渲染目標。

  • 參數一:應該復制紋理部分的渲染器。
  • 參數二:源紋理
  • 參數三:指向源矩形的指針,設置為0則全部。
  • 參數四:指向目標矩形的指針,設置為0則全部。

SDL_DestroyRenderer()

void SDL_DestroyRenderer(SDL_Renderer * renderer);

  銷毀渲染器。

SDL_DestroyWindow()

void SDL_DestroyWindow(SDL_Window * window);

  銷毀窗口。

SDL_Quit()

void SDL_Quit(void);

  此函數用於清除所有初始化的子系統。在所有退出條件后調用它。

 

Demo源碼

void SDLManager::testRenderWindow()
{
    int ret = 0;
    SDL_Window *pSDLWindow = 0;
    SDL_Renderer *pSDLRenderer = 0;
    SDL_Event event;

    // 步驟一:初始化視頻子系統
    ret = SDL_Init(SDL_INIT_VIDEO);
    if(ret)
    {
        LOG << "Failed";
        return;
    }
    // 步驟二:創建窗口,支持opengl、大小可變
    pSDLWindow = SDL_CreateWindow("SDL Widget", 
                                   0, 
                                   0, 
                                   800,
                                    480, 
                                   SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    if(!pSDLWindow)
    {
        LOG << "Failed";
        return;
    }
    // 步驟三:基於窗口創建渲染器
    pSDLRenderer = SDL_CreateRenderer(pSDLWindow, -1, 0);
    if(!pSDLRenderer)
    {
        LOG << "Failed";
        return;
    }

#if 0
    // 步驟四:開始渲染-渲染簡單的顏色
    for(int index = 0; index < 100000; index++)
    {
        SDL_SetRenderDrawColor(pSDLRenderer,
                               index/255%255, 
                               index/10%255, 
                               index/20%255, 128);
        SDL_RenderClear(pSDLRenderer);
        SDL_RenderPresent(pSDLRenderer);

        SDL_PollEvent(&event);
    }
#endif

#if 0
    // 步驟四:開始渲染-渲染簡答的顏色,接受按鍵輸入0~9對應不同的顏色,
    // 對鍵盤事件進行處理
    bool out = false;
    int r = 0;
    int g = 0;
    int b = 0;
    while(true)
    {
        SDL_SetRenderDrawColor(pSDLRenderer, r, g, b, 255);
        SDL_RenderClear(pSDLRenderer);
        SDL_RenderPresent(pSDLRenderer);
        SDL_PollEvent(&event);
        switch (event.type)
        {
        case SDL_KEYDOWN:
            switch (event.key.keysym.sym)
            {
            case SDLK_ESCAPE:
                out = true;
                break;
            case SDLK_1:
                r = 255; g = 0; b = 0;
                break;
            case SDLK_2:
                r = 0; g = 255; b = 0;
                break;
            case SDLK_3:
                r = 0; g = 0; b = 255;
                break;
            case SDLK_4:
                r = 255; g = 255; b = 0;
                break;
            case SDLK_5:
                r = 0; g = 255; b = 255;
                break;
            case SDLK_6:
                r = 255; g = 0; b = 255;
                break;
            case SDLK_7:
                r = 255; g = 255; b = 255;
                break;
            case SDLK_8:
                r = 255; g = 140; b = 0;
                break;
            case SDLK_9:
                r = 0; g = 191; b = 255;
                break;
            case SDLK_0:
                r = 255; g = 215; b = 0;
                break;
            default:
                break;
            }
            break;
        case SDL_QUIT:
            out = true;
            break;
        default:
            break;
        }
        if(out)
        {
            break;
        }
    }
#endif

#if 1
    // 步驟四:開始渲染-渲染bmp圖片,1-2兩張圖片
    SDL_Surface *pSDLSurface = 0;
    SDL_Texture *pSDLTexture = 0;
    SDL_Surface *pSDLSurface2 = 0;
    SDL_Texture *pSDLTexture2 = 0;

    SDL_Texture *pSDLTextureTemp = 0;       // 用於臨時存放

    bool out = false;
    pSDLSurface = SDL_LoadBMP("testBMP/1.bmp");
    pSDLTexture = SDL_CreateTextureFromSurface(pSDLRenderer, pSDLSurface);
    pSDLSurface2 = SDL_LoadBMP("testBMP/2.bmp");
    pSDLTexture2 = SDL_CreateTextureFromSurface(pSDLRenderer, pSDLSurface2);

    pSDLTextureTemp = pSDLTexture;
    while(true)
    {

        // 清空渲染器
        SDL_RenderClear(pSDLRenderer);
        // 將問題copy到渲染器上
        SDL_RenderCopy(pSDLRenderer, pSDLTextureTemp, 0, 0);
        // 顯示渲染器內容
        SDL_RenderPresent(pSDLRenderer);
        // 事件處理
        SDL_PollEvent(&event);

        switch (event.type)
        {
        case SDL_KEYDOWN:
            switch (event.key.keysym.sym)
            {
            case SDLK_ESCAPE:
                out = true;
                break;
            case SDLK_1:
                pSDLTextureTemp = pSDLTexture;
                break;
            case SDLK_2:
                pSDLTextureTemp = pSDLTexture2;
                break;
            default:
                break;
            }
            break;
        case SDL_QUIT:
            out = true;
            break;
        default:
            break;
        }
        if(out)
        {
            break;
        }
    }
#endif
    // 步驟五:銷毀渲染器
    SDL_DestroyRenderer(pSDLRenderer);
    // 步驟六:銷毀窗口
    SDL_DestroyWindow(pSDLWindow);
    // 步驟七:退出SDL
    SDL_Quit();
}
 

工程模板:對應版本號v1.2.0

  對應版本號v1.2.0:按鍵渲染顏色和BMP圖片

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM