シェーディング・ノード・プラグイン

シェーディング・ノード・プラグインとは

シェーディング・ノード・プラグインによって、Maya のシェーディング・ノードを作成することができます。

シェーディング・ノード・プラグインに必要なクラス・関数

ノードを作成するためのクラス
クラス名は自由ですが、maya.OpenMayaMPx.MPxNode を継承する必要があります。
クラス内には以下の関数が必要です。
__init__(self)
クラスの初期化関数では、 最低限 maya.OpenMayaMPx.MPxNode.__init__() を実行します。
compute(self, plug, dataBlock)
ノードが実行する処理を記述します。
nodeCreator()
クラスのインスタンスを作成する関数です。
nodeInitializer()
ノードのアトリビュートを初期化する関数です。
initializePlugin(mobject)
プラグインがロードされるときに実行されます。
ノードの登録などを行います。
uninitializePlugin(mobject)
プラグインがアンロードされるときに実行されます。
ノードの登録取り消しなどを行います。

ダイナミックシェーディングアトリビュート

以下のアトリビュート名は、シェーダ用に予約されているダイナミックアトリビュート(<レンダリングアトリビュート)の名前です。
これらの名前をアトリビュート名として使用すると、特別な意味になります。
blobbySurfaceFactor , displacement , easMask , farPointCamera , farPointObj , farPointWorld , filterSize , flippedNormal , illuminationIndex , infoBits , lightData , lightTable , matrixObjectToWorld , matrixWorldToObject , mediumRefractiveIndex , normalCamera , numShadingSamples , objectId , objectType , opticalDepth , outColor , outGlowColor , outMatteOpacity , outParticleEmission , outTransparency , particleAge , particleAttrArray , particleColor , particleEmission , particleEntryParam , particleExitParam , particleIncandescence , particleLifespan , particleOrder , particleTransparency , particleWeight , pixelCenter , pixelCoverage , pointCamera , pointObj , pointWorld , primitiveId , rayDepth , rayDirection , rayOrigin , receiveShadows , refPointCamera , refPointObj , refPointWorld , renderState , shadowAttenuation , tangentUCamera , tangentVCamera , translucenceDepth , triangleNormalCamera , uvCoord , uvFilterSize , vertexCameraOne , vertexCameraThree , vertexCameraTwo , vertexUvOne , vertexUvThree , vertexUvTwo

シェーディング・ノード・プラグインの例

オブジェクトのノーマルベクトルの X 成分が 0 のときに黒、0 以上のときは指定した色になるシェーダを作成してみましょう。

  1. 以下の Python スクリプトを myShader1.py という名前で作ります。
    import sys
    import maya.OpenMaya
    import maya.OpenMayaMPx
    
    kPluginNodeName = 'myShader1'
    kPluginNodeId = maya.OpenMaya.MTypeId(0x87004)
    
    class myShader1(maya.OpenMayaMPx.MPxNode):
        aInColor = maya.OpenMaya.MObject()
        aNormalCamera = maya.OpenMaya.MObject()
        aOutColor = maya.OpenMaya.MObject()
        def __init__(self):
            maya.OpenMayaMPx.MPxNode.__init__(self)
    
        def compute(self, plug, block):
            if plug == myShader1.aOutColor or plug.parent() == myShader1.aOutColor:
                resultColor = maya.OpenMaya.MFloatVector(0.0, 0.0, 0.0)
                
                inColor = block.inputValue(myShader1.aInColor).asFloatVector()
                normalCamera = block.inputValue(myShader1.aNormalCamera).asFloatVector()
                if normalCamera.x >= 0:
                    resultColor.x = inColor.x
                    resultColor.y = inColor.y
                    resultColor.z = inColor.z
    
                outColorHandle = block.outputValue(myShader1.aOutColor)
                outColorHandle.setMFloatVector(resultColor)
                outColorHandle.setClean()
            else:
                return maya.OpenMaya.kUnknownParameter
    
    
    def nodeCreator():
        return maya.OpenMayaMPx.asMPxPtr(myShader1())
    
    def nodeInitializer():
        nAttr = maya.OpenMaya.MFnNumericAttribute()
    
        myShader1.aNormalCamera = nAttr.createPoint('normalCamera', 'n')
        nAttr.setKeyable(True) 
        nAttr.setStorable(True)
        nAttr.setReadable(True)
        nAttr.setWritable(True)
        nAttr.setDefault(1.0, 1.0, 1.0)
    
        myShader1.aInColor = nAttr.createColor('inColor', 'ic')
        nAttr.setStorable(True)
        nAttr.setReadable(True)
        nAttr.setWritable(True)
        nAttr.setDefault(1.0, 1.0, 1.0)
    
        myShader1.aOutColor = nAttr.createColor('outColor', 'oc')
        nAttr.setStorable(False)
        nAttr.setHidden(False)
        nAttr.setReadable(True)
        nAttr.setWritable(False)
    
        myShader1.addAttribute(myShader1.aInColor)
        myShader1.addAttribute(myShader1.aNormalCamera)
        myShader1.addAttribute(myShader1.aOutColor)
    
        myShader1.attributeAffects (myShader1.aInColor, myShader1.aOutColor)
        myShader1.attributeAffects (myShader1.aNormalCamera, myShader1.aOutColor)
    
    
    def initializePlugin(mobject):
        mplugin = maya.OpenMayaMPx.MFnPlugin(mobject)
        try:
            mplugin.registerNode( kPluginNodeName, kPluginNodeId, nodeCreator, 
                        nodeInitializer, maya.OpenMayaMPx.MPxNode.kDependNode, 'utility/color' )
        except:
            sys.stderr.write( 'Failed to register node: %s' % kPluginNodeName )
            raise
    
    def uninitializePlugin(mobject):
        mplugin = maya.OpenMayaMPx.MFnPlugin(mobject)
        try:
            mplugin.deregisterNode( kPluginNodeId )
        except:
            sys.stderr.write( 'Failed to deregister node: %s' % kPluginNodeName )
            raise
    
    
  2. myShader1.py をロードします。
    以下のどちらかの方法でロードします。
  3. スクリプト エディタ のインプットウインドウの Python タブで以下のように実行してみます。
    import maya.cmds
    sn = maya.cmds.createNode('myShader1')
    maya.cmds.connectAttr(sn + '.oc', 'lambert1.color', f=True)
  4. lambert1 マテリアルのアサインされた NURBS の球体を作成してみると、 ノーマルベクトルの X 成分が 0 以下の部分は黒になっているのがわかります。

スクリプトの解説

import sys
sys モジュールをインポートします。
エラーの表示をするために必要です。
import maya.OpenMaya
maya.OpenMaya モジュールをインポートします。
import maya.OpenMayaMPx
maya.OpenMayaMPx モジュールをインポートします。
kPluginNodeName = 'myShader1'
このプラグインの名前を myShader1 として、変数 kPluginNodeName に代入します。
kPluginNodeId = maya.OpenMaya.MTypeId(0x87004)
プラグインごとにユニークな識別番号を決めます。
プラグインは、この番号によって Maya の中で登録・識別・登録取り消しなどが行われます。
ローカルだけで使用する場合などは0x00000000以上、0x0007ffff以下の番号を、 プラグインを公表する場合は Autodesk からユニークな番号を取得します。
class myShader1(maya.OpenMayaMPx.MPxNode):
maya.OpenMayaMPx.MPxNode を継承して、 シェーディングノード作成のためのクラスを定義します。
aInColor = maya.OpenMaya.MObject()
色を表す入力データのために、 MObject インスタンスを作成して、クラス変数 aInColor に代入します。
aNormalCamera = maya.OpenMaya.MObject()
ノーマルベクトルを表す入力データのために、 MObject インスタンスを作成して、クラス変数 aNormalCamera に代入します。
aOutColor = maya.OpenMaya.MObject()
色を表す出力データのために、 MObject インスタンスを作成して、クラス変数 aOutColor に代入します。
def __init__(self):
クラス myShader1 のインスタンス作成時に実行される初期化関数を定義します。
maya.OpenMayaMPx.MPxNode.__init__(self)
myShader1 クラスを初期化するために、 親クラス MPxNode の __init__() を実行します。
def compute(self, plug, block):
シェーディングノードが実行する処理を記述しておく関数です。
引数の意味は以下のとおりです。
plug
他のノードにコネクトされているプラグを表します。
dataBlock
このノードに関するデータを保存しているオブジェクトです。
if plug == myShader1.aOutColor or plug.parent() == myShader1.aOutColor:
プラグまたは、プラグの親クラスが出力 aOutColor かどうか調べます。
resultColor = maya.OpenMaya.MFloatVector(0.0, 0.0, 0.0)
3 つの float をもつ MFloatVector を、 初期値 (0.0, 0.0, 0.0) で作成し、内部変数 resultColor に代入します。
resultColor にこのノードから出力される結果の数値が入ります。
inColor = block.inputValue(myShader1.aInColor).asFloatVector()
データブロックから、入力データ aInColor のデータハンドルを得て、 asFloatVector() によって float の数値に変換し inColor に代入します。
normalCamera = block.inputValue(myShader1.aNormalCamera).asFloatVector()
データブロックから、入力データ aNormalCamera のデータハンドルを得て、 asFloatVector() によって float の数値に変換し normalCamera に代入します。
if normalCamera.x >= 0:
  resultColor.x = inColor.x
  resultColor.y = inColor.y
  resultColor.z = inColor.z
normalCamera の X 成分が 0 以上のときに、 入力の色と出力の色を同じにします。
outColorHandle = block.outputValue(myShader1.aOutColor)
データブロックから出力データ output のデータハンドルを得て、 outColorHandle に代入します。
outColorHandle.setMFloatVector(resultColor)
出力データのデータハンドルに出力データ resultColor を floatVector のデータとして与えます。 (floatVector は float が 3 つ並んだ型です)
outColorHandle.setClean()
プラグをクリーンにします。 これをしないとノードの計算が終わっているとみなされません。
else:
  return maya.OpenMaya.kUnknownParameter
プラグが aOutColor 以外の場合は、kUnknownParameter を返して Maya に処理を任せます。
計算する必要の無いプラグは、kUnknownParameter を返しておきます。
def nodeCreator():
Maya がノードのインスタンスを作成するための関数です。
  return maya.OpenMayaMPx.asMPxPtr(myShader1())
myShader1 クラスのインスタンスを作成し、asMPxPtr() 関数に与えます。
asMPxPtr() 関数を使わないとインスタンスが Maya に渡すことができません。
def nodeInitializer():
ノードの初期化関数です。
nAttr = maya.OpenMaya.MFnNumericAttribute()
MFnNumericAttribute のインスタンスを作成します。
myShader1.aNormalCamera = nAttr.createPoint('normalCamera', 'n')
normalCamera アトリビュートを作成し、短縮名は n 、型は Point にします。
normalCamera アトリビュートはダイナミックシェーダアトリビュートなので、 このアトリビュートを定義することによって、 オブジェクトの表面のノーマルベクトルを得ることができます。
nAttr.setKeyable(True)
normalCamera アトリビュートにアニメーションキーを設定可能にします。
nAttr.setStorable(True)
シーンの保存時に normalCamera アトリビュートの値を保存する設定です。
nAttr.setReadable(True)
normalCamera アトリビュートの値を読み取り可能にします。
nAttr.setWritable(True)
normalCamera アトリビュートの値を書き込み可能にします。
nAttr.setDefault(1.0, 1.0, 1.0)
normalCamera アトリビュートのデフォールト値を (1.0, 1.0, 1.0) にします。
myShader1.aInColor = nAttr.createColor('inColor', 'ic')
inColor アトリビュートを作成し、短縮名は ic 、型は Color にします。
nAttr.setStorable(True)
シーンの保存時に inColor アトリビュートの値を保存する設定です。
nAttr.setReadable(True)
inColor アトリビュートの値を読み取り可能にします。
nAttr.setWritable(True)
inColor アトリビュートの値を書き込み可能にします。
nAttr.setDefault(1.0, 1.0, 1.0)
inColor アトリビュートのデフォールト値を (1.0, 1.0, 1.0) にします。
myShader1.aOutColor = nAttr.createColor('outColor', 'oc')
outColor アトリビュートを作成し、短縮名は oc 、型は Color にします。
nAttr.setStorable(False)
シーンの保存時に outColor アトリビュートの値を保存しない設定です。
nAttr.setHidden(False)
outColor アトリビュートを GUI で操作できるようにする設定です。
nAttr.setReadable(True)
inColor アトリビュートの値を読み取り可能にします。
nAttr.setWritable(False)
inColor アトリビュートの値を書き込み不可にします。
myShader1.addAttribute(myShader1.aInColor)
inColor アトリビュートを myShader1 ノードのアトリビュートとして設定します。
myShader1.addAttribute(myShader1.aNormalCamera)
normalCamera アトリビュートを myShader1 ノードのアトリビュートとして設定します。
myShader1.addAttribute(myShader1.aOutColor)
outColor アトリビュートを myShader1 ノードのアトリビュートとして設定します。
myShader1.attributeAffects (myShader1.aInColor, myShader1.aOutColor)
inColor アトリビュートが変化したとき、 プラグを aOutColor として myShader1 の compute メソッドを実行するように設定します。
myShader1.attributeAffects (myShader1.aNormalCamera, myShader1.aOutColor)
normalCamera アトリビュートが変化したとき、 プラグを aOutColor として myShader1 の compute メソッドを実行するように設定します。
def initializePlugin(mobject):
プラグインがロードされたときに実行される初期化関数です。
mplugin = maya.OpenMayaMPx.MFnPlugin(mobject)
MFnPlugin クラスのインスタンスを作成します。
mobject は MObject のインスタンスです。
try:
  mplugin.registerNode( kPluginNodeName, kPluginNodeId, nodeCreator,
    nodeInitializer, maya.OpenMayaMPx.MPxNode.kDependNode, 'utility/color' )
