4 Tips

● MMD標準のシェーダを使用する

オブジェクトの描画の一部にのみ、エフェクトを使用し、それ以外の描画にはMMD標準のシェーダを使用したい場合には、MMD標準のシェーダを使用したい場面のテクニックを、エフェクトファイルに記述しなければよい。 (1.2 テクニックのアノテーションを参照)

/* エフェクトファイルにこのテクニックしか無ければ、 オブジェクト描画(セルフシャドウON時)以外はMMD標準のシェーダで描画される */
  technique Tech1 < string MMDPass = "object_ss"; > {
      pass Pass1 {
          ...
      }
      pass Pass2 {
          ...
      }
  }

また、パスのデフォルトのシェーダはMMD標準のシェーダであるため、以下のように、パスのVertexShaderやPixelShaderを設定しなければ、そのパスの描画にはMMD標準のシェーダが使用される。

technique Tech1 < string MMDPass = "object_ss"; > {
    pass Pass1 {
      // VertexShader = xxx
      // PixelShader  = xxx
    }
}

● 空のテクニック

以下のように、テクニックを空にすると、そのテクニックでは一切描画が行われなくなる。これを利用すると、オブジェクトの一部または全部の描画を抑止することができる。

      technique ShadowTech < string MMDPass = "shadow"; > {
         
      }

● オブジェクトの有無でパスをON/OFF

以下のようにスクリプトを記述すると、特定のオブジェクトの表示がONになっている間のみパスを実行させることができる。これは、真偽値true/falseが数値としては1と0に解釈されることを利用している。

      bool flag : CONTROLOBJECT < string name = "aaa.x"; >;
    
      technique Tech1 <
          string Script =
              "LoopByCount=flag;"
              "Pass=Pass1;"
              "LoopEnd=;"
               ; 
      > {
          pass Pass1 {
              ...
          }
      }

● エフェクトファイル間でパラメータを共有

通常、異なるエフェクトファイル間でパラメータは共有されない。しかし、パラメータの宣言に"shared"キーワードを指定することにより、同じ名前のパラメータをエフェクトファイル間で共有することができる。

以下の例では、effect1.fxで生成したテクスチャを、effect2.fxから参照できる。このように、両方のパラメータ宣言で"shared"キーワードを指定する必要がある。また、名前だけでなく、型名とセマンティクスも一致させる必要がある。

/************** effect1.fx ******************/
shared texture ShadowBuffer : RENDERCOLORTARGET &
    float2 ViewPortRatio = {2.0,2.0};
    int MipLevels = 1;
    string Format = "A8R8G8B8" ;
>;
/********************************************/
/************** effect2.fx ******************/
shared texture ShadowBuffer : RENDERCOLORTARGET;
/********************************************/

● if文

描画を高速にしたければ、シェーダを記述する際に、できるだけif文のような条件分岐は使わないほうがよい。

テクスチャの有無でシェーダの処理を切り替えるような場合、use_textureパラメータを参照して、シェーダ内のif文で条件分岐するより、テクスチャが有るサブセットと無いサブセットとで、テクニック自体を分けてしまうほうが高速に描画できる。

● uniformキーワード

関数の引数の宣言に"uniform"キーワードを指定すると、その引数の値をコンパイル時の定数として与えることができる。

以下の例では、Basic_PS()内のif文が、コンパイル時に除去されるので、条件分岐による速度低下は避けられる(多分)。

float4 Basic_PS( VS_OUTPUT IN, uniform bool useTexture ) : COLOR0
{
    float4 Color = IN.Diffuse;
    if ( useTexture ) {
        Color *= tex2D( ObjTexSampler, IN.Tex );
    }
    ...
}

technique TechWithTex {
    pass P1 {
        /* useTexture=true でシェーダをコンパイル */
        PixelShader  = compile ps_2_0 Basic_PS(true);  
        ...
    }
}

technique TechWithoutTex {
    pass P1 {
        /* useTexture=false でシェーダをコンパイル */
        PixelShader  = compile ps_2_0 Basic_PS(false);
        ...
    }
}

● エフェクトファイル内での日本語使用

基本的に、コメント部分以外では、エフェクトファイル中に日本語の文字を使用することは推奨しない。

あえて使用する場合は、文字コードに注意すること。テクスチャ生成用の画像ファイルのパスやコントロールオブジェクトのオブジェクト名など、ファイル名の指定に日本語を使用する場合は、そのエフェクトファイルの文字コードは必ずShift-JISでなければならない。

● ポストエフェクト

ポストエフェクト用のエフェクトファイルを作成する場合は、以下のパラメータがエフェクトファイル中で宣言されている必要がある。(2.8 エフェクトファイル STANDARDSGLOBALを参照)

float Script : STANDARDSGLOBAL &
    string ScriptOutput = "color";
    string ScriptClass = "scene";
    string ScriptOrder = "postprocess";
> = 0.8;

また、典型的なポストエフェクトでは、テクニックのスクリプトで以下の処理を行う。

(1) レンダリングターゲットを自前のテクスチャに変更し、クリアする。

スクリプト例:
"RenderColorTarget0=(RENDERCOLORTARGETテクスチャ);"
"RenderDepthStencilTarget=(RENDERDEPTHSTENCILTARGETテクスチャ);"
"ClearSetColor=(クリアの色);"
"ClearSetDepth=(クリアのZ値);"
"Clear=Color;"
"Clear=Depth;"
 

(2) プリエフェクト,オブジェクト,他のポストエフェクトを描画する。このとき、描画結果は(1)で指定したテクスチャに保存される。

スクリプト例:

"ScriptExternal=Color;"

(3) レンダリングターゲットを元に戻し、描画結果のテクスチャを入力として、パスを実行する。

スクリプト例:

"RenderColorTarget0=;"
"RenderDepthStencilTarget=;"
"Pass=(パス1);"
"Pass=(パス2);"