このトピックでは、ファイル テクスチャ ノードの既存のカラー管理プロパティにアクセスし、これらをカスタム シェーダの入力として使用して、ファイル テクスチャ ノードに関連付けられたテクスチャをレンダリングできるようにする方法について説明します。
注: このトピックの内容は Maya 2016 Extension 2 にも適用可能ですが、次の修正がまだ行われていないことにご注意ください。
- MShaderInstance::createShaderInstanceWithColorManagementFragment() で、プレまたはポスト レンダー コールバックが失われなくなりました。
- MShaderManager::k3dSolidTextureShader には exposure および alphaAsLuminance パラメータが含まれています。
プラグイン ノード P で、テクスチャ モード レンダー項目(MRenderItem)を作成するとします。この項目を作成できるのは、ジオメトリまたはサブシーン オーバーライド(MPxGeometryOverride または MPxSubSceneOverride)に対してです。このレンダー項目のシェーダ インスタンスは、露光および入力カラー トランスフォームのプロパティをサポートします。
既定では、MShaderManager 経由で取得されたシェーダは、カラー トランスフォームをサポートしません。カラー トランスフォームは、ユーザ プリファレンスのカラー管理設定(プリファレンス(Preferences)ウィンドウ)とファイル テクスチャ ノードに基づいて動的に作成されます。
この問題を回避するには、まず、カラー管理をサポートしないシェーダ インスタンスを作成してから、サポートを動的に追加します。便宜上、フラグメント mayaTextureShader は開始フラグメントとして使用できるようになっています。このフラグメントをフラグメント グラフの一部として使用し、新しいシェーダ インスタンスを作成することができます。また、MShaderManager::k3dSolidTextureShader を目的のシェーダとして指定して、このフラグメントのみを使用する新しいストック シェーダを取得することもできます。
カラー管理をサポートしないシェーダ インスタンスを使用して、カラー トランスフォームをサポートする新しいシェーダ インスタンスを返すことができます。そのためには次のメソッドを呼び出します。**
MShaderInstance:createShaderInstanceWithColorManagementFragment(<colorSpace>)
このメソッドを使用するための要件は、入力カラー スペース
現在の入力カラー スペースを特定するには、ファイル テクスチャ ノードのアトリビュートを照会します。目的のアトリビュートは作業スペース(「workingSpace」)および入力カラー スペース(「colorSpace」)です。 カラー スペースは作業スペースに対して相対的であるため、両方の値を照会して、新しいシェーダ インスタンスの作成タイミングを特定する必要があります。カラー スペース アトリビュートの文字列値は、上記の MShaderInstance:createShaderInstanceWithColorManagementFragment() メソッドと併用できます。 カラー管理が無効になっている可能性があります。この状態をテストするには、ファイル テクスチャ ノードでアトリビュート「colorManagementEnabled」の値を照会します。 サンプルのコード スニペットを以下に示します。このスニペットでは、ファイル テクスチャが「color」アトリビュートを介してプラグイン ノード P に接続されていると想定しています。 ファイル テクスチャ ノードの「exposure」アトリビュートを取得し、上記の内部シェーダ インスタンスの「exposure」パラメータや、プラグインで使用されるカスタム パラメータを設定するために使用することができます。 露光は、カラー管理がグローバルに有効になっているのか、それともファイル ノード上で有効になっているのかに関係なく設定できます。MObject connectedObject = MObject::kNullObj;
// Get connections to “color” attribute on node of interest
//
MPlug plug = P.findPlug("color");
if (!texture)
{
if (!plug.isNull())
{
MPlugArray plugArray;
if (plug.connectedTo(plugArray, true, false) && plugArray.length() == 1)
{
// Check for a file texture node connection
//
const MPlug& connectedPlug = plugArray[0];
connectedObject = connectedPlug.node();
if (connectedObject.hasFn( MFn::kFileTexture))
{
// Get the name of the file texture image and acquire a texture to use
MString fileTextureName;
MRenderUtil::exactFileTextureName(connectedObject, fileTextureName);
if (fileTextureName.length())
{
texture = textureManager->acquireTexture(fileTextureName);
}
// Check if color management is even enabled
MFnDependencyNode fileNode(connectedObject);
MPlug cmEnabledPlug = fileNode.findPlug("colorManagementEnabled");
bool cmEnabled = false;
if (!cmEnabledPlug.isNull())
{
MString workingColorSpace;
MString colorSpace;
cmEnabled = true;
cmEnabledPlug.getValue(cmEnabled);
if (cmEnabled)
{
// Get working space and input color space values.
//
MPlug workingColorSpacePlug = fileNode.findPlug("workingSpace");
workingColorSpacePlug.getValue(workingColorSpace);
MPlug colorSpacePlug = fileNode.findPlug("colorSpace");
colorSpacePlug.getValue(colorSpace);
// If working or input color space changes then
// we need to create a new shader. Previous shader resource
// will be released when a new one is created.
//
// Note that is the shader initially
// created which does not have a CM fragment.
//
// m_texturedColorManagedShader
if (!m_texturedColorManagedShader ||
workingColorSpace != m_workingColorSpace ||
colorSpace != m_inputColorSpace)
{
m_texturedColorManagedShader =
m_texturedShader->createShaderInstanceWithColorManagementFragment(colorSpace);
if (!m_texturedColorManagedShader)
cmEnabled = false;
m_workingColorSpace = workingColorSpace;
m_inputColorSpace = colorSpace;
}
}
}
}
}
}
}