2013年7月8日 星期一

Imagination公司的PVRTC


iPhone的圖形芯片(PowerVR MBX)對一種稱為 PVRTC 的壓縮技術提供硬件支持,Apple推薦在開發iPhone應用程序時使用 PVRTC 紋理。他們甚至提供了一篇很好的 技術筆記 描述了怎樣通過使用隨開發工具安裝的命令行程序將標準圖像文件轉換為 PVRTC 紋理的方法。
你應該知道當使用 PVRTC 時與標準JPEG或PNG圖像相比有可能有些圖像質量的下降。是否值得在你的程序中做出一些犧牲取決於一些因素,但使用 PVRTC 紋理可以節省大量的內存空間。
儘管因為沒有Objective-C類可以解析 PVRTC 數據獲取其寬和高1信息,你想要手工指定圖像的高和寬,但加載 PVRTC 數據到當前綁定的紋理實際上甚至比加載普通圖像文件更為簡單。
 
下面的例子使用默認的texturetool設置加載一個PVRTC紋理:
    NSString *path = [[NSBundle mainBundle] pathForResource:@"texture" ofType:@"pvrtc"];
    NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 512, 512, 0,
        [texData length], [texData bytes]);
 
使用glCompressedTexImage2D()從文件加載數據並傳送給OpeNGL ES。而隨後怎樣處理紋理則絕對沒有任何區別。

glCompressedTexImage2D定義了二維紋理圖像或者立方體映射紋理圖像,圖像數據是壓縮的並存儲在客戶端內存中。紋理圖形根據internalformat指定的格式來解碼。 OpenGL ES並沒有指定壓縮紋理格式,但是它提供一個機制:獲取這些由擴展名指定的格式所對應的OpenGL符號​​常量。所支持壓縮紋理格式數量可以查詢GL_NUM_COMPRESSED_TEXTURE_FORMATS值來獲取。
所支持的壓縮格式列表可以查詢GL_COMPRESSED_TEXTURE_FORMATS值來獲取。 
 
使用參考 http://www.dreamingwish.com/dream-2012/glcompressedteximage2d.html 
 
 
 
 
而壓縮PVRTC可使用 Apple提供一個內建的壓縮工具texturetool,
這是一個shell程式,因此可以內嵌在xcode伴隨及時執行
位置在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin
 

操作方法及範例
texturetool -m -e PVRTC -f PVR -p Preview.png -o Grid16.pvr Grid16.png 

Some of the parameters are explained below.

-m
Generate mipmaps.
-e PVRTC
Use PVRTC compression. This can be tweaked with additional parameters, explained below.
-f PVR
This may seem redundant, but it chooses the file format rather than the encoding. The PVR format includes a simple header before the image data that contains size and format information. I'll explain how to parse the header later.
-p PreviewFile
This is an optional PNG file that gets generated to allow you preview the quality loss caused by compression.
-o OutFile
The name of the resulting PVR file.
The encoding argument can be tweaked with optional arguments. Some examples:
只支援下面兩種模式,其他的RGBA5551 RGBA8888  RGBA4444 ....都不支援。
-e PVRTC --bits-per-pixel-2
Specifies a 2 bits-per-pixel encoding.
-e PVRTC --bits-per-pixel-4
Specifies a 4 bits-per-pixel encoding. This is the default, so there's not much reason to include it on the command line.
-e PVRTC --channel-weighting-perceptual -bits-per-pixel-2
Use perceptual compression and a 2 bpp format. Perceptual compression doesn't change the format of the image data; rather, it tweaks the compression algorithm such that the green channel preserves more quality than the red and blue channels. Humans are more sensitive to variations in green.
-e PVRTC --channel-weighting-linear
Apply compression equally to all color components. This defaults to "on", so there's no need to specify it explicitly.
注意: Apple tool 不產生Mipmap的部位。



一般使用的壓縮檔都是事先轉換好的,使用Script來同步執行有些麻煩,可以使用Imagination提供的SDK來做,這是GUI的Tool。並且所有的壓縮模式都支援。

工具下载地址
http://www.imgtec.com/powervr/insider/sdkdownloads/index.asp?installer=Windows%20Installer



安裝後的參考目錄



由於需要其PVRTC的textheader來記錄讀取PVRTC的資料,來源有兩個
一個從Apple:  http://developer.apple.com/library/ios/#samplecode/PVRTextureLoader/Listings/Classes_PVRTexture_m.html

一個從安裝的Imagination的SDK: 位置在/Users/Shared/Imagination/PowerVR/GraphicsSDK/SDK_3.1/Tools/PVRTTexture.h 及PVRTGlobal.h


Version2與Version3的Header並不相同,Imagination的Tool預設市Version3,使用Save As Legacy才能存成version2,參考如圖



Version 2 PVR Texture Header
typedef struct _PVRTexHeader
{
    uint32_t headerLength;
    uint32_t height;
    uint32_t width;
    uint32_t numMipmaps;
    uint32_t flags;
    uint32_t dataLength;
    uint32_t bpp;
    uint32_t bitmaskRed;
    uint32_t bitmaskGreen;
    uint32_t bitmaskBlue;
    uint32_t bitmaskAlpha;
    uint32_t pvrTag;
    uint32_t numSurfs;
} PVRTexHeader;
 
Version 3 PVR Texture Header
typedef struct _PVRTexHeaderV3{
    uint32_t    version;            
    uint32_t    flags;          
    uint64_t    pixelFormat;        
    uint32_t    colourSpace;        
    uint32_t    channelType;        
    uint32_t    height;         
    uint32_t    width;          
    uint32_t    depth;          
    uint32_t    numSurfaces;        
    uint32_t    numFaces;       
    uint32_t    numMipmaps;     
    uint32_t    metaDataSize;   
} PVRTexHeaderV3;




最後texture的壓縮格式,因為格式太多,似乎有些難懂。有需要的時候再來仔細研究
在這之前,先用Apple所提供的Tool來實作吧

官方資料   http://www.opengl.org/wiki/Image_Format

一個壓縮texture的Paper
http://titania-x3d.googlecode.com/git/Papers/ARB_texture_compression.pdf

壓縮格式的代號,參考nvidia
http://developer.download.nvidia.com/opengl/includes/glext.h

常见的压缩纹理格式
基于OpenGL ES的压缩纹理有常见的如下几种实现:
1
ETC1(Ericsson texture compression)
2
PVRTC (PowerVR texture compression)
3
ATITC (ATI texture compression)
4
S3TC (S3 texture compression)

ETC1:
ETC1格式是OpenGL ES图形标准的一部分,并且被所有的Android设备所支持。
扩展名为: GL_OES_compressed_ETC1_RGB8_texture,不支持透明通道,所以仅能用于不透明纹理。
当加载压缩纹理时,<internal format>参数支持如下格式:
    GL_ETC1_RGB8_OES(RGB,每个像素0.5个字节)

PVRTC:
支持的GPU为Imagination Technologies的PowerVR SGX系列。
OpenGL ES的扩展名为: GL_IMG_texture_compression_pvrtc。
当加载压缩纹理时,<internal format>参数支持如下几种格式:
    GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG (RGB,每个像素0.5个字节)
    GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG (RGB,每个像素0.25个字节)
    GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG (RGBA,每个像素0.5个字节)
    GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG (RGBA,每个像素0.25个字节)










ATITC:
支持的GPU为Qualcomm的Adreno系列。
支持的OpenGL ES扩展名为: GL_ATI_texture_compression_atitc。
当加载压缩纹理时,<internal format>参数支持如下类型的纹理:
    GL_ATC_RGB_AMD (RGB,每个像素0.5个字节)
    GL_ATC_RGBA_EXPLICIT_ALPHA_AMD (RGBA,每个像素1个字节)
    GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD (RGBA,每个像素1个字节)

S3TC
也被称为DXTC,在PC上广泛被使用,但是在移动设备上还是属于新鲜事物。支持的GPU为NVIDIA Tegra系列。
OpenGL ES扩展名为:
GL_EXT_texture_compression_dxt1和GL_EXT_texture_compression_s3tc。
当加载压缩纹理时,<internal format>的参数有如下几种格式:
    GL_COMPRESSED_RGB_S3TC_DXT1 (RGB,每个像素0.5个字节)
    GL_COMPRESSED_RGBA_S3TC_DXT1 (RGBA,每个像素0.5个字节)
    GL_COMPRESSED_RGBA_S3TC_DXT3 (RGBA,每个像素1个字节)
    GL_COMPRESSED_RGBA_S3TC_DXT5 (RGBA,每个像素1个字节)

    由此可见,Mali系列GPU只支持ETC1格式的压缩纹理,而且该纹理不支持透明通道,有一定局限性。
    以上压缩纹理格式每个像素大小相对A8R8G8B8格式的比例,最高压缩比是16:1,最低压缩比是4:1,对于减小纹理的数据容量有明显作用,相应在显 存带宽上也有明显优势,从而提高游戏的运行效率(此特性没有绝对数值,根据每个游戏的用法和瓶颈点不同而有差别)。



在使用glCompressedTexImage2D來讀取資料時,需要將壓縮格式告知,放在format這個變數上
glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, 0, size, data);

壓縮代碼定義在<OpenGLES/ES2/glext.h>

/* GL_IMG_texture_compression_pvrtc */
#ifndef GL_IMG_texture_compression_pvrtc
#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
#endif

/* GL_IMG_texture_compression_pvrtc2 */
#ifndef GL_IMG_texture_compression_pvrtc2
#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG                     0x9137
#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG                     0x9138
#endif



參考網址

http://m.mydrivers.com/newsview.aspx?id=266555&cid=1&p=4

http://zh.wikipedia.org/wiki/PowerVR

https://developer.apple.com/library/ios/#qa/qa2008/qa1611.html

http://www.tuicool.com/articles/meuiii

http://wiki.sparrow-framework.org/manual/pvr_textures

沒有留言: