A3サイズの升目帖(旧)

ゲーム制作やプログラミングに関する雑記

グラフィックの表示に成功した

こんな感じ

デモ用のスプライトを画面内に撒き散らしてみた

やっぱり絵が表示されると気分もあがるなあ。

あとドット絵っていいよねー


じつは、ざっくりしたグラフィックの表示自体は6月3日あたりで達成していたんだが、やっぱり公開するならちゃんと体裁を整えたい!…ということで色々やっていたら、なんやかんやてこずって時間がかかった。

だって、動きもしないただの市松模様を見せられてもおもんないでしょ…?

ハマりポインツ

DirectX11 定数バッファのパッキング規則

グラフィックの描画には DirectX11 を使っている。

ゲームエンジンとかは使わず、生の API を直接叩いて実装していくスタイル。


で、何にハマったかというと、DirectX11 の定数バッファの仕様だ。

頂点バッファにパラメータを送る際に、「四辺形だから4頂点あるし」とか思って配列を使ったんだが、このせいでドはまりしてしまった。


DirectX11 の定数バッファでは、16bytes を境界としてアラインメントの再配置が起こる。

これについてはネット上に情報がいっぱいあったし、筆者も警戒してコーディングしていたんだが…

問題は、配列の場合は このルールが1要素ずつ適用される ということ。

だから、パラメータとしてこのように定義していたとしても…

// D言語
struct VSNormalArg
{
    float[2][4] vertexes;
}

// HLSL
cbuffer VSNormalParams : register(b0)
{
    float2 vertexes[4];
}

HLSL 側は(イメージとしては)パラメータをこのように解釈する。

// えぇ…
cbuffer VSNormalParams : register(b0)
{
    // 16bytes
    float2 vertex0;
    float2 dummy0;
    // 16bytes
    float2 vertex1;
    float2 dummy1;
    // 16bytes
    float2 vertex2;
    float2 dummy2;
    float2 vertex3;
}

渡したつもりのデータは、まるっきりズレた領域に書き込まれるので、レンダリングがさっぱりうまくいかないのだ。

こんなん分かるか。

あたまおかしくなるかと思ったぞ。




解決方法としては至極単純で、16bytes に調整されてしまうなら最初っから1頂点を 16bytes として渡せばいい。

こんな風にね。

// D言語
struct VSNormalArg
{
    float[4][4] vertexes;  // float * 4 [2] と [3] は使わない
}

// HLSL
cbuffer VSNormalParams : register(b0)
{
    float4 vertexes[4];  // float4 'z' と 'w' は使わない
}

使わない末尾 8bytes がもったいない気もするが、まあいいや。配列で処理できたほうが断然便利だし。

シンプルイズベスト。


いやはや、しかし、知ってる人には当たり前の話なのかもしれないが、大変だったぞ。

DUB の stringImportPaths

まあこれはしょうもない話かもしれない…

パスを複数指定していた場合、各パスに同じ名前のファイルがあると、一番先頭にあるパスのものを参照しちゃうっぽい。

// ディレクトリ構成
aaa\bbb\ccc\name.bin
xxx\yyy\zzz\name.bin
// dub.json
"stringImportPaths": [
    "aaa/bbb/ccc",
    "xxx/yyy/zzz"
]
// Dソースコード
import("name.bin"); // <- aaa\bbb\ccc のファイルが参照される。

これ、コンパイルエラーにならんのか…。まあならんよなー

でもさ、import でシンボル名が被ったときは「どっちか分かんねえ!」ってコンパイルエラーになるやん…(´・ω・`)

この問題にも結構時間を食ってしまった。

以上

まあ色々と壁にはぶち当たったが、グラフィックを無事表示できて満足。

引き続き頑張っていきましょう。



うわああああああ!!

実装にあたっての参考文献

本当に助かりました…。皆様ありがとうございます。