強火で進め

このブログではプログラム関連の記事を中心に書いてます。

テクスチャ圧縮(PVRTC)のクオリティを徹底比較してみた

Appleの人達が事あるごとにOpenGL ESの最適化にはテクスチャ圧縮使えとプッシュしてるのでいい加減、テクスチャ圧縮に手を付ける事にしました。

iPhoneの開発環境にはテクスチャ圧縮作成(PVRTC圧縮)ツールが付属していて簡単に作ることができます。

iPhone SDKをインストールすると以下のパスにインストールされる様です。

/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/texturetool

オプション設定により以下のような設定が可能な様です。

オプション 説明
-h ヘルプの表示
-l エンコーダオプションとファイルフォーマットの表示
-m ミップマップの作成
-e エンコード設定。エンコードを指定
-p プレビュー画像の出力。にプレビューファイル名を指定
-o 出力ファイルの指定
-f 出力ファイルのファイルフォーマットを指定

エンコードオプションとしては以下の設定が可能な様です。

オプション 説明
--bits-per-pixel-2 1ピクセルに2ビット割り当てる
--bits-per-pixel-4 1ピクセルに4ビット割り当てる
--channel-weighting-linear RGBAすべてのチャンネルで均等に圧縮する
--channel-weighting-perceptual --channel-weighting-linearに比べ緑(G)のチャンネルの損失を押さえた圧縮

※緑(G)のチャンネルの損失を押さえた圧縮が準備して有るのは人間の目は緑色の識別能力が高いことに由来してる思われます。

詳細はこちらのページを参照下さい。

Technical Q&A QA1611: Creating textures in the PVRTC compression format
https://developer.apple.com/iphone/library/qa/qa2008/qa1611.html

取りあえず適当に記述例をチョイスし、「はちゅね」のテクスチャを圧縮してみたところ 124KB の「はちゅね」のテクスチャが 128KB に!

サイズ増えちゃってるよorz

しょうが無いのでもう少し、読み進めたところ「line art(線画)は苦手だけど写真まかせろ」みたいな記述を見かけたので写真の画像も準備してどうせなら全パターン検証してやろうと以下の様なシェルスクリプトを準備し、一括でテクスチャ圧縮生成しました。

#!/bin/sh

TEXTURE_TOOL=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/texturetool
cmd="${TEXTURE_TOOL} -e PVRTC --channel-weighting-linear --bits-per-pixel-2 -p ${1%.*}_linear2bpp.png -o ${1%.*}_linear2bpp.pvrtc ${1}"
echo ${cmd}
${cmd}

cmd="${TEXTURE_TOOL} -e PVRTC --channel-weighting-linear --bits-per-pixel-4 -p ${1%.*}_linear4bpp.png -o ${1%.*}_linear4bpp.pvrtc ${1}"
echo ${cmd}
${cmd}

cmd="${TEXTURE_TOOL} -e PVRTC --channel-weighting-perceptual --bits-per-pixel-2 -p ${1%.*}_perceptual2bpp.png -o ${1%.*}_perceptual2bpp.pvrtc ${1}"
echo ${cmd}
${cmd}

cmd="${TEXTURE_TOOL} -e PVRTC --channel-weighting-perceptual --bits-per-pixel-4 -p ${1%.*}_perceptual4bpp.png -o ${1%.*}_perceptual4bpp.pvrtc ${1}"
echo ${cmd}
${cmd}

こちらのスクリプトは例えば pvrtc.sh などのファイル名で保存し、実行権限を追加後、以下の様に引数に元のファイルを指定して実行して下さい。

./pvrtc.sh miku.png

実行権限の追加が面倒くさかったら以下でもOK。

sh pvrtc.sh miku.png

データサイズ比較

はちゅねのテクスチャ(サイズは512x512)はこちら

写真(サイズは128x128)のテクスチャはこちらを変換しました。

それぞれの変換後のサイズは以下の様になりました。

以降はこのように省略して記載します。

--bits-per-pixel-2 → 2bpp
--bits-per-pixel-4 → 4bpp
--channel-weighting-linear → linear
--channel-weighting-perceptual → perceptual

はちゅねのテクスチャ

種別 サイズ
元データ 124KB(125584byte)
linear/2bpp 64KB(65536byte)
perceptual/2bpp 64KB(65536byte)
linear/4bpp 128KB(131072byte)
perceptual/4bpp 128KB(131072byte)

写真画像

種別 サイズ
元データ 128KB(128510byte)
linear/2bpp 16KB(16384byte)
perceptual/2bpp 16KB(16384byte)
linear/4bpp 32KB(32768byte)
perceptual/4bpp 32KB(32768byte)

なかなかおもしろい結果が出ました。 linear と perceptual とで同じビット数を使用するものは同じサイズになる様です。また、写真画像の場合かなり圧縮されるようですね。

データ欠損の比較

次にどの程度、元画像と異なる部分が有るのかを確認してみました。

判定ルールとしては元画像と圧縮後のプレビュー画像のRGB値を以下の様に計算をし、結果をグレースケールの画像ファイルとして出力しました。

(Rの差分+Gの差分+Bの差分) / 3 → グレースケールの値

※Aの差分も入れた方が良かったかな?(^_^;)

差分がそのままグレースケールの値となるため差分が大きいほど白く、差分が無い部分は黒く出力されます。

それではまず「はちゅね」のテクスチャの差分から

linear/2bpp

perceptual/2bpp

linear/4bpp

perceptual/4bpp

じっくり見ると色が変わる部分の境界辺りが白くなっていますね。実際の画像でも境界辺りの色がボケていました。

しかし、正直 linear と perceptual とどちらの方が綺麗に見えるかは自分にはイマイチ判断に悩みますねぇ(実際にどちらを選択するかはデザイナーの方と相談して作業を進めた方が良いのではないでしょうか?)。

次に写真の場合の差分
linear/2bpp

perceptual/2bpp

linear/4bpp

perceptual/4bpp

さすが写真は「自信あり」なだけあってほとんど白い部分がないです。右下の辺りが多少白くなってるだけみたいです。4bppのものだとほとんど真っ黒です。

多少、実際の画像を見ると階調が減ってのっぺりとした印象を受けましたが実際にテクスチャに使用されたときは縮小・拡大の処理がかかる場合も多いためそんなに問題になる場面は少ないような気がします。

なお、元ファイルと実際に生成されたテクスチャ圧縮のプレビュー画像との比較をしたい場合はこちらのファイルをDLして下さい。

こちらには上記の差分画像の生成プログラムも含まれています。そちらを実行すると差分画像の生成もできます。

まとめ

テクスチャ圧縮、予想以上のクオリティでびっくりしました。この程度の劣化であれば実際には動いているモデルに使う場合などにはほとんど元画像と区別がつかないのでは無いでしょうか。

このクオリティでVRAMの使用量を削減できるのであれば確かに「使う価値あり」ですね。

でも、アニメ調のテクスチャの場合は要検討ですかねw