未分類一覧

Windows8のブートローダー

Windows8を既に複数のOSが入ったディスクにインストールしてみたら、ブートローダーがさらに変わってた!

以前のようなコンソールの味気ない物に比べると、かなり見栄えがよくなったように思います。
ちなみにこの写真は、自分の動作検証用PCに入れてみたときのものです。検証用なのでいくつものOSを入れてます。

Windows7以降のVHDブートは便利ですね。できればVistaから対応して欲しかった・・・。


ATCテクスチャのデコード

先日のPVRTCに引き続き、ATCテクスチャのデコードにチャレンジしてみました。
ATCでは、AMD_compressed_ATC_texture.txt にあるように3つの種類の方式があるようです。

  • 不透明: ATC_RGB_AMD
  • アルファあり: ATC_RGBA_EXPLICIT_ALPHA_AMD
  • アルファあり: ATC_RGBA_INTERPOLATED_ALPHA_AMD

これらはそれぞれFourCCが割り当てられているようで次のようになっています。
圧縮後をDDSに出力するツール(Compressonator:AMD製)で確認してみました。

  • ‘ATC’: 4bpp: ATC_RGB_AMD
  • ‘ATCA’: 8bpp: ATC_RGBA_EXPLICIT_ALPHA_AMD
  • ‘ATCI’: 8bpp: ATC_RGBA_INTERPOLATED_ALPHA_AMD

ATCはQualcommのSnapdragonでサポートされている形式でもあり、AdrenoSDK 3.0で提供されるツールでも出力が可能となっています。しかしながら EXPLICIT_ALPHA と INTERPOLATED_ALPHA のFourCCが逆に出力されるようです。
テクスチャツールが割と扱いやすいだけにこのバグは修正されて欲しいなと思います。
それともこれらの圧縮形式を使う場合にはKTXフォーマットの方がいいのかも。

とりあえずわかっている情報からATC圧縮形式をデコードしてRGBA8にして、DDSとして出力してみました。次のような感じに変換できており無事に処理できていそうです。


右側には対等な関係にあるDXT圧縮の物を比較のために並べてみました。
だいたい同様のアルファ変化となっていますし、正しそうな気配です。


NVIDIAのシェーダー言語とか その2

前回の続きです。

結局、NVIDIAの配布するライブラリ(Cg Toolkit)に依存してしまうけど、DirectX/OpenGLで共通のシェーダーソースコードを使用することが可能になります。Cg言語は HLSL と大分似ているのでコードは書きやすいと思われます。 OpenGLに純粋に従うのであれば、 GLSL にてシェーダーを記述することになりますが、DirectX版も用意しなければいけない環境だと HLSL & GLSL の2種類を書かなくてはいけなくなり、ちょっと手間です。

(HLSL2GLSLや HLSL2GLSLfolk といったトランスレータを用意して何とかのりきる手もあるにはあると思いますが)

そこで NVIDIAが用意している強力なOpenGL拡張があります。
GL_EXT_Cg_shader というものです。とても奇妙な、でも強力な拡張機能です。
現時点ではほとんど情報が出てこないので、このブログでちょっと取り上げてみようと思った次第です。

この機能で何ができるかを列挙します。

  • GLSLにはないが、Cg言語で備えている組み込み関数が GLSLで使用できる。litとかlerpとか。
  • #include ディレクティブが使える
  • vec2,vec3といったGLSLの型の代わりに、HLSL(Cg)の float2, float3 といった馴染みの型が使用できる
  • GLSLシェーダーソースコードの代わりに、Cgシェーダーソースコードを渡してOpenGLのシェーダーを生成できる

一番最後の項目が、とっても奇妙で、すごすぎる機能です。
NVIDIA限定とはいえ、CgランタイムなしでCgコードをコンパイルできるわけですから。
これを前提とすれば、ほぼHLSLで書いておけば、OpenGL版に移行するときも楽ちんということです。

あとは、#include でしょうか。 「GLSLには #include がない!」とはよく騒がれたりする人がいるようですし。これが使えるという点は、結構大きなポイントかもしれません。

なお、使い方は簡単で、
glCreateShader 関数の引数に、GL_VERTEX_SHADER / GL_FRAGMENT_SHADER を渡す代わりに、
GL_CG_VERTEX_SHADER, GL_CG_FRAGMENT_SHADER をセットして、Cg言語で記述されたソースコードを与えてあげるだけです。

※ わかりにくいという指摘がありましたので、修正しました。


glGetActiveUniformの挙動

AMD製グラフィックボード搭載環境時に glGetActiveUniform関数が正常動作しない模様。
Catalystドライバが悪いのかも知れないが。
uniform sampler*のデータが取得できない。
有効なUniform変数の個数は意図通りなのに、sampler用と思われる部分でLocationIdが -1 という値が返ってくる。

NVIDIA製グラフィック搭載環境の場合、この問題は発生せずuniform sampler*を使用しても、
正しくLocationIdの値を返してくれる。
また、変数名をソートしてその順序でLocationIdが割り当てられるようだ*1
OpenGLの場合、シェーダー変数へのアクセスはLocationIdを介して行うので、
名前指定して値のセットということはDirectXのEffectと違い行わないのでこの最適化はしなくてもと思ったり。
それでもシェーダーコンパイル時にやってしまうという点は評価できるけど。
毎回名前からLocationIdとってきて値のセットというようなプログラムコードを書く場合にはこの部分は有効に効いてきそうだ。
逆に言えば、この最適化を期待したコードを作ってしまうと、他の環境やドライバでは速度に問題が発生するかも。

*1 : ドライバ 259.09にて確認.

追記

AMD製グラフィックカード搭載のWindowsXP環境で試してみた。
すると、sampler*に関してもただしくLocationIdが取得でき、定数名はソート済みになっていた。
問題となっている環境は Windows7 64bit, Catalyst 10.7 の状況。ここに何か問題があるのかもしれない。

追記2

Windows7 64bit環境の方でもコードを書き直ししていたら、
正常にsamplerの場合でも値がとれるようになった。
もしかしたら大本のソースがバグっていたのかもしれない。

まとめ

単純に自分のミスだったのかもしれないなぁ…。
glGetActiveUniformに問題はなし、ということで。

また、AMD製グラフィックボード時でも、
シェーダー定数群においては辞書順にソートされて結果が列挙されました。

結果がソート済みになることは仕様に入っていなかったと思うので、
この部分について必要ならば自前ソートをかけておく、というのが
よいかなと思います。


シェーダー定数(GLSL)

ボーンの行列60個

どこかのブログでボーン用マトリックスパレットが60個くらいまでしか使えなかったと見たので、その理由を書いてみます。
実はその制限は単純なもので、ShaderModel3系までだと、シェーダー定数は256個のレジスタが使えることになっています。
マトリックスだとfloatの16個分なので、float4に換算すると4つ使うことになります。

そして、Matrixが60個の場合 240個の定数レジスタを使ってしまうことになります。
頂点変換用のViewやProjectionのマトリックスも使うことを考えると、
この時点で250個くらいは使っていることになるので、約60個までボーン使えたという結果に合致していると思います。

ずいぶん前の記事だったようで、もうすでに解決しているかもしれません。

GLSLとHLSLとの違いで嵌った

DirectX(HLSL)の行列型は実はfloat4の設定APIを呼んでも設定が可能だったりします。
しかしながらOpenGL(GLSL)の行列型はそのような設定を許さないようです。それぞれで共通のシェーダーを作る場合には、この部分に注意が必要そうです。


マニュアル間違ってる…

DirectX SDKのヘルプで、
D3DXSaveMeshHierarchyToFileの部分で、形式設定が間違ってた。

  • D3DXF_FILEFORMAT_BINARY
  • D3DXF_FILEFORMAT_TEXT

が使用可能。

DXFILEFORMAT_BINARY って書いてあったけど、こんな定義がどこにも見あたらない・・・。

それとこの関数使うとメモリがリークしてるんですが、どう解消すればいいかがさっぱり。