except:
  sys.stderr.write( 'Failed to register node: %s' % kPluginNodeName )
  raise
MFnPlugin のインスタンスに、myShader1 に関する設定を与えています。
もし設定に失敗した場合は、メッセージを出力して例外を送出します。
引数の最後の 2 つは以下のような意味です。
maya.OpenMayaMPx.MPxNode.kDependNode
ノードのタイプを表します。
'utility/color'
シェーダノードの種類を詳しく説明した文字列です。
GUI の表示などで利用されます。
def uninitializePlugin(mobject):
プラグインをアンロードするときに実行される関数です。
mplugin = maya.OpenMayaMPx.MFnPlugin(mobject),,
MFnPlugin クラスのインスタンスを作成します。
mobject は MObject のインスタンスです。
try:
  mplugin.deregisterNode( kPluginNodeId )
except:
  sys.stderr.write( 'Failed to deregister node: %s' % kPluginNodeName )
  raise
プラグインをアンロードします。
もしアンロードに失敗した場合は、メッセージを出力して例外を送出します。

練習

  1. 上の myShader1.py を参考にして myShader2.py という Python スクリプトを作ってください。
    myShader2.py は、以下の図のように白黒の縞模様がつくシェーダープラグインにしてください。
    (実行例)
    作成した myShader2.py を、プラグインとしてロードして以下の Python 関数を実行します。
    import maya.cmds
    sn = maya.cmds.createNode('myShader2')
    maya.cmds.connectAttr(sn + '.oc', 'lambert1.color', f=True)
    この lambert1 をアサインしたオブジェクトは、以下のようなテクスチャーがつきます。

    (ヒント)
    このような縞模様がつくようにするためには、UV 座標を調べて色をつけてゆきます。
    たとえば、U の値を 0.05 きざみで色を変えてゆきます。 UV 座標を調べるには、uvCoord という名前のダイナミックアトリビュートを使用します。

参考


Prev | Next
Home | Contents
Mail