# D3D12渲染技术之向量法线

（a）面法线与面上的所有点正交。
（b）表面法线是与表面上的点的切平面正交的矢量。

## 计算法线向量

u = p1 – p0
v = p2 – p0

MVECTOR ComputeNormal(FXMVECTOR p0,
FXMVECTOR p1,
FXMVECTOR p2)
{
XMVECTOR u = p1 - p0;
XMVECTOR v = p2 - p0;

return XMVector3Normalize(
XMVector3Cross(u,v));
}

// 1. An array of vertices (mVertices). Each vertex has a
// position component (pos) and a normal component (normal).
// 2. An array of indices (mIndices).

// For each triangle in the mesh:
for(UINT i = 0; i < mNumTriangles; ++i)
{
// indices of the ith triangle
UINT i0 = mIndices[i3+0];
UINT i1 = mIndices[i
3+1];
UINT i2 = mIndices[i*3+2];

// vertices of ith triangle
Vertex v0 = mVertices[i0];
Vertex v1 = mVertices[i1];
Vertex v2 = mVertices[i2];

// compute face normal
Vector3 e0 = v1.pos - v0.pos;
Vector3 e1 = v2.pos - v0.pos;
Vector3 faceNormal = Cross(e0, e1);

// This triangle shares the following three vertices,
// so add this face normal into the average of these
// vertex normals.
mVertices[i0].normal += faceNormal;
mVertices[i1].normal += faceNormal;
mVertices[i2].normal += faceNormal;
}

// For each vertex v, we have summed the face normals of all
// the triangles that share v, so now we just need to normalize.
for(UINT i = 0; i < mNumVertices; ++i)
mVertices[i].normal = Normalize(&mVertices[i].normal));
`

## 转换法线向量

static XMMATRIX InverseTranspose(CXMMATRIX M)
{
XMMATRIX A = M;
A.r[3] = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);

XMVECTOR det = XMMatrixDeterminant(A);
return XMMatrixTranspose(XMMatrixInverse(&det, A));
}

V，（A-1）T的第四列中的转置平移会导致错误。 因此，我们将其归零以避免此错误， 正确的方法是通过以下方式转换法线：（（AV）-1）T， 下面是缩放和平移矩阵的示例，以及第四列不是[0,0,0,1] T的逆转置看起来是这样的：