PC用眼鏡【管理人も使ってますがマジで疲れません】 解約手数料0円【あしたでんき】 Yahoo 楽天 NTT-X Store

無料ホームページ 無料のクレジットカード 海外格安航空券 ふるさと納税 海外旅行保険が無料! 海外ホテル

log

2012.07.12 C++:カスタムUI

ファイル 408-1.jpg

エディタがあったら便利だなと前から思っていたので、まず最初にウィンドウとボタンを
作成・管理できるクラスを作ってみました。呼び出すところは以下のような感じになってます。

// ウィンドウを作成
Window1.CreateCustomWindow( "Window1", 500, 500, NULL, Draw1 );
// ウィンドウ内にボタンを作成
Window1.AddButton( "Button0", 20, 20, 98, 16, NULL );

Draw1という引数部分でウィンドウ描画用の関数を渡すことで、それぞれのウィンドウで
別々の描画が出来るようにしています。UDKやUnityみたいにエディタ上で簡単に
ゲームが作れるようになるのが一番理想的なんですが…まだまだ遠いですね苦笑。

2012.07.10 考察:CPUとGPUの速度の関係

最近は色々考察していたことが多かったので、おまけにもう一つ考察メモを書いて
おこうと思います。こちらはCPUによる3D計算の話。かなり憶測な部分が多いので
冗談半分程度に読んでもらえれば幸いです苦笑。

最近のCPUであるIntel Corei7はHDグラフィックスという機能を用いてDirectX10.1
相当をサポートし、処理速度でいえばGeforce7の上位版もしくはGeforce8の下位版に
相当している訳ですが。これは従来のIntel CPUのように内臓GPUを搭載しているわけ
ではなくCPUで全て計算しているので、そのことを考えると「何でCPUでこんなに処理
できんの?」と思ったりした訳です。

まずGPUはCPUと比べて何故早いのかということについて考えてみると、GPUは複数の
ユニットを持ちそれらのユニットで並列に処理させており、なおかつベクトル処理を
まとめて1命令で実行できるように設計されています。つまりこれをCPUに置き換えると
マルチコア+マルチスレッド+SIMDということになる訳です。
Intel Corei7のSIMD命令は従来のSSEだけではなくAVXという256bit単位の処理
も可能となり、SIMDだけでいえばGPUと同等のはずです。問題はマルチスレッド処理
ということになります。Intel Corei7のコア数は8もしくは16なので「それらのスレッド全て
を使って並列に動作させ且つSIMDを使用した場合、ユニット数が16程度のGPUと同等
程度ということになるのでは?」と仮定し、ネットで調べてみたところ、Geforce7の
ユニット数は12-20程度とかなり似通っていることが分かりました。ということで、HD
グラフィックスはコア数が同程度のGeforce7の上位版と同程度の性能ということに
なるのではないかと思いました(CPU-GPU間転送とか考慮していない上にCPUには
GPUに無い処理スキップ用の機能があるのでアレですが)。
ちなみに最新のGPUのコア数は千幾つとかなので、CPUとGPUの差は縮まるどころ
か広がってます(そう考えると昔のGPUってそれほど大したものでもなかったんだなあ)。

将来的にコア数が32,64のCPUが登場した場合を考えてみると、Geforce8の上位版と
同等の性能になるのではないかと予想されます。
画像処理以外の計算もコア数分のスレッド+SIMDでかなり高速化するはずですが…
そんな大規模な並列処理って画像処理くらいだからなあ。とりあえず自前のレイトレー
サーを機会があれば高速化しようかなと思います。

2012.07.10 C++:DirectX11の話

前々から色々と試したいと思っていたDirectX11を今回ようやく試してみることにしま
した。とりえずここここを参考に、ポリゴンとテクスチャの描画やコンピュートシェーダを
実装してみたので、今まで使用していたDirectX9との違いと利点についてまとめて
みようと思います。

・デバイスロスト処理が不要
 他のサイトでも色々説明されてますが、デバイスロストしなくなりました。
 ただしGPUのドライバ更新時はロストするとかしないとか(まぁ実行中にドライバ更新
 する人なんてまずいないと思いますが)。
・D3Dデバイスが3つに分離
 従来のD3DデバイスがD3Dデバイス、デバイスコンテキスト、スワップチェインの3つに
 分離しました。具体的にはD3DデバイスがVRAMリソースの作成、デバイスコンテキスト
 がGPUに描画コマンドを発行、スワップチェィンがウィンドウへの描画を実行といった
 感じに担当が分かれています。何故こんな面倒なことになったのかというとこれは自分
 の予想なのですが、コードを見渡してみるとロード周りはD3Dデバイスを使用し、描画
 周りはデバイスコンテキストとスワップチェインを使用するといった風に見事に分かれて
 いるため、マルチスレッドで次のシーン読み込みを行っている場合従来のようにD3Dデバ
 イスをクリティカルセクション等で制御する必要がなくなっているのです。つまり、処理を
 高速化させるためにこういった分離がされているのだろうなと推察しました。
・Shader Model4.0
 SM4.0では従来のGPUの構造とは全然違うので、シェーダ命令数が無限です(
 ちなみにWebGLのGLSLも命令数が無限ぽいのでおそらくSM4.0以上で動作させて
 んだろうと思います。
・フューチャレベル
 WindowsVista以降ではDXGIという新しいシステムによってDirectX9,10,11での
 GPUへのアクセスを共通化できるようになったのでDirectX11SDKからはフューチャ
 レベルというものを使用してD3DデバイスをDirectX9.x,10,10.1,11のいずれかの
 モードで作成出来るようになりました。
 なので実は自分の環境はDirectX11に対応していないのですが、DirectX10.1で
 DirectX11SDKを利用している訳です;
・Compute Shader
 従来のシェーダは1プリミティブがシェーダに渡されて対応した1プリミティブを返すと
 いった感じでしたが、Compute Shaderでは構造化バッファという構造体のバッファを
 利用して任意の位置のデータを拾って来たり、任意の位置にデータを渡したり出来ます。
 つまりCPUで計算するのと同じように処理出来ます。更にこの恩恵はピクセルシェーダに
 も適応され、SM4.1,5.0ではピクセルシェーダでも一部の構造化バッファにアクセス
 出来るようです(この辺はまだ試していないので何とも言えませんが)。
 更に新しいDirectX11.1+SM5.1ではピクセルシェーダだけでなく全てのシェーダから
 もアクセス出来るようになるとのことで、GPUがCPUとほとんど同じような働きが出来る
 ようになるのではないかと思います。
 ちなみにCompute ShaderはいわゆるGPGPU用なので従来のパイプラインと同じ
 流れの中で処理するのではなく、Compute Shaderから開始してCompute Shader
 で終了する、いわば唯我独尊シェーダです笑。

パッと思いつく限りこんな感じです。ただ利点ばかりではなく欠点もそれなりにあるわけで。
例えばD3DX算術関数がサポートされていないので、D3DX算術関数を利用する場合は
D3DX10math.hとd3dx10.libを読み込んDirectX10の機能を借りなければならないです。
更にはHLSLコードも含めて、DirectX9とは仕様ががらりと違うのでDirectX9を一から
覚えるのと同じ位面倒だと感じました。なまじDirectX9の作法が頭に入っていると混乱
するみたいなところがあるので新しく触る方はお気を付けください。

2012.07.08 C++:樹木生成

ファイル 405-1.jpg

地形の動的生成の次はオブジェクトの自動生成だ!ということで樹木の自動生成を試して
みることにしました。とりあえず、樹木の生成で最もよく知られている手法としてL-システ
ムが有名なので、その手法について調べてみました。

今までは樹木の生成についてのアルゴリズムかと思ってましたがどうも形式文法という
アルゴリズムのようで、有限長の集合を文字列パターン+再帰処理によって生成する
というもののようです。なのでコッホ曲線やシェルピンスキーの3角形も表現でき、それ
こそ幾何系のオブジェクトならほとんど表現出来てしまいます。いやぁ、いいなこれ。

さっそく2Dで樹木生成を試してみました。…思いっきり再帰処理しているのがバレバレな
画ですね笑。実際は乱数を使用して不規則性を持たせるんだと思いますが、最初なので
とりあえずはこんなもんです。にしても我ながら、、シンプルすぎるなあ。

2012.07.01 お気に入り:WebGL+GLSLなサイト

ファイル 404-1.jpgファイル 404-2.jpg

今回は新しく見つけたお気に入りサイトをご紹介したいと思います。

GLSL Sandbox
WebGLのGLSLだけを使って沢山のビジュアルエフェクトを表現しています。更に面白い
のは各ページ上にGLSLのソースコードがオーバーレイ表示されているのですが、その
ソースコードを書き換えて独自のビジュアルを作ったりできるのがいいなと思いました。

ちょうど海のサンプルも発見したので、地形生成の参考になりそうです。それにしても
forループで100回ループ等など、結構命令数が多いコードがありますが、命令数制限
とか無いんだろか。GLSLとかあまり詳しくないのですが、その辺が何だか気になります。

2012.06.28 C++:地形生成

ファイル 403-1.jpg

つい最近実装したパーリンノイズを利用して地面の動的生成(のようなもの)を作って
みました。モノクロで試してみると何だか雪っぽいなと思ったので、せっかくなので
雪に見立ててみました。それと地形の動的生成の参考になるかなと思い、ネット上に
公開されていたElevatedのソースコードを色々解析したりしてましたが…ソースが短い
くせにHLSLの処理部分で何をやっているのやら全然わからない感じでした(とほほ)。

ちなみにElevatedはデモの中でもかなり重い部類なのですが、ソースコードのテッセ
レーション部分の分割数を下げるだけでそれなりにサクサク動きます。古いPCだけど
Elevated動かしたいなという方はソースコードを探してみるといいと思います(もちろん、
プログラミングが出来る方限定ですが;)。

2012.06.27 C++:視点をずらすお話

ファイル 402-1.jpg

今回はちょっと豆知識的な話を書こうかと思います。カメラと視点に関する話です。
3Dで普通に射影行列(知識の無い方は、まぁカメラの画角を設定するものだと思って
下さい)を作成した場合、あまり意識する人は少ないかと思いますが視点の位置はスク
リーンのちょうど中心になります。つまり真っ直ぐな道路の向こう側を見ている場合、
道路のパースの先は画面の中心に来るということです。

視点が中心に来ないと不自然な印象になるので、視点の位置をずらすなんてことは
普通はやらないですが、ムービー等で写真や画の一部をトリミングした風に見せたい
こともあったりします。そこで、そんな場合は射影行列をD3DXMatrixPerspectiveOff
CenterLHやD3DXMatrixOrthoOffCenterLHで作成します。今までこの関数一体何
なんだろうと思っていましたが、つまりはこの関数は射影変換した後にスクリーン位置を
オフセット移動させるような行列を作成するという訳です(カメラの位置をずらすという訳
ではなくスクリーン変換した2D画面をずらすというやつです)。

ただ、実をいうとこんな関数を使わなくても今まで通りの射影行列のパラメータを以下
のように少しいじるだけでオフセット移動をさせることが出来ます。
・透視投影の場合:_31,_32の値を調節する。
・正射投影の場合:_41,_42の値を調節する。
ちなみに、とっても分かりにくいですが…画像は以下のように透視投影の_31に1を設定
してスクリーンを半分だけ左にずらしたものです。ただの変な画像ではありません苦笑;
D3DXMatrixPerspectiveFovLH( &ProjMatrix,Fov,Aspect,Near,Far );
ProjMatrix._31 = 1.0f;
とっても簡単です。画面をずらしたいという方は是非お試しあれ。

2012.06.20 C++:地平線の描画

ファイル 401-1.jpgファイル 401-2.jpgファイル 401-3.jpg

今回はCryEngine風の海の表現が出来たらいいなと思い、手始めに地平線のラインを
描画してみました。…えーっと、「何故地平線?」って感じですね;

まずCryEngineの海の手法をザックリと説明します。CryEngineの海は無限平面の海
なのですが、ポリゴンが大量に使用されているのかと思いきや、ワイヤーフレームで表示
してみると実は数十ポリゴンしか使用していないことが分かります。ちなみに画像の2つ目
がCryEngineの元の画像、3つ目がワイヤーフレーム画像です。ワイヤーフレーム画像
のワイヤーはスカイドームのワイヤーと海面下の地面のワイヤーと残るはスクリーンに
平行なワイヤーの3つに分かれていますがその3つめのワイヤーが海面のポリゴンの
ワイヤーとなります。要するにスクリーン内の無限平面の範囲をあらかじめ求めて、
ポリゴン数を減らしている訳です。

この手法をやろうと思うと画面の地平線の位置を求める必要があるなと気が付き、
そういうことで地平線の位置の取得と描画の実装に至った訳です。

一応、地平線の高さの求め方も説明しようと思います。
まず、視点からスクリーン左上への方向のy成分の絶対値をY0、視点からスクリーン
左下への方向のy成分の絶対値をY1、スクリーン左上の高さを0、スクリーン左下の
高さをHとします。スクリーン左端に地平線が入る場合は、スクリーン左端の高さYは
以下で求まります。
・Y = H * Y0 / (Y0+Y1);
この式は衝突判定で衝突距離を求める式P = P0 + N * t;(P0がt=0のときの座標、
NがP0からP1への方向ベクトル、tが衝突時刻)の式と同じような感じで求まった
と考えてください。P0は0で、Y0/(Y0+Y1)がt部分、HがN部分です。
スクリーン内に地平線が存在しない場合は以下のようになります。
・地平線が画面の下:Y = H * Y1/Y0;
・地平線が画面の上:Y = -H * Y0/Y1;
スクリーン内に地平線が存在しているかどうかは左上、左下の方向のy成分が両方とも
正値もしくは負値かどうかで判断します。正値なら地平線が画面の上、負値なら
地平線は画面の下になります。で、同様の方法で右側の地平線の高さも求まります。

さて、それで(…長いですがこれでラスト)。視点が無限平面の上なら地平線の下側が
描画側、視点が無限平面の下なら地平線の上側が描画側となります。ちなみにCryEn
gineでは海面より上か下かで海上/海中と描画が切り替わっています。

無限平面、デフォルトで実装してほしい機能だと思うんですが…あまり需要ないのかな。

追記:
これだけだとカメラが90度回転した状態(首をかしげた状態)だとおかしくなることに
気づきました。それを修正するにはカメラが90度回転しているとき(つまりY0=Y1=0の
場合)には上側と下側で地平線の位置を求めれるようにすればいいはずです。
それと後は正射投影の場合、必ずY0=Y1になるためこれも別の処理を加えないと
いけない気がします。

2012.06.18 C++:パーリンノイズ

ファイル 400-1.jpg

地形の動的生成を以前からやりたいなと思っていたので、とりあえず簡単なところから
ということでパーリンノイズでテクスチャ生成をしてみました。
それでパーリンノイズのアルゴリズムについても一応説明を入れようと思います(簡単な
アルゴリズムなので説明の必要がない気もしますが)。

パーリンノイズは乱数でノイズを生成する手法なのですが、隣接ピクセル同士で滑らかに
変化するように工夫を加えています。その工夫はというと、サイズの違うノイズを何段階も
作成し、それらの段階の色を足し合わせるといった感じです。一番荒いノイズ時の色を
I1、次のノイズの色をI2,I4,I8…とすると、最終的な色Iは以下の方法で求まります。
I = I1/ 1 + I2/ 4 + I4 / 16 + I8 / 64 + …
 = Σ( Ii / (i*i) ); ( i(ノイズサイズ) = 1,2,4,8,16,32,64,… )
ただ、この式だとボケすぎるので自分のプログラムでは以下のように設定しました。
I = Σ( Ii / i );

パーリンノイズは割と簡単に出来ましたが、そこから自然な地形が生成できるのかは
怪しいな…。そしてMineCraftやElevatedのデモはやっぱり凄いなと思うのであった。

2012.05.22 その他:XPの呪い?

少し前にウィルスに感染したことを書きましたが、今度はXPのPCのHDDがおかしく
なりました。起動時に"ntoskrnl.exeが無いよ"とか何とかいわれてOSが起動出来なく
なったので、調べてみるとBoot.ini当たりがおかしいと起こる現象とのこと。アップ
デート途中でPCを閉じると稀に起こるらしいですが。ひょっとしてこれ、例のXPの無限
ループアップデートが原因なのかなぁ、なんて思いました。とりあえず1日2日で再
セットアップが出来て、現在はちまちまWindows7のPCにデータをバックアップ中です。

巷では「ビルゲイツの嫌がらせだ」等と云われていますが、どうなんだろうな笑。