MPassContext 内の情報は、SSAO (スクリーンスペース アンビエント オクルージョン)をサポートする必要があるパスをレンダリングするためにプラグインが呼び出されているかを示すための十分な情報を提供します。
SSAO の内部アルゴリズムには、中間結果を生成するための特定の法線の深度のパスが必要です。 既定では、レンダラは、このパスに使用される特定のシェーダを設定します。 プラグイン シェーダによってジオメトリがディスプレイスされる、または法線が変更される場合は、この既定値シェーダをオーバーライドすることができます。
この法線の深度パスは、シャドウ マップのパスを検出するのと同様の方法で MPassContext 情報を照会することで検出します(セクション 4.2.1 「 シャドーイング コントロール」を参照)。このパスでは、パス識別子は MPassContext::kNormalDepthPassSemantic となります。
テッセレーション シェーダが必要な場合、オーバーライドを MShaderInstance ではなく MPxShaderOverride に追加する必要があります。
サポートを追加するには、カスタム シェーダは以下の条件を考慮する必要があります。以下に、HLSL で記述された、このパスで使用されるシェーダのサンプルを示します。
// Check if the back-facing normal needs to be flipped. extern bool isSingleSided = false; extern float mayaNormalMultiplier = 1.0f; // Shader semantic supported by Viewport 2.0 to indicate whether // the projection matrix flips the Z component of a point when transformed // -1.0 if so, otherwise 1.0. float gProjZSense : ProjectionZSense; // Vertex shader input structure. struct VS_INPUT_NormalDepth { float3 Pos : POSITION; float3 Normal: NORMAL; }; // Vertex shader output structure. struct VS_TO_PS_NormalDepth { float4 HPos : SV_Position; float4 NormalDepth : TEXCOORD0; }; // Vertex shader. VS_TO_PS_NormalDepth VS_NormalDepth(VS_INPUT_NormalDepth In) { VS_TO_PS_NormalDepth Out; // Transform the vertex from object space to clip space. Out.HPos = mul(float4(In.Pos, 1.0f), gWVPXf); // Record the normal and depth components for the pixel shader. // NOTE: This depends on whether the view direction is along the +Z or -Z axis. // The projection matrix "Z sense" determines this. Out.NormalDepth.xyz = mul(In.Normal, gWVITXf); Out.NormalDepth.z = gProjZSense * Out.NormalDepth.z; Out.NormalDepth.w = gProjZSense * mul(float4(In.Pos, 1.0f), gWVXf).z; return Out; } // Pixel shader output structure. struct PS_OUT { float4 Normal : SV_Target0; float4 Depth : SV_Target1; }; // Pixel shader. PS_OUT PS_NormalDepth(VS_TO_PS_NormalDepth In, bool isFrontFace : SV_IsFrontFace) { PS_OUT Out; float3 normal = normalize(In.NormalDepth.xyz); if ( !isSingleSided ) { float normalMul = isFrontFace ? mayaNormalMultiplier : -mayaNormalMultiplier; normal *= normalMul; } // Set the normal for an unsigned normalized integer target, and depth for a floating-point target. Out.Normal = float4((normal + 1.0f) * 0.5f, 0.0f); Out.Depth = In.NormalDepth.wwww; return Out; }
MPassContext 内の情報は、モーション ブラーをサポートする必要があるパスをレンダリングするためにプラグインが呼び出されているかを示すための十分な情報を提供します。
モーション ブラーの内部アルゴリズムには、中間結果を生成する特定のモーション ベクトル パスが必要です。既定では、レンダラは、このパスに使用される特定のシェーダを設定します。 プラグイン シェーダによってジオメトリがディスプレイスされる場合は、この既定値シェーダをオーバーライドできます。
このモーション ベクトル パスは、MPassContext 情報を照会し、文字列 motionVectorPass または MPassContext::kMotionVectorPassSemantic に一致するパス セマンティックをチェックすることで検出できます。
テッセレーション シェーダが必要な場合、オーバーライドを MShaderInstance ではなく MPxShaderOverride に追加する必要があります。
サポートを追加するには、カスタム シェーダで以下の条件を考慮する必要があります。
以下に、HLSL で記述された、このパスで使用されるシェーダのサンプルを示します。
// Shader semantics supported by Viewport 2.0. extern float4x4 World : world; extern float4x4 previousWorld : previousWorld; extern float4x4 WorldViewProj : worldviewprojection; extern float4x4 viewProjection : viewProjection; extern float4x4 previousViewProjection : previousViewProjection; extern float2 viewportSize : viewportPixelSize; // The uniform variable will be set by Viewport 2.0 with the value of the // hardwareRenderingGlobals.motionBlurShutterOpenFraction attribute, // which denotes the percentage of frame time for which the shutter // is open, with 0 denoting that the shutter is not open at all, and 1 // denoting that the shutter is open for 100% of the frame time. extern float shutterOpenFraction = 0.200000f; // Vertex Shader VS_TO_PS_MotionVector VS_MotionVector(VS_INPUT_MotionVector In ) { VS_TO_PS_MotionVector Out; Out.Pw = mul( float4(In.pm,1), World).xyz; Out.OtherFramePw = mul( float4(In.pm,1), previousWorld).xyz; Out.Pc = mul( float4(In.pm,1), WorldViewProj ); return Out; } // Pixel Shader float4 PS_MotionVector(VS_TO_PS_MotionVector In ) : SV_Target { float k = shutterOpenFraction * 100.0f; float4 Pc = mul( float4(In.Pw, 1.0f), viewProjection ); float4 prevPc = mul( float4(In.OtherFramePw, 1.0f), previousViewProjection ); float2 curUV = Pc.xy / Pc.w; float2 prevUV = prevPc.xy / prevPc.w; float2 vec = (curUV - prevUV) * shutterOpenFraction * 0.5f; vec *= viewportSize; float vecLength = length(vec); vec *= min(k / vecLength, 1.0f); vec /= viewportSize; return float4( vec.x, -vec.y, 1.0f - (Pc.z / Pc.w), vecLength ); }
特定のリリースへのこの実装の XML ラッパーは、MEL コマンドを使用して検索できます。
ogs -xml mayaMotionVector;
API から MFragmentManager:: getFragmentXML() メソッドを使用して、このフラグメントを照会できます。サンプル プラグイン fragmentDumper は、このメソッドを使用してフラグメントをダンプする方法を示します。
dumpFragment -fn mayaMotionVector;
MPassContext 内の情報は、被写界深度(DOF)をサポートする必要があるパスをレンダリングするためにプラグインが呼び出されているかを示すための十分な情報を提供します。
DOF の内部アルゴリズムには、中間結果を生成するための特定のパスが必要です。既定では、レンダラはこのパスに対して、特定のシェーダを設定します。
このパスは、MPassContext 情報を照会し、文字列 dofPass または MPassContext::kDOFPassSemantic に一致するパス セマンティックをチェックすることで検出できます。
プラグイン シェーダによってジオメトリがディスプレイスされる場合は、この既定値シェーダをオーバーライドできます。
このシェーダは、錯乱円(CoC)値とピクセルあたりの深度値を計算する必要があります。これらの値は、カラー ターゲット 0 としてバインドされている、浮動小数点の出力ターゲット(R32G32)の R チャネルと G チャネルに書き込まれます。深度テストはローカルにバインドされた深度ターゲットを使用して実行されます。
計算は次のようになります。
0.5 * alpha * abs( Z - Zf ) / Z, where alpha = F*F/(A*(Zf-F))
この場合:
F はレンズの焦点距離
A は絞りの数値
Zf は焦点距離
alpha は無限大での CoC
以下に、HLSL で記述された、このパスで使用されるシェーダのサンプルを示します。
float4 mayaCoCDepth( float alpha, float focusDist, float3 Pw, float4x4 view ) { float z = abs( mul( float4(Pw, 1), view ).z ); float CoC = 0.5f * alpha * (z - focusDist) / z; // Write to R, G channels of output return float4( CoC, z, 0, 1 ); }
この場合、Pw はワールド空間の位置で、view はマトリクスです。
アルファと焦点距離の現在の内部計算を以下に示します。
float ItoM = 0.0254f; // inches converted to m float CMtoM = 0.01f; // cm converted to m // Obtain the hyperfocal distance from the camera in m. // float focus = <camera shape’s focusDistance> * CMtoM; focusDist = focus * 100; // Convert back to cm. // Compute alpha, the COC at infinity, in m // float fStop = <camera shape’s fStop> * <camera shape’s focus region scale> // Apply region scale float F = <camera shape’s camera scale> * <camera shape’s focal length> * 0.001f; // in m float alpha = F * F / (fStop * (focus - F)); // Convert to UV space float apertureX = <camera shape’s horizontal film aperture> * 0.001f; float apertureY = <camera shape’s vertical film aperture> * 0.001f; alpha /= min( apertureX, apertureY );
カメラのシェイプ パラメータは、上記の疑似コードでは、区切り文字 <> で示されています。
MPassContext 内の情報は、ポスト エフェクトのあるビューティ パスの上にポスト エフェクトのないビューティ パスを合成する必要があるパスをレンダリングするために、プラグインが呼び出されているかを示すための十分な情報を提供します。
合成の内部アルゴリズムには、アルファ マスクを生成するためのポスト エフェクト パターン パスと非ポスト エフェクト パターン パスが必要です。
ポスト エフェクト パターン パス中に、ポスト エフェクトに含まれている各レンダー項目は、可視サーフェス(アルファ テストとブレンディングは不透明でも透明でも無効になっているので、どちらでもかまいません)の深度値で中間深度ターゲットを塗り潰すため、既定では、カラーの書き込みを無効にし、深度書き込みを有効にして描画されます。このパスは、MPassContext 情報を照会し、文字列 PEPatternPass または MPassContext::kPEPatternPassSemantic に一致するパス セマンティックをチェックすることで検出できます。
非ポスト エフェクト パターン パス中に、ポスト エフェクトから除外された各レンダー項目は、上記の深度ターゲットに対して描画されますが、深度テストをパスしたときにアルファ マスク ターゲットと深度ターゲットが更新されるように、このパスでカラーの書き込みが有効化されます。ビューティ パスと同様に、各レンダー項目に割り当てられているシェーダは、既定でジオメトリをシェーディングするために使用されますが、シェーディング出力のアルファ チャネルのみがアルファ マスク ターゲットに書き込まれます。このパスは、MPassContext 情報を照会し、文字列 nonPEPatternPass または MPassContext::kNonPEPatternPassSemantic に一致するパス セマンティックをチェックすることで検出できます。
レンダー項目は既定でポスト エフェクトから除外されます。MPxGeometryOverride インタフェースと MPxSubSceneOverride インタフェースには、レンダー項目レベルのコントロールがあり、必要に応じて、MRenderItem::setExcludedFromPostEffects() を false に設定することで、特定のレンダー項目がポスト エフェクトに含まれるように指定できます。MPxDrawOverride インタフェースにはオブジェクト レベルのコントロールがあり、仮想関数 MPxDrawOverride::excludedFromPostEffect() が false を返すようにオーバーライドするか、登録時に drawdb/geometry/includePostEffects/ で描画の分類を開始することで、ポスト エフェクトに含めることができます。
非ポスト エフェクト パターン パス中にプラグインでカスタマイズしたパターンを生成する場合、MPxShaderOverride と MPxDrawOverride でこの情報を使用して、より複雑なまたはより簡易なレンダリングを実行できます。MShaderInstance は便宜上、どちらのインタフェース内からも使用できます。サポートを追加するには、カスタム シェーダで以下の条件を考慮する必要があります。
非ポスト エフェクト パターン パス後に、中間カラー ターゲット ポスト エフェクトは、内部合成中に、次のように AlphaMask としてバインドされるのに対し、ポスト エフェクトがあるビューティ パス出力は SrcTarget としてバインドされ、ポスト エフェクトがないビューティ パス出力は DstTarget としてバインドされます。合成操作は、2 つを結び付けるため、SrcTarget がバックグラウンドに表示され、DstTarget がフォアグラウンドに表示されます。これは DstTarget over SrcTarget として表すことができます。
float4 CompositeWithAlphaMask( float3 UV, texture2D SrcTarget, sampler SrcTargetSampler, texture2D DstTarget, sampler DstTargetSampler, texture2D AlphaMask, sampler AlphaMaskSampler ) { float4 srcColor = SrcTarget.Sample( SrcTargetSampler, UV.xy ); // Color with post effects float4 dstColor = DstTarget.Sample( DstTargetSampler, UV.xy ); // Color with no post effects float alphaMask = AlphaMask.Sample( AlphaMaskSampler, UV.xy ).a; return lerp( srcColor, dstColor, alphaMask ); }
特定のリリースへのこの実装の XML ラッパーは、MEL コマンドを使用して検索できます。
ogs -xml maya_CompositeWithAlphaMask;
API から MFragmentManager:: getFragmentXML() メソッドを使用して、このフラグメントを照会できます。Developer Kit の fragmentDumper サンプル プラグインは、このメソッドを使用してフラグメントをダンプする方法を示します。
dumpFragment -fn maya_CompositeWithAlphaMask;
フレームと描画コンテキストの詳細については、「フレームと描画のコンテキスト」を参照してください。
描画時にオーバーライド シェーダを取得するために MPassContext::shaderOverrideInstance() が呼び出される場合、MFrameContext から取得したライトの状態に基づいて、プラグインで isSingleSided パラメータを更新する必要があります。