SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

MikuMikuEffectで学ぶHLSL入門

3DCGツール「MikuMikuDance」のエフェクトを拡張する「MikuMikuEffect」
はじめてのエフェクト制作

MikuMikuEffectで学ぶHLSL入門(4)

エフェクト編集

 では、早速fxファイルを開いて中を見てみましょう。

頂点シェーダ

構造体の編集

 まずは頂点シェーダからピクセルシェーダにデータを送る構造体に必要な情報を追加します。

//PSへの受け渡し用構造体定義
struct OutVS
{
    float4 Pos           : POSITION;
    //追加
    float3 Normal        : TEXCOORD0;
    float3 Eye           : TEXCOORD1;
    float2 ScreenTex     : TEXCOORD2;
    //
};

 まず「Normal」ですが、これは法線情報を代入する項目です。法線とは、その頂点がどの方向を向いているかを表す数値のことで、X:0,Y:1,Z:0で上方向を向いていることになります。XYZ3方向の数値が必要なのでfloat3型で宣言します。

法線
法線

 次に「Eye」ですが、これは視線のベクトルを代入する項目です。単純にカメラ(視点)座標から頂点座標を引くことで求めることができます。このデータもXYZ3方向の数値が必要なためfloat3で宣言します。

カメラ
カメラ

 最後のScreenTexは、背景を歪ませて表示する際に必要になる「現在の頂点のスクリーン上の座標」を代入する項目です。計算方法については後述します。2D的な位置情報を格納するため、float2型で宣言を行います。

 以上で構造体の編集は終了です。

本体の編集

 それでは頂点シェーダ本体を編集していきます。

//頂点シェーダ本体
OutVS TestShader_VS(float4 Pos : POSITION,float3 Normal : NORMAL)
{
    //構造体宣言
    OutVS Out;
    
    // カメラ視点のワールドビュープロジェクション変換
    Out.Pos     = mul( Pos, WorldViewProjMatrix );
    
    //---追加---//
    
    // 法線をワールド行列で回転
    Out.Normal    = mul( Normal, WorldMatrix );
    // カメラとの相対位置計算
    Out.Eye = CameraPosition - mul( Pos, WorldMatrix );
    // スクリーン座標を計算
    Out.ScreenTex.x = (Out.Pos.x / Out.Pos.w)*0.5f+0.5f;
    Out.ScreenTex.y = (-Out.Pos.y / Out.Pos.w)*0.5f+0.5f;
    
    //----------//
    
    //PSへ渡す
    return Out;
}

 次の部分では、ワールドビュープロジェクション変換(以下WVP変換)を行い、頂点座標を画面の表示位置座標に変換しています。

Out.Pos     = mul( Pos, WorldViewProjMatrix );

法線の計算

 頂点シェーダ宣言時の引数で受け取っている法線情報を使用し、移動、回転、拡大を計算するワールド変換を行ったものを代入しています。

Out.Normal    = mul( Normal, WorldMatrix );

 なお、MMEの仕様としてキャラクター等のモデル(*.pmd)はすでに計算済みの数値が格納されており、ステージや小物等のアクセサリ(*.x)のみ計算の必要がありますが、ここでは両種類に対応するため計算を行っています。

視線ベクトルの計算

 カメラの座標を格納している変数CameraPositionから引数として渡される頂点座標Posを引き、視線ベクトルを計算します。ここでも前述した通り、モデル、アクセサリ両方に対応するためワールド変換を行っています。

Out.Eye = CameraPosition - mul( Pos, WorldMatrix );

スクリーン座標計算

 先ほどワールドビュープロジェクション変換を行った画面の表示位置座標を元に、数値を0~1になるよう調節しています。

// スクリーン座標を計算
 Out.ScreenTex.x = (Out.Pos.x / Out.Pos.w)*0.5f+0.5f;
 Out.ScreenTex.y = (-Out.Pos.y / Out.Pos.w)*0.5f+0.5f;
ScrtoTex
ScrtoTex

 次は今回頂点シェーダから送った情報を使い、ピクセルシェーダを書き変えていきます。

コラム:もしエラーが起きたら?

 fxファイルを保存した際に何らかの問題があった場合、下のようなエラーが表示されます。

 

Serror
Serror

 エラーメッセージにはエラーを起こしているシェーダファイル、シェーダ内のエラー箇所、エラー内容が記載されています。

 

 今回の場合54行26列目にエラーがあり、「WorldViewProjMtrixという変数は存在しない」とあります。Matrixと表記するべき箇所をMtrixと書いてしまった単純なスペルミスでしたので正しいスペルに書き変え、保存します。

 

 正常なコードに修正できればエラーが発生しなくなります。

次のページ
ピクセルシェーダ

修正履歴

この記事は参考になりましたか?

MikuMikuEffectで学ぶHLSL入門連載記事一覧

もっと読む

この記事の著者

ビームマンP(ビームマンピー)

ニコニコ動画等でMikuMikuEffect用シェーダプログラム開発者として活動。 開発を始めた理由はカッコいいビームやミサイルが作りたかった為。 エフェクト配布用サイト http://www43.atwiki.jp/beamman/

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/6192 2011/10/19 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー