XNA VertexBuffer для редактора ландшафта - PullRequest
0 голосов
/ 16 февраля 2012

Я работаю над личным проектом, который, как и многие проекты XNA, начался с карты смещения ландшафта, которая используется для генерации набора вершин, которые отображаются в вызове Device.DrawIndexedPrimitives().

Я обновил пользовательский VertexDeclaration, но сейчас у меня нет доступа к этому коду, поэтому я опубликую немного более старый, но парадигматически идентичный (?) Код.

Я определяю VertexBuffer как:

VertexBuffer = new VertexBuffer(device, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
VertexBuffer.SetData(vertices);

, где 'вершины' определяются как:

VertexPositionNormalTexture[] vertices

I 'У нас также есть два индексных буфера, которые меняются местами на каждой итерации Update ().В вызове Draw() я установил буферы GraphicsDevice:

Device.SetVertexBuffer(_buffers.VertexBuffer);
Device.Indices = _buffers.IndexBuffer;

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

Изменение позиций вершин массива VertexPositionNormalTexture[] не отражается на экране, хотя значения позиций вершин изменяются.Я считаю, что это связано с вызовом VertexBuffer.SetData(), но вы не можете просто вызвать SetData() с массивом вершин после его изменения.

После повторного изучения того, как обрабатывается IndexBuffer (2 буфера,поменялся местами и перешел в SetData() в Update() время), я думаю, что это должен быть способ обработки VertexBuffer манипуляций, но работает ли это?Есть ли более подходящий способ?Я видел еще одну ссылку на подобный вопрос здесь, но ссылка на источник была на MegaUpload, так что ...

Я попробую мою идею VertexBuffer.Swap(), но я также видел ссылки на DynamicVertexBuffer и интересно, какой выигрыш есть?Предполагается, что производительность снижается, но для редактора ландшафта я не вижу в этом слишком большого компромисса, если я могу динамически манипулировать данными вершин.

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

РЕДАКТИРОВАТЬ: Решение, предложенное ниже, является правильным.Я скоро опубликую свой код.

1 Ответ

1 голос
/ 16 февраля 2012

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

Второе: вы правы, признавая, что простое редактирование массива вершин не изменит то, что отображается на экране. VertexBuffer полностью отделен от вершин, из которых он создан, и не сохраняет ссылку на исходный их массив. Это «снимок» ваших вершин, когда вы устанавливаете данные.

Я не уверен насчет некоторых из ваших предположений. Вы можете , насколько мне известно, в любое время вызвать VertexBuffer.SetData (). Если вы не меняете количество вершин в своей местности, только их положения, это хорошо. Просто переустанавливайте данные в буфере каждый раз, когда вы меняете положение вершины. [Примечание: если я ошибаюсь, и вы можете установить данные в буфере только один раз, просто замените старый экземпляр буфера новым и установите для него данные. Я не думаю, что вам нужно, если только вы не изменили количество вершин]

Вызов SetData довольно дорог для большого буфера. Вы можете рассмотреть возможность «разбить» свою местность на множество небольших буферов, чтобы избежать накладных расходов, необходимых для установки данных при изменении местности.

Я не знаю много о классе DynamicVertexBuffer, но я не думаю, что он оптимален для этой ситуации (даже если это звучит так). Я думаю, что это больше используется для вершин частиц. Хотя я могу ошибаться. Обязательно исследуйте это.

Из любопытства, зачем вам два индексных буфера? Если ваши вершины одинаковы, зачем вам использовать разные индексы на кадр?

Редактировать: Ваш код для создания VertexBuffer использует BufferUsage.WriteOnly. Хорошая практика - сделать BufferUsage совпадающим с GraphicsDevice. Если вы не установили BufferUsage устройства, вы, вероятно, просто хотите использовать BufferUsage.None. Попробуйте оба варианта и проверьте различия в производительности, если хотите.

...