「 DirectX 」一覧

Windows8でDirectX9デバッグランタイム不可らしい


先日公開したライブラリはWindows8でも動くだろうと思っていたのですが、実は動かないことが判明しました。とりあえず修正コードを埋めてみたり色々といじってみたのですが、どうやら本格的に使えないようです。
これは明らかにDirectX9を捨てた感じです・・・。DirectX11に乗り換えてねってことなんでしょう。

さて、具体的にはDirect3DCreate関数の中で、デバッグランタイムへの切り替えのコードがまるっと存在しないようです。
言ってしまえばWindows8に付属するd3d9.dllはWindows8専用で、それ故にデバッグランタイムの存在など知らない、という感じです。一方Windows7までは一応存在そのものは知っていて、一応切り替えが出来るようなコードが埋めてあるようです。

思ったよりDirectX9デバッグランタイム制御ライブラリの出番は少ないようです。時期が遅すぎたのかもしれません。
もうちょっとだけ関数インターフェースいじったらもう放置になっちゃいそうです。


DirectX9デバッグランタイムの制御ライブラリ


DirectX9を使用している人は割とおなじみの SDKをインストールすると使用できる DirectX DebugRuntime というものがあります。
これは使用方法が不味いときにエラーを出力してくれたり、冗長な設定を行っているときに警告を発してくれたりととても役立つツールです。
ちょっと厄介なのは、SDKのインストールが必須で、再配布を行えないところとVista以降では管理者権限を必要とするようでUACによる暗転が発動してしまうことです。

今回、開発者が一時的にSDKをインストールしていないターゲットで問題解決のためにデバッグランタイムを使用するという想定で、
ターゲットでデバッグランタイムを使用可能にするライブラリを作成しました。

こちらからダウンロードしてください。d3d9_drt_v100

開発者の環境から必要なDLL(d3d9d.dll, XPならd3dx9_32,33.dllも)をアプリケーションexeと同じ場所にコピーするという手間と、ライブラリを組み込むという手間はかかりますが、デバッグランタイムを使用することが出来るようになります。

メリット/デメリット

  • 管理者権限が不要
  • SDKのインストール無しにデバッグランタイムが使える
  • プログラム主導でデバッグランタイムのON/OFFが(起動時に)設定できる
  • 安定動作しないかも。動作チェックが十分ではない
  • 再配布禁止の物を使えるようにするという性質上、公開がぁゃιぃ。公開停止要求受けたら閉じます

使用方法

プログラムは以下のようになります。Direct3DCreate9の前後で関数を呼び出します。

不具合とか

発見したらコメントの方で報告頂けると、修正を検討することが出来ます。

動作環境

ターゲット環境としては以下のものを想定しています。
調査した結果、Windows8では動きません!! 追記しました 2013/06/04

  • WindowsXP
  • WindowsVista
  • Windows7
  • Windows8 (まだ未検証. レポート求む)

ライブラリのリンクについては、下記のツールで確認しています。

  • VisualStudio2010 Professional SP1
  • VisualStudio2012 Professional

おそらく VisualStudio2010(SPなし), VisualStudio2012 Update XX らでも問題なく動作すると思います。
また、VisualStudio2008でもリンクは正常に出来る気がしています。

注意事項

WindowsVista以降の環境から d3d9d.dllをコピーして、WindowsXP環境へ持って行くことはできません。
これはVista以降の環境でインストールされるd3d9d.dllがVista以降専用のもののためです。
一度別のWindowsXP環境にDirectX SDKをインストールして、d3d9d.dllを取得するようにしてください。

「プロシージャエントリポイント _ftol2_sseがダイナミックリンクライブラリ msvcrt.dll から見つかりませんでした」というようなエラーがWindowsXPで表示された場合、このケースに該当していると考えられます。

最後に

機能として足りていないところもあるかと思いますので、ひとまずは要望などありましたらコメントの方にお願い致します。
開発において本ライブラリが役立ってくれることを願います。


Windows 8でXAudio2のトラブルに出遭う 解説編


前回の日記でふれたVisualStudio 2012 + XAudio2 + Windows 8 というコンボ発動で、アプリケーションを正常に起動出来ない!という罠にはまった内容を説明したいと思います。

実は、Windows 7で使用している(できる)最新のXAudio2は、 2.7 というバージョンのもので、これは DirectX SDK 2010 Juneに含まれています。またDirectXの再頒布ランタイムをインストールすることで導入できます。
一方、Windows 8で標準で使用するXAudio2は 2.8 というバージョンのものになります。これは VisualStudio 2012付属のWindows SDKを使用してアプリケーションを作成するとこちらを使うようになります。

標準状態の Windows 8 では、XAudio2は 2.8 のものだけが入っており、従来のDirectX SDKを使用していると 2.7のものを要求するために動作しません。
.Net framework をインストールした後で、DirectXのランタイムをインストールすると、Windows 8でも動作するようになりますが、これをアプリケーションを単に動かしたい人々がやるには手間もいいところです。
できるなら、そのままアプリケーションが動くのを目指したいところです。

これを表にするとこうなります。

DirectX SDKを使ってXAudio2 Windows 8ではそのまま動作しない
VS2012のWindowsSDKでXAudio2 Windows8では動作、Windows7では動かない

Windows7までの環境では対応したDirectX再頒布パッケージがあるのでそれをインストールすることができます。
ただそれらをインストールすること無しで XPから8まで、単一アプリケーションとしてサウンドを再生するには、実はDirectSoundを使用すると良さそうです(XPの標準状態でもDirectSoundは含まれていました)。

おそらくVista以降のDirectSoundはXAudio2より上位にレイヤーとしては位置付けられているようなので、
これを使うことでXAudio2に関係する依存関係を断ち切ってくれそうです。
ただし、DirectSoundは既にレガシーなAPIとなっているため、そのあたりが懸念事項でしょうか。
ただ互換性の点からOSから使用できない・削除されているわけではないため、XPから8まで一応使うことは出来るようです。

※ そのため単一アプリとして提供する際にはとても都合がよかったり。

DirectX9とXAudio2と。

D3DX関連のAPIもVS2012のWindows SDKに入っていないので、DirectX9+XAudio2という構成は VisualStudio 2012での開発にとってはなかなかの鬼門といえそうです。シェーダーのコンパイルはD3DXですし、XAudio2は今回のような問題があるし。

再頒布ランタイムをとりあえず強引にででもインストールさせるのであれば、DirectX SDK 2010 Juneを使って開発しておくでOKでしょう。
なるべくなら標準の状態で開発&配布したいと考えるなら、DirectX9やXAudio2を諦めて、OpenGLとDirectSoundを選択しておくと、余計なことを考えずともどこでも動く状態の物ができあがるように思います。

Windows Vista以降だけでよいというなら、WASAPI も選択肢に上がってくるかと思いますが、これは使うのが大変なので手軽にという点も考慮するなら、やはり情報も多いDirectSoundでお茶を濁しておくのが手っ取り早いでしょう。

参考元
XAudio2 Versions


Windows 8でXAudio2のトラブルに出遭う


VisualStudio 2012を使っていたら、Windows8でのXAudio2で問題に遭遇したのですが、
この件で、有名な吉野屋テンプレがうまく使えそうだと閃いたためちょっと貼ってみます。
ちゃんとした説明は次回に行いたいと思います。

では、どうぞ。

昨日、XAudio2 を使ったアプリを Windows 8 で動かしたんです。Windows 8。
そしたらなんかアプリが起動出来ないって言われるんです。

で、よく見たらヌルポでアクセス違反、とかのようなんです。
もうね、アホかと。馬鹿かと。

お前らな、XAudio2 引き如きで普段使わない Windows 8に来てんじゃねーよ、ボケが。
XAudio2 だよ、XAudio2。

なんかDirectX9とかもいるし。DirectX9 + XAudio2でWindows 8か。おめでてーな。
よーしパパ、プログラムをWindows 8対応しちゃうぞ、とか言ってるの。もう見てらんない。
お前らな、Windows SDK やるからその席空けろと。

Windows 8 対応ってのはな、もっと殺伐としてるべきなんだよ。
OS環境ごとにプログラムを用意しないで、
単一プログラムがそのまま動くか動かないか、そんな雰囲気がいいんじゃねーか。
女子供は、すっこんでろ。

で、やっと座れたかと思ったら、隣の奴が、WASAPI で、とか言ってるんです。
そこでまたぶち切れですよ。

あのな、WASAPI なんてきょうび流行んねーんだよ。ボケが。
得意げな顔して何が、WASAPI、だ。

お前は本当にWASAPIを使いたいのかと問いたい。問い詰めたい。小1時間問い詰めたい。
お前、WASAPI って言いたいだけちゃうんかと。

Windows 8通の俺から言わせてもらえば今、Windows 8での最新流行はやっぱり、
DirectSound、これだね。

素のDirectX9+DirectSound。これが通の頼み方。
DirectSoundってのは古くからあるDirectXのサウンド担当。そん代わり今やオーバーヘッドが多め。これ。

で、素のDirectX9(D3DXとかナシ)。これ最強。

しかしこれを頼むと次からマイクロソフトにマークされるという危険も伴う、諸刃の剣。
素人にはお薦め出来ない。
まあお前らド素人は、OpenGL + DirectSoundでも使ってなさいってこった。

※ 注意: OpenGL + DirectSound なら今や多くの環境でそのまま動くことでしょう。


VisualStudio 2012とDirectX SDK 再び


以前の日記にて、Visual Studio 2012 と DirectX SDK (2010June) を使って開発する際の手順を書きましたが、
どうやら最近ではマイクロソフトのほうに注意書きが用意されているようです。

そのページがこちら(http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275(v=vs.85).aspx)です。

基本的には、DXSDK_DIRのインクルードとライブラリを標準のものより優先されるようにすること、という以前の日記情報と同じです。
ただ上記URLの中身ではそれよりももうちょっと踏み込んで、手順が書いてありました。

  • コンフリクトするので DXGIType.h をインクルードしているコードを修正する(インクルードしないように)。
  • テクスチャ関連は DirectXTex や DirectXTK といったものを利用するように検討すること
  • 算術に関しては D3DX から DirectXMath の実装へ切り替えを検討すること
  • XInput や XAudio2 を使う場合には要注意

気になった点をざっと列挙してみました。
XAudio2は厄介そうです。 使用するDLLがVS2012とDXSDKとで異なってしまうようで・・・。
どこでも動くように、というならば DXSDKのものをつかわないといけない、ということのようです。


DirectX11で旧シェーダーコード(HLSL)を使う


DirectX11(DX11) は DirectX9(DX9) に対応したハードでも一応動かすことが出来ます。このとき、DX9 にのみ対応ハードで動かす場合、DX11 の機能は当然使えません。シェーダーに関しても同様で、頂点シェーダー、ピクセルシェーダーのみを使用することになります。

fxcや関連するドキュメントをみると、そういった DX9 ハード用のシェーダープロファイルとして、次のものを使用するようになっています。

  • vs_4_0_level_9_0
  • vs_4_0_level_9_1
  • vs_4_0_level_9_3
  • ps_4_0_level_9_1
  • ps_4_0_level_9_3

確かに、DirectX11 の仕様を守って新規にシェーダーファイルを作って行く場合には何の問題も無いのですが、昔からのコードを現世代で動くようにと作業している場合、これだけの指定では足りないのです。

例えば、以下のようなシェーダーファイルのコードがあったとして、これを上記のプロファイルに従い、 vs_4_0_level_9_3 でコンパイルしたとします。

これをコンパイルすると次のようにエラーが表示されます。

fxc /T vs_4_0_level_9_3 vs.hlsl

error X4541: vertex shader must minimally write all four components of SV_Position
compilation failed; no code produced

これをエラー無く、かつ、シェーダーコードを修正することなくシェーダーコンパイルを成功させるためには、/Gec オプションを指定します。

fxc /T vs_4_0_level_9_3 /Gec vs.hlsl

これで vs_4_0 系のタイプでシェーダーをコンパイルすることが出来、DirectX11 のプログラム上で使用することが可能になります。
内部的には、出力セマンティクスのPOSITION を SV_POSITION として勝手に扱ってくれるようです。コマンドラインでコンパイルした結果を見るとそんな感じに見えます。

なお、D3DX11ShaderCompileFromFile で、この “Gec” オプションに相当するものは、 D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY となるようです。

感想

意外と DirectX11 で古いシェーダーコードをそのまま使うという話はないのかな?と思いました。
調べてみても情報はほとんど出てきませんでした。
確かにDirectX11 は初心者にはちょっと手間な部分も多いですし、ある程度までなら DirectX9 を使ってしまった方が楽で、やりたいことを実現できますし。
それでもどこかで、同じように悩んだ人に、この記事が役立ってくれるといいなと思います。


D3DXでERROR_MOD_NOT_FOUND


