我还在学习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;
}
如何围绕纹理中心旋转纹理?
答案 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度,就像它通过条形连接到原点一样。下图以图形方式显示。
现在我们已经处理了基础知识,让我们继续讨论实际的代码。
仔细观察,我可以看到你对这个问题的初步假设是对是错 - 你弄清楚问题是什么,但是错误解释了原因。
第一个主要问题 - 您的几何体完全在世界空间中指定。如果几何体永远不会移动,这很好,但这个问题的重点是让所述几何体移动,所以......
要解决这个问题,请以最简单的方式构建您的形状:以原点为中心,边长为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轴的旋转矩阵来旋转它,最后将它乘以平移矩阵以将其移动到positionX
和positionY
。我们可以按如下方式重写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;
}
最后一次修改是删除UpdateBuffers
中BitmapClass::Render
的来电,并在致电GetWorldMatrix
之前拨打电话。这将确保渲染过程使用适当的变换矩阵。