[DirectX12] World, View, Projection マトリックス

[DirectX12] World, View, Projection マトリックス

World 行列

View 行列

XMVECTOR Eye = XMVectorSet( 0.0f, 0.0f, -5.0f, 0.0f );
XMVECTOR At = XMVectorSet( 0.0f, 0.0f, 0.0f, 0.0f );
XMVECTOR Up = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
g_View = XMMatrixLookAtLH( Eye, At, Up );

カメラ位置(座標)と、カメラの見ている場所(注視点)、そしてカメラの上方向のベクトルをXMMatrixLookAtLH に指定することで View 行列が作られる。この行列によって、World 座標から定義した View 座標への変換が行える。

上記の Eye, At, Up から作られる View 行列はこちら。

{1.00, 0.00, 0.00, 0.00}
{0.00, 1.00, 0.00, 0.00}
{0.00, 0.00, 1.00, 0.00}
{0.00, 0.00, 5.00, 1.00} 

計算式は以下。

zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)

 xaxis.x           yaxis.x           zaxis.x          0
 xaxis.y           yaxis.y           zaxis.y          0
 xaxis.z           yaxis.z           zaxis.z          0
-dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  1
https://learn.microsoft.com/ja-jp/windows/win32/direct3d9/d3dxmatrixlookatlh

計算式を見れば分かるが up ベクトルが必要なのは、カメラからの視線のベクトルと up 方向のベクトルの外積を取って、横方向(xaxis)のベクトルを計算するために使用している。つまり、カメラの3次元での軸を決定するために、上方向がどちらかという情報が必要になる。

Projection 行列

g_Projection = XMMatrixPerspectiveFovLH( XM_PIDIV4, width / (FLOAT)height, 0.01f, 100.0f );
  • XM_PIDIV4 は 0.785398163f(3.14/4)
  • 2つ目はビュースペースのアスペクト比。(640/480=1.333333)
  • 3つ目と、4つ目は NearPlane と FarPlane。(0.01~100.0)

これによって、下記の Projection 行列が得られる。

{1.81066, 0.00, 0.00, 0.00}
{0.00, 2.41421, 0.00, 0.00}
{0.00, 0.00, 1.0001, 1.00}
{0.00, 0.00, -0.01, 0.00}

計算式としては下記。

xScale     0          0               0
0        yScale       0               0
0          0       zf/(zf-zn)         1
0          0       -zn*zf/(zf-zn)     0
where:
yScale = cot(fovY/2)

xScale = yScale / aspect ratio

https://learn.microsoft.com/ja-jp/windows/win32/direct3d9/d3dxmatrixperspectivefovlh

Viewport 行列

640×480 のレンダーターゲットに描画する場合は、Viewport も Width 640, Height 480 に設定する。他は通常はデフォルト値の X, Y 0で、Min 0.0, Max 1.0 になるのが普通。

    dwWidth/2,              0,             0, 0,
            0,    -dwHeight/2,             0, 0,
            0,              0, dwMaxZ-dwMinZ, 0,
dwX+DwWidth/2, dwHeight/2+dwY,        dwMinZ, 1,

https://learn.microsoft.com/ja-jp/windows/win32/direct3d9/viewports-and-clipping

実際は width, height ぐらいしかパラメータは設定しないので、

w = width / 2
h = height / 2

w  0 0 0
0 -h 0 0
0  0 1 0
w  h 0 1

ぐらいの単純な行列になる。

SV_Position の値

頂点シェーダーを使用して、上記のような View, Projection 行列で、ローカル座標 [ -1.0f, 1.0f, -1.0f] を変換した場合はこのような結果になる。

 [-1.81066, 2.41421, 3.9904, 4.00]

頂点シェーダーから SV_Position へ渡している値はこれ。
ラスタライザを通り、ピクセルシェーダーの入力として渡ってくる SV_Position は下記のようになる。

[175.50, 95.50, 0.9976, 4.00]

X, Y はピクセルのスクリーン座標。
Z は Depth Buffer に書かれる値と一致する。頂点シェーダーからの出力 3.9904 / 4.0 = 0.9976 になる。
W は頂点シェーダーでの World, View, Projection の計算結果がそのまま来る。

Reference

https://shikihuiku.github.io/post/projection_matrix/

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA