ハードウェア シェーディング ノード プラグインを実装する

Maya の他の部分との統合

MPxHwShaderNode クラスを使用すると、ハードウェア シェーディング ノード プラグインを Maya の他の部分と統合できます。

ソフトウェア レンダーとシェーダ スウォッチ(Shader Swatch)

アトリビュート エディタ(Attribute Editor)でソフトウェア レンダーとシェーダ スウォッチ(Shader Swatch)の適切な出力が生成されるように、ハードウェア シェーディング ノード プラグインを実行することができます。この機能では、outColor アトリビュートに作用する compute() を使用します。この方法を使うと、ソフトウェア レンダーとシェーダ スウォッチは、既定の黒ではなくなります。

また、ハードウェア シェーディング ノード プラグインで特定の仮想メソッドを実行して、シェーダ スウォッチ(Shader Swatch)だけを描画することもできます。このメソッドを次に示します。

virtual MStatus renderSwatchImage( MImage & image );

この機能では、次のスウォッチ分類文字列が必要です。

const MString UserClassify( "shader/surface/utility/:swatch/"+swatchName );

文字列指定は、プラグインが MFnPlugin::registerNode() をコールするときに Maya に渡されます。

UV テクスチャ エディタ(UV Texture Editor)

MPxHwShaderNode には、ハードウェア シェーディング ノード プラグインを UV テクスチャ エディタ(UV Texture Editor)に統合するのに役立つメソッドがあります。これらのメソッドは、次のとおりです。

virtual MStatus getAvailableImages( const MString& uvSetName, MStringArray& imageNames);
virtual MStatus renderImage( const MString& imageName, const float region[2][2], int& imageWidth, int& imageHeight);

最初のメソッド getAvailableImages() は、UV テクスチャ エディタ(UV Texture Editor)で利用できるようになる UV チャネルのリストを提供します。2 番目のメソッド renderImage() は、UV テクスチャ エディタ(UV Texture Editor)でチャネルを選択するときにコールされます。その後、このルーチンが必要に応じてイメージを描画します。

ハードウェア シェーディング ノード プラグインが標準的な Maya のテクスチャを使用する場合、これらの仮想メソッドを使用する必要はありません。標準的な Maya のテクスチャは、テクスチャ エディタ(Texture Editor)で利用できます。

ハイパーシェード(Hypershade)ウィンドウのアイコン

ハードウェア シェーディング ノード プラグインのアイコンを指定して、ハイパーシェード(Hypershade)ウィンドウに表示できます。アイコンを指定しない場合、既定のブランク アイコンが表示されます。ハードウェア シェーディング ノード プラグインのアイコンを指定するには、次の操作を実行します。

  • render_nodeName.xpm という名前の xpm アイコン ファイルを作成します。たとえば、render_hwPhongShader.xpm といったファイル名を使用します。
  • アイコンを環境変数 XBMLANGPATH で定義された場所(パス)に配置します (あるいは、アイコンを発見できるように XBMLANGPATH を修正します)。

ドラッグ & ドロップ動作

MPxDragAndDropBehavior クラスを使用すると、ハードウェア シェード ノード上でドラッグ & ドロップ動作を実装できます。MPxDragAndDropBehavior クラスは、ハイパーシェード(Hypershade) メニューでノードのドラッグ & ドロップをサポートする多数の仮想メソッドを提供しています。ドラッグ & ドロップ動作を実装する方法については、hwPhongShaderBehavior.cpp のサンプルを参照してください。

ビューポートでのシェーディング

ハードウェア シェーダ プラグイン ノードは、内部の Lambert シェーダから派生したノード上に存在する hardwareShader アトリビュートに接続できます。これにより、ノードが Maya のハードウェア レンダリングだけに影響するようにできます。ビューポート 2.0 統合では、代わりに、特定のプラグイン ノードのシェーダ フラグメントを書くことができます。

hardwareShader アトリビュートの詳細については、「テクニカル ドキュメント」セクション、「ノード」セクション、Lambert ノード ドキュメントを参照してください。