ある環境でプログラムを動かそうとしたら、D3DXAssembleShaderFromFile 関数で ERROR_MOD_NOT_FOUND というエラーコードが返ってきた!
こんなエラーは初めてで、エラーメッセージのログも何もなくとても困った・・・。

よくよく調べてみるとこのエラーは、必要なモジュール(DLL)がロードできなくてエラーとなったことを意味しており、今回の件も、確かに強引にプログラムを動かそうとしていたことが原因となっているようでした。
DirectX の再頒布ランタイムをインストールすれば問題は解決になりそうです。

追記

さらなる調査の結果、どうやらシェーダーコンパイラである D3DCompiler_XX.dll が見つからなかったために起こった模様。
これが原因だとすると、D3DXAssembleShader系だけでなく、D3DXCompileShader系やD3DXEffect系もおそらく同じようなエラーになるだろうと推測します。


透明ウィンドウ(半透明ウィンドウ)の話 その3


透明なウィンドウということで、このシリーズも第3回。今回が最後となりそうです。
ようやく Windows7,Windows8両方ともで動かせるやり方が発見できました。
なお、Windows7のAeroGlassOFF状態でも動くので、注意して実装すればWindowsXPでもこの方法でいけるのではないかと思います。

その方法は、レイヤードウィンドウを使う方法です。
これを使っての半透明ウィンドウはWindows7,Windows8ともに正常に動作することが手元では確認できました。
ただし、レイヤードウィンドウの簡単なサンプルによくあるSetLayeredWindowAttributes関数を使ってしまうと、ウィンドウ全体での半透明設定や、カラーキーによる抜き色指定になってしまうため、背景とうまく溶け込ませた半透明の処理があまりうまく出来ないため、使用しないでおきます。

半透明もうまく処理するレイヤードウィンドウの作り方としては、DIBとUpdateLayeredWindowとを使って実現します。
DIBで半透明用のメモリ上のフレームバッファを用意して、その中にデータを書き込み、その結果をUpdateLayeredWindow関数で転送して、画面に表示します。この部分はGDIに関係する処理となります。
この手順の中で、「その中にデータを書き込み」の部分ですが、レイヤードウィンドウの各ピクセルの条件において、乗算済みアルファであることを要求されるので、その点に注意しながら実装を行います。

さて、ピクセル列にまでなったデータを表示する方法はこれでわかりました。あとはこれをどう用意するかですが、これにはDirectXであれOpenGLであれ、一度書いたデータをメインメモリ上に読み直す、取得し直すことが必要になってきます。いくつかの方法はあるでしょうが、環境に合わせてパフォーマンスと相談しながら実装を検討することになるかと思います。手頃で簡単なものは、DirectXであればバックバッファをロックできるようにフラグを立ててしまうか、OpenGLならglReadPixelsの関数で読み出してしまうとか。
ただ、ラスタライズした結果を読み戻す処理になるのでそれなりに負荷がかかるのは仕方のないことでしょう。
(ただ、今はPCI-Express接続になっているし、昔のAGP接続に比べて転送がネックになることが少なくなってきている、との話もあるので実際に計測してみないことには何とも。)

結果

手元で実装したものの結果を貼っておきます。まずはWindows7で動かした物です。
背景にコードが若干見えると思いますが、これはOpenGLで実装しているものです。

一方で、これをWindows8で実行したものです。こちらはスマホのカメラで撮ったのでちょっと画質がイマイチです。

でも、どちらの場合でも描画した結果をデスクトップ上に半透明も有効にして重ねて描画できていることが確認できるかとおもいます。

 

追記

この透明ウィンドウ関連の話をされている、こちらhttp://umezawa.dyndns.info/wordpress/?p=3455 のページでもレイヤードウィンドウを使ってWindows8で期待通りに動いてくれる、とあります。 Windows8ではやはりこの方法できまり、という感じですかね。


透明ウィンドウとWindows8


ようやくWindows8が発売されていろいろと話題になっているようですが、Aeroがなくなってしまった点は個人的に残念に思います。また、このAeroがなくなったことで、透明なウィンドウの扱いがちょっと困ったことになっているように見受けられます。

参考: http://umezawa.dyndns.info/wordpress/?p=3335

Windows Vista/Windows7 では、DWMの機能をつかってうまく実現できていたようですが、これが半透明は無効状態になったことで出来なくなったのかなと思います。

