こんにちは! Suです。
この記事は Akatsuki Advent Calendar 2022 24日目の記事です。
昨日はいたみんさんの Jenkins Log Parser Plugin の話でした。
色つけてログがみやすくなります。うちのプロジェクトにも導入したいですね〜
読みやすくていい記事でした。勉強になりました!
はじめに
cocos2d-x-3.17.2 はASTCという画像フォーマットをサポートしないので、サポートできるように色々頑張ったことをここに書き残します。
ソフトウェアデコードとハードウェアデコード両方とも実装してみました。
ASTC とは?
ASTCは綺麗で容量もそこそこ抑えられるテクスチャの圧縮フォーマットです。
iPhone6 以降、2015年以降に発売したAndroid端末などは大体使えます。
Block サイズは大きくなるど、綺麗に見えるがサイズも増えます。
ASTC のアルゴリズムはこの文章にて詳しく紹介しません 🙏
cocos2dx は ASTC サポートしていますが、Axoml という cocos2dx-4.0 から派生したゲームエンジンはサポートしています。それを参考しつづ cocos2dx-3.17 で実装してみます!
ASTCソフトウェアデコード
まず Axoml エンジンから ASTC デコードコードを拝借いたします。
ファイル/フォルダ | 場所 |
---|---|
axmol/astc.h | cocos2d/cocos/base |
axmol/astc.cpp | cocos2d/cocos/base |
axmol/thirdparty/astc | cocos2d/external |
xcodeprojに追加することもお忘れ無く!
ここでビルドして問題ないと確認しましょう。
続いて端末が ASTC に対応できるのかの実装です。
他のフォーマットを真似して、CCImage に ASTC の実装を追加します。
bool Image::isASTC(const unsigned char *data, ssize_t dataLen)
bool Image::initWithASTCData(const unsigned char * data, ssize_t dataLen)
を新規追加して、既存の
Image::initWithImageData(const unsigned char * data, ssize_t dataLen)
Image::detectFormat(const unsigned char * data, ssize_t dataLen)
に ASTC の分岐文を追加します。
▼クリックでコードを表示する
最後に HellowWorldScene に astc 画像を表示するボタンを作成します。
画像はみなさんご存知のレナさんにしました。
下記の ARM 社の astc-encoder を使って PNG から ASTC に変換しました。
▼クリックでコードを表示する
下記はソフトウェアデコードがかかった時間です。
ASTC 8x8のサイズ圧倒的に優秀ですが、
やはり遅いですね...ハードウェアでコード実装しないと使えないの気がします。
解像度 | フォーマット | サイズ | 時間 |
---|---|---|---|
512 | png | 386KB | 約35ms |
512 | astc 4x4 | 226KB | 約270ms |
512 | astc 8x8 | 70KB | 約300ms |
1024 | png | 1.4MB | 約80ms |
1024 | astc 4x4 | 1.1MB | 約892ms |
1024 | astc 8x8 | 266KB | 約930ms |
1960 | png | 4.1MB | 約185ms |
1960 | astc 4x4 | 3.8MB | 約3100ms |
1960 | astc 8x8 | 963KB | 約3210ms |
※時間は10回平均、cacheなし
動画はこちらです
ASTCハードウェアデコード
まず最初の問題は、GLES 3.0 から ASTC ldr が対応していますが、cocos2dx-3.17 が GLES 3 に対応しないです。昔一時 GLES 3.0 対応させたですが、どうやら一部 Android シミュレーターがクラッシュするとパフォーマンスの問題で revert されたみたいです。
実験として、ios を GLES 3.0 に対応させます。
▼クリックでコードを表示する
手元の端末 iPhone 8 で対応できる ASTC フォーマットを調べると、ldr しか対応できないので、今回はそれを対応させてみます。
GL_KHR_texture_compression_astc_ldr
ちなみに、このサイトで対応しない端末が調べます。
端末が ASTC に対応できるのかをチェックするため、CCConfiguration に isSupportsASTC() を追加します。
▼クリックでコードを表示する
続いて ASTC 4x4、8x8 のPixelFormat を追加します。
それそれの internalformat は この仕様書 に書かれてます。
COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
▼クリックでコードを表示する
bpp(BitsPrePixel) は Wikipedia で確認できます。
Block footprint | Bit rate |
---|---|
4×4 | 8.00 |
8×8 | 2.00 |
主に下記 CCTexture2D.cpp の PixelFormat マップに ASTC の項目を追加することです。
static const PixelFormatInfoMapValue TexturePixelFormatInfoTablesValue[]
▼クリックでコードを表示する
最後にCCImage.cppにハードウェアデコードの処理を追加すればOK!
▼クリックでコードを表示する
では時間を測ってみましょう〜
解像度 | フォーマット | サイズ | ソフトウェア時間 | ハードウェア時間 |
---|---|---|---|---|
512 | png | 386KB | 約35ms | 約35ms |
512 | astc 4x4 | 226KB | 約270ms | 約3ms |
512 | astc 8x8 | 70KB | 約300ms | 約2ms |
1024 | png | 1.4MB | 約80ms | 約80ms |
1024 | astc 4x4 | 1.1MB | 約892ms | 約5ms |
1024 | astc 8x8 | 266KB | 約930ms | 約3ms |
1960 | png | 4.1MB | 約185ms | 約185ms |
1960 | astc 4x4 | 3.8MB | 約3100ms | 約17ms |
1960 | astc 8x8 | 963KB | 約3210ms | 約6ms |
※時間は10回平均、cacheなし
爆速じゃん!!!
Fooooooo 🎉🎉🎉
動画はこちらです
Github repo もありますー
最後に
ハードウェアデコードがすごかった...
Androidも試したいですね 🤔
もし今後他のフォーマットを追加したい時、もっとちゃんとしたコード書かないと思いますが、大体同じやり方でできると思います。
自分のメモもなりましたし、この記事読んだ君の役に立てればいいですね〜
明日は Sieben.L さんのドライブと関連した内容です。楽しみですね!
アカツキでは一緒に働くエンジニアを募集しています。
カジュアル面談もやっていますので、気軽にご応募ください。
https://hrmos.co/pages/aktsk/jobs?category=1220948640529788928