旧式の既定ビューポートのリファレンス情報

このセクションには、旧式の既定ビューポートでレンダリングする際のハードウェア シェーダのリファレンス情報が含まれています。現在は、ビューポート 2.0 で使用するシェーダを作成することをお勧めします。「Maya ビューポート 2.0 API ガイド」を参照してください。

MPxHwShaderNode には、レンダラのハードウェア シェーディング ノード プラグインに使用できる 2 つのインタフェースが存在します。これらのインタフェースのパラメータは似ていますが、コールする方法がまったく異なっています。

bind/geometry/unbind インタフェース

bind()geometry()unbind() メソッドを使用すると、Maya シーン ビューでハードウェア シェーディング ノード プラグインによるレンダーが可能になります。これら 3 つのメソッドの目的は、次のとおりです。

  • バインド(bind)は OpenGL の状態とリソースを設定する場合に使用します。
  • ジオメトリ(geometry)はシェーダ エフェクトをレンダーする場合に使用します。
  • バインド解除(unbind)は OpenGL の状態を復元し、リソースをクリーンアップする場合に使用します。

このモードでサポートされるのはメッシュ(Mesh)シェイプだけです。描画する場合には、次の手順を使用します。

  • Maya が DAG (Directed Acyclic Graph)ノードにアクセスして、描画要求を収集します。
  • 描画要求が不透明待ち行列と透明待ち行列にソートされます。
  • Maya がソートを行わずに不透明オブジェクトの描画を実行します。
  • Maya 深度が透明待ち行列をソートして、透明オブジェクトの描画を実行します。

Maya の描画情報要求に対する反応は、次のとおりです。

  • メッシュ シェイプ ノードが描画要求を受け取ります。
  • マテリアルがハードウェア シェーダであるかどうかをシェイプ ノードが確認します。
  • マテリアルがハードウェア シェーディング ノード プラグインである場合、ジオメトリがバンドルされて、ノードの仮想メソッドに渡されます。
  • ハードウェア シェーディング ノード プラグインは、渡された情報を使用して画面にレンダーする方法を決定します。

インタフェースの仮想メソッドがコールされる順序は、次のとおりです。

for every shape
    bind(...)
    geometry(...)
    unbind(...)

このコール パターンにより、OpenGL の状態は bind() メソッドで設定、geometry() コールで使用、unbind() で復元されます。

M3dView パラメータは、このインタフェースのメソッドに渡されます。このパラメータは、描画に使用されるグラフィックス コンテキストを設定する場合に必ず使用します。仮想メソッドの機能は、beginGL() メソッド コールと endGL() メソッド コールを使用して、このインタフェースにまとめる必要があります。例:

MStatus hwShader::bind( const MDrawRequest& request, M3dView& view )
{
    view.beginGL();
    // Operations ...
    
    view.endGL();
}

これらのメソッドをコールしなければ、プログラムが正常に動作しない可能性があります。

glBind/glGeometry/glUnbind インタフェース

glBind()glGeometry()glUnbind()メソッドを使用すると、Maya シーン ビューでハードウェア シェーディング ノード プラグインによるレンダーが可能になります。これら 3 つのメソッドの目的は、次のとおりです。

  • glBind はプラグインの状態とリソースを設定する場合に使用します。
  • glGeometry は OpenGL の状態の設定、シェーダ エフェクトのレンダー、OpenGL の状態の復元を行う場合に使用します。
  • glUnbind はプラグインの状態とリソースを復元する場合に使用します。

このインタフェースでの仮想メソッドのコール順序は次のとおりです。

for every pass // a refresh may have more than one pass
{
    for every object
    {
        if glBind() has not been called for this refresh
            glBind(...)
        glGeometry(...)
    }
}
for every object
    glUnbind(...)

コール順が変更されているため、いくつかの注意点があます。このインタフェースでは、OpenGL の状態は glBind() ではなく glGeometry() で設定する必要があります。現在、glBind() が使用されるのは、リソースを読み込んで、glGeometry() で使用するアトリビュートを処理する場合だけです。

前のインタフェースと異なり、グラフィックス コンテキストは設定済みのため、beginGL() または endGL() をコールする必要はありません。

geometry/glGeometry に渡される情報の制御

geometry() メソッドと glGeometry() メソッドは、大きなパラメータ リストを持っています。これには、シェーダが現在のジオメトリをレンダーするのに必要な必須データとオプション データ(頂点とフェースのデータ)が含まれています。次のメソッドは、シェーダに渡すオプション データを制御します。

virtual int normalsPerVertex();
virtual int colorsPerVertex();
virtual int getColorSetNames(MStringArray& names);
virtual int texCoordsPerVertex();
virtual int getTexCoordSetNames(MStringArray& names);
virtual bool provideVertexIDs();

使用できない情報を要求すると、シェーダに NULL が渡されることに注意してください。ハードウェア シェーダ プラグイン ノードは、NULL に対してパラメータ情報をテストして、データが有効であることを確認します。

透明度とハードウェア シェーダ プラグイン ノード

Maya 深度は、シェーダに透明度がある場合に描画情報をソートします。ハードウェア シェーダ プラグイン ノードが透明度をサポートしていない場合、シェーディングを実行するには、次の仮想メソッドを使用して false を返します。

virtual bool 	hasTransparency();

geometry() メソッドと glGeometry() メソッドでのインデックス付けと疎配列

データがこれらのメソッドに渡される際には、インデックス付けの仕組みが使用されます。これらのメソッドは、次のとおりです。

virtual MStatus geometry( const MDrawRequest& request, M3dView& view, int prim, unsigned int writable, int indexCount, const unsigned int * indexArray, int vertexCount, const int * vertexIDs, const float * vertexArray, int normalCount, const float ** normalArrays, int colorCount, const float ** colorArrays, int texCoordCount, const float ** texCoordArrays);
virtual MStatus glGeometry( const MDagPath& shapePath, int glPrim, unsigned int writeMask, int indexCount, const unsigned int* indexArray, int vertexCount, const int * vertexIDs, const float * vertexArray, int normalCount, const float ** normalArrays, int colorCount, const float ** colorArrays, int texCoordCount, const float ** texCoordArrays);

インデックス付けに使用されるパラメータは indexCount で、これには配列 indexArray の長さが含まれます。indexArray に含まれるインデックスは、頂点位置、カラー、法線などの他の配列の対応する要素にアクセスする場合に使用されます。

配列の配列であるジオメトリのメソッドに渡されるパラメータは複数存在します。これらは、ポイントに対するポイントのパラメータです。これらの配列には NULL が含まれていても構いません。いずれかの情報要求メソッドが実際に存在する情報よりも多くの情報を要求すると、NULL が含まれる場合があります。たとえば、getTexCoordSetNames() メソッドが 3 つの UV セットを要求できるときに、1 つ目と 3 つ目の情報しか存在しない場合です。この場合、配列の 2 つ目の位置は NULL になります。そのため、NULL をチェックして、データが有効であることを確認する必要があります。

ブラインド データ

ハードウェア シェーディング ノード プラグインでベイク処理された頂点メッシュのブラインド データを使用するテクニックは、レンダリングに非常に役立ちます。この方法は、両方のジオメトリ メソッドで利用できます。ハードウェア シェーディング ノード プラグインでは、provideVertexIDs() を使用して true を返す必要があります。この処理を実行すると、vertexIDs 配列に要求された情報が格納され、vertexCount に配列の長さが格納されます。MDrawRequest を使用する場合、次の方法を使用してメッシュにアクセスします。

request.multiPath().node();

インタフェースの gl バージョンを使用する場合、メッシュは shapePath パラメータで使用できます。シェイプと頂点の ID を併用すると、MFnMesh クラスを通じて頂点のブラインド データにアクセスできます。