DirectX 11: Как обвести ограничивающий прямоугольник?

0

В 2D-платформенной игре я хочу визуализировать ограничительную рамку, созданную мной для облегчения отладки. Как я могу это сделать в Visual C++ 2012?

  • 0
    DirectX 9, 10 или 11?
  • 0
    В DirectX 9 есть интерфейс ID3DXLine который может вас заинтересовать.
Показать ещё 5 комментариев
Теги:
visual-c++
directx
visual-studio-2012
directx-11

2 ответа

2

Сначала определим простую структуру вершин:

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.

  • 0
    Спасибо за ответ, однако я получаю красные линии. Это говорит о том, что он не определен: {left, top, 0.0}, {right, top, 0.0}, {right, bottom, 0.0}, {left, bottom, 0.0}, { left, top, 0.0} ... Новое ключевое слово здесь говорит: «значение типа unsigned long не может быть инициализировано для объекта unseded long» ... индексы unsigned long = new unsigned long [5] ... и более red линии повсюду. Я что-то пропустил?
  • 0
    Я включил файл D3DXVECTOR3.h.
Показать ещё 9 комментариев
0

Поскольку вы не хорошо описали, что вы уже можете сделать, мой ответ основан на некоторых предположениях.

Предположения

Итак, я предполагаю, что

  • вы можете нарисовать спрайт (т.е. цветной/текстурированный прямоугольник, т.е. квадрат вершин/дуэт треугольников)
  • у вас уже есть данные, которые определяют ограничивающий объем (любым из нескольких способов)

и не объяснит, как это сделать.

Возможные решения

  • Вариант 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 или любую библиотеку, доступную в Интернете. Очевидно, что вы получите дополнительную зависимость.

PS

Если мои первоначальные предположения были неправильными, то вы не получите ответ здесь. Ни один человек из StackOverflow не объяснит вам такие основные вещи. Чтобы исправить ситуацию:

  • Есть два миллиона способов рисовать прямоугольник. Выберите любой учебник онлайн (например: rastertek, braynzarsoft), чтобы получить представление о том, что происходит в части "Возможные решения" этого ответа.
  • Существует два миллиона способов вычисления ограничивающего прямоугольника для каждого из миллионов способов его определения. Обратите внимание, что для определения прямоугольника в 2D-пространстве вам нужно как минимум 2 балла. А для определения двумерной точки вам нужны 2 значения координат. Таким образом, 4 значения на каждый прямоугольник. Google или выберите математическую книгу для дополнительной информации.

Надеюсь, поможет!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню