Как UIImageView анимира толкова гладко? (Или: как да накарате OpenGL ефективно да анимира текстури рамка по рамка)

За да поясня, знам, че атласът на текстурата подобрява производителността при използване на множество различни изображения. Но ми е интересно как се правят нещата, когато вие не правите това.

Опитах се да направя ръчно анимация кадър по кадър в персонализиран OpenGL, където всеки кадър обвързвам нова текстура и я рисувам върху същия точков спрайт. Работи, но е много бавен в сравнение със способността UIImageView да абстрахира същото. Зареждам всички текстури отпред, но повторното свързване се извършва за всеки кадър. За сравнение, UIImageView приема отделните изображения, а не текстурен атлас, така че бих си представил, че се справя по подобен начин.

Това са 76 изображения, заредени поотделно, а не като текстурен атлас, и всяко е около 200 пиксела квадрат. В OpenGL подозирам, че тясното място е изискването за повторно свързване на текстура във всеки кадър. Но как UIImageView прави това, тъй като бих очаквал подобно тясно място?? UIImageView създава ли по някакъв начин атлас зад кулисите, така че да не е необходимо повторно свързване на текстури? Тъй като UIKit в крайна сметка има OpenGL, работещ под него, любопитен съм как трябва да работи това.

Ако има по-ефикасно средство за анимиране на множество текстури, вместо да се разменят различни обвързани текстури всеки кадър в OpenGL, бих искал да знам, тъй като може да намекне какво прави Apple в тяхната рамка .

Ако наистина получа нов кадър за всеки от 60 кадъра за секунда, тогава ще са ми необходими около 1,25 секунди за анимиране на моите 76 кадъра. Наистина получавам това с UIImageView, но OpenGL отнема около 3 - 4 секунди.


person johnbakers    schedule 24.04.2013    source източник


Отговори (2)


Бих казал, че вашето тясно място е някъде другаде. OpenGL е повече от способен да прави анимация по начина, по който го правите вие. Тъй като всички текстури се зареждат и вие просто свързвате още една за всеки кадър, няма време за зареждане или нещо друго. Помислете за сравнение. Имам приложение, което по време на изпълнение може да генерира или изтрива текстури и може в даден момент да има голямо количество текстури, заредени на GPU, трябва да обвържа всички тези текстури на всеки кадър (не по 1 на всеки кадър), като използвам всички от буфер за дълбочина, шаблон, множество FBO, интензивен потребителски вход, около 5 нишки с тесни места в 1 за обработка на целия GL код и изобщо нямам проблеми с FPS.

Тъй като работите с iOS, предлагам да стартирате някои програми за профилиране, за да видите кой код е отговорен за режийните разходи. И ако по някаква причина вашият времеви профил ви каже, че редът с glBindTexture отнема твърде много време, пак ще кажа, че проблемът е някъде другаде.

Така че, за да отговоря на въпроса ви, нормално и страхотно е, че UIImageView върши работата си толкова гладко и не би трябвало да има проблем с постигането на същата производителност с openGL. Въпреки това, има няколко неща, които трябва да имате предвид на този етап. Как можете да кажете, че изгледът на изображението не пропуска изображения, може да задавате показалец към различно изображение 60 пъти в секунда, но изгледът на изображението може просто да поиска 30 пъти в секунда да преначертае и когато го направи, просто използва текущо присвоено изображение към него. От друга страна с вашия GL код вие принуждавате приложението да преначертае 60FPS, независимо дали е в състояние да го направи.

Като вземем всичко предвид, има нещо, наречено връзка за показване, което разработчиците на Apple създадоха за вас. Вярвам, че е предназначен точно за това, което искате да направите. Връзката за показване ще ви каже колко време е изминало между кадрите и чрез този ключ трябва да се запитате каква текстура да обвържете, вместо да се опитвате да ги принудите всички в рамките на време, което може да е твърде кратко.

И още нещо, видях, че ако се опитате да представите буфер за изобразяване при 100 FPS на повечето iOS устройства (може да са всички), ще получите само 60 FPS, тъй като методът за представяне на буфер за изобразяване ще постави на пауза вашата нишка, ако е бил извикан за по-малко от 1/60s. Като се има предвид това, е доста невъзможно изобщо да се покаже нещо при 60 FPS на iOS устройства и всичко, което работи с 30+ FPS, се счита за добро.

person Matic Oblak    schedule 24.04.2013
comment
Благодаря, ще се поразровя още малко, за да видя какво ще намеря в профилирането и т.н. Между другото, 60 кадъра в секунда изобщо не са невъзможни, редовно ги получавам с прости 2D игри. - person johnbakers; 24.04.2013

„не като текстурен атлас“ е изречението, което е червен флаг за мен.

Използването на текстурен атлас е добро нещо... текстурата се зарежда в паметта веднъж и след това просто премествате позицията на правоъгълника, за да възпроизведете анимацията. Бързо е, защото всичко вече е в паметта. Всяка операция, която включва постоянно зареждане и презареждане на нови кадри на изображение, ще бъде по-бавна от тази.

Ще трябва да публикувате изходния код, за да получите по-точен отговор от този.

person Delete    schedule 24.04.2013
comment
Въпросът ми е как UIImageView работи толкова ефективно, когато не се захранва с текстурен атлас. - person johnbakers; 24.04.2013