绘制带纹理的四边形看起来变形了
Drawing a textured quad looks distorted
我正在阅读名为 Introduction To 3D Game Programming With Directx 9.0
的书,我已经从书中复制并粘贴了以下示例:
struct Vertex
{
float _x, _y, _z;
float _nx, _ny, _nz;
float _u, _v; // texture coordinates
static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
void D3DGraphics::drawBMP()
{
pDevice->CreateVertexBuffer(6 * sizeof(Vertex), D3DUSAGE_WRITEONLY, Vertex::FVF, D3DPOOL_MANAGED, &quadVertexBuffer, 0);
Vertex* v;
quadVertexBuffer->Lock(0, 0, (void**)&v, 0);
// quad built from two triangles, note texture coordinates:
v[0] = { -1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f }; // was Vertex()
v[1] = { -1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f };
v[2] = { 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f };
v[3] = { -1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f };
v[4] = { 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f };
v[5] = { 1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f };
quadVertexBuffer->Unlock();
// Load texture data.
if (!texture)
{
D3DXCreateTextureFromFile(pDevice, L"C:\Users\Owner\Desktop\Result.bmp", &texture);
}
// Enable the texture.
pDevice->SetTexture(0, texture);
// Set texture filters.
pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
pDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
// set projection matrix
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * 0.5f, (float)1280 / (float)720, 1.0f, 1000.0f);
pDevice->SetTransform(D3DTS_PROJECTION, &proj);
// don't use lighting for this sample
pDevice->SetRenderState(D3DRS_LIGHTING, false);
// render code
pDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
pDevice->BeginScene();
pDevice->SetStreamSource(0, quadVertexBuffer, 0, sizeof(Vertex));
pDevice->SetFVF(Vertex::FVF);
// Draw primitives using presently enabled texture.
pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
pDevice->EndScene();
pDevice->Present(0, 0, 0, 0);
}
我只改变了一件事。书中的结构体是这样初始化的:
v[0] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
v[1] = Vertex(-1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
v[2] = Vertex( 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
v[3] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
v[4] = Vertex( 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
v[5] = Vertex( 1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);
但这似乎会导致编译器错误,所以我在我的代码中进行了更改。总之,Result.bmp 的尺寸是 1280x720。我正在渲染的 window 也是 1280x720。这是 Result.bmp. Here is the output 我得到的。通常我不会问这么简单的问题,但我正在努力学习,这是一个直接来自教科书的例子(这是行不通的)。考虑到这是书中的复制和粘贴,我认为我(还)没有犯任何错误,我想知道这是否是书中的错误。如果我将 0.5f 更改为 0.4f,那么玩转 D3DXMatrixPerspectiveFovLH
的第二个参数似乎会让事情变得更好,但它仍然失真。
由于您使用的是 D3DXMatrixPerspectiveFovLH
,因此您正在渲染一个带有角 (-1,-1) -> (1,1) 的方形四边形。由于BMP有一个16:9 aspect ratio,结果是一个扭曲的纹理图像。
如果想让图片全屏,需要使用非透视投影如D3DXMatrixOrthoLH
:
// set projection matrix
D3DXMATRIX proj;
D3DXMatrixOrthoLH(&proj, 2.0f, 2.0f, 1.0f, 1000.0f);
pDevice->SetTransform(D3DTS_PROJECTION, &proj);
在这种情况下,同一个四边形将具有使输入图像消除失真所需的 16:9 纵横比。
顺便说一句:我建议转向 DirectX 11 并使用 DirectX Tool Kit 的 SpriteBatch
而不是十年前的 Direct3D 9 API...
我正在阅读名为 Introduction To 3D Game Programming With Directx 9.0
的书,我已经从书中复制并粘贴了以下示例:
struct Vertex
{
float _x, _y, _z;
float _nx, _ny, _nz;
float _u, _v; // texture coordinates
static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
void D3DGraphics::drawBMP()
{
pDevice->CreateVertexBuffer(6 * sizeof(Vertex), D3DUSAGE_WRITEONLY, Vertex::FVF, D3DPOOL_MANAGED, &quadVertexBuffer, 0);
Vertex* v;
quadVertexBuffer->Lock(0, 0, (void**)&v, 0);
// quad built from two triangles, note texture coordinates:
v[0] = { -1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f }; // was Vertex()
v[1] = { -1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f };
v[2] = { 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f };
v[3] = { -1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f };
v[4] = { 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f };
v[5] = { 1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f };
quadVertexBuffer->Unlock();
// Load texture data.
if (!texture)
{
D3DXCreateTextureFromFile(pDevice, L"C:\Users\Owner\Desktop\Result.bmp", &texture);
}
// Enable the texture.
pDevice->SetTexture(0, texture);
// Set texture filters.
pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
pDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
// set projection matrix
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * 0.5f, (float)1280 / (float)720, 1.0f, 1000.0f);
pDevice->SetTransform(D3DTS_PROJECTION, &proj);
// don't use lighting for this sample
pDevice->SetRenderState(D3DRS_LIGHTING, false);
// render code
pDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
pDevice->BeginScene();
pDevice->SetStreamSource(0, quadVertexBuffer, 0, sizeof(Vertex));
pDevice->SetFVF(Vertex::FVF);
// Draw primitives using presently enabled texture.
pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
pDevice->EndScene();
pDevice->Present(0, 0, 0, 0);
}
我只改变了一件事。书中的结构体是这样初始化的:
v[0] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
v[1] = Vertex(-1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
v[2] = Vertex( 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
v[3] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
v[4] = Vertex( 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
v[5] = Vertex( 1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);
但这似乎会导致编译器错误,所以我在我的代码中进行了更改。总之,Result.bmp 的尺寸是 1280x720。我正在渲染的 window 也是 1280x720。这是 Result.bmp. Here is the output 我得到的。通常我不会问这么简单的问题,但我正在努力学习,这是一个直接来自教科书的例子(这是行不通的)。考虑到这是书中的复制和粘贴,我认为我(还)没有犯任何错误,我想知道这是否是书中的错误。如果我将 0.5f 更改为 0.4f,那么玩转 D3DXMatrixPerspectiveFovLH
的第二个参数似乎会让事情变得更好,但它仍然失真。
由于您使用的是 D3DXMatrixPerspectiveFovLH
,因此您正在渲染一个带有角 (-1,-1) -> (1,1) 的方形四边形。由于BMP有一个16:9 aspect ratio,结果是一个扭曲的纹理图像。
如果想让图片全屏,需要使用非透视投影如D3DXMatrixOrthoLH
:
// set projection matrix
D3DXMATRIX proj;
D3DXMatrixOrthoLH(&proj, 2.0f, 2.0f, 1.0f, 1000.0f);
pDevice->SetTransform(D3DTS_PROJECTION, &proj);
在这种情况下,同一个四边形将具有使输入图像消除失真所需的 16:9 纵横比。
顺便说一句:我建议转向 DirectX 11 并使用 DirectX Tool Kit 的 SpriteBatch
而不是十年前的 Direct3D 9 API...