Java 2D Drawing Оптимальная производительность - PullRequest
31 голосов
/ 29 сентября 2008

Я нахожусь в процессе написания Java 2D-игры. Я использую встроенные библиотеки Java 2D-рисования, рисуя на Graphics2D, который я получаю из BufferStrategy из Canvas в JFrame (который иногда полноэкранный). BufferStrategy является двойной буферизацией. Перекраска делается активно, через таймер. У меня проблемы с производительностью, особенно в Linux.

А в Java2D так много способов создания графических буферов и рисования графики, что я просто не знаю, правильно ли я поступаю. Я экспериментировал с graphics2d.getDeviceConfiguration (). CreateCompatibleVolatileImage, который выглядит многообещающе, но у меня нет реальных доказательств того, что будет быстрее, если я переключу код рисования на это.

По вашему опыту, какой самый быстрый способ визуализации 2D-графики на экране в Java 1.5+? Обратите внимание, что игра довольно далеко впереди, поэтому я не хочу переходить на совершенно другой метод рисования, такой как OpenGL или игровой движок. Я в основном хочу узнать, как получить самый быстрый способ использования объекта Graphics2D для рисования чего-либо на экране.

Ответы [ 9 ]

29 голосов
/ 14 октября 2008

Синтез ответов на этот пост, ответов на Consty's и моего собственного исследования:

Что работает:

  • Используйте GraphicsConfiguration.createCompatibleImage для создания изображений, совместимых с тем, что вы рисуете. Это абсолютно необходимо!
  • Использовать чертеж с двойной буферизацией через Canvas.createBufferStrategy.
  • Используйте -Dsun.java2d.opengl=True там, где это возможно, для ускорения рисования.
  • Избегайте использования преобразований для масштабирования. Вместо этого кэшируйте масштабированные версии изображений, которые вы собираетесь использовать.
  • Избегайте полупрозрачных изображений! Растровые изображения в порядке, но прозрачность очень дорогая в Java2D.

В моих тестах, использующих эти методы, я получил увеличение скорости в 10–15 раз, что делает возможным создание 2D-графики Java.

15 голосов
/ 13 октября 2008

У меня такие же проблемы, как и у вас, я думаю. Проверьте мой пост здесь:

Проблемы производительности Java2D

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

10 голосов
/ 01 октября 2008

Вот несколько советов от моей головы. Если бы вы были более конкретны и что вы пытались сделать, я мог бы помочь больше. Звучит как игра, но я не хочу предполагать.

Нарисуй только то, что тебе нужно! Не вызывайте вслепую все время вслепую (), попробуйте некоторые из братьев и сестер, такие как repaint (Rect) или repaint (x, y, w, h).

Будьте очень осторожны с альфа-смешиванием, так как это может быть дорогой операцией для смешивания изображений / примитивов.

Старайтесь максимально отрисовывать / кэшировать. Если вы обнаружите, что снова и снова рисуете круг, рассмотрите возможность рисования в BufferedImage, а затем просто нарисуйте BufferedImage. Вы жертвуете памятью ради скорости (типично для игр / графики с высокой производительностью)

Рассмотрите возможность использования OpenGL, используйте JOGL из LWJGL. JOGL больше похож на Java, тогда как LWJGL предоставляет больше игровых функций поверх доступа OpenGL. OpenGL может рисовать на порядки (с соответствующим оборудованием и драйверами), чем Swing.

3 голосов
/ 01 мая 2009

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

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

1 голос
/ 30 сентября 2008

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

Тем временем я обнаружил следующую Белую книгу Sun , написанную после бета-версии jdk 1.4. Здесь есть несколько интересных рекомендаций по тонкой настройке, включая флаги времени выполнения (внизу статьи):

" Флаг выполнения для Solaris и Linux

Начиная с версии SDK Beta 3, версия 1.4, Java 2D по умолчанию сохраняет изображения в растровых изображениях, когда DGA недоступен, независимо от того, работаете ли вы в локальной или удаленной среде отображения. Вы можете переопределить это поведение с помощью флага pmoffscreen:

-Dsun.java2d.pmoffscreen = true / false

Если для этого флага установлено значение true, поддержка закадрового изображения будет включена, даже если DGA доступен. Если для этого флага установлено значение false, поддержка закадрового изображения отключается. Отключение поддержки закадрового изображения может решить некоторые проблемы с рендерингом."

1 голос
/ 29 сентября 2008

Я сделал несколько базовых приложений для рисования с использованием Java. Я не работал над чем-то слишком насыщенным графикой, но я бы порекомендовал, чтобы вы хорошо разбирались во всех вызовах перерисовки. Дополнительный вызов перерисовки в родительском контейнере может удвоить объем рендеринга.

0 голосов
/ 17 ноября 2008

Альтернативой, если вы не хотите использовать чистый Java 2D, является использование игровой библиотеки, такой как GTGE или JGame (ищите их в Google), а затем предлагайте легкий доступ к графике, а также двойную буферизацию и намного более простое рисование. команды.

0 голосов
/ 29 сентября 2008

Есть несколько вещей, о которых вам нужно помнить

1) обновляет эта ссылка показывает, как использовать свингтимеры, которые могут быть хорошим вариантом для вызова перерисовки. Разобраться в перекраске (как говорили предыдущие авторы, важно, чтобы вы не выполняли слишком много работы).

2) Убедитесь, что вы рисуете только в одном потоке. Обновление пользовательского интерфейса из нескольких потоков может привести к неприятным последствиям.

3) Двойная буферизация. Это делает рендеринг более плавным. на этом сайте есть еще много полезной информации для вас

0 голосов
/ 29 сентября 2008

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

...