本サイトでは、アフィリエイト広告およびGoogleアドセンスを利用しています。

OpenGLでBC7テクスチャ圧縮を使う

今回は今までにやっていそうでやっていなかった OpenGL で圧縮テクスチャを使用する方法です。
基本的には、定番のDXT1,DXT3,DXT5 などの形式をロードする方法と全く同じなのですが、意外と誰もBC6H, BC7 で書いていなかったため、情報として残しておこうと思った次第です。

BC7テクスチャ圧縮について

詳しいことは他のサイトにお任せしますが、BC7はアルファチャンネル付きでも見た目の情報劣化が少ないテクスチャ圧縮形式です。従来はこの領域では DXT5 が使用されましたが、DXT5 は意外と汚いという認識があるようです。BC7はこの点を改善していますが、今のところ圧縮時間がそれなりにかかるのが懸念点となっています。
とはいっても、GPUの支援を使い一定レベルの変換は割と早くできますし、今となっては問題も少ないんじゃないでしょうか

BC7テクスチャをどう作るか

テクスチャを使用するプログラムは難しくないのですが、データを作成するところが現時点では問題になるかと思います。
いくつか方法はあるのですが、ここではマイクロソフトの公開している方法を紹介したいと思います。

DirectXTex プロジェクト一式をダウンロードすると、その中に TexConv というプロジェクトが含まれています。これをVisualStudio で開いて、ビルドするとコマンドラインツールとしての TexConv ができあがります。

詳しいオプションはツールのヘルプを見てほしいのですが、大体以下のような感じで使えます。入力フォーマットもそこそこ対応しているようです。

texconv -f BC7_UNORM  input.png

通常だとGPUが支援として使える状況であればそちらを使うようで、 -nogpu というオプションをつけるとフルにCPUで演算するモードとなります。
どのくらい重い処理なのか一度試してみるのもおもしろいと思います。2048×2048 なデータで試してみると15~20分くらい返ってこなかった気がします・・・。

BC7 形式で dds 出力すると従来の DDS と違い、DX10 用のヘッダも格納されている点に注意して、ロードプログラムを作成します。

プログラム

ロードする際の肝は、従来と変わらずの glCompressedTexImage2D 関数を使用します。気をつけるポイントは前に述べたデータ開始位置が異なることでしょうか。
DDSを識別するマジックナンバー、DDSヘッダ、DX10ヘッダ の分を先頭からずらした位置が BC7データの開始位置となります。

コード例としてはこんな感じになりました。
BC7 をロードする際には、 GL_COMPRESSED_RGBA_BPTC_UNORM_ARB をフォーマットとして設定して glCompressedImage を呼び出します。また本来ならば、DDSのヘッダから画像解像度を取り出して使うべきですが、手抜きして直接 256×256 を指定してしまっています。

FILE* fp;
fopen_s( &fp, "sakura.dds", "rb" );
fseek( fp, 0, SEEK_END );
int fileSize = ftell(fp);
rewind(fp);

std::vector ddsImage;
ddsImage.assign(fileSize,0);
fread( &ddsImage[0], 1, fileSize, fp );
fclose(fp);fp=0;

glGenTextures( 1, &texId );
glBindTexture( GL_TEXTURE_2D, texId );
int ddsheaderSize = sizeof(DDS_HEADER)+sizeof(DDS_HEADER_DXT10) + sizeof(uint32_t);
const void* imageData = &ddsImage[ddsheaderSize];
int imageSize = fileSize - ddsheaderSize;
glCompressedTexImage2D( 
  GL_TEXTURE_2D, 
  0, 
  GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, 
  256, 256, 
  0, 
  imageSize, imageData );

OpenGL-BC7

補足

BC6Hの場合には、GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB を指定します。
また、BC7のSRGBが要求されるときには、GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB を使用します。
それ以外はロードの方法に変更はありません。

OpenGL
すらりんをフォローする
すらりん日記
タイトルとURLをコピーしました