Platform SDK: DirectX |
メッシュの各面には、垂直の法線ベクトルがある。法線ベクトルの方向は、頂点が定義されている順序と、座標系が左手座標系か右手座標系かによって決まる。面の法線ベクトルは面の前面から離れる方向に向く。Direct3D では、面の前面のみ表示される。前面とは、各頂点が時計回りの順に定義された面である。
前面以外の面は背面である。Direct3D では、背面が常にレンダリングされるわけではない。これを背面カリングと言う (カリング モードを変更すれば背面をレンダリングできる)。詳細については、「カリング ステート」を参照すること。
Direct3D アプリケーションでは面法線を指定する必要はない。必要なときはシステムで自動的に計算される。システムでは、フラット シェーディング モードで面法線を使用する。グーロー シェーディング モードでは頂点法線を使用する。また、Direct3D はライティング エフェクトとテクスチャ エフェクトの制御にも頂点法線を使用する。
C++ で記述された Direct3D アプリケーションでは、通常、頂点に D3DVERTEX 構造体を使用する。D3DVERTEX 構造体のメンバで、頂点の位置座標と方向を指定する。頂点の方向は頂点法線ベクトルで示される。次のコードは、頂点法線を含め頂点の値を設定する方法を示す。法線ベクトルはビューポートの方向を向き、ビューポートはワールド座標系の原点にある。この例では、頂点の位置座標はワールド座標で指定されている。
D3DVERTEX lpVertices[3]; // 1 つの頂点は 1 つの構造体で一度に指定できる。 lpVertices[0].x = 0; lpVertices[0].y = 5; lpVertices[0].z = 5; lpVertices[0].nx = 0; // 法線ベクトルの x 成分。 lpVertices[0].ny = 0; // 法線ベクトルの y 成分。 lpVertices[0].nz = -1; // 原点の裏の法線を指す。 lpVertices[0].tu = 0; // テクスチャを使用する場合にのみ使用。 lpVertices[0].tv = 0; // テクスチャを使用する場合にのみ使用。 // 頂点は、いくつかの D3DOVERLOADS マクロを使用することにより、 // 頂点ごとに 1 行のコードで指定することもできる。 lpVertices[1] = D3DVERTEX(D3DVECTOR(-5,-5,5),D3DVECTOR(0,0,-1),0,0); lpVertices[2] = D3DVERTEX(D3DVECTOR(5,-5,5),D3DVECTOR(0,0,-1),0,0);
Visual Basic で記述された Direct3D アプリケーションでは、通常、頂点に D3DVERTEX 型を使用する。D3DVERTEX 構造体のメンバで、頂点の位置座標と方向を指定する。頂点の方向は頂点法線ベクトルで示される。次のコードは、頂点法線を含め頂点の値を設定する方法を示す。法線ベクトルはビューポートの方向を向き、ビューポートはワールド座標系の原点にある。この例では、頂点の位置座標はワールド座標で指定されている。
D3DVERTEX Vertices(3) ' 1 つの頂点には、一度に 1 つの構造体メンバを指定できる。 Vertices(0).x = 0 Vertices(0).y = 5 Vertices(0).z = 5 Vertices(0).nx = 0 ' 法線ベクトルの x 成分。 Vertices(0).ny = 0; ' 法線ベクトルの y 成分。 Vertices(0).nz = -1; ' 原点の裏の法線を指す。 Vertices(0).tu = 0; ' テクスチャを使用する場合にのみ使用。 Vertices(0).tv = 0; ' テクスチャを使用する場合にのみ使用。
グーロー シェーディングをポリゴンに適用するとき、Direct3D では頂点法線を使用して光源とサーフェス間の角度を計算する。Direct3D では、頂点の色と強度の値を計算し、プリミティブのサーフェス全体のすべての点に対してこの値を補間する。Direct3D では、この角度を使用してライティングの強度の値を計算する。角度が大きいほど、サーフェスを照らす光が弱くなる。
平坦なオブジェクトを作成する場合、次の図に示すように、頂点法線をサーフェスに対して垂直に設定する。2 つの三角形で構成される平坦なサーフェスが定義されている。
しかし、通常はオブジェクトが三角形ストリップで構成され、それらの三角形が同一平面上にないことが多い。ストリップのすべての三角形全体に滑らかなシェーディングを施すには、まず頂点に関係付けられている各ポリゴンのサーフェスについて、面法線ベクトルを計算するのが簡単である。頂点法線は、その周りの各サーフェスの法線からの角度が等しくなるように設定できる。ただし、この方法はプリミティブが複雑な場合には効率的でないことがある。
この方法について次の図で説明する。この図では、S1 と S2 の 2 つのサーフェスがあり、上から見るとエッジが重なっている。S1 と S2 の法線ベクトルは青色で示す。頂点法線ベクトルは赤色で示す。S1 の面法線と頂点法線ベクトルのなす角度は、S2 の面法線と頂点法線のなす角度と同じである。これら 2 つのサーフェスにライトを当て、グーロー シェーディングで陰影を付けると、サーフェス間のエッジの陰影が滑らかになって丸みを帯びる。
頂点法線が、関係付けられているサーフェスのうち 1 つの方へ傾いている場合、光源と面の角度に応じてサーフェス上の点に対する光の強度が増加または減少する。この例を次の図で示す。この図でも、サーフェスのエッジは重なっている。頂点法線は S1 の方に傾いているので、S1 と光源の角度は、頂点法線と 2 つの面法線の角度が等しい場合よりも小さくなる。
グーロー シェーディングを使用して、鋭いエッジのあるオブジェクトを 3D シーンに表示できる。このためには、次の図に示すように、鋭いエッジが必要な、面が交差する位置座標 2 つの頂点でそれぞれの面と同じ法線ベクトルが必要だ。
IDirect3DDevice7::DrawPrimitive または IDirect3DDevice7::DrawIndexedPrimitive メソッドを使用してシーンをレンダリングする場合、エッジが鋭いオブジェクトは、三角形ストリップではなく三角形リストとして定義する。オブジェクトを三角形ストリップとして定義すると、Direct3D ではそのオブジェクトを複数の三角形の面で構成された単一のポリゴンとして扱う。グーロー シェーディングは、ポリゴンの面全体および隣接する面との間の両方に適用される。その結果、オブジェクトの面の境が滑らかにシェーディングされる。三角形リストは、一連の独立した三角形の面から構成されるポリゴンなので、Direct3D ではポリゴンの各面にグーロー シェーディングを適用する。ただし、面と面の境にはグーロー シェーディングは適用されない。三角形リストの複数の三角形が隣接している場合、その三角形の間には鋭いエッジが表示される。
Direct3DDevice7.DrawPrimitive または Direct3DDevice7.DrawIndexedPrimitive メソッドを使用してシーンをレンダリングする場合、エッジが鋭いオブジェクトは、三角形ストリップではなく三角形リストとして定義する。オブジェクトを三角形ストリップとして定義すると、Direct3D ではそのオブジェクトを複数の三角形の面で構成された単一のポリゴンとして扱う。グーロー シェーディングは、ポリゴンの面全体および隣接する面との間の両方に適用される。その結果、オブジェクトの面の境が滑らかにシェーディングされる。三角形リストは、一連の独立した三角形の面から構成されるポリゴンなので、Direct3D ではポリゴンの各面にグーロー シェーディングが適用される。ただし、面と面の境にはグーロー シェーディングは適用されない。三角形リストの複数の三角形が隣接している場合、その三角形の間には鋭いエッジが表示される。
また、エッジが鋭いオブジェクトをレンダリングするとき、フラット シェーディングに変更する方法もある。これはコンピュータには最も効率的であるが、グーロー シェーディングを適用したオブジェクトよりもリアリティに欠けるオブジェクトがシーンに表示される可能性がある。