D3D11之坐标空间的转换

世界坐标系转换:

世界坐标系转换其实就是将顶点从几何模型坐标系移到世界坐标系中,在游戏里就是构建游戏场景,将物品放置到一个场景里。通常在世界坐标系转换时,还将通过改变大小来控制基元物件的放大或缩小,通过改变方向来设置旋转,通过改变位置来进行转变。在一个场景中,每一个物件都有他自己的世界坐标系转换矩阵,这是由于每一个物件都有其自己的大小,方向和位置。

 观察坐标系转换:

所有顶点在转换到世界坐标系后,观察坐标系转换将其从世界坐标系转换为观察坐标系中。前面我们讲过,观察坐标系即是在世界坐标系内,从观测者或者摄像机角度透视所能够看到的图像,在观察坐标系内,观测者将站在原点(或者说以观测者为原点),透视的方向即是Z轴方向,即观察方向为Z轴方向。

 很值得注意的是,虽然观察坐标空间是从观测者在世界坐标系内所能够看到的一个框架,但是观察坐标系矩阵却是由定点来填充的,而非观测者。因此,观察矩阵所填充的数据是和观测者或者摄像机里的正好相反,比如说,我们想把摄像机往-z方向移动4个单位,那么我们必须计算出观察矩阵转换的定点正好为4个单位的Z轴方向。虽然摄像机是往反方向移动,但是在摄像机里的成像却是相反的。在Direct3D中有一个方法可以用来计算这种观察矩阵,那就是XMMatrixLookAtLH()方法,我们只要告诉他观测者的位置,所观看的位置,并且告诉他观察者向上方向,就可以计算出观察矩阵。

投影坐标系转换:

投影坐标系转换即是将定点从3D坐标系如:世界和观察坐标系转换为投影坐标系,在投影坐标系中,一个顶点的X和Y坐标是根据在3D空间中的X/Z和Y/Z的比率获得的。首先我们来看一个图,那样有助于我们理解这个概念,如下所示:

D3D11之坐标空间的转换_第1张图片

在3D中,根据透视法,越靠近的物体越大,从上图可以看出,一棵高为h单位在远离观测点d单位的树,和一棵高为2h单位距离观测点2d位置的树是一样大的。因此,顶点在2D屏幕上呈现是依据X/Z和Y/Z的比率决定的。

在Direct3D中以一个叫做FOV(field-of-view),这个主要是通过特定方向判断特定位置的顶点是否可见。每个人都有一个FOV,当然那是在我们的前方,因为我们不可能看到后面,如果两个物体离得太近或非常远也是看不到的。在计算机绘图里,FOV包含在一个视截体里,在3D中这个视截体被定义一个六面体,有两个面是XY面平行,他们被叫做近Z视平面和远Z视平面。其它的面被定义为观测者的横向和纵向可视界面,FOV越大,视截体的体积也越大,当然容纳的物体也更多,如下图所示。

D3D11之坐标空间的转换_第2张图片

GPU会过滤视截体外部的东东以至于不会浪费那些不需要显示的部分,这个被称为裁剪,GPU将会将顶点转换为投影顶点,那样就可以知道是否在视截体内。在Direct3D 11中,这些换行都被一个方法完成,那就是XMMatrixPerspectiveFovLH(),我们将提高4个参数,FOVy,比率,Zn和Zf即可以获得投影矩阵。其中FOVy就是Y方向的投影角度,比率就是宽和高比率,Zn和Zf分别是近视面和远视面的大小。

下面我们通过我们之前实现(D3D11之三,创建三角形)的例子来说明:

我们来看到colorshaderclass.cpp中的SetShaderParameters函数,函数把世界坐标,观察坐标,投影坐标传入顶点着色器中

进行计算。

bool ColorShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix,
	XMMATRIX projectionMatrix)
{
	HRESULT result;
	D3D11_MAPPED_SUBRESOURCE mappedResource;
	MatrixBufferType* dataPtr;
	unsigned int bufferNumber;
	//确保在将矩阵发送到着色器之前进行转置,这是DirectX 11的要求
	// Transpose the matrices to prepare them for the shader.
	worldMatrix = XMMatrixTranspose(worldMatrix);
	viewMatrix = XMMatrixTranspose(viewMatrix);
	projectionMatrix = XMMatrixTranspose(projectionMatrix);
	// Lock the constant buffer so it can be written to.
	result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
	if (FAILED(result))
	{
		return false;
	}

	// Get a pointer to the data in the constant buffer.
	dataPtr = (MatrixBufferType*)mappedResource.pData;

	// Copy the matrices into the constant buffer.
	dataPtr->world = worldMatrix;
	dataPtr->view = viewMatrix;
	dataPtr->projection = projectionMatrix;

	// Unlock the constant buffer.
	deviceContext->Unmap(m_matrixBuffer, 0);
	// Set the position of the constant buffer in the vertex shader.
	bufferNumber = 0;

	// Finanly set the constant buffer in the vertex shader with the updated values.
	deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer);

	return true;
}
而我们的worldMatrix,viewMatrix,projectionMatrix又是从哪里来的,我们可以看到graphicsclass.cpp中的分别来源

worldMatrix来自于d3dclass.cpp

// Initialize the world matrix to the identity matrix.世界矩阵,将我们对象的顶点转换为3D场景中的顶点
m_worldMatrix = XMMatrixIdentity();//单位矩阵
viewMatrix

void CameraClass::Render()
{
	XMFLOAT3 up, position, lookAt;
	XMVECTOR upVector, positionVector, lookAtVector;
	float yaw, pitch, roll;
	XMMATRIX rotationMatrix;


	// Setup the vector that points upwards.
	up.x = 0.0f;
	up.y = 1.0f;
	up.z = 0.0f;

	// Load it into a XMVECTOR structure.
	upVector = XMLoadFloat3(&up);

	// Setup the position of the camera in the world.
	position.x = m_positionX;
	position.y = m_positionY;
	position.z = m_positionZ;

	// Load it into a XMVECTOR structure.
	positionVector = XMLoadFloat3(&position);

	// Setup where the camera is looking by default.
	lookAt.x = 0.0f;
	lookAt.y = 0.0f;
	lookAt.z = 1.0f;

	// Load it into a XMVECTOR structure.
	lookAtVector = XMLoadFloat3(&lookAt);

	// Set the yaw (Y axis), pitch (X axis), and roll (Z axis) rotations in radians.
	pitch = m_rotationX * 0.0174532925f;
	yaw = m_rotationY * 0.0174532925f;
	roll = m_rotationZ * 0.0174532925f;

	// Create the rotation matrix from the yaw, pitch, and roll values.
	rotationMatrix = XMMatrixRotationRollPitchYaw(pitch, yaw, roll);

	// Transform the lookAt and up vector by the rotation matrix so the view is correctly rotated at the origin.
	lookAtVector = XMVector3TransformCoord(lookAtVector, rotationMatrix);
	upVector = XMVector3TransformCoord(upVector, rotationMatrix);

	// Translate the rotated camera position to the location of the viewer.
	lookAtVector = XMVectorAdd(positionVector, lookAtVector);

	// Finally create the view matrix from the three updated vectors.
	m_viewMatrix = XMMatrixLookAtLH(positionVector, lookAtVector, upVector);

	return;
}
projectionMatrix

// Setup the projection matrix.设置投影矩阵
fieldOfView = 3.141592654f / 4.0f;
screenAspect = (float)screenWidth / (float)screenHeight;

// Create the projection matrix for 3D rendering.为3D渲染创建投影矩阵,可以把3D转换为2D窗口
m_projectionMatrix = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, screenNear, screenDepth);
// Initialize the world matrix to the identity matrix.世界矩阵,将我们对象的顶点转换为3D场景中的顶点
推导过程未完待续。。。。。





你可能感兴趣的:(Direct)