在其中心的2D纹理中实现旋转

时间:2018-05-24 18:53:30

标签: directx-11

我还在学习Directx 11。

我正在关注Rastertek Directx 11教程11,我能够在屏幕上渲染2D纹理,这里是教程的链接:http://www.rastertek.com/dx11tut11.html

我想知道如何在轴的中心旋转这个纹理。我不知道从哪里开始。我尝试使用z旋转矩阵使其旋转,但它不会围绕其中心旋转,而是围绕其他地方旋转。

我的猜测是我们必须在GraphicsClass :: Render

中添加旋转
bool GraphicsClass::Render(float rotation)
{
    D3DXMATRIX worldMatrix, viewMatrix, projectionMatrix, orthoMatrix;
    bool result;


    // Clear the buffers to begin the scene.
    m_D3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);

    // Generate the view matrix based on the camera's position.
    m_Camera->Render();

    // Get the world, view, projection, and ortho matrices from the camera and d3d objects.
    m_Camera->GetViewMatrix(viewMatrix);
    m_D3D->GetWorldMatrix(worldMatrix);
    m_D3D->GetProjectionMatrix(projectionMatrix);
    m_D3D->GetOrthoMatrix(orthoMatrix);

    // Turn off the Z buffer to begin all 2D rendering.
    m_D3D->TurnZBufferOff();

    // Put the bitmap vertex and index buffers on the graphics pipeline to prepare them for drawing.
    result = m_Bitmap->Render(m_D3D->GetDeviceContext(), 100, 100);
    if(!result)
    {
        return false;
    }

    // Render the bitmap with the texture shader.
    result = m_TextureShader->Render(m_D3D->GetDeviceContext(), m_Bitmap->GetIndexCount(), worldMatrix, viewMatrix, orthoMatrix, m_Bitmap->GetTexture());
    if(!result)
    {
        return false;
    }

    // Turn the Z buffer back on now that all 2D rendering has completed.
    m_D3D->TurnZBufferOn();

    // Present the rendered scene to the screen.
    m_D3D->EndScene();

    return true;
}

bool BitmapClass::Render(ID3D11DeviceContext* deviceContext, int positionX, int positionY)
{
    bool result;


    // Re-build the dynamic vertex buffer for rendering to possibly a different location on the screen.
    result = UpdateBuffers(deviceContext, positionX, positionY);
    if(!result)
    {
        return false;
    }

    // Put the vertex and index buffers on the graphics pipeline to prepare them for drawing.
    RenderBuffers(deviceContext);

    return true;
}


bool BitmapClass::UpdateBuffers(ID3D11DeviceContext* deviceContext, int positionX, int positionY)
{
    float left, right, top, bottom;
    VertexType* vertices;
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    VertexType* verticesPtr;
    HRESULT result;


    // If the position we are rendering this bitmap to has not changed then don't update the vertex buffer since it
    // currently has the correct parameters.
    if((positionX == m_previousPosX) && (positionY == m_previousPosY))
    {
        return true;
    }

    // If it has changed then update the position it is being rendered to.
    m_previousPosX = positionX;
    m_previousPosY = positionY;

    // Calculate the screen coordinates of the left side of the bitmap.
    left = (float)((m_screenWidth / 2) * -1) + (float)positionX;

    // Calculate the screen coordinates of the right side of the bitmap.
    right = left + (float)m_bitmapWidth;

    // Calculate the screen coordinates of the top of the bitmap.
    top = (float)(m_screenHeight / 2) - (float)positionY;

    // Calculate the screen coordinates of the bottom of the bitmap.
    bottom = top - (float)m_bitmapHeight;

    // Create the vertex array.
    vertices = new VertexType[m_vertexCount];
    if(!vertices)
    {
        return false;
    }

    // Load the vertex array with data.
    // First triangle.
    vertices[0].position = D3DXVECTOR3(left, top, 0.0f);  // Top left.
    vertices[0].texture = D3DXVECTOR2(0.0f, 0.0f);

    vertices[1].position = D3DXVECTOR3(right, bottom, 0.0f);  // Bottom right.
    vertices[1].texture = D3DXVECTOR2(1.0f, 1.0f);

    vertices[2].position = D3DXVECTOR3(left, bottom, 0.0f);  // Bottom left.
    vertices[2].texture = D3DXVECTOR2(0.0f, 1.0f);

    // Second triangle.
    vertices[3].position = D3DXVECTOR3(left, top, 0.0f);  // Top left.
    vertices[3].texture = D3DXVECTOR2(0.0f, 0.0f);

    vertices[4].position = D3DXVECTOR3(right, top, 0.0f);  // Top right.
    vertices[4].texture = D3DXVECTOR2(1.0f, 0.0f);

    vertices[5].position = D3DXVECTOR3(right, bottom, 0.0f);  // Bottom right.
    vertices[5].texture = D3DXVECTOR2(1.0f, 1.0f);

    // Lock the vertex buffer so it can be written to.
    result = deviceContext->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if(FAILED(result))
    {
        return false;
    }

    // Get a pointer to the data in the vertex buffer.
    verticesPtr = (VertexType*)mappedResource.pData;

    // Copy the data into the vertex buffer.
    memcpy(verticesPtr, (void*)vertices, (sizeof(VertexType) * m_vertexCount));

    // Unlock the vertex buffer.
    deviceContext->Unmap(m_vertexBuffer, 0);

    // Release the vertex array as it is no longer needed.
    delete [] vertices;
    vertices = 0;

    return true;
}

void BitmapClass::RenderBuffers(ID3D11DeviceContext* deviceContext)
{
    unsigned int stride;
    unsigned int offset;


    // Set vertex buffer stride and offset.
    stride = sizeof(VertexType); 
    offset = 0;

    // Set the vertex buffer to active in the input assembler so it can be rendered.
    deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);

    // Set the index buffer to active in the input assembler so it can be rendered.
    deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);

    // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
    deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    return;
}

如何围绕纹理中心旋转纹理?

1 个答案:

答案 0 :(得分:0)

不完全。它比那更微妙。让我先介绍一下转换的基础知识。

在DirectX和3D图形中,转换通常由4x4仿射变换矩阵表示,该矩阵执行三个连续的几何变换:一个从局部空间到世界空间(世界矩阵),一个从世界空间到以摄像机为中心的空间(视图矩阵),一个从以摄像机为中心的空间到“同质的剪辑空间”(投影矩阵)。您通常会听到这被称为WVP( W orld- V iew- P 投影)矩阵。

单个变换矩阵是通过将构成它的每个变换矩阵相乘来创建的。该乘法过程不是可交换的,意味着矩阵AB与矩阵BA不同。在变换的上下文中,AB应用变换A然后变换B,而BA应用变换B然后变换A.如果A是绕Z旋转45度,并且b是沿X的3个单位的平移,则AB将旋转将物体放置45度并将其放置在右侧3个单位,而BA将物体向右移动3个单位并将其向左摆动45度,就像它通过条形连接到原点一样。下图以图形方式显示。

RxT vs. TxR

现在我们已经处理了基础知识,让我们继续讨论实际的代码。

仔细观察,我可以看到你对这个问题的初步假设是对是错 - 你弄清楚问题是什么,但是错误解释了原因。

第一个主要问题 - 您的几何体完全在世界空间中指定。如果几何体永远不会移动,这很好,但这个问题的重点是让所述几何体移动,所以......

要解决这个问题,请以最简单的方式构建您的形状:以原点为中心,边长为1.这会将四个角改变为以下,假设+ X在右边,+ Y在向上,并且+ Z离开(进入屏幕):( - 0.5,5,0),(0.5,0.5,0),( - 0.5,-0.5,0),(0.5,-0.5,0)。它们分别代表左上角,右上角,左下角和右下角。

这也允许你在构造函数中创建一次顶点缓冲区,之后再也不需要再次更新它,即使图像的大小在运行时也会发生变化。

其次,由于几何的原始规格已经在世界空间中,我们不需要现实世界矩阵。既然我们的几何是一个围绕当地起源的单位正方形,我们就是这样做的。为了获得与源位图大小相同的图像,我们制作了一个缩放矩阵,在X轴上缩放m_bitmapWidth,在Y轴上缩放m_bitmapHeight。然后我们将它乘以围绕Z轴的旋转矩阵来旋转它,最后将它乘以平移矩阵以将其移动到positionXpositionY。我们可以按如下方式重写UpdateBuffers

bool BitmapClass::UpdateBuffers(int positionX, int positionY, float rotationAngle)
{
    D3DXMATRIX scaling, rotation, translation, worldMatrix;
    // If the position we are rendering this bitmap to has not changed,
    // don't update the world matrix since it currently has the correct 
    // parameters.
    if((positionX == m_previousPosX) && (positionY == m_previousPosY))
    {
        return true;
    }
    // If it has changed then update the position it is being rendered to.
    m_previousPosX = positionX;
    m_previousPosY = positionY;

    // scale, rotate, and translate our unit square
    D3DXMatrixScaling(&scaling, m_bitmapWidth, m_bitmapHeight, 1);
    D3DXMatrixRotationZ(&rotation, rotationAngle);
    D3DXMatrixTranslation(&translation, positionX, positionY, 0);

    //Now concatenate all the transformations together,
    D3DXMatrixMultiply(&worldMatrix, &scaling, &rotation);
    D3DXMatrixMultiply(&worldMatrix, &worldMatrix, &translation);

    // And tell D3D this is our new world matrix.
    m_D3D->SetWorldMatrix(worldMatrix);

    return true;
}

最后一次修改是删除UpdateBuffersBitmapClass::Render的来电,并在致电GetWorldMatrix之前拨打电话。这将确保渲染过程使用适当的变换矩阵。