具体的に出来なくなっているように見られたのが、DirectXやOpenGLを用いた結果をデスクトップ上に半透明を有効にした状態での合成という点です。単純にアルファ無しの不透明で、背景を抜くような方法についてはうまくいくようです。

今回DirectX用に使ったサンプルは DWMTestという下記のサイトで公開されていたものを利用させて頂きました。

参考: http://nyaruru.hatenablog.com/entry/20060628/p2

また、OpenGL用には自分で作ったプログラムです。うまく行かなくてちょっと試行錯誤していたので、こちらはWin7ではかろうじて動いているもののもしかしたらよくない作りをしているかもしれません。

これらのプログラムをWindows7で動かすとこのようになります。

どちらの場合もDirectX, OpenGLでのアルファ付き描画の結果を、透過なウィンドウに対してうまく動いているように見えています。

これらをAeroをOFFにして動かす(ベーシックやクラシックのテーマで動かす)と、以下のようになります。

透過して欲しいところが全く抜けていない状態となっています。

さて、これをWindows8で動かしてみて画面をキャプチャしてみます。

このキャプチャ結果を見ると一見うまく動いているようにみえますが、先ほどの結果と比較すると色がちょっとおかしいことに気付くと思います。DirectXのほうは概ね問題ないように見え、OpenGL側はちょっとアルファが効き過ぎている、そんな感じでしょうか。

しかし、キャプチャしたデータではなく実際に動かすと、これらの両方ともの透明部分が妙な動きをするのです!それゆえどちらも正常に動いているとは言いがたい状況です。この部分は参考(1)のサイトさんのほうに詳しくかかれています。

まとめ

どうも今までの作りでうまくいっていた半透明ウィンドウ(透過型のアプリ)はちょっと作りを考え直さないといけないのかもしれません。Vista, Windows7とAeroの流れはどうやらここで終わりのようです。半透明のウィンドウ枠は結構好きだったので残念です。

※ Windows8でもこれらDirectXやOpenGLを併用した半透明でもうまく合成できる方法をご存じの方は教えて頂けるとうれしいです。


スキニングメッシュのバウンディングボックス


久しぶりにスキニングメッシュ(エンベロープモデル)のネタです。
キャラクターのモデルでバウンディングボックスやスフィアを使って、あたり判定を行っていましたが、
結構無駄な部分が出来てしまい、結果厳密なチェックが出来ないという残念な結果になってしまいます。

かといって、頂点変形をCPUで全ての頂点で行って厳密なバウンディングボックスを作るのもこのご時世に何かあっていないようなそんな気がします。今だとシェーダーでスキニングロジック実装しちゃいますしね。

そんなわけでもう少しまともなバウンディングボックスを作れないかチャレンジしてみました。今回はこの中身に触れたいと思いますが、まずは処理結果の図を以下に示します。

割と各部位に従ってボックスが出来ているのがわかると思います。これが動きに合わせて追従してくれるので、使い勝手はよいかなと思っています。ボックス自体の頂点情報は固定で、単にボーンの行列に合わせて変形されるので処理も結構軽い物となっています。

処理手順

画像を見てもわかるようにDirectXサンプルの定番 tiny.x を使用しています。
そして、SkinnedMeshサンプルの改造です。

  1. 各ボーンの影響頂点群を取得して、各頂点で一番大きなボーンはどれなのかの情報を保持します。
    D3DXにはこの操作に便利な GetBoneInfluence, GetNumBoneInfluence というID3DXSkinInfoのメンバ関数が用意されているので楽に処理できます。
  2. 各頂点を走査して、自身が一番影響を受けるボーンのボーン行列と頂点位置を乗算します。
  3. 計算されたボーンローカルの位置で、そのボーンがもつバウンディングボックス情報を更新します。
    位置が最小、最大なら現在の値で置き換えるという処理。

これらの処理により、各ボーンが自分の影響する範囲でのバウンディングボックスを構築することが出来ます。

その他

動かしてみていると若干つなぎ目部分で隙間が出来ていたりします。
あたり判定に使うにはちょっとまずい場合があるのかもしれません。
あと、ConvertToIndexedBlendedMesh でメッシュを更新したあとだと、GetBoneInfluenceで返ってくる値と食い違いが出て悩みました。どうやらこれは変換前の頂点データ群についての結果を返してくるようです。
変換前後での頂点のマップを用意して処理してあげることが必要でした。