【DirectX11】【学习笔记(6)】世界和局部坐标系

介绍:

世界中的不同空间有以下几个:世界坐标,视角坐标,局部坐标,屏幕坐标。

我们可以使用这些效果来创建一个空间中的摄像机。为了使用这些空间,我们要把他们放在一个常量缓冲里,然后把缓冲传入VX(Vertex Shader)用来改变物体的顶点坐标。

Local Space

局部坐标是一个物体的坐标,当我们创建一个物体的时候,这个物体就在坐标的中心。这样的话,更容易定义顶点。

如果要创建一片森林,如果不用局部坐标,我们就需要知道每棵树的坐标,现在这种情况下,我们只需要创建一棵树,然后对树进行复制,然后顶点平移(在VX中)就可以了。

View Space

视角空间是基于摄像机的空间。摄像机在(0, 0, 0),看向Z轴正半轴,上方向是Y轴,当世界坐标变换为摄像机坐标系的时候,我们就需要做平移,看起来是我们的摄像机在动,其实是世界在做反方向移动。

Projection Space

这个空间就是定义了一个摄像机的一个视锥体,当物体在里面的时候,就会被渲染,如果不在,就不会被看见(相当于人的视角)

要渲染。

这个空间变换主要有以下几个部分构成。

FOV (Field of view in radians), aspect ratio, near z-plane, and far z-plane.(远近平面是说,太近的物体看不到,太远的物体看不到)

FOV是说:FOV越大,远平面对于近平面的比率就越大。

Screen Space

这是渲染的最后一个空间。就是由后台缓存的像素的X,Y坐标来表示的。左上角是0,0。

(这个空间坐标变换不需要我们来做)

Transforming Spaces

把物体从一个坐标空间转换到另一个坐标空间(通过矩阵变换来实现,但是必须要按照顺序)

Constant Buffers

常量缓冲区就是effect file中的一个变量结构体。示例代码如下:

cbuffer cbPerObject
{
    float4x4 WVP;
};

常量缓冲区应该按照调用的频次来区分,比如说按照每帧,每个场景,每个物体来调用。

比如说,WVP这个变量就是按照每个物体来区分的。

Global Declarations

申明一个D3D11的缓冲区,用来存储我们的变量。

然后定义变换矩阵和照相机的方向向量

XMMATRIX WVP;
XMMATRIX World;
XMMATRIX camView;
XMMATRIX camProjection;

XMVECTOR camPosition;
XMVECTOR camTarget;
XMVECTOR camUp;

然后我们需要创建一个结构体,对应着effect file中的相同Buffer,(布局必须一致)



struct cbPerObject
{
    XMMATRIX  WVP;
};

cbPerObject cbPerObj;

记得释放缓冲!

cbPerObjectBuffer->Release();

Create the Constant Buffer in code

创建一个缓冲,这个缓冲保存了我们想要传到effect file中的变量信息。首先我们需要创建他的描述信息。

D3D11_BUFFER_DESC cbbd;    
ZeroMemory(&cbbd, sizeof(D3D11_BUFFER_DESC));
cbbd.Usage = D3D11_USAGE_DEFAULT;
cbbd.ByteWidth = sizeof(cbPerObject);
cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbbd.CPUAccessFlags = 0;
cbbd.MiscFlags = 0;
hr = d3d11Device->CreateBuffer(&cbbd, NULL, &cbPerObjectBuffer);

最终利用缓冲描述信息来创建缓冲。

Camera

创建camera的三个向量,向量中的第四个参数我们设置为0

camPosition = XMVectorSet( 0.0f, 0.0f, -0.5f, 0.0f );
camTarget = XMVectorSet( 0.0f, 0.0f, 0.0f, 0.0f );
camUp = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );

接着创建视角矩阵函数

camView = XMMatrixLookAtLH( camPosition, camTarget, camUp );

创建投影矩阵

XMMATRIX XMMatrixPerspectiveFovLH
(
    FLOAT FovAngleY, 
    FLOAT AspectRatio, 
    FLOAT NearZ, 
    FLOAT FarZ
)

四个参数的意义如下:

FovAngleY - The Field of View in radians along the y-axis. (在Y轴上的视角)

AspectRatio - The aspect ratio, usually Width/Height. (长宽比)

NearZ - A float describing the distance from the camera to the near z-plane.

FarZ - A float describing the distance from the camera to the far plane.

如果一个物体太远或者太近,那么都看不到。+

camProjection = XMMatrixPerspectiveFovLH( 0.4f*3.14f, (float)Width/Height, 1.0f, 1000.0f);

最终创建世界变换矩阵。

世界矩阵是一个单位矩阵,这是物体自己的位置。然后创建WVP矩阵

World = XMMatrixIdentity();
WVP = World * camView * camProjection;

Update the Constant Buffer

接下来我们要把创建好的WVP传入effect file中(这一步很重要!)

首先要对矩阵进行转置,因为effect 文件中的矩阵和 code中的矩阵行和列都是反的

然后把矩阵赋值给结构体中的矩阵。然后用结构体更新代码中的常量缓冲区,使用了DeviceContext中的UpdateSource方法。

然后我们把VX中的常量缓冲区设置为上一步中的代码中的常量缓冲对象。(这样就完成了code到effect数据的传输)

cbPerObj.WVP = XMMatrixTranspose(WVP);    
d3d11DevCon->UpdateSubresource( cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0 );
d3d11DevCon->VSSetConstantBuffers( 0, 1, &cbPerObjectBuffer );

Updated Vertex Buffer

我们只需要加一行代码,让顶点的坐标与变换矩阵相乘。

VS_OUTPUT VS(float4 inPos : POSITION, float4 inColor : COLOR)
{
    VS_OUTPUT output;

    output.Pos = mul(inPos, WVP);
    output.Color = inColor;

    return output;
}

这样的话,我们就已经有一个静态的摄像机,并且可以从摄像机来观察世界了。

做了一个简单的思维导图以供参考:

本节内容就到这里拉。

本节内容代码可以在我的Github找到,今天在宿舍,还没有上传代码,明天到了实验室再跑一下示例代码。

游戏开发路途遥远,但我相信只要坚持,总能到达彼岸!

如果我的文章对于你学习DirectX11有点帮助,欢迎评论给出建议,让我们一起学习进步!

                                                                                               ———————— 小明 2018.11.30 22.04

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值