Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Мерцание при движении объекта (пример внутри)) (http://www.flasher.ru/forum/showthread.php?t=174695)

Black Soviet 31.01.2012 11:09

Мерцание при движении объекта (пример внутри))
 
Товарищи, вчера весь день лопатил и рунет и буржуйские форумы в поиске проблемы, связанной с мерцанием графического объекта при его программном движении. Эта проблема и здесь на форуме поднималась различными пользователями в нескольких темах, но нигде результирующего решения так и не было озвучено.(или я слепой).
НЕТ ПРОБЛЕМ С ПЛАВНОСТЬЮ ДВИЖЕНИЯ Есть проблема с отрисовкой объекта при его перемещении. То есть как я понимаю проблема в том Flash начинает рисовать объект на новом месте, до конца не удалив его с предыдущего, в результате на объекте видны мерцающие горизонтальные полосы.
В качестве примера быстро набросал программку с вращением шара по эллипсоидной траектории (фон черный, объект белый, специально для лучшего контраста), где сами можете даже не на слишком большой угловой скорости увидеть эффект с мерцанием.
http://megaswf.com/serve/2104891
Код:
Код AS3:

package 
{
 
        import flash.display.MovieClip;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.display.Shape;
        import flash.display.BitmapData;
        import flash.display.Bitmap;
        import flash.utils.getTimer;
        import flash.events.TimerEvent;
        import flash.utils.Timer;
 
 
        public class main extends MovieClip
        {
                var a:int=100; // горизонтальный радиус (для эллипса)
                var b:int=100; // вертикальный радиус (эллипса)
                var cx:int = 350; // Х центра точки вокруг которой вращается шар
                var cy:int = 150; // Y центра точки вокруг которой вращается шар
                var t:Number=0;      // текущий угол в радианах
                var speed:Number = 0.05; // скорость вращения в радианах
                var mc:MovieClip; // Шар
                var dx,dy:Number; // используются как вспомогательные в формуле эллипса
 
                public function main()
                {
                mc = new Planet();
                addChild(mc);
                //mc.cacheAsBitmap = true;
                //mc.scaleX=1.1;
 
                addEventListener(Event.ENTER_FRAME,Vertigo);
                upBtn.addEventListener(MouseEvent.CLICK,Up); // нажатие на поле увеличивает скорость вращения
                downBtn.addEventListener(MouseEvent.CLICK,Down); // нажатие на поле уменьшает скорость вращения
 
                }
 
                function Vertigo(e:Event):void
                {
                        t +=  speed; // увеличиваем угол
                        dx = a * Math.cos(t); // определяем положение по Х на эллипсе
                        dy = b * Math.sin(t); // определяем положение по Y на эллипсе
                        mc.x = cx + dx; //выставляем координаты шара, учитывая центр вращения (сх, су)
                        mc.y = cy + dy;
 
 
                        speedBar.text=String(speed); // показываем скорость на экране
                }
                function Up(e:MouseEvent):void
                {
                        speed+=0.01;       
                }
                function Down(e:MouseEvent):void
                {
                        speed-=0.01;       
                }
        }
 
}

Что пробовал для решения этой проблемы:
  • запихивать в мувиклип и вектор и растр - не помогает
  • cacheAsBitmap - не помогает
  • Использовать Timer с updateAfterEvent вместо EnterFrame - не помогает
  • прямолинейное движение только по целым координатам - не помогает
  • Увеличение FPS - не помогает

Кто-то говорит что надо ждать новой версии флеш-плеера, кто-то что это проблема ВООБЩЕ на флеше не решается. Но может есть у кого какой-нибудь опыт в борьбе с этим эффектом ? Был бы очень признателен.

i.o. 31.01.2012 11:29

Полет нормальный (win7 x64):
Цитата:

10.3.181.34 release
11.0.1.60 debug

Black Soviet 31.01.2012 11:39

i.o.

Ух ты! Ух ты! У меня уже при угловой скорости =0.12 мерцает, при 0.18 аццкие перетяжки.
Спасибо, уже интереснее!

Hauts 31.01.2012 12:10

Попробуйте поменять частоту обновления экрана :)

Black Soviet 31.01.2012 12:16

Hauts

Вы хотите сказать, что и у вас шар не мерцает ?

Hauts 31.01.2012 12:20

Мерцает. Но я к такому эффекту давно привык и как-то не задумывался об этом.

Black Soviet 31.01.2012 12:31

i.o.

Скачал 11 версию плеера, всё равно мерцает.

Добавлено через 2 минуты
Hauts

Вспомните любую мало-мальскую флеш-игру в которой достаточно крупные объекты (или даже фон) двигаются по криволинейной траектории и при том не мерцают.

expl 31.01.2012 13:34

Да, что-то здесь этот отвратительный эффект плеера во всей красе проявляется. Может попробовать градиент в растр загнать (научного обоснования у меня нет, но вдруг поможет)?

fish_r 31.01.2012 13:47

Только недавно такая тема поднималась

Black Soviet 31.01.2012 13:59

fish_r

Нет, я в первом посте написал что Я НЕ ПРО ДЕРГАННОСТЬ при перемещении говорю. Шар в моём проекте движется плавно, он мерцает, Флеш не успевает отрисовать его.

GBee 31.01.2012 14:27

Не мерцает в ИЕ9, Опере 11, и Хроме.
Win 7 Ultimate
Плеер везде 11.1.102.55

fish_r 31.01.2012 14:58

а у меня дергается )

Black Soviet 31.01.2012 15:31

GBee
не мерцает, даже если скорость увеличить ?

fish_r
у вас шар не плавно, а дёргано двигается, правильно понимаю ?

Что ж это у всех по-разному то отображается. :( Попробую на шустрой машине сейчас посмотреть что да как.

i.o. 31.01.2012 15:42

опишу то, что вижу:
Шар мерцает при 0,16, но!
Во-первых у меня LCD монитор и резкое перемещение белых пикселей на черном фоне действительно вызывает некое мерцание (время отклика и overdrive), и я к этому привык давно. Как вариант - попробуй протестировать на CRT мониторе.
Во-вторых есть ощущение, что FPS выставлен не в 60. Соответственно частота экрана выше скорости перерисовки круга -> резкие перескоки -> то бишь мерцание.
В-третьих не наблюдаю именно самой перерисовки. Всегда вижу шар целиком, а не половину старого и половину нового с ползущей горизонтальной линией. Такого нет.

GBee 31.01.2012 16:13

Не мерцает, ни на ноуте, ни на "большом" компе. Моники все ЖК. Может видяха у вас?

Black Soviet 01.02.2012 13:17

Ребят, вот откопал картинку которая характеризует этот эффект ("screen tearing"), чтобы внести однозначность.
http://static.gamesradar.com/images/...icle_image.jpg

GBee
на работе разные мониторы и разные компьютеры опробовал. Везде мерцает. На домашнем компьютере при большой скорости вращения перестаёт мерцать и всё выглядит круто, но на медленном вращении, явно видно как шар "потрескивает".

i.o.
Выставил на 60, шар "трещать" начал вообще безбожно. А в чём магическое дао FPS=60 ?

Hauts 01.02.2012 13:23

Вот, кстати, статья по этому же поводу: http://unitzeroone.com/blog/2009/11/...creen-tearing/

i.o. 01.02.2012 13:46

Цитата:

А в чём магическое дао FPS=60 ?
макс. частота перерисовки флешплеера.

Black Soviet 01.02.2012 14:03

Hauts

Да, я читал эту статейку, и решение как-будто бы кроется в выставлении свойства wmode = "direct", типа оно как-то помогает отображать быстрее в браузере. А что это за свойство и как его выставить ?

Также пишут про:
Adding system text to the display list (seems to work on windows xp)
Но тут я вообще не понял, что ещё за системный текст ?

i.o.

Я задумывался уже о том что частота обновления моего экрана = 60 Гц, и что такое мерцание возникает из-за разницы между FPS проекта, и частотой обновления экрана. Но выставление FPS =60 не решило проблему.

КорДум 01.02.2012 14:04

Linux x86, FP 11.1r102 тоже без мерцания, все годно.

Black Soviet 01.02.2012 14:15

КорДум
Вот мы мне и нужны! В старых темах вы отписывались как-то по решению этой проблемы, но я читал в некомфортных условиях(снежная пурга) и на другом нетбуке. Можете что-нибудь посоветовать из стареньких приёмов?

GBee 01.02.2012 14:20

Хе у меня "мерцает", если выставить High Color вместо True Color.

i.o. 01.02.2012 14:29

У меня единственный вариант приходит на ум:
1. Убираете все объекты с дисплей-листа.
2. Создаете один Bitmap (назовем frontBufferContainer) и добавляете его на дисплей-лист.
3. Создаете две BitmapData. Одну именуем frontBuffer, другую backBuffer.
4. На каждом обновлении экрана:
а) отрисовываем все объекты в backBuffer через BitmapData#draw()
б) копируем пикселы из backBuffer во frontBuffer через BitmapData#copyPixels()
PROFIT.

Выглядит извратно, но других вариантов в голову не приходит. Навеяно двойной буферизацией.

Black Soviet 01.02.2012 14:59

В параметрах публикации Flash, выставил "Аппаратное ускорение - direct (прямое ускорение)" как советовали на буржуйских форумах. Тоже не помогло.

Добавлено через 1 минуту
i.o.

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

ЗлОй ПрОграММер 01.02.2012 15:17

у меня тож норм, не мерцает
при угловой скорости 1.20 эффект интересный)

КорДум 01.02.2012 17:10

Нет, я не решил эту проблему и просто закрыл глаза. Тем более, что на разных машинах показывает по разному. На ноутбуке с ХРю есть косяки в отрисовке, а на нетбуке с убунтой нету.

XoJlToH 01.02.2012 17:41

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

Black Soviet 01.02.2012 18:31

XoJlToH
Ни на скриншоте, ни на видео-захвате глюка с отображением нет. :(

anmelegov 01.02.2012 22:52

ты скорее всего пытаешься устранить проблему которой нет =) запустил на своей тачке всё работает как и должно (кор и3 причем под нагрузкой некислой сейчас, плеер не знаю какой самый последний под линукс который)

Black Soviet 02.02.2012 09:10

anmelegov

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

maxkar 02.02.2012 12:40

Цитата:

Сообщение от Black Soviet (Сообщение 1060453)
В параметрах публикации Flash, выставил "Аппаратное ускорение - direct (прямое ускорение)" как советовали на буржуйских форумах. Тоже не помогло.

А покажите код, которым вы флешку на страницу вставляете. Там должно быть wmode="direct". И только direct! Если он не стоит, результат рендеринга кадра отдается бразуеру, а браузерам обычно не интересно заниматься вертикальной синхронизацией.

Цитата:

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

Цитата:

То есть как я понимаю проблема в том Flash начинает рисовать объект на новом месте, до конца не удалив его с предыдущего, в результате на объекте видны мерцающие горизонтальные полосы.
Нет!

Придется, правда, рассказать, как работают мониторы и видеотракт.
Так получилось, что первые мониторы были на электронно-лучевых трубках. В них "луч" бегал по экрану сверху вниз и слева направо, зажигая нужные люминофоры. В сигнале передавалась служебная информация (информация о начале/конце строки/кадра) и уровни сигналов для каждой точки, проходимой лучом.
Проще всего реализовывать такой обмен так - выделяется непрерывный блок памяти, и при обмене на выход видеокарты просто передаются "перекодированные в сигнал" значения байтов этой памяти. После окончания прохода буфер начинает передаваться заново. Занимается этим специальный чип (или часть общего чипа), который подключен к видеовыходам.
Сейчас схема передачи изображения на монитор принципиально не поменялась. Да, сигнал стал цифровым, но значения пикселей все равно передаются по-очереди и видеокарты также используют непрерывный буфер.

Теперь рассмотрим способы формирования изображения.
Как проще всего формировать изображение? Да просто изменяя значения байтов в той самой выделенной области. А что будет, если область одновременно читается и записывается? Правильно, на монитор уйдет часть "старых" данных и часть "новых". Где будет старая часть, а где новая - зависит от скоростей "читателя" (передающего картинку на монитор) и писателя. Если скорость писателя выше, новая часть будет "снизу". Если выше скорость "читателя" - сверху. Вот так и образуется "tearing" на экране. (Кстати, двойной "tearing" как у вас на картинке - все же ситуация нетипичная и редкая)
Для избавления от tearing'а тоже было придумано решение. И достаточно простое. Не нужно писать в "выводимый" кадр, нужно писать в отдельную область и после выдачи экрана выводить только полностью сформированную область. Это называется double buffering. Отрисовка производится в один буфер, а в это время второй буфер передается на монитор. После полной передачи буфера они меняются местами. Теперь на монитор передается тот буфер, который рисовался, а отрисовка производится в буфер, который только что выводился на экран. Этот механизм реализуется видеокартой. Но есть одна проблема - приложение, выполняющее отрисовку, тоже должно знать об этой схеме и правильно переключать буфера. "Просто автоматически" переключать не получится - приложение может не успеть обновить буфер и продолжит писать в "выводимый на экран" буфер. Если я не ошибаюсь, переключение буферов делается явно приложением (командой видеокарте).

Теперь вернемся к браузерам и флешу. При большинстве значений wmode флеш генерирует картинку и передает ее браузеру со словами "отрисуй-ка ты мне ее". Даже wmode="gpu" работает по этой схеме, правда само изображение формируется с использованием видеокарты. Дальше за вывод картинки отвечает браузер. Сейчас браузеры не используют вертикальную синхронизацию (им это особо и не нужно), поэтому он работает по "первой" схеме (прямая запись в видеобуфер). Ну а это и приводит к артефактам. Заметьте, что ошибка происходит на этапе вывода изображения и передачи на монитор! Никакие программные ухищрения во флеш не могут повлиять на этот эффект. А сам эффект зависит от стечения множества обстоятельств (например, от того, попал ли обмен с кадром "посередине" передачи кадра или нет).
Теперь разберем wmode="direct". Он позволяет флешке установить контроль над выводимой частью экрана. Для этого используется технология "overlay", которая позволяет составлять образ экрана из нескольких различных буферов. В основном буфере требуемая область заливается определенным цветом (одним и сплошным, цвет может быть разный). Само изображение формируется в другом буффере. При выводе проверяется цвет выводимого пикселя и при необходимости пиксель заменяется другим из буфера (с необходимой трансляцией координат). Сейчас вывод overlay-поверхностей поддерживается аппаратно видеокартой. overlay'и часто используются при выводе видео. Для буферов в этом случае тоже доступны почти все имеющиеся возможности, в том числе двойная буферизация. wmode="direct" как раз и включает эту технологию. В этом случае на странице рисуется прямоугольник определенного цвета, а flash-player формирует буфер кадра в памяти видеокарты минуя браузер. И только в этом случае флеш может переключать выдаваемый кадр "целиком", что и избавляет от проблемы tearing'а.

Выводы.
1. Никакие программные пляски с бубном вокруг двойной и тройной буферизации на стороне flash-player'а не помогут без включенного wmode="direct". С другой стороны, со включенным wmode="direct" (и при правильной реализации флеша, сейчас она правильная) данная проблема не возникает вообще. И никакие пляски с бубном вокруг программной двойной буферизации не нужны.
2. Проявление эффекта зависит от массы различных факторов и может нестабильно проявляться даже на одном и том же компьютере (например, в разных частях изображения или не во всех случаях).

Black Soviet 02.02.2012 13:01

maxkar
Огромное спасибо за развернутый ответ.
Итак кое-какие результаты есть.

Выставление в хтмл-коде параметра "wmode=direct" сработало, и шар ПЕРЕСТАЛ ДЕРГАТЬСЯ и МЕРЦАТЬ. Но я искренне надеялся что установив в параметре публикации - прямое аппаратное ускорение он мне скомпилирует swf без багов. Правильно ли я понимаю, что никак кроме размещения swf в html-странице с включенным параметром wmode=direct, нельзя включить ускорение ? Меня интересует именно swf, проигрываемый в Flash Player.

Дело в том, что весьма огорчительно было увидеть коды страницы различных игровых флеш-сайтов, и увидеть что ВСЕ динамичные и сложные игры имеют параметр "wmode = window", то есть аппаратного ускорения не включено вообще.

Как вы правильно сказали, двойная буферизация мне не помогла. Изменился лишь характер артефактов. Где-то 4 секунды шар вертится плавно, потом секунду его жестко раздирает и колбасит.

maxkar 02.02.2012 18:47

Вывод через overlay и с vsync? В самой флешке никак. И здесь тоже все более-менее причины понятны. Например, вывод через overlay не совместим с wmode="transparent". Оверлей буквально выводит область видеопамяти вместо другого прямоугольника. Т.е. никакой "прозрачности" не получится - у плеера при рендеринге просто нет нужного прямоугольника (и верхних слоев на веб-странице). Это должен делать браузер.

Таким образом, остаются только варианты, когда весь "прямоугольник" выводит сам плеер. Это режимы direct и window. С direct все понятно, он работает правильно. С window - не совсем. Например, здесь пишут, что вывод ведется через GDI в windows (создается отдельное окно и т.п.). Вполне вероятно, там используется стандартная "оконная" отрисовка (прямоугольная область пикселей) и без двойной буферизации. И не факт, что в GDI вообще можно делать "двойную буферизацию" при выводе на экран. Чисто теоретически, плеер мог бы создавать там directx overlay surface и рисовать туда. Но судя по всему он этого не делает. Так что если флажок "аппаратное ускорение" при публикации не помог, то больше ничего плеер включить двойную буферизацию не заставит.

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

Black Soviet 05.02.2012 12:57

Кое-какие положительные результаты всё же есть которые помогли минимизировать эффект "мерцания". Итак в ходе различных тестов было замечено и подмечено:

1) При маленьких скоростях объекта мерцания почти нет.
2) При маленьком размере картинки мерцания почти нет.
3) Наличие контрастного фона (белые объекты на черном фоне) увеличивают, по-крайней мере визуально, мерцание.
2) Мерцание усиливается если у объекта в первую очередь большая горизонтальная скорость. На вертикальных заходах мерцание не так сильно. (проверено на эллиптических траекториях)
3) Все картинки обязательно в растр и кэшируем.
4) В выводе графики используем copyPixels если есть альфа-канал(прозрачность), и используем beginBitmapFill если альфа не используется.
5) Для BitmapData рекомендуется lock() и unlock()
6) Если религия не позволяет использовать EnterFrame, и используем вместо него Timer, то не забываем про updateAfterEvent()
7) И самое главное, при публикации в html выставляйте параметр wmode=direct, и тогда мерцания не будет вообще.

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


Часовой пояс GMT +4, время: 13:53.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.