Эффективное рисование линий в Direct3D (Transformation2D?) - PullRequest
2 голосов
/ 11 марта 2009

Справочная информация: Я использую оболочку SlimDX C # для DirectX и рисую многие 2D-спрайты с помощью класса Sprite (традиционно из расширения Direct3DX в базовых библиотеках). Я рисую несколько сотен спрайтов на экране одновременно, и производительность потрясающая - на моем четырехъядерном ядре он использует примерно 3-6% процессора для всей моей игры, включая логику для 10 000+ объектов, ai подпрограммы во втором потоке и т. д., и т. д. Итак, ясно, что спрайты рисуются с полным аппаратным ускорением, и все так, как и должно быть.

Проблема: Проблема возникает, когда я начинаю вводить вызовы в классе Line. Как только я рисую 4 линии (для поля выбора перетаскивания), загрузка процессора возрастает до 13-19%. Это только с четырьмя строками!

Вещи, которые я пробовал:

  1. Выключение и включение сглаживания линии.
  2. Выключение и включение GLLines.
  3. Вручную вызывая line.begin и line.end вокруг моих вызовов для рисования.
  4. Пропуск всех вызовов line.begin и line.end.
  5. Обеспечение того, чтобы мои вызовы line.draw не находились внутри блока sprite.begin / sprite.end.
  6. Вызов line.draw внутри блока sprite.begin / sprite.end.
  7. Рендеринг 4 строк или рендеринг 300.
  8. Отключение всех спрайтов и рендеринга текста, и просто оставление рендеринга строк на 4 строки (чтобы увидеть, было ли это какой-то проблемой изменения режима).
  9. Большинство вышеперечисленных комбинаций.

В целом, ни один из них не оказал существенного влияния на производительность. # 3 сократил использование процессора, возможно, на 2%, но даже тогда он все еще на 8% и более выше, чем должен быть. Самое странное, что № 7 сверху оказал абсолютно нулевое влияние на производительность - он был таким же медленным с 4 строками, как и с 300. Единственное, что я могу понять, это то, что он по какой-то причине работает в программном обеспечении и / или из-за того, что видеокарта постоянно переключается между режимами рисования.

Матричный подход:

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

Но я предполагаю, что это может быть просто проблемой внутри Directx в целом, поэтому я выбрал другой путь - создание собственной линии на основе спрайтов. По сути, у меня есть белое изображение размером 1 пиксель, и я использую диффузный цвет и преобразования для рисования линий. Это работает с точки зрения производительности - рисование 300 таких «линий» приводит меня к 3-6% -ному диапазону производительности использования процессора, который я ищу на своем четырехъядерном процессоре.

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

    public void DrawLineHorizontal( int X1, int X2, int Y, float HalfHeight, Color Color )
    {
        float width = ( X2 - X1 ) / 2.0f;
        Matrix m = Matrix.Transformation2D( new Vector2( X1 + width, Y ), 0f, new Vector2( width, HalfHeight ),
            Vector2.Zero, 0, Vector2.Zero );
        sprite.Transform = m;

        sprite.Draw( this.tx, Vector3.Zero, new Vector3( X1 + width, Y, 0 ), Color );
    }

Это работает, поскольку оно рисует линии в основном нужного размера в основном в нужном месте на экране. Однако вещи кажутся смещенными вправо, что странно. Я не совсем уверен, правильно ли подходит мой матричный подход: я просто хочу масштабировать спрайт 1x1 на некоторое количество пикселей по горизонтали и другое количество по вертикали. Тогда я должен быть в состоянии расположить их - по центру все в порядке, и я думаю, что это то, что я должен сделать, но если бы я мог расположить его по левому верхнему углу, это было бы еще лучше. Это кажется простой проблемой, но мое знание матриц довольно слабое.

Это получило бы чисто горизонтальные и чисто вертикальные линии, работающие на меня, что является основной битвой. Я мог бы жить с этим и использовать другой вид графики в местах, где я в настоящее время использую наклонные линии. Но было бы очень хорошо, если бы у меня был способ рисовать линии под углом, используя этот подход растянутых пикселей. Другими словами, нарисуйте линию от 1,1 до 7,19, например. С вращением матрицы и т. Д. Кажется, что это выполнимо, но я не знаю, с чего начать, кроме как угадывать и проверять, что заняло бы вечность.

Любая помощь очень ценится!

Ответы [ 2 ]

1 голос
/ 11 марта 2009

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

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

0 голосов
/ 11 марта 2009

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

    public void DrawLineHorizontal( int X1, int X2, int Y, float HalfHeight, Color Color )
    {
        float width = ( X2 - X1 );
        Matrix m = Matrix.Transformation2D( new Vector2( X1, Y - HalfHeight ), 0f, new Vector2( width, HalfHeight * 2 ),
            Vector2.Zero, 0, Vector2.Zero );
        sprite.Transform = m;

        sprite.Draw( this.tx, Vector3.Zero, new Vector3( X1, Y - HalfHeight, 0 ), Color );
    }

Мне бы хотелось иметь версию, которая бы работала и для линий под углами (как упоминалось выше). Любые предложения для этого?

...