简介
假设我有以下顶点:
const VERTEX World::vertices[ 4 ] = {
{ -960.0f, -600.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f }, // side 1 screen coordinates centred
{ 960.0f, -600.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f },
{ -960.0f, 600.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f },
{ 960.0f, 960.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f }
};
您可能已经猜到960 * 2是1920 ..这是我的屏幕宽度,同样600 * 2是1200。
这些顶点代表一个矩形,它将填满我的整个屏幕,原点位于我的屏幕中心。
问题
到目前为止,我一直在使用没有投影的正交视图:
matView = XMMatrixOrthographicLH( Window::width, Window::height, -1.0, 1.0 );
任何发送到屏幕的矩阵都会被matView乘以它看起来效果很好。更具体地说,我的形象;使用上面的顶点数组,紧贴在我的屏幕上,与原始形状的比例为1:1。
不幸的是,我现在需要3D ......我才意识到我需要一些投射...所以我准备了这只小狗:
XMVECTOR vecCamPosition = XMVectorSet( 0.0f, 0.0f, -1.0f, 0 ); // I did try setting z to -100.0f but that didn't work well as I can't scale it back any more... and it's not accurate to the 1:1 pixel I want
XMVECTOR vecCamLookAt = XMVectorSet( 0.0f, 0.0f, 0.0f, 0.0f );
XMVECTOR vecCamUp = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
matView = XMMatrixLookAtLH( vecCamPosition, vecCamLookAt, vecCamUp );
matProjection = XMMatrixPerspectiveFovLH(
XMConvertToRadians( 45 ), // the field of view
Window::width / Window::height, // aspect ratio
1.0f, // the near view-plane
100.0f ); // the far view-plan
你可能已经知道问题是什么......但如果没有,我只是将我的视野设置为45度..这将是一个很好的视角,并且做了很多的东西,但是我的顶点数组是没有的更长时间切割芥末... 因为fov和屏幕方面已经大大减少(或增加)所以顶点对于我正在观察的当前视图来说太大了(见图)
我在想我需要对输出矩阵进行一些缩放,以便将巨大的坐标缩放到我的fov和屏幕方面现在要求的相应大小。
我必须做什么来原样使用顶点数组(与原始图像大小的像素比为1:1),同时仍然允许3d内容发生,就像在屏幕上飞行并旋转并靠近并进一步进入frustrum等......
目标
我试图避免将每个单个对象顶点数组更改为粗略缩放预测原始图像在世界空间中的样子。
一些额外信息
我只是想澄清一下我目前正在对世界做什么样的矩阵运算,然后我如何使用这些变化进行渲染...所以这就是我在我的大背景图片上做了一些翻译:
// flipY just turns the textures back around
// worldTranslation is actually the position for the background, so always 0,0,0... as you can see 0.5 was there to make sure I ordered things that were drawn correctly when using orthographic
XMMATRIX worldTranslation = XMMatrixTranslation( 0.0f, 0.0f, 0.5f );
world->constantBuffer.Final = flipY * worldTranslation * matView;
// My thoughts are on this that somehow I need to add a scaling to this matrix...
// but if I add scaling here... it's going to mean every other game object
// (players, enemies, pickups) are going to need to be scaled... and really I just want to
// have to scale the whole lot the once.. right?
最后这就是它被画到屏幕上的地方:
// Background
d3dDeviceContext->PSSetShaderResources( 0, 1, world->textures[ 0 ].GetAddressOf( ) ); // Set up texture of background
d3dDeviceContext->IASetVertexBuffers( 0, 1, world->vertexbuffer.GetAddressOf( ), &stride, &offset ); // Set up vertex buffer (do I need the scaling here?)
d3dDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // How the vertices be drawn
d3dDeviceContext->IASetIndexBuffer( world->indexbuffer.Get( ), DXGI_FORMAT_R16_UINT, 0 ); // Set up index buffer
d3dDeviceContext->UpdateSubresource( constantbuffer.Get( ), 0, 0, &world->constantBuffer, 0, 0 ); // set the new values for the constant buffer
d3dDeviceContext->OMSetBlendState( blendstate.Get( ), 0, 0xffffffff ); // DONT FORGET IF YOU DISABLE THIS AND YOU WANT COLOUR, * BY Color.a!!!
d3dDeviceContext->DrawIndexed( ARRAYSIZE( world->indices ), 0, 0 ); // draw
然后我做了什么来应用我的matProjection,它已经超越了我的所有顶点
world->constantBuffer.Final = flipY * worldTranslation * matView * matProjection; // My new lovely projection and view that make everything hugeeeee... I literally see like 1 pixel of the background brah!
请随意复制我的游戏并按原样运行(Windows 8应用程序Visual Studio 2013快速项目),希望您可以帮助我将所有内容整合到3D中: https://github.com/jimmyt1988/FlyGame/tree/LeanerFramework/Game
答案 0 :(得分:0)
<强> 1 强>
这是我的编辑的一个小截图:
我用小黑框编辑了一些东西。您在周围看到的轴圆圈以完全相同的尺寸呈现。但是,它们是通过透视投影渲染的。正如你所看到的那样,最左边的那个像中心那个大两倍。这完全是由于这样的投影的性质。如果这是不可接受的,则必须使用非透视投影。
<强> 2 强>
保持屏幕空间与uv空间的1:1
比率的唯一方法是在纹理上每1像素在屏幕上以1像素渲染对象。没有什么比这更重要了。但是,您可以做的是更改纹理过滤器选项。过滤器选项是具体的设计,用于呈现非1:1
比率。例如,代码:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
告诉opengl:“如果你被告知要对一个像素进行采样,请不要插入任何内容。只需在纹理上取最近的值并将其粘贴在屏幕上。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
然而,这段代码做得更好:它在像素之间进行插值。如果您还没有这样做,我想这可能就是您想要的。
这些照片(摘自http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/)显示:
最近的:
线性:
这就是它归结为什么。你要求:
我必须做什么才能使用顶点数组(与原始图像大小的像素比为1:1),同时仍然允许3d内容发生,就像在屏幕上飞行并旋转并且更接近并进一步进入frustrum等...
根据定义,您所要求的是不可能的,因此您必须寻找替代解决方案。我希望这有所帮助。