2012-03-28 31 views
4

因此,我在一個整潔的小系統中設置了我的框架,將SDL,openGL和box2D全部封裝在一起用於2D遊戲。openGL在運行時創建紋理圖集?

現在它的工作原理是我創建一個「GameObject」類的對象,指定一個「源PNG」,然後它自動創建一個相同尺寸的openGL紋理和box2d主體。

現在我擔心如果我開始需要在屏幕上呈現許多不同的紋理。

是否有可能在運行時加載我的所有精靈表,然後將它們組合成一個紋理?如果是這樣,怎麼樣?什麼是實現它的好方法(這樣我就不必手動指定任何參數或任何東西)。

我想在運行時完成而不是預先完成的原因是,我可以輕鬆地將所有(或大部分)瓷磚,敵人等加入到一個紋理中,每個級別都不會有相同的敵人。它也會使整個創作過程變得更加簡單。

+0

_many_有多少?我更擔心重用現有紋理 - 引擎是否處理這個問題? – 2012-03-28 04:07:13

+0

我認爲最多我會有100個不同的紋理在任何時候,所以這將是100綁定操作。另外,當你說重複使用現有的紋理,你的意思是,如果我有一個使用12次的特定瓦片,引擎應該繪製它12次,而只綁定一次,而不是重新綁定?這將是一個好主意..任何方式來檢查哪些紋理當前綁定,所以我不重新綁定它?或者我必須建立一個系統來繪製相同的紋理,所以我減少了綁定......但是如果我想按照特定的順序繪製它們以進行深度排序呢? – 2012-03-28 04:35:17

+0

是的,對 - 保存綁定。第二個評論更多的是針對具有相同數據的紋理,忘記了這一點。 – 2012-03-28 05:17:59

回答

5

可能有一些庫已經存在用於創建紋理地圖集(最佳包裝是一個非平凡的問題)並將舊的紋理座標轉換爲新的紋理圖集。

但是,如果你想自己做,你可能會做這樣的事情:

  • 從磁盤加載所有紋理(你的「源PNG」),以及獲取原始像素數據緩衝區,
  • 如果有必要,所有源紋理轉換成相同的像素格式,
  • 創建一個新的紋理大到足以容納所有現有的紋理,具有相應的緩衝沿着容納像素數據
  • 「位圖傳送」的像素從數據將源圖像放入新的緩衝區中n偏移量(請參見下文)
  • 使用新緩衝區的數據照常創建紋理。
  • 這樣做時,確定從「舊」紋理座標到「新」紋理座標的映射(應該是爲紋理圖集的每個元素記錄偏移量並進行快速轉換)。在像素着色器中執行它可能也很容易,但是需要進行一些分析以查看傳遞額外參數的開銷是否值得。

顯然,你還需要檢查,以確保你是不是做一些愚蠢像加載相同的紋理成冊的兩倍,但是這是一個關注,就是這個過程之外。


要「位圖傳送」從原始圖像(複印件)你會做這樣的事情的目標圖像(假設你拷貝一個128×128的紋理成512x512的圖冊的質感,從(128,0 )目標):

unsigned char* source = new unsigned char[ 128 * 128 * 4 ]; // in reality, comes from your texture loader 
unsigned char* target = new unsigned char[ 512 * 512 * 4 ]; 

int targetX = 128; 
int targetY = 0; 

for(int sourceY = 0; sourceY < 128; ++sourceY) { 
    for(int sourceX = 0; sourceX < 128; ++sourceX) { 
     int from = (sourceY * 128 * 4) + (sourceX * 4); // 4 bytes per pixel (assuming RGBA) 
     int to = ((targetY + sourceY) * 512 * 4) + ((targetX + sourceX) * 4); // same format as source 

     for(int channel = 0; channel < 4; ++channel) { 
      target[to + channel] = source[from + channel]; 
     } 
    } 
} 

這是一個非常簡單的蠻力實現:有更快,更簡潔,更巧妙的方法來複制一個數組,但這個想法是,你基本上是複製的內容在給定的X和Y偏移量處將源紋理轉換爲目標紋理。最後,您將創建一個包含其中的舊紋理的新紋理。

如果索引數學對您沒有意義,請考慮how a 2D array is actually indexed inside a 1D space(如計算機內存)。

請原諒任何錯誤。這不是生產代碼,而是我編寫而不檢查其編譯或運行的東西。


由於您使用SDL,我應該指出,它有一個很好的功能,可能是能夠幫助你:SDL_BlitSurface。您可以在SDL中完全創建SDL_Surface,並簡單地使用SDL_BlitSurface將源表面複製到它,然後convert the atlas surface into a GL texture

它會照顧所有的數學,並且還可以爲你動態地進行格式轉換。

+0

謝謝你的回答ravuya! 我想我知道怎麼做的所有的東西,你只是說: 「」位圖傳送「從源圖像到新的緩衝區的像素數據的給定偏移」 上我將如何做到這一點的任何鏈接或方向代碼明智的將不勝感激,再次,謝謝! – 2012-03-28 04:38:56

+0

我添加了一個快速解釋我的意思是「blitting」 - 它有效地將一個數組複製到另一個數組中。 – ravuya 2012-03-28 05:06:49

+0

等等,基本上,openGL中的紋理包含它們的像素數據(稱爲緩衝區?),我們要做的就是複製每個單獨紋理中的像素數據,並將它們全部放入大像素緩衝區中,然後將其應用於我大質地,有效地將所有的小紋理複製到大紋理中? 我想我可以處理複製的數學,我只是不確定我需要在openGL中使用哪些函數來訪問像素數據。 再次感謝您的幫助,我非常感謝! – 2012-03-28 05:20:16