DirectX と OpenGL には異なるカメラ規則があります。
ビューポート 2.0 は、カメラのプロジェクションの行列を設定するときに右手の座標系を使用することで、Maya の他の部分との一貫性を維持しています。ただし、ニア クリップ プレーンとファー クリップ プレーンは Z の[0,1]範囲にマッピングされます。
そのため、
MDrawContext::getDepthRange() を使用して深度の範囲を照会する場合、DirectX と OpenGL の戻り値は[0,1]範囲になります。MDrawContext::viewDirectionAlongNegZ() を使用してビュー方向を照会する場合、OpenGL と DirectX の両方の戻り値はビュー方向が常に –Z に沿っていることを示します。kViewDirection (方向)、kViewUp (上)、kViewRight (右)列挙型を MFrameContext::getTuple() メソッドに渡すことで、ワールド空間のカメラ ベクトルを照会することができます。これらの 3 つのベクトルは、右手の座標系の基礎を形成します。
また、MDrawContext はアクティブ カメラへのアクセスを提供します。MFnCamera インタフェースを介してそのプロパティを照会すると、同じ一貫したカメラ ベクトル値を照会することができます。オブジェクト空間のベクトルが返された場合、値は Z- ビュー方向の一貫した右手の座標系を示します。
次のような照会に使用できるいくつかの便利なメソッドがあります。
MFnCamera::unnormalizedNearClippingPlane(). NDC ではなく、オブジェクト空間またはワールド空間の値を返します。MFnCamera::unnormalizedFarClippingPlane(). NDC ではなく、オブジェクト空間またはワールド空間の値を返します。MFnCamera::eyePoint(). ワールド空間座標を照会する場合は、kViewPosition の照会と同等です。MFnCamera::viewDirection(). ワールド空間座標を照会する場合は、kViewDirection の照会と同等です。MFnCamera::upDirection(). ワールド空間座標を照会する場合は、kViewUp の照会と同等です。MFnCamera::rightDirection(). ワールド空間座標を照会する場合は、kViewRight の照会と同等です。旧式の既定ビューポート(ビューポート 1)では、アクティブ カメラがカメラ セットに属する場合に、OpenGL で追加クリップ プレーンを直接設定することができました。
ビューポート 2.0 では、固定機能のユーザ クリップ プレーンが特定の描画 API で使用できない可能性があるため、デバイスを直接照会することはお勧めできません。そのため、ビューポート 1 の動作はビューポート 2.0 では既定で無効にされていますが、OpenGL (ENABLE_DEFAULT_VIEWPORT_CAMERA_SETS)の実行時に必要な場合には環境変数を介してアクセスできます。
ワールド空間のクリップ プレーンを取得するための、描画 API に依存しないオプションを以下に示します。カメラは MDrawContext から取得しますが、すべてのカメラ シェイプに対応することができます。クリップ プレーンを照会するための正規化されていないメソッドの使用に注目してください。**
MDrawContext context;
// Get the current camera from the context
MFnCamera activeCamera(context.getCurrentCameraPath());
// Get relative near and far clip values with respect to the camera position
// You should ignore any override values set when using a
// camera set; therefore, do not use the nearClippingPlane() and farClippingPlane()
// methods on MFnCamera.
double nearD = activeCamera.unnormalizedNearClippingPlane();
double farD = activeCamera.unnormalizedFarClippingPlane();
// Get world space camera information
MPoint eyePoint = activeCamera.eyePoint(MSpace::kWorld);
MVector viewDirection = activeCamera.viewDirection(MSpace::kWorld); // Positive value
double dist = eyePoint[0]*viewDirection[0] +
eyePoint[1]*viewDirection[1] +
eyePoint[2]*viewDirection[2];
// Compute near clip plane facing away from the camera direction (for OpenGL)
double distNear = -1.0 * (dist + nearD);
MVector OpenGL_NearClipPlaneVector(
viewDirection[0], viewDirection[1], viewDirection[2], distNear);
// Compute far clip plane facing towards the camera direction (for OpenGL)
double distFar = dist + farD;
MVector OpenGL_FarClipPlaneVector(
-viewDirection[0], -viewDirection[1], -viewDirection[2], distFar);
MDrawContext のみを使用する場合の同等のコードは、次のようになります。
// Query the camera coordinate system
MDoubleArray vPos = context.getTuple(MHWRender::MFrameContext::kViewPosition);
MDoubleArray vDir = context.getTuple(MHWRender::MFrameContext::kViewDirection);
MDoubleArray vNear = context.getTuple(MHWRender::MFrameContext::kViewUnnormlizedNearClipValue);
MDoubleArray vFar = context.getTuple(MHWRender::MFrameContext::kViewUnnormalizedFarClipValue);
// Compute the world space planes for the near and far clip planes
// The near plane is pointing away from the camera and is thus pointing in the
// negative direction, while the far plane is pointing towards the camera (positive
// direction.
double distW = vPos[0]*vDir[0] +
vPos[1]*vDir[1] +
vPos[2]*vDir[2];
// Near clip plane faces away from the camera
double distNearW = -1.0 * (distW + vNear[0]);
MVector OpenGL_NearPlane(vDir[0], vDir[1], vDir[2], distNearW);
// Far clip plane faces torwards the camera
double distFarW = distW + vFar[0];
MVector OpenGL_NearPlane(-vDir[0], -vDir[1], -vDir[2], distFarW);
シェーダは、ビュー方向に沿ったジオメトリの位置をオフセットするために深度の優先順位を使用できます。シェーダ コード内での計算は、実際のデバイスの深度範囲に関連するため、OpenGL と DirectX で異なります。depthPriority と呼ばれるユニフォーム パラメータが適切に設定されている場合は、次のサンプル コードが DirectX と OpenGL でのオフセットを実行します。
// DX range is [0,1] or 1 in size.
float4 iPcPriority( float3 pm, float depthPriority, float4x4 worldViewProjectionC )
{
float4 P = mul( float4(pm,1), worldViewProjectionC );
P.z -= P.w * depthPriority;
return P;
}
// OpenGL range is [-1,1] or 2 in size
vec4 iPcPriority( vec3 pm, float depthPriority, mat4 worldViewProjectionC )
{
vec4 P = worldViewProjectionC * vec4(pm,1.0f);
P.z -= P.w * 2.0 * depthPriority;
return P;
}
選択項目は、描画用に使用されるものと同じ情報を使用します。
(ジオメトリ シェーダを使用して生成された)太い線およびポイント、またはスクリーン位置合わせジオメトリでは、反時計回りの巻上げ方向が前に向いたジオメトリを示すことに注目してください。これは DirectX と OpenGL の両方で一貫しています。
たとえば、次の DirectX コードでは、4 つの点は次のように定義されます。
static const float4 cQuadPts[4] = {
float4( -1.0, 1.0, 0, 0 ),
float4( -1.0, -1.0, 0, 0 ),
float4( 1.0, 1.0, 0, 0 ),
float4( 1.0, -1.0, 0, 0 )};
ジオメトリ シェーダの展開が先に進む順序でポイントを横切り、それぞれが反時計回りの方向を持つ三角形を備えた三角ストリップが作成されます。
void point2ScreenQuad( geometryInS inputs[1], float2 pointSz, float2 screenSize,
float4x4 viewProjInverse, float depthPriorityUnit, bool orthographic, float DPThresholdInView,
inout TriangleStream<geometryInS> outStream )
{
geometryInS outS = inputs[0];
float size = max(0, max(pointSz.x, pointSz.y));
float dpScale = orthographic ? 1.0f : -DPThresholdInView;
float dp = 2.0f * size * cDepthPriorityUnit * dpScale;
float4 sizeInZ = float4(pointSz.xy / screenSize.xy, 0, 0) * outS.Pc.w;
[unroll] for( int i = 0; i < 4; ++i ) {
outS.Pc = inputs[0].Pc + sizeInZ * cQuadPts[i];
outS.Pc.z = inputs[0].Pc.z - dp;
outStream.Append( outS );
}
outStream.RestartStrip();
}
MDrawContext/MFnCamera および MFrameContext の照会を実行するサンプル デバッグ コードがあります。MayaBlinnDirectionalLightShadowGL.cgfx、MayaBlinnDirectionalLightShadowGL.ogsfx、および MayaBlinnDirectionalLightShadow10.fx ファイルは、同じシェーダに深度の優先順位オフセットを使用する DirectX と OpenGL のサンプル実装を提供します。これらのファイルは、Maya インストール フォルダの bin\Cg、bin\OGSFX、bin\HLSL フォルダにあります。上記の iPcPriority 関数であるため、mayaDepthPriorityShader フラグメントを検討することもできます。mayaFatPointShader で太いラインを描画するために使用されるジオメトリ シェーダ コードのサンプルとして、mayaPoint2Quad フラグメントを検討することができます。これには mayaDepthPriorityShader フラグメントも組み込まれていて、ビュー方向にオフセットすることができます。注: フラグメントは、次のいずれかの方法を使用して検討することができます。
ogs –xml <fragmentName>コマンド(<fragmentname>引数はフラグメント名)MFragmentManager::getFragmentXML()API インタフェースfragmentDumper サンプル プラグインは、-fnオプションを使用してフラグメントの検討にも使用できるdumpFragmentコマンドを実装します。