Оптимальная производительность 2D-чертежей Java

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

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

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

Просто из любопытства, о чем игра? : D

Mario Ortegón 29.09.2008 16:48

Re: Марио Ортегон: metalbeetle.com/spaceexploration. Я не вставил ссылку в главную, потому что это была бы скрытая реклама.

Zarkonnen 29.09.2008 16:53

ссылка выглядит немного странно (..но это было 8 лет назад)

Oliver Watkins 31.03.2016 16:51
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
33
3
40 561
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

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

В настоящее время я использую myCanvas.createBufferStrategy (2). Но я не знаю, будет ли создание временного буфера вручную быстрее.

Zarkonnen 29.09.2008 16:38

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

Вам нужно помнить о нескольких вещах.

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

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

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

связьсвязь It's better to avoid swing timers and rely on threads for anmation. It's also good practice to use active rendering instead of passing rendering relying on repaint()
ingframin 12.01.2016 08:38

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

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

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

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

-Dsun.java2d.pmoffscreen = истина / ложь

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

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

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

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

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

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

Ответ принят как подходящий

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

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

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

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

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

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

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

В моем случае флаг opengl снизил использование процессора до 13% с 25% ...

VocoJax 24.09.2018 03:20

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

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

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

Другие вопросы по теме