2012年2月2日 星期四

以 OpenGL ES 1.x 在 iOS 上貼圖(texture) 的限制

最近為了要製作 Media Player 開始研究怎麼在 iOS 上畫圖,其中一種畫圖的方式是使用 OpenGL ES。OpenGL ES 對於我這初學者來說難度不小,而在先前『試作』Media Player 的經驗,我們能運用 Texture 來貼圖。參考了 iPhone 遊戲自作入門,我已經知道如何畫出一個方形的圖片。

More about iPhone遊戲自作入門


值得注意的是在書上的 93 頁提到:

讀入材質中的圖像尺寸的長與寬必須分別都是 2 的倍數。若沒有遵守這個條件,圖像可能無法正常描繪,必須多加注意。

同樣的限制在著名的 OpenGL ES From the Ground Up, Part 6: Textures and Texture Mapping 也有提到:

Images used for textures must be sized so that their width and height are powers of 2, so both the width and height should be 2, 4, 8, 16, 32, 64, 128, 256, 512, or 1024. An image could be, for example, 64x128, or 512x512.


所以,我們能知道書上的翻譯不太正確,是 2 的次方,而非 2 的倍數。在這限制大約在半年前就有遇過,那時只是先對於在 iOS 上貼圖的方法進行調查與撰寫雛型,隨著時間過去與忙碌於其他專案而將程式碼弄丟了(也忘了筆記下來)。在重新開始這個工作前,我試著在 StackOverflow 提問:How do I render frames from FFmpeg to the screen in an iOS app? 在網友的回覆中,得到一些重要的 keyword!其中最有用的資訊就是知道 NPOT。並且由另一篇提問得到畫出非 2 次方邊長是可行的 Rendering to non-power-of-two texture on iPhone

因此,對於畫出非 2 次方邊長的 texture 的條件在於:

一、你的裝置必需支援 GL_APPLE_texture_2D_limited_npot Extension,可以利用官方文件提到的 CheckForExtension 測試

二、必需滿足 APPLE_texture_2D_limited_npot 的使用條件

In the absence of OES_texture_npot, which lifts these restrictions, neither mipmapping nor wrap modes other than CLAMP_TO_EDGE are supported in conjunction with NPOT 2D textures. A NPOT 2D texture with a wrap mode that is not CLAMP_TO_EDGE or a minfilter that is not NEAREST or LINEAR is considered incomplete. If such a texture is bound to a texture unit, it is as if texture mapping were disabled for that texture unit
這句話在實作上的意義就是:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

完整的範例如下:
https://s3.amazonaws.com/qrtt1.articles/xcode.sample/texture.npot.tgz

沒有留言:

張貼留言