XNA - Использование динамического буфера вершин и только четыре (4) вершины

Небольшой вопрос по рисованию квадрациклов. В настоящее время я использую:

GraphicsDevice.DrawPrimitives(PrimitiveType primitiveType,
                        int startVertex, int primitiveCount);

Это отлично рисует мои квадраты, но единственный способ заставить его работать - это использовать шесть (6) вершин для моих квадратов (рисуя их как два треугольника). Мне просто интересно, можно ли накормить GPU четырьмя (4) вершинами и при этом сохранить мой динамический буфер вершин.

Я знаю, что могу сделать это с помощью DrawUserIndexedPrimitives (), но мне нужен свой буфер! ;)

Изменить: нужно ли мне, и если да, где я могу сообщить своему графическому процессору, что я скармливаю ему четыре вершины на два треугольника? В настоящее время я храню свои квадраты как вершины nQuads * 6 в буфере вершин, а мой графический процессор использует каждые три вершины как треугольник. Таким образом, простое переключение на четыре вершины означает:

Quads: {v1,v2,v3,v4} {v5,v6,v7,v8} ...
Triangles: {v1,v2,v3} {v4,v5,v6} {v7,v8 ...}

Это нехорошо, поскольку в треугольнике номер два используется одна вершина из первого четырехугольника, в третьем - две из второго четырехугольника, и так далее и так далее.

Редактировать 2: Извините, я действительно использую динамический буфер вершин.

Публикуем код о том, как я делаю свои квадроциклы с шестью вершинами:

        // ## CONSTRUCTION
        // Setting up buffer and vertex holder.
        particleVertexBuffer = new DynamicVertexBuffer(graphicsDevice,
            ParticleQuad.VerticesSizeInBytes * nMaxParticles,
            BufferUsage.WriteOnly);
        particleVertices = new ParticleVertex[nMaxParticles * 6];

        // ## ADD VERTICES
        particleVertices[i].Set();
        particleVertices[i+1].Set();
        particleVertices[i+2].Set();
        particleVertices[i+3].Set();
        particleVertices[i+4].Set();
        particleVertices[i+5].Set();


        // ## SET BUFFER
        particleVertexBuffer.SetData(particleVertices, 0, nMaxParticles * 6, SetDataOptions.NoOverwrite);
        graphicsDevice.Vertices[0].SetSource(particleVertexBuffer, 0, ParticleVertex.SizeInBytes);

        // ## DRAW
        graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList,
                    FirstUsedParticle * 6, ((LastUsedParticle - FirstUsedParticle)+1)* 2);

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


person Vectovox    schedule 07.07.2010    source источник
comment
Я не понимаю часть после Edit. Почему nQuads * 6. Что вы имеете в виду под умножением на 6? А что плохого?   -  person Dave O.    schedule 07.07.2010
comment
Если я хочу нарисовать 10 квадратов, это будет означать 60 вершин, поскольку у меня 6 вершин на квадрат. Технически мои 60 вершин - это 20 треугольников. Поэтому я могу представить свой четырехугольник, состоящий из шести вершин, хотя на самом деле это два треугольника, состоящих из трех вершин. Если я вдруг использую только четыре вершины вместо шести, четырехугольник будет состоять из 4/3 треугольников, перекрывающих друг друга.   -  person Vectovox    schedule 07.07.2010
comment
Ваши квадрицепсы связаны друг с другом или вы хотите нарисовать один квад?   -  person Dave O.    schedule 07.07.2010
comment
Визуально они не связаны, но они часть одного буфера, да. Насколько я понимаю, графический процессор берет этот буфер и использует вершины 1-3, 4-6, 7-9 и т. Д. Для рисования треугольников. Я отредактировал код, если это проясняет ситуацию: \   -  person Vectovox    schedule 07.07.2010


Ответы (1)


Да, это возможно. Вам нужно будет использовать TriangleStrip в качестве PrimitiveType. В VertexBuffer вы определяете свои вершины в следующем порядке:

1---3
|\  |
| \ |
|  \|
0---2
EDIT to adress Your modified question

Не знаю, как выглядит Ваш код, но в целом информация о количестве примитивов используется в следующих местах:

  • Создание буфера: public VertexBuffer ( GraphicsDevice graphicsDevice, int sizeInBytes, BufferUsage usage ) // sizeInBytes зависит от количества примитивов.
  • Вызов розыгрыша: public void DrawPrimitives ( PrimitiveType primitiveType, int startVertex, int primitiveCount )

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

Обновлять

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

 (0,1)________(1,1)
     |        |
     |        |
     |________|
 (0,0)        (1,0)

То, что Вы сделали раньше, было следующим:

Vector3 v0, v1, v2, v3;
v0 = new Vector3(0, 0, 0);
v1 = new Vector3(1, 0, 0);
v2 = new Vector3(0, 1, 0);
v3 = new Vector3(1, 1, 0);

List vertices = new List();
//first triangle
vertices.add(v0);
vertices.add(v2);
vertices.add(v1);

//second triangle
vertices.add(v2);
vertices.add(v1);
vertices.add(v3);

VertexBuffer vb = new VertexBuffer(...);
vb.setData(verticesToDraw);

//draw the scene using PrimitiveType.TriangleList and primitive count 2

Что вы делаете сейчас, так это:

//vertices stay the same as in the example above!
List vertices = new List();
vertices.add(v0);
vertices.add(v1);
vertices.add(v2);
vertices.add(v3);

int[] indices = new int[6];
//first triangle
indices[0] = 0;
indices[1] = 2; 
indices[2] = 1;

//second triangle
indices[3] = 2;
indices[4] = 1;
indices[5] = 3;

VertexBuffer vb = new VertexBuffer(...);
IndexBuffer ib = new IndexBuffer(...);

vb.setData(vertices);
ib.setData(indices);

/*draw using the DrawIndexedPrimitives() method rather than the
DrawPrimitives() method and use PrimitiveType.TriangleList and
primitive count 2.*/

Видите ли, вы сохраняете 2 вершины на квадрат, но вместо этого должны использовать 6 индексов, которые определяют порядок построения треугольника из вершин. Таким образом, этот метод полезен только в том случае, если ваши вершины большие (содержат много информации, например, нормали, координаты текстуры и т. Д.) И являются общими для многих треугольников.

Riemers.net имеет действительно красивый, короткий и простой для понимания учебник по буферам вершин и индексов.

person Dave O.    schedule 07.07.2010
comment
Значит ли это, просто изменить мой текущий: - Примитивный тип. - Вершины от 6 до 4 (по вашему заказу) - Изменение расчетов на основе nVertices. Потому что, если так, у меня повсюду очереди. Как будто мой графический процессор не знает, что я хочу, чтобы 4 вершины были двумя треугольниками: / - person Vectovox; 07.07.2010
comment
Какой тип PrimitiveType вы использовали раньше? Думаю, TriangleList? Затем вам нужно будет изменить PrimitiveType и определение вершины (/ create). Единственное место, где я знаю, где XNA хочет знать количество примитивов, - это создание буфера и вызов отрисовки - что вы имеете в виду под всем? - person Dave O.; 07.07.2010
comment
Большое вам спасибо за терпение! Именно тот ответ, который я искал! Моя собственная кастомная вершина довольно велика, так что это как раз то, что мне нужно для оптимизации. Еще раз спасибо! :) - person Vectovox; 07.07.2010