「SDL第五篇」徹底理解紋理(Texture)
- 2020 年 4 月 1 日
- 筆記
前言
這是SDL系列文章的第五篇,本文將徹底讓你理解什麼是紋理。並帶你深入探討SDL的幾個重要概念SDL_Window、SDL_Render、SDL_Surface 與 SDL_Texture。在文章的最後向你展示SDL如何通過SDL_Texture進行渲染。
對於前面系列文章感興趣的同學可以通過下面的鏈接查看:
另外,我在慕課網分享了音影片免費入門課程,有興趣的同學可以去學習更多的音影片知識。
SDL_Surface vs SDL_Texture
在SDL系列文章的第二篇里,我詳細的介紹了SDL 渲染的工作原理。即在SDL_Render對象中有一個影片緩衝區,該緩衝區我們稱之為SDL_Surface,它是按照像素存放影像的。我們一般把真彩色的像素稱為RGB24數據。也就是說,每一個像素由24位組成,每8位代表一種顏色,像素的最終顏色是由RGB三種顏色混合而成的。
SDL_Texture 與SDL_Surface相似,也是一種緩衝區。只不過它存放的不是真正的像素數據,而是存放的影像的描述資訊。當渲染紋理時,SDL以這些描述資訊為數據,底層通過OpenGL、D3D 或 Metal操作GPU,最終繪製出與SDL_Surface一樣的圖形,且效率更高(因為它是GPU硬體計算的)。
看了以上的介紹,是不是對紋理有了一個清楚的認識了?
介紹完 SDL_Surface 和 SDL_Texture後,我們再看下SDL_Window 與 SDL_Render。
SDL_Window 與 SDL_Render
SDL_Window代表的是窗口的邏輯概念,它是存放在主記憶體中的一個對象。所以當我們調用SDL API 創建窗口後,它並不會被顯示出來。
SDL_Render 是渲染器,它也是主存中的一個對象。對Render操作時實際上分為兩個階段:
一、渲染階段。在該階段,用戶可以畫各種圖形渲染到SDL_Surface或SDL_Texture 中;
二、顯示階段。參SDL_Texture為數據,通過OpenGL操作GPU,最終將 SDL_Surfce 或SDL_Texture中的數據輸出到顯示器上。
通過上面的介紹,我們就將 SDL_Window、SDL_Render、SDL_Surface與 SDL_Texture之間的關係梳理清楚了,下面我們來看一下如何使用 SDL_Texture。
使用SDL_Texture
SDL提供了非常好用的操作SDL_Texture的方法,下面我們來重點介紹一下使用SDL_Texute的基本步驟。
- 創建一個 SDL_Texture。
- 渲染 Texture
- Destory Texture
API詳細介紹
- 創建 SDL_Texture SDL_Texture* SDL_CreateTexture(SDL_Renderer* renderer, Uint32 format, int access, int w, int h)
- format: 指明像素格式,可以是YUV,也可以是RGB
- access: 指明Texture的類型。可以是 Stream(影片),也可以是Target一般的類型。
- 渲染 int SDL_RenderCopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srcrect, const SDL_Rect* dstrect)
- srcrect: 指定 Texture 中要渲染的一部分。如果將 Texture全部輸出,可以設置它為 NULL。
- dstrect: 指定輸出的空間大小。
- 銷毀Texture void SDL_DestroyTexture(SDL_Texture* texture)
例子
下面這個例子非常簡單,我這裡就不做特別的說明了。對這個程式看不懂的同學可以看我之前的幾篇 SDL 的相關文章。
#include "SDL.h" /* Moving Rectangle */ 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; }
小結
本文重點介紹了 SDL_Window、SDL_Render、SDL_Surface以及SDL_Texture之間的關係。搞清楚它們之前的關係對於理解 SDL 渲染起著至關重要的作用。
大家一定要仔細的理解文章中所講的內容,在我後序的文章中,尤其是後面介紹 播放器 相關內容時,都要用到現在所講的這些內容。
希望本文能對你有所幫助,謝謝!