如何将世界坐标转换为屏幕坐标

时间:2014-01-08 01:26:45

标签: c++ directx-11 coordinate-transformation

我正在创建一个在3d世界中有2d图片的游戏。

我最初开始时并不关心我的图像被拉伸到正方形,而我更多地了解了游戏机制的工作方式......但是现在是时候让我的纹理以正确的比例和......尺寸显示。

只是一个侧面说明,我玩过正交左手投影,但我注意到你不能做那个...(我想这有道理......但我可能是错的,我试过它,当我旋转了我的形象,它变得有弹性和怪异。)

我的游戏性质如下:

enter image description here

在图像中它显示-1.0到1.0 ...如果坐标是:

,我不会被打扰
  • topleft = 0,0,0
  • 右下= 1920,1200,0

但是,如果这是解决方案,那么无论如何...... (ps目前没有设置游戏,所以-1.0和1.0左右是屏幕。实际上我不知道我怎么回事使屏幕边界(但这是另一天的问题)


问题:

我遇到的问题是我的播放器(2d)的图像是 128 x 64 像素。在世界矩阵乘法(我认为它就是这样)之后,我放入的顶点大大地扩展了我的纹理......这很有意义但它看起来很丑陋而且我不想只是将一个巨大的缩放矩阵打入混合中,因为它很难弄清楚如何将纹理1:1设置为我的屏幕像素(尽管你可能会告诉我它实际上是如何做到的,但是你需要做一个聪明的公式来计算出缩放应该是什么)。

但基本上,我希望顶点保持我图像的1:1像素大小,未拉伸......

所以我假设我需要在输出纹理和顶点之前将我的世界坐标转换为屏幕坐标?我不确定它是如何工作的......

无论如何,这是我的顶点..你可能会注意到我做了什么:

struct VERTEX
{
    float X, Y, Z;
    //float R, G, B, A;
    float NX, NY, NZ;
    float U, V;          // texture coordinates
};

const unsigned short SquareVertices::indices[ 6 ] = {
    0, 1, 2,    // side 1
    2, 1, 3
};

const VERTEX SquareVertices::vertices[ 4 ] = {
        //{ -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f,  0.0f, 0.0f },    // side 1
        //{ 1.0f, -1.0f, 0.0f,  0.0f, 0.0f, -1.0f,  1.0f, 0.0f },
        //{ -1.0f, 1.0f, 0.0f,  0.0f, 0.0f, -1.0f,  0.0f, 1.0f },
        //{ 1.0f, 1.0f, 0.0f,       0.0f, 0.0f, -1.0f,  1.0f, 1.0f }

    { -64.0f, -32.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f },    // side 1
    { 64.0f, -32.0f, 0.0f,  0.0f, 0.0f, -1.0f, 1.0f, 0.0f },
    { -64.0f, 32.0f, 0.0f,  0.0f, 0.0f, -1.0f, 0.0f, 1.0f },
    { 64.0f, 64.0f, 0.0f,   0.0f, 0.0f, -1.0f, 1.0f, 1.0f }
};

(128像素/ 2 = 64),(64/2 = 32),因为中心是0.0 ......但是我需要做些什么来进行投影,世界的跨界以及什么不能让世界变成屏幕呢? / p>

我目前的设置如下:

// called 1st
void Game::SetUpViewTransformations( )
{
    XMVECTOR vecCamPosition = XMVectorSet( 0.0f, 0.0f, -20.0f, 0 );
    XMVECTOR vecCamLookAt = XMVectorSet( 0, 0, 0, 0 );
    XMVECTOR vecCamUp = XMVectorSet( 0, 1, 0, 0 );
    matView = XMMatrixLookAtLH( vecCamPosition, vecCamLookAt, vecCamUp );
}

// called 2nd
void Game::SetUpMatProjection( )
{
    matProjection = XMMatrixPerspectiveFovLH(
        XMConvertToRadians( 45 ),                                      // the field of view
        windowWidth / windowHeight,  // aspect ratio
        1,                                                           // the near view-plane
        100 );                                                        // the far view-plan
}

这里是一个偷偷摸摸的看我的更新和渲染方法:

// called 3rd
void Game::Update( )
{
    world->Update();
    worldRotation = XMMatrixRotationY( world->rotation );

    player->Update( );
    XMMATRIX matTranslate = XMMatrixTranslation( player->x, player->y, 0.0f );
    //XMMATRIX matTranslate = XMMatrixTranslation( 0.0f, 0.0f, 1.0f );
    matWorld[ 0 ] = matTranslate;
}

// called 4th
void Game::Render( )
{
    // set our new render target object as the active render target
    d3dDeviceContext->OMSetRenderTargets( 1, rendertarget.GetAddressOf( ), zbuffer.Get( ) );

    // clear the back buffer to a deep blue
    float color[ 4 ] = { 0.0f, 0.2f, 0.4f, 1.0f };
    d3dDeviceContext->ClearRenderTargetView( rendertarget.Get( ), color );
    d3dDeviceContext->ClearDepthStencilView( zbuffer.Get( ), D3D11_CLEAR_DEPTH, 1.0f, 0 ); // clear the depth buffer

        CBUFFER cBuffer;
        cBuffer.DiffuseVector = XMVectorSet( 0.0f, 0.0f, 1.0f, 0.0f );
        cBuffer.DiffuseColor = XMVectorSet( 0.5f, 0.5f, 0.5f, 1.0f );
        cBuffer.AmbientColor = XMVectorSet( 0.2f, 0.2f, 0.2f, 1.0f );
        //cBuffer.Final = worldRotation * matWorld[ 0 ] * matView * matProjection;
        cBuffer.Final = worldRotation * matWorld[ 0 ] * matView * matProjection;
        cBuffer.Rotation = XMMatrixRotationY( world->rotation );

        // calculate the view transformation
        SetUpViewTransformations();
        SetUpMatProjection( );

            //matFinal[ 0 ] = matWorld[0] * matView * matProjection;

            UINT stride = sizeof( VERTEX );
            UINT offset = 0;

                d3dDeviceContext->PSSetShaderResources( 0, 1, player->texture.GetAddressOf( ) ); // Set up texture
                d3dDeviceContext->IASetVertexBuffers( 0, 1, player->vertexbuffer.GetAddressOf( ), &stride, &offset ); // Set up vertex buffer
                d3dDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // How the vertices be drawn
                d3dDeviceContext->IASetIndexBuffer( player->indexbuffer.Get( ), DXGI_FORMAT_R16_UINT, 0 ); // Set up index buffer
                d3dDeviceContext->UpdateSubresource( constantbuffer.Get( ), 0, 0, &cBuffer, 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( player->indices ), 0, 0 ); // draw

    swapchain->Present( 1, 0 );
}

只是为了澄清,如果我使我的顶点使用2和1各自的事实我的图像是128 x 64 ..我得到一个看起来很正常的大小图像..然而在0,0 ,0它不是1:1大小... wadduuuppp buddyyyy

    { -2.0f, -1.0f, 0.0f,   0.0f, 0.0f, -1.0f,  0.0f, 0.0f },    // side 1
    { 2.0f, -1.0f, 0.0f,    0.0f, 0.0f, -1.0f,  1.0f, 0.0f },
    { -2.0f, 1.0f, 0.0f,    0.0f, 0.0f, -1.0f,  0.0f, 1.0f },
    { 2.0f, 2.0f, 0.0f,     0.0f, 0.0f, -1.0f,  1.0f, 1.0f }

期望的结果2 teh max:

enter image description here

酷图片不是吗?D?

评论帮助:

enter image description here

1 个答案:

答案 0 :(得分:0)

我不喜欢direct-x,但据我所知,你的图像中的屏幕坐标是x和y上的[-1 ... + 1]。因此,两个轴上的总长度等于2,并且您的图像按比例缩放为2.尝试在相机矩阵中考虑此比例。