Как нарисовать два отдельных прямоугольника в DirectX с использованием примитивного типа D3DPT_TRIANGLESTRIP - PullRequest
3 голосов
/ 28 августа 2009

Я новичок в DirectX и пытаюсь нарисовать два прямоугольника в одной сцене, используя D3DPT_TRIANGLESTRIP. Один прямоугольник не проблема, но два прямоугольника - совершенно другая игра с мячом. Да, я мог бы нарисовать их, используя четыре треугольника, нарисованных примитивным типом D3DPT_TRIANGLELIST. Мое любопытство связано с техникой использования D3DPT_TRIANGLESTRIP. Части кода, который я использую для одного прямоугольника, используя D3DPT_TRIANGLESTRIP, выглядит следующим образом:

CUSTOMVERTEX recVertex[] = {
    {  10.0f,  10.0f, 0.10f, 1.0f, 0xffffffff, }, // x, y, z, rhw, color
    { 220.0f,  10.0f, 0.10f, 1.0f, 0xffffffff, },   
    {  10.0f, 440.0f, 0.10f, 1.0f, 0xffffffff, },   
    { 220.0f, 440.0f, 0.10f, 1.0f, 0xffffffff, },
}; 

if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4 * sizeof( CUSTOMVERTEX ),
               0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
    return E_FAIL;
}

Более жизненно важный код ...

VOID* precVertex;    
if( FAILED( g_pVB->Lock( 0, sizeof( recVertex ), ( void** )&pGameField, 0 ) ) ) 
{
return E_FAIL; 
}
 memcpy( precVertex, recVertex, sizeof( recVertex ) );

затем сделать так, как ...

g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

На основе этой модели я мог бы легко продублировать код, изменить значения x и y в пользовательской вершине и создать еще один буфер вершин, и он будет работать.

Лично я чувствую, что это не лучший путь, особенно учитывая ситуацию, когда мне приходится рисовать, скажем, 100 прямоугольников или что-то в этом роде. Дело в том, что у меня нет других идей. Итак, мой вопрос: как наиболее эффективно нарисовать два прямоугольника с D3DPT_TRIANGLESTRIP? Также возможен ли способ дублирования и преобразования текущего прямоугольника?

Ответы [ 4 ]

3 голосов
/ 28 августа 2009

Самый эффективный способ - использовать индексированное рисование, а затем повторять индексы между двумя прямоугольниками.

то есть индексы 0, 1, 2, 3, 3, 4, 4, 5, 6, 7 производят следующие треугольники из зачистки треугольника

0, 1, 2 - 1, 2, 3 - 2, 3, 3 - 3, 3, 4 - 3, 4, 4 - 4, 4, 5 - 4, 5, 6 - 5, 6, 7

треугольники 2, 3, 3 - 3, 3, 4 - 3, 4, 4 и 4, 4, 5 - все имеют нулевую площадь и будут отброшены очень рано на видеокарте. Таким образом, вы получите 4 треугольника, отображаемых за один вызов DrawIndexedPrimitive.

Конечно, это означает, что вы отправляете 10 индексов. Вы также можете просто отправить 12 индексов и нарисовать оба прямоугольника как 4 треугольника в списке три. При использовании индексированного чертежа вы обнаружите, что аппаратное обеспечение отслеживает, какие вершины оно уже преобразовало, чтобы ему больше не пришлось беспокоиться.

т.е. если вы определите свой индексный буфер как

0, 1, 2, 3, 0, 2, 4, 5, 6, 7, 4, 6

и у вас есть кэш посттрансформирования, по крайней мере, с 4 вершинами (почти каждая графическая карта имеет значительно больший кэш посттрансформации, конечно, GeForce 3!) будет преобразован только один раз. Неудобно на любом оборудовании после DX8 (то есть на любом оборудовании DX9 или 10) вы обнаружите, что использование этого кеша после преобразования и дополнительная простота списков треугольников означает, что вы на самом деле получите ЛУЧШУЮ производительность из списка треугольников, чем треугольника полоса.

Итак, в заключение, отвечая на вопрос "Итак, мой вопрос: как наиболее эффективно нарисовать два прямоугольника с помощью D3DPT_TRIANGLESTRIP?" ответ - нарисовать D3DPT_TRIANGLELIST и перестать беспокоиться об этом:)

1 голос
/ 28 августа 2009

Вы можете продлить recVertex до 8 баллов. Это обычная техника. 3D-оборудование предназначено для работы именно в таком режиме. Посмотрите этот учебник, например.

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

1 голос
/ 28 августа 2009

Добавьте четыре вершины для второго прямоугольника в буфер вершин, затем дважды вызовите DrawPrimitive.

g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 4, 2 );
0 голосов
/ 03 сентября 2009

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

Для крошечной геометрии и фиксированной функции, подобной этой, вам определенно следует складывать всю партию в один буфер.

...