XNA - использование динамического буфера вершин и только четыре (4) вершины - PullRequest
3 голосов
/ 07 июля 2010

Просто быстрый вопрос по рисованию четырехугольников.В настоящее время я использую:

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

Это прекрасно рисует мои четырехугольники, но единственный способ заставить его работать - это использовать шесть (6) вершин для четырехугольников (рисуя их в виде двух треугольников).Мне просто интересно, возможно ли заполнить графический процессор четырьмя (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);

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

1 Ответ

2 голосов
/ 07 июля 2010

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

1---3
|\  |
| \ |
|  \|
0---2
РЕДАКТИРОВАТЬ, чтобы адресовать Ваш измененный вопрос

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

  • Создание буфера: public VertexBuffer ( GraphicsDevice graphicsDevice, int sizeInBytes, BufferUsage usage ) // sizeInBytes зависит от числа примитивов.
  • Вызов Draw: 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 имеет очень хороший, короткийи простой в понимании учебник по вершинным и индексным буферам.

...