2012-05-12 3 views
2

Я пытаюсь создать 3D-WP7-игру в XNA, рисуя модели, состоящие из строк, используя DrawUserIndexedPrimitives Все это прекрасно работает, но теперь я хочу дать каждой модели свое собственное вращение. В настоящее время я использую BasicEffect для рисования всех моделей. Я могу установить его вращение, но тогда все объекты будут иметь такое же вращение. Есть ли способ установить другое вращение для каждого объекта? Я в настоящее время придумать пару решений, которые я мог бы использовать, но я не доволен ни с одной из них:XNA для WP7: DrawUserIndexedPrimitives

  • Создать новую BasicEffect для каждого объекта, со своим собственным миром, то перебираем все объекты, чтобы получить их основной эффект и привлечь его - я думаю, что все те BasicEffects создадут много накладных расходов, и я хочу отделить эффект от моделей.
  • Выполняйте расчет самих точек (то есть вычислите поворот и передайте эти значения методу DrawUserIndexedPrimitives). Это довольно дорогостоящий расчет, который сильно утащил производительность.

Есть ли какой-либо предлагаемый маршрут?

Я не знаю, является ли DrawUserIndexedPrimitives лучшим методом использования, я просто хочу, чтобы иметь возможность рисовать линии и давать им поворот. Если есть лучший способ сделать это, скажите, пожалуйста :)

моего текущим решения:

protected override void Draw(GameTime gameTime) 
{ 
    GraphicsDevice.Clear(Color.Black); 

    foreach (var model in _models) 
    { 

     foreach (var pass in model.Effect.CurrentTechnique.Passes) 
     { 
      pass.Apply(); 
      model.Effect.World = _model.GetWorld(); 

      var points = model.GetPoints(); 
      GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineList, points, 0, points.Length, model.Lines, 0, model.Lines.Length/2); 

      _models[0].Draw(GraphicsDevice); 
     } 
    } 

    base.Draw(gameTime); 
} 

model.GetWorld() возвращает матрицу вращения, перевод и масштаб объекта, модель. GetPoints() список с точками и model.Lines представляет собой список с индексами связанных точек

ответ

2

Обычно вам нужен только один из эффектов любого типа (например, BasicEffect). Причина в том, что эффекты состоят из двух основных вещей: кода, написанного для графического процессора (освещения и т. Д.), И параметров, которые он предоставляет (например, Effect.World, мировой матрицы). Было бы не так много, чтобы скомпилировать код GPU более одного раза, так как каждый раз он будет одинаковым, так что единственное, что мы должны рассмотреть, это параметры.

Обратите внимание на вызов pass.Apply(). Фактически это то, что вы загружаете все параметры, которые вы задавали на эффект, на GPU каждый раз, прежде чем рисовать. То, что, надеюсь, вам скажет, заключается в том, что вы должны иметь возможность установить вращение на одном эффекте прямо перед каждой ничью и вызвать «Применить», вместо того, чтобы создавать кучу эффектов с индивидуально установленными вращениями. Более того, установка Эффекта. Мир должен на самом деле прибыть перед прохождением.Apply().

Чтобы ответить на второй пункт, вы совершенно правы. Графический процессор сделан для преобразования в точках с массивным параллелизмом, поэтому лучше не пытаться самостоятельно, потому что он будет медленным.

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

Как повезло, графическая карта фактически реализует специальный режим рисования под названием «Wireframe», который вместо рисования треугольников просто рисует края треугольников как линии. Для того, чтобы установить режим каркасного, сделайте это, прежде чем позвонить Draw:

this.GraphicsDevice.RasterizerState.FillMode = FillMode.WireFrame; 

Теперь с точки зрения применения собственное вращение, все, что вам действительно нужно сделать, это умножить мировую матрицу на матрицу вращения (использовать что-то вроде Matrix.CreateRotationX (yourAngle)).

0

Ваше текущее решение в порядке, хотя я бы THW мира назначить до pass.Apply()

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

Таким образом, вы могли бы нарисовать всю свою модель за один проход.

Смежные вопросы