DirectX 9 - 以精确尺寸绘制2D精灵

时间:2017-11-06 06:00:32

标签: windows 2d directx sprite directx-9

我正在尝试使用DirectX9构建一个简单的2D游戏,我希望能够使用精灵尺寸和坐标而不应用缩放。

我正在关注的这本书(由Frank Luna撰写的“使用DirectX 9.0c进行3D游戏编程简介”)展示了使用Direct3D的精灵函数在2D中渲染图形的技巧,但书籍代码仍然使用D3DXMatrixLookAtLH设置摄像机和D3DXMatrixPerspectiveFovLH,精灵图像以透视方式进行缩放。如何将视图和投影设置为以原始尺寸渲染精灵的位置,并将X-Y坐标作为窗口内的实际像素位置进行寻址?

更新

虽然这可能不是理想的解决方案,但我确实提出了一种解决方法。我意识到如果我将投影矩阵设置为90度视场和近平面z = 0,那么我所要做的就是用D3DXMatrixLookAtRH和步骤查看原点(0,0,0)后退一半的屏幕宽度(Isosceles Right Triangle的高度是基数的一半)。

因此,对于我的客户区域为400 x 400,以下设置对我有用:

// get client rect
RECT R;
GetClientRect(hWnd, &R);
float width  = (float)R.right;
float height = (float)R.bottom;

// step back by 400/2=200 and look at the origin
D3DXMATRIX V;
D3DXVECTOR3 pos(0.0f, 0.0f, (-width*0.5f) / (width/height)); // see "UPDATE 2" below
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
D3DXMatrixLookAtLH(&V, &pos, &target, &up);
d3dDevice->SetTransform(D3DTS_VIEW, &V);

// PI x 0.5 -> 90 degrees, set the near plane to z=0
D3DXMATRIX P;
D3DXMatrixPerspectiveFovLH(&P, D3DX_PI * 0.5f, width/height, 0.0f, 5000.0f);
d3dDevice->SetTransform(D3DTS_PROJECTION, &P);

关闭所有纹理滤镜(或设置为D3DTEXF_POINT)似乎可以获得最佳的像素精确感。

另一个需要注意的重要事项是,请求400 x 400大小的CreateWindowEx()返回的客户区域大小为387 x 362,所以我必须检查GetClientRect(),计算差异并使用SetWindowPos重新调整窗口大小()在最初创建之后。

下面的屏幕截图显示了采取上述步骤的结果。渲染原始位图(右),在应用程序中没有应用缩放/拉伸(左)......最后!

enter image description here

更新2

当宽高比不是1:1时,我没有测试上述方法。我调整了代码 - 你为相机位置退后的数量应该是...... window_width * 0.5 / aspect_ratio(或宽度/高度)。

1 个答案:

答案 0 :(得分:0)

DirectX Tool Kit SpriteBatch类旨在完全按照您的描述进行操作。使用Direct3D绘图时,屏幕坐标为(-1,-1)到(1,1),右上角有(-1,-1)。

这将设置一个矩阵,让您在屏幕坐标中指定右上角的(0,0)。

// Compute the matrix.
float xScale = (mViewPort.Width  > 0) ? 2.0f / mViewPort.Width  : 0.0f;
float yScale = (mViewPort.Height > 0) ? 2.0f / mViewPort.Height : 0.0f;

switch( rotation )
{
case DXGI_MODE_ROTATION_ROTATE90:
    return XMMATRIX
    (
         0,       -yScale,  0,  0,
         -xScale, 0,        0,  0,
         0,       0,        1,  0,
         1,       1,        0,  1
    );

case DXGI_MODE_ROTATION_ROTATE270:
    return XMMATRIX
    (
         0,       yScale,   0,  0,
         xScale,  0,        0,  0,
         0,       0,        1,  0,
        -1,      -1,        0,  1
    );

case DXGI_MODE_ROTATION_ROTATE180:
    return XMMATRIX
    (
        -xScale,  0,       0,  0,
         0,       yScale,  0,  0,
         0,       0,       1,  0,
         1,      -1,       0,  1
    );

default:
    return XMMATRIX
    (
         xScale,  0,       0,  0,
         0,      -yScale,  0,  0,
         0,       0,       1,  0,
        -1,       1,       0,  1
    );
}
  

在Direct3D 9中,像素中心的定义与Direct3D 10/11/12稍有不同,因此传统API中的典型解决方案是在所有位置添加0.5,0.5半中心偏移。您不需要使用Direct3D 10/11/12执行此操作。