В 2D-платформенной игре я хочу визуализировать ограничительную рамку, созданную мной для облегчения отладки. Как я могу это сделать в Visual C++ 2012?
Сначала определим простую структуру вершин:
struct Vertex
{
D3DXVECTOR3 position; //a 3D point even in 2D rendering
};
Теперь вы можете создавать массивы вершин и индексов:
Vertex *vertices;
unsigned long *indices = new unsigned long[5];
D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
D3D11_SUBRESOURCE_DATA vertexData, indexData;
//create the vertex array
vertices = new Vertex[5];
if(!vertices)
{
//handle error
}
//load the vertex array with data
vertices[0].position = D3DXVECTOR3(left, top, 0.0f);
vertices[1].position = D3DXVECTOR3(right, top, 0.0f);
vertices[2].position = D3DXVECTOR3(right, bottom, 0.0f);
vertices[3].position = D3DXVECTOR3(left, bottom, 0.0f);
vertices[4].position = D3DXVECTOR3(left, top, 0.0f);
//create the index array
indices = new unsigned long[5];
if(!indices)
{
//handle error
}
//load the index array with data
for(i=0; i<5; i++)
indices[i] = i;
И загрузите их в буферы:
ID3D11Buffer *vertexBuffer, *indexBuffer;
HRESULT result;
//set up the description of the dynamic vertex buffer
vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; //enables recreation and movement of vertices
vertexBufferDesc.ByteWidth = sizeof(Vertex) * 5;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; //couples with dynamic
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
//give the subresource structure a pointer to the vertex data
vertexData.pSysMem = vertices;
vertexData.SysMemPitch = 0;
vertexData.SysMemSlicePitch = 0;
//now create the vertex buffer
result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &vertexBuffer);
if(FAILED(result))
{
//handle error
}
//set up the description of the static index buffer
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(unsigned long) * 5;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;
//give the subresource structure a pointer to the index data
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;
//create the index buffer
result = device->CreateBuffer(&indexBufferDesc, &indexData, &indexBuffer);
if(FAILED(result))
{
//handle error
}
Настройте прямоугольник, который будет отображаться следующим образом:
unsigned int stride = sizeof(Vertex);
unsigned int offset = 0;
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
deviceContext->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP);
Теперь визуализируйте с помощью шейдера по вашему выбору, не забывая передать орфографическую матрицу в шейдер вместо перспективной матрицы. Вуаля! Прямоугольник. Но вы еще не можете его перенести... Вы должны определить другую функцию для этого:
bool UpdateRectBuffers(ID3D11Buffer *vertexBuffer, ID3D11DeviceContext *deviceContext, float top, float left, float bottom, float right)
{
Vertex *vertices;
D3D11_MAPPED_SUBRESOURCE mappedResource;
VertexType *verticesPtr;
HRESULT result;
//create a temporary vertex array to fill with the updated data
vertices = new Vertex[5];
if(!vertices)
{
return false;
}
vertices[0].position = D3DXVECTOR3(left, top, 0.0f);
vertices[1].position = D3DXVECTOR3(right, top, 0.0f);
vertices[2].position = D3DXVECTOR3(right, bottom, 0.0f);
vertices[3].position = D3DXVECTOR3(left, bottom, 0.0f);
vertices[4].position = D3DXVECTOR3(left, top, 0.0f);
//lock the vertex buffer so it can be written to
result = deviceContext->Map(vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if(FAILED(result))
{
return false;
}
verticesPtr = (Vertex*)mappedResource.pData;
//copy the data into the vertex buffer
memcpy(verticesPtr, (void*)vertices, (sizeof(Vertex) * 5));
deviceContext->Unmap(vertexBuffer, 0);
delete [] vertices;
vertices = 0;
return true;
}
Зависимости этого кода: float top
, float left
, float right
, float left
, ID3D11DeviceContext *deviceContext
и ID3D11Device *device
.
Поскольку вы не хорошо описали, что вы уже можете сделать, мой ответ основан на некоторых предположениях.
Итак, я предполагаю, что
и не объяснит, как это сделать.
Вариант 1: вам не нужно ничего особенного для рисования краев. "Края" (прямые) - это просто длинные и тонкие прямоугольники. Итак, вам нужно положить 4 тонких прямоугольника на место, где должны быть ваши края.
Таким образом, вы можете выбрать толщину, цвет линии и даже использовать текстуру (пунктирные линии, пунктирные линии, линии с розовыми котятами и т.д.) Или эффекты шейдера, такие как процедурная окраска, сглаживание, размытие и т.д. В любом случае вам, вероятно, понадобится линии для вашей игры.
Вариант 2: вы можете рисовать линии вместо треугольников. Используйте примитивную топологию "line list" вместо "списка треугольников". (См.: ID3D11DeviceContext :: IASetPrimitiveTopology(), D3D11_PRIMITIVE_TOPOLOGY_LINELIST).
Таким образом вы не можете настраивать вещи. Но это намного проще.
Вариант 3: Нарисуйте прямоугольник в режиме каркаса. Просто настройте режим заполнения растеризатора. См.: ID3D11DeviceContext :: RSSetState, D3D11_RASTERIZER_DESC :: FillMode, D3D11_FILL_MODE :: D3D11_FILL_WIREFRAME
Вы получите края треугольников, даже те, которые являются диагоналями прямоугольника. Таким образом, вы не можете установить ни толщину, ни цвет. Но этот способ действительно, очень простой.
Вариант 4: используйте любую 2D-библиотеку чертежей, которая будет использовать для вас вариант 1. Поскольку D3DX устарел, больше не рекомендуется использовать D3DXLine. Вы можете попробовать DirectX toolkit или любую библиотеку, доступную в Интернете. Очевидно, что вы получите дополнительную зависимость.
Если мои первоначальные предположения были неправильными, то вы не получите ответ здесь. Ни один человек из StackOverflow не объяснит вам такие основные вещи. Чтобы исправить ситуацию:
Надеюсь, поможет!
ID3DXLine
который может вас заинтересовать.