Как реализовать статическую пакетную обработку, как в Unity, в DirectX 11

Как пользователь Unity, я не понимаю, как реализовать что-то похожее на их статическую пакетную обработку. Несколько сеток (разные сетки, но один и тот же материал) отображаются как отображаемые в 1 вызове отрисовки, однако я не нахожу, как я мог бы сделать это в DirectX.

Я вижу, как рисовать в DirectX с помощью Draw(). Я знаю, что вы можете рисовать одни и те же меши несколько раз за один вызов (DrawiInstanced()?), однако я не понимаю, как вы можете рисовать несколько разных мешей за один вызов отрисовки. Я бы хотел, чтобы мне указали в правильном направлении или предоставили образец, показывающий, скажем, куб и треугольник, визуализируемые в одном вызове отрисовки с использованием одного материала.

Я использую DirectX11.1 и делаю это через SharpDX, пример SharpDX предпочтительнее, но DX подойдет, однако нет примеров DX9/10, если правильный способ сделать это изменился, меня строго интересует только DX11.

Спасибо.


person Ronan Thibaudau    schedule 11.10.2013    source источник


Ответы (1)


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

В качестве примера, который рисует куб и треугольник, просто настройте свой VB так, чтобы он содержал и то, и другое:

float cubeAndTriangleVertices[] = 
{
  -1, -1, -1, // cube vertices
  -1, -1,  1,
  -1,  1, -1,
  -1,  1,  1,
   1, -1, -1,
   1, -1,  1,
   1,  1, -1,
   1,  1,  1,
   2,  0,  0, // triangle vertices
   2,  1,  0,
   3,  0,  0,
};
D3D11_SUBRESOURCE_DATA cubeAndTriangleVData = { cubeAndTriangleVertices };
device->CreateVertexBuffer(&cubeAndTriangleVData, &vb);

unsigned short cubeAndTriangleIndices[] =
{
  0, 2, 1, 2, 3, 1, // -x face
  7, 6, 5, 6, 4, 5, // +x face
  0, 1, 4, 4, 1, 5, // -y face
  2, 6, 3, 6, 7, 3, // +y face
  6, 2, 0, 4, 6, 0, // -z face
  3, 7, 1, 7, 5, 1, // +z face
  8, 9, 10, // triangle
}

D3D11_SUBRESOURCE_DATA cubeAndTriangleIData = { cubeAndTriangleIndices };
device->CreateIndexBuffer(&cubeAndTriangleIData, &ib);

// ...pipeline setup

context->DrawIndexed(6 * 6 + 3, 0, 0);
person MooseBoys    schedule 11.10.2013
comment
Мне было интересно, как это работает, так как я не видел, как можно отправить несколько мешей, даже если они находились в одном и том же буфере в вызове отрисовки. Правильно ли я понимаю, что это работает, потому что вы рисуете с помощью DrawIndexed и, следовательно, можете указывать лица? До сих пор я использовал только отрисовку (поэтому полигоны рисуются в том порядке, в котором они находятся в буфере), поэтому я не видел, как это было возможно. Правильно ли я предполагаю, что невозможно сделать то же самое без указания лиц? Нет волшебного Draw (Model1Index, Model2Index, Model3Index) или подобного? - person Ronan Thibaudau; 11.10.2013
comment
@RonanThibaudau Вы должны иметь возможность объединять сетки в один и тот же буфер вершин, даже если вы используете неиндексированный вызов Draw (хотя сегодня почти все игры используют DrawIndexed). Чтобы преобразовать код в моем ответе в неиндексированный, вы можете просто создать новый буфер вершин с (6 * 6 + 3) вершинами, каждая со значением, равным vertices[indices[i]]. Ключевой концепцией здесь является то, что D3D на самом деле не заботится о мешах — если у вас есть несколько мешей с одинаковыми шейдерами, текстурами и т. д., то он может рассматривать их как один объект. - person MooseBoys; 11.10.2013
comment
На самом деле, теперь я вижу, где я был сбит с толку, если я отправлю V1 V2 V3 V4 V5 V6, я получу лицо V1 V2 V3 и лицо V4 V5 V6, между вершинами 3 и 4 в любом случае не будет длинной в треугольнике список, я думал о другом макете (три на набор вершин, так что 1 2 3 / 2 3 4 / 3 4 5 и т. д.). Так что я думаю, что вообразил несуществующую проблему. - person Ronan Thibaudau; 11.10.2013