Directx Direct3D9全屏应用程序-变形渲染

Directx Direct3D9全屏应用程序-变形渲染,directx,fullscreen,direct3d,direct3d9,Directx,Fullscreen,Direct3d,Direct3d9,我几乎没有在基于Direct3D9的游戏上编写代码。当我遇到一个大问题时,一切都很顺利。我创建了一个类,它封装了从.x文件加载网格的过程。我成功加载了一个只有一个面可见的立方体。理论上,该面应该看起来像一个正方形,但实际上它被渲染为一个矩形。我很确定D3DPRESENT_参数结构有问题。下面是我的应用程序初始化中最重要的几行 要创建的第一个部分是焦点窗口: HWND hWnd = CreateWindowEx(0UL, L"NewFrontiers3DWindowClass", Title.c_

我几乎没有在基于Direct3D9的游戏上编写代码。当我遇到一个大问题时,一切都很顺利。我创建了一个类,它封装了从.x文件加载网格的过程。我成功加载了一个只有一个面可见的立方体。理论上,该面应该看起来像一个正方形,但实际上它被渲染为一个矩形。我很确定D3DPRESENT_参数结构有问题。下面是我的应用程序初始化中最重要的几行

要创建的第一个部分是焦点窗口:

HWND hWnd = CreateWindowEx(0UL, L"NewFrontiers3DWindowClass", Title.c_str(), WS_POPUP | WS_EX_TOPMOST, 0, 0, 1280, 1024, nullptr, (HMENU)false, hInstance, nullptr);
然后填写D3DPRESENT_参数结构

D3DDISPLAYMODE D3DMM;
SecureZeroMemory(&D3DMM, sizeof(D3DDISPLAYMODE));
if(FAILED(hr = Direct3D9->GetAdapterDisplayMode(Adapter, &D3DMM)))
{
    // Error is processed here
}

PresP.BackBufferWidth = D3DMM.Width;
PresP.BackBufferHeight = D3DMM.Height;
PresP.BackBufferFormat = BackBufferFormat;
PresP.BackBufferCount = 1U;
PresP.MultiSampleType = D3DMULTISAMPLE_NONE;
PresP.MultiSampleQuality = 0UL;
PresP.SwapEffect = D3DSWAPEFFECT_DISCARD;
PresP.hDeviceWindow = hWnd;
PresP.Windowed = false;
PresP.EnableAutoDepthStencil = EnableAutoDepthStencil;
PresP.AutoDepthStencilFormat = AutoDepthStencilFormat;
PresP.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
PresP.FullScreen_RefreshRateInHz = D3DMM.RefreshRate;
PresP.PresentationInterval = PresentationInterval;
然后创建Direct3D9设备,然后创建SetRenderState函数

接下来,将指定视口

D3DVIEWPORT9 D3D9Viewport;
SecureZeroMemory(&D3D9Viewport, sizeof(D3DVIEWPORT9));
    D3D9Viewport.X = 0UL;
    D3D9Viewport.Y = 0UL;
    D3D9Viewport.Width = (DWORD)D3DMM.Width;
    D3D9Viewport.Height = (DWORD)D3DMM.Height;
    D3D9Viewport.MinZ = 0.0f;
    D3D9Viewport.MaxZ = 1.0f;
if(FAILED(Direct3D9Device->SetViewport(&D3D9Viewport)))
{
    // Error is processed here
}
在初始化之后,我全局声明了一些稍后将使用的参数

D3DXVECTOR3 EyePt(0.0f, 0.0f, -5.0f), Up(0.0f, 1.0f, 0.0f), LookAt(0.0f, 0.0f, 0.0f);
D3DXMATRIX View, Proj, World;
更新函数如下所示:

Mesh.Render(Direct3D9Device);

D3DXMatrixLookAtLH(&View, &EyePt, &LookAt, &Up);
Direct3D9Device->SetTransform(D3DTS_VIEW, &View);

D3DXMatrixPerspectiveFovLH(&Proj, D3DX_PI/4, 1.0f, 1.0f, 1000.f);
Direct3D9Device->SetTransform(D3DTS_PROJECTION, &Proj);

D3DXMatrixTranslation(&World, 0.0f, 0.0f, 0.0f);
Direct3D9Device->SetTransform(D3DTS_WORLD, &World);
D3DXMatrixPerspectiveFovLH(&Proj, D3DX_PI/4, (double) D3DMM.Width / D3DMM.Height,
                           1.0f, 1000.f);
设备不是空指针

我最近意识到,声明和设置视图端口与不这样做没有区别


如果有人能给我指出正确的答案,请帮我解决这个恼人的问题。

我认为你的问题不在于D3DPP参数,而在于你的投影矩阵。如果使用D3DXMatrixPerspectiveFovLH,请将纵横比检查为1280/1024=1.3333f

如果未设置任何变换矩阵,则会将标识变换应用于网格,然后立方体的面将拉伸到视口的相同形状。如果您的视口不是方形的,例如,它与屏幕大小相同,则立方体的面也不会是方形的

可以使用方形视口来解决此问题,但这会将渲染限制为仅在屏幕上显示该方形。如果要渲染整个屏幕,需要设置合适的投影矩阵。可以使用D3DXMatrixPerspectiveFovLH计算法线透视矩阵。如果需要正交透视图,无论距离摄影机多远,所有物体都是相同大小的,则使用D3DXMatrixOrthoLH计算透视矩阵。请注意,如果在后面的函数中使用视口的宽度和高度,它将缩小立方体。单位大小的立方体将在屏幕上渲染为单个像素。您可以使用“世界”或“视图”变换将其再次放大,也可以使用“宽度/高度”和“1”作为D3DXMatrixOrthoLH的宽度和高度参数

如果您使用D3DXMatrixPerspectiveFovLH,那么您需要以下内容:

Mesh.Render(Direct3D9Device);

D3DXMatrixLookAtLH(&View, &EyePt, &LookAt, &Up);
Direct3D9Device->SetTransform(D3DTS_VIEW, &View);

D3DXMatrixPerspectiveFovLH(&Proj, D3DX_PI/4, 1.0f, 1.0f, 1000.f);
Direct3D9Device->SetTransform(D3DTS_PROJECTION, &Proj);

D3DXMatrixTranslation(&World, 0.0f, 0.0f, 0.0f);
Direct3D9Device->SetTransform(D3DTS_WORLD, &World);
D3DXMatrixPerspectiveFovLH(&Proj, D3DX_PI/4, (double) D3DMM.Width / D3DMM.Height,
                           1.0f, 1000.f);

如果立方体不完全在视图的中间,由于透视投影,它的前侧不会看起来是正方形。否则,变换矩阵可能会出现问题。立方体位于场景的正中心。更重要的是,我没有使用任何变换矩阵,我还创建了一个视口。这有关系吗?我是做错了还是做错了什么?嗯。。。它不起作用。我还创建了一个视口。这有关系吗?非常感谢您的回复。我试着使用上面提到的函数D3DXMatrixPerspectiveFovLH,我还使用了D3DXMatrixLookAtLH和D3DXMatrixTranslation。问题是我不确定调用这些函数的正确顺序。在update函数中,我按下一个顺序调用它们:D3DXMatrixLookAtLH、D3DXMatrixPerspectiveFovLH、D3DXMatrixTranslation,但这没有帮助。我还使用IDirect3DDevice9::SetTransform在每一个之后。我做得对吗?有什么我错过的吗?你能给我推荐一个好的教程吗?请让我知道。你叫他们什么顺序无关紧要。D3DXMatrix投影函数将根据请求的变换填充矩阵,覆盖矩阵中以前的任何值。设置转换矩阵后,立即使用适当的参数调用SetTransform。无论调用SetTransform的顺序如何,在绘制网格时,变换都将以正确的顺序应用。要获得更多帮助,您需要发布更多详细信息。试着用一个最小的完整的例子来说明这个问题。我刚刚意识到,如果我使用视口,这并不重要。我现在很确定问题来自更新函数。首先绘制网格,然后按照前面描述的顺序处理变换矩阵。我应该发布矩阵的更新代码吗?发布一个最小的完整的可验证示例:您可以使用D3DXCreateBox在MCVE中创建立方体网格,而不是从文件中加载。这里没有太多代码可发布:创建设备后,我创建的视口的宽度和高度等于D3DPRESENT_参数结构中指定的宽度和高度。然后我加载了一个在DirectX官方样本中测试过的立方体,它的工作完全没有问题。在此之后,我首先绘制立方体,然后更新矩阵。我将编辑这个问题以发布更多代码。请检查一下。