​線の描画

 直線を一本描画します。プログラムの内容も前回とほぼ同じです。異なるところと言えば、頂点が2つに増えました。それに伴い、D3D11_BUFFER_DESC構造体のメンバByteWidthの値や、Draw関数の最初の引数も1から2へ増えました。また、描画の種類を指定する定数もD3D11_PRIMITIVE_TOPOLOGY_LINELISTへ変わっています。本ページでは、シェーダをメインに説明を行いたいと思います。

 パイプラインの構築を終えて、データがパイプラインを流れ始めると、各シェーダステージ内でデータが加工されます。どのように加工するのかは、プログラマが定義します。シェーダの定義にはシェーディング言語であるHLSLを使って、C言語の関数のような形式で記述されます。どこで定義をして、どうやって利用するのかについてはいくつか方法があります。ここでは、シェーダを記述する専用のファイルを用意し、プログラム実行時にシェーダファイルをコンパイルして利用するようにします。それでは、シェーダを利用するために、

 ・メインのソースコードでどのような設定を行い
 ・どうやってシェーダに定数の値を送り
 ・シェーディング言語をどのように記述しなければいけないのか

以上の3点について見ていきたいと思います。

​コード解説

① シェーダのコンパイル時設定
 ここでは実行時にコンパイルが出来るよう、予めシェーダの内容との関連付けを行っています。今回シェーダの記述は一つのファイルで行っていますが、コンパイル設定はシェーダ毎に必要なので、頂点シェーダ、ピクセルシェーダそれぞれに対して行います。

3、4行目で頂点シェーダ、5、6行目でピクセルシェーダについてのそれぞれ設定とシェーダの作成を行っています。3行目と5行目のD3DCompileFromFile関数で設定を行います。特にD3DCompileFromFile関数の引数は、

  第1引数:シェーダが記述されたファイル名

  第4引数:シェーダのエントリポイント名(シェーダが記述されたファイル内のVSやPSのこと)

  第5引数:シェーダのバージョン

となっています。

② シェーダへのデータ転送
 DirectX描画のためのメインループ内では、絶えず線が回転するための行列が生成され、その行列が生成されるとシェーダに送られるという処理が行われています。

シェーダに値を送るためには、1行目から3行目のように、まず​送りたい値を一まとめにした構造体を定義します。ここでは、座標変換で使う行列ひとつだけです。定義した構造体を使って、6行目のように送りたい値の代入を行います。その下3行で実際に値を送る作業をしています。

  7行目:GPUからのアクセスを禁止して、値の送り先のアドレスを取得

  8行目:7行目で取得したアドレスへ値をコピーすることで送る

​  9行目:禁止していたGPUからのアクセスを解除する

このようにCPUから値を送るという作業があるため、ここで使われている定数バッファの定義時に、メンバのCPUAccessFlagsのフラグに対しては、D3D11_CPU_ACCESS_WRITEというフラグの設定を行いました。

③ シェーダの記述
 シェーダの中身を実際に記述します。シェーダを記述するファイル名は、D3DCompileFromFile関数で指定された名前と同じでなくてはいけません(ここのサンプルではshader.hlsl)。

内容を具体的に見ていきます。

  1行目 ~  3行目 : 定数バッファ(CPU側から受け取る値の変数一覧)

  5行目 ~  7行目 : 頂点シェーダの定義

  9行目 ~ 11行目 : ピクセルシェーダの定義

 

2行目の変数は行列を扱うものです。ただし、この変数に入る数値は、②の所で説明したDirectX描画のためのメインループ内で生成され送られる値、線が回転するための行列の値です。そのため、シェーダ内でこのgWVPへ何か値を勝手に代入することはできません。シェーダ内では定数の振る舞いをします。

 

5行目、9行目では頂点シェーダ、ピクセルシェーダをそれぞれ、VS、PSという名前で定義しています。見た目はC言語での関数定義に似ています。違いといえば「:」が付いていることです。「:」は使用する変数の意味を明示したい時に使用するものです(「:」以降に続く文字列はセマンティクスと呼ばれています)。シェーダ側に送られてくる引数の値は、プログラマが決めたものです。特にそれが複数存在する場合は、どの引数で何の値を受け取れば良いのかわかりません。そのため、5行目と所では、「pos」は「POSITION」、即ち頂点情報を受け取るためのも、ということを示しています。また、5行目のVSの定義そのものに対しても「:SV_POSITION」が書かれています。これにも、VSの返す値は頂点情報ですよ、という意味があります。

中身を見てみると、それぞれreturn文1つしかありません。頂点シェーダでは、送られてきた頂点データ「pos」と変換行列「gWVP」の値を掛け算し、得られた新しい頂点座標を返しています。ピクセルシェーダでは、描画される直線の色を直接返しています。float4(R, G, B, A)という順番で、それぞれの値は0.0から1.0の間で指定します。ここの数値を変えると、直線の色も変わります。

サンプル​コード

< 動作確認環境 >
 ・Windows10 Pro
 ・Visual Studio Community 2017


基本的には空のプロジェクトを作ってもらい、以下のソースコードをコピペするだけでうまく実行できるかと思います。もしうまくいかない場合がありましたら、サンプルコードの実行に関する注意事項を一度参照してみてください。

​ソースコード

シェーダのソースコード (shader.hlsl ※必ずこの名前で保存してください)