0.5ドットの罠
かなりマニアックな罠です。
DirectX 9 を使っていて、ドットバイドット(ディスプレイの1ドットが、ビットマップ画像の1ドットに完全に対応している状態)で表示をしようとしている方は、0.5 ドットのズレに気を付けてください。
テクスチャ画像を載せたポリゴンとかをそのまま素直に整数座標で表示しようとすると、ぼやけてしまったり画像がゆがんだりします。
詳しくはリンク先に書いてあります:
DirectX9のスクリーンドット化(ラスタライゼーション)ルール
http://marupeke296.com/DXG_No63_RasterizationRule.html
Directly Mapping Texels to Pixels (Direct3D 9)
https://docs.microsoft.com/en-us/windows/desktop/direct3d9/directly-mapping-texels-to-pixels
テクセルとピクセル間の直接マッピング
https://docs.microsoft.com/ja-jp/previous-versions/direct-x/cc373047(v=msdn.10)
要するに、テクスチャのサンプリング位置がテクセル(テクスチャ上のピクセル)のド真ん中ではなくテクセル境界上になってしまうことが原因で、ドットバイドットで表示しようとしたときに変に補完されてぼやけてしまう、というものです。
(ちなみに DirectX 10 以降ではサンプリング位置がテクセル中心になっているので、この問題は起こりません)
でもよく考えてみれば、ドットバイドット前提で表示するなら補間する必要がないんですよね。
SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR)
SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR)
ではなくて
SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
にしとけば問題なくね?ってことです。補完されちゃうからダメなのであって、補間しなければ問題ね―じゃないかと。
……ところがこれ、結構微妙なことになります。
次の画像は開発中のあやかし紅白戦のものですが、何も考えずに補間を切って(D3DTEXF_POINT) 、ポリゴンを表示させた状態です。
いろいろ微妙に歪んでいるのが分かるでしょうか?
分かりやすいようにキャラだけ拡大してありますが、他にも色々おかしいです。
これらの歪みは全てポリゴン接合部で発生しています。
補完は切ったまま、オブジェクトを描画する時の座標を 0.5 ドット左上にずらすと、こうなります。
歪みがキレイに取れていますね。
こんな感じで、変な風に歪んでいたらまず 0.5 ドットのずらし忘れを疑ってみてください。私が初めてこの問題に当たったときは、その原因に気づくまでかなりの時間を費やしました……。
特にドット絵を売りにしているゲームは同人やインディーズでは多いので、引っ掛かる方も多いのではないでしょうか。
……と思ったけど今更DirectX 9 を使う人はもうあまり居ないのかな?