Технология наложения текстур на двумерные или трёхмерные модели широко применяется в компьютерной графике. Делается это для того, чтобы улучшить детализацию объектов, которые представлены моделями. Android поддерживает множество форматов сжатия текстур, каждый из них обладает собственными преимуществами и недостатками.
Предварительные сведения о работе с текстурами и о форматах их хранения
Наложение текстур (texture mapping) – это метод «наклеивания» изображения на поверхности фигур или многоугольников. Для того чтобы было понятнее, фигуру можно сравнить с коробкой, а текстуру – с узорной обёрточной бумагой, в которую эту коробку заворачивают для того, чтобы положить в неё что-нибудь хорошее и кому-нибудь подарить. Поэтому в англоязычной литературе наложение текстур называют ещё и «texture wrapping», что можно перевести как «обёртывание текстурами».
Первый танк – это полигональная модель, а второй – та же модель, на которую наложены текстуры.
MIP-карты (Mipmaps) – это оптимизированные группы изображений, которые генерируются для основной текстуры. Обычно их создают для того, чтобы увеличить скорость рендеринга картинки и для сглаживания изображений (anti-aliasing), то есть – для избавления от эффекта «ступенчатых» линий. Каждый уровень карты (его называют «mip», фактически – это одно из растровых изображений, из них состоит набор текстур, входящих в MIP-карту) – это версия исходной текстуры с пониженным разрешением.
Такое изображение используется в случаях, когда текстурированный объект виден с большого расстояния, или когда его размеры уменьшены. Идея использования MIP-карт строится на том факте, что мы попросту не можем различить мелкие детали объекта, который находится далеко от нас или имеет маленькие размеры. Основываясь на этой идее, различные фрагменты карты можно использовать для представления различных частей текстуры, основываясь на размерах объекта. Это увеличивает скорость рендеринга за счёт того, что уменьшенные варианты основной текстуры имеют намного меньше текселей (пикселей текстуры), то есть GPU приходится обрабатывать меньше данных для вывода текстурированной модели. Кроме того, так как MIP-карты обычно подвергаются сглаживанию, серьёзно уменьшается количество заметных артефактов. Здесь мы рассмотрим MIP-карты в форматах PNG, ETC (KTX), ETC2 (KTX), PVRTC, и S3TC.
MIP-карта
Portable Network Graphics (PNG)
PNG – это растровый формат хранения изображения, особенно заметный тем, что в нём используется алгоритм сжатия графических данных без потерь информации. Он поддерживает цветные индексированные изображения (24 бита RGB или 32 бита RGBA), полноцветные и полутоновые изображения, а так же – альфа-канал.
Преимущества
- Формат использует сжатие графических данных без потерь, как результат, PNG-изображения весьма качественны.
- Поддерживает и 8-ми битную и 16-битную прозрачность.
Недостатки
- Файлы имеют большие размеры. Это увеличивает размер приложений и потребление памяти.
- Сравнительно высокая потребность в вычислительных ресурсах (что ведет к ухудшению производительности).
Ericsson Texture Compression (ETC)
Ericsson Texture Compression – это формат сжатия текстур, который оперирует блоками пикселей размером 4x4. Изначально Khronos использовал ETC как стандартный формат для Open GL ES 2.0. (эта версия ещё называется ETC1). В результате этот формат доступен практически на всех Android-устройствах. С выходом OpenGL ES 3.0. в качестве нового стандарта использован формат ETC2 – переработанная версия ETC1. Основное различие между этими двумя стандартами заключается в алгоритме, который оперирует пиксельными группами. Улучшения в алгоритме привели к более высокой точности вывода мелких деталей изображений. Как результат, качество изображений улучшилось, а размер файлов – нет.
ETC1 и ETC2 поддерживают сжатие 24-битных RGB-данных, но они не поддерживают сжатие изображений с альфа-каналом. Кроме того, есть два разных формата файлов, относящихся к алгоритму ETC: это KTX и PKM.
KTX – это стандартный формат файла Khronos Group, он предоставляет контейнер, в котором можно хранить множество изображений. Когда MIP-карта создаётся с использованием KTX, генерируется единственный KTX-файл. Формат PKM-файла гораздо проще, такие файлы, в основном, используют для хранения отдельных изображений. Как результат, при использовании PKM в ходе создания MIP-карты получатся несколько PKM-файлов вместо единственного KTX. Поэтому для хранения MIP-карт использовать формат PKM не рекомендуется.
Преимущества
- Размер ETC-файлов, заметно меньше чем размер PNG-файлов.
- Формат поддерживает аппаратное ускорение практически на всех Android-устройствах.
Недостатки
- Качество не так высоко, как у PNG (ETC – это формат сжатия изображений с потерями информации).
- Нет поддержки прозрачности.
Для сжатия изображений в ETC можно использовать Mali GPU Texture Compression Tool и ETC-Pack Tool.
PowerVR Texture Compression (PVRTC)
PowerVR Texture Compression – это формат компрессии графических данных с потерями, с фиксированным уровнем сжатия, который используется, преимущественно, в устройствах Imagination Technology PowerVR MBX, SGX и Rogue. Он применяется в качестве стандартного метода сжатия изображений в iPhone, iPod, iPad.
В отличие от ETC и S3TC, алгоритм PVRTC не работает с фиксированными блоками пикселей. В нём используется билинейное увеличение и смешивание с низкой точностью двух изображений низкого разрешения. В дополнение к уникальному процессу сжатия, PVRTC поддерживает формат RGBA (с прозрачностью) и для варианта 2-bpp (2 бита на пиксель), и для варианта 4-bpp (4 бита на пиксель).
Преимущества
- Поддержка альфа-каналов.
- Поддержка RGBA для варианта 2-bpp (2 бита на пиксель) и для варианта 4-bpp (4 бита на пиксель).
- Размер файлов намного меньше, чем у PNG.
- Поддержка аппаратного ускорения на GPU PoverVR.
Недостатки
- Качество не так высоко, как при использовании PNG (PVRTC – это формат сжатия изображений с потерями).
- PVRTC поддерживается только на аппаратном обеспечении PoverVR.
- Обеспечивается поддержка квадратных POT-текстур, то есть текстур, ширина и высота которых являются степенью числа 2, хотя в некоторых случаях имеется поддержка прямоугольных текстур.
- Сжатие текстур в этот формат может быть медленным.
Для сжатия можно использовать PVRTexTool.
S3 Texture Compression (S3TC) или DirectX Texture Compression (DXTC)
S3 Texture Compression – это формат сжатия графических данных с потерями, с фиксированным уровнем сжатия. Его особенности делают этот формат идеальным для сжатия текстур, используемых в 3D-приложениях, рассчитанных на использование графического ускорителя. Интеграция S3TC с Microsoft DirectX 6.0 и OpenGL 1.3 способствовала его широкому распространению. Существует как минимум 5 различных вариантов формата S3TC (от DXT1 до DXT5). Приложение-пример поддерживает чаще всего используемые варианты (DXT1, DXT3 и DXT5).
DXT1 обеспечивает наиболее сильное сжатие. Каждый входной 16-пиксельный блок конвертируется в 64-битный блок, состоящий из двух 16-битных RGB 5:6:5 цветовых значений и 2-х битной таблицы подстановок размером 4x4. Поддержка прозрачности ограничена одним цветом (1-битная прозрачность).
DXT3 конвертирует каждый блок из 16 пикселей в 128 бит, 64 бита приходятся на данные альфа-канала, 64 – на цветовую информацию. DXT3 очень хорошо подходит для изображений или текстур с резкими переходами между прозрачными и непрозрачными областями. Однако если градаций прозрачности нет, а прозрачные участки в изображении имеются, стоит рассмотреть использование DXT1.
DXT5, как и DXT3, конвертирует каждый блок из 16 пикселей в 128 бит, 64 бита приходятся на данные альфа-канала, 64 – на цветовую информацию. Однако, в отличие от DXT3, DXT5 подходит для изображений или текстур с плавными переходами между прозрачными и непрозрачными областями.
Преимущества
- Размер файла значительно меньше аналогичного PNG-файла.
- Достойное качество, низкий процент артефактов в виде полосок, связанных с наложением цветов.
- Хорошая скорость кодирования и декодирования.
- Аппаратное ускорение на множестве GPU. На настольных системах поддерживается практически всеми решениями, постепенно распространяется и на платформе Android.
Недостатки
- Качество ниже, чем у PNG (S3TC – это формат сжатия изображений с потерями информации).
- Поддерживается не на всех Android-устройствах.
Для работы с этим форматом можно пользоваться DirectX Texture Tool из DirectX (включен в DX SDK)
Доступ к данным текстур
Большинство файловых форматов для хранения сжатых текстур предусматривают наличие заголовка, расположенного перед данными изображения. Обычно заголовок содержит сведения о названии формата сжатия текстур, о ширине и высоте текстуры, о её цветовой глубине, о размере данных, о внутреннем формате и другие сведения о файле.
Наша цель заключается в том, чтобы загрузить текстурные данные из различных файлов и наложить их на двумерную модель для сравнения качества изображений и размеров данных. Заголовок, который расположен перед графическими данными, не должен обрабатываться как часть текстуры, если счесть его фрагментом изображения и наложить на модель, это приведет к искажениям. Заголовки файлов у разных форматов сжатия текстур различаются, поэтому каждый формат нуждается в индивидуальной поддержке, иначе правильно загрузить и наложить текстуру не получится.
Обратите внимание
Заголовок PVRTC упакован с учётом наличия члена данных 64-битного пиксельного формата (mPixelFormat в примере). В коде, скомпилированном для ARM, проводится выравнивание заголовка с добавлением к нему 4 дополнительных байтов, в итоге он, из исходного 52-байтового, становится 56-байтовым. Это приводит к тому, что при выводе на ARM-устройствах изображение искажается. В коде, скомпилированном для процессоров от Intel, подобного не происходит. Упаковка заголовка решает проблему с выравниванием на ARM-устройствах, в итоге текстура отображается правильно как на ARM-устройствах, так и на Intel-устройствах.
Вот как выглядит искажение изображения на ARM-устройстве, вызванное выравниванием заголовка
О приложении-примере
Пример Android Texture Compression, фрагменты которого будут приведены ниже, позволяет всем желающим быстро сравнивать качество текстур пяти форматов. А именно, это Portable Network Graphics (PNG), Ericsson Texture Compression (ETC), Ericsson Texture Compression 2 (ETC2), PowerVR Texture Compression (PVRTC), и S3 Texture Compression (S3TC), который иногда называют DirectX Texture Compression (DXTC).
В примере показано, как загружать и использовать текстуры этих форматов с помощью OpenGL ES в Android. Изображения, хранящиеся в разных форматах, располагаются рядом друг с другом, что позволяет сравнить их размер и качество. Выбор наиболее подходящего под конкретный проект формата хранения сжатых текстур позволяет разработчику найти верный баланс между размером приложения, визуальным качеством картинки и производительностью.
В примере производится загрузка изображения, хранящегося в файле каждого из форматов, определение координат для его наложения на модель и отображение фрагмента каждой текстуры. В итоге получается одно изображение, разбитое на четыре текстуры соответствующего формата. Форматы указаны в верхней части экрана, размер файла приведен внизу.
Рассматриваемый здесь пример основан на коде, который создал Уильям Гуо (William Guo). Кристиано Феррейра (Christiano Ferreira), специалист по графическим приложениям Intel, дополнил его примером использования сжатия текстур ETC2. Загрузить код можно здесь.
Форматы сжатия текстур: размеры и качество
Загрузка PNG
С MIP-картами в формате PNG можно работать с помощью простой функции glGenerateMipmap из Khronos OpenGL, которая была создана специально для этой цели. Мы, для чтения и загрузки PNG-файлов, воспользовались кодом, подготовленным Шоном Барретом (Sean Barret), stb_image.c, который находится в открытом доступе. Так же этот код используется для нахождения и выборки участка текстуры, который нужно обработать.
// Инициализация текстуры
glTexImage2D( GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, pData );
// Поддержка MIP-карты
glGenerateMipmap( GL_TEXTURE_2D );
Загрузка ETC / ETC2
Как было упомянуто выше, ETC-текстуры могут храниться в файлах формата KTX и PKM. KTX – это стандартный формат сжатия, используемый как контейнер для нескольких изображений, он идеально подходит для создания MIP-карт. В свою очередь, PKM создан для хранения отдельных сжатых изображений, поэтому создание на его основе MIP-карт приводит к необходимости генерировать множество файлов, а это неэффективно. Поддержка MIP-карт для ETC в примере ограничена форматом KTX.
Khronos предоставляет библиотеку с открытым кодом, написанную на C (libktx), в которой поддерживается загрузка MIP-карт из KTX-файлов. Мы этой библиотекой воспользовались и реализовали код в функции LoadTextureETC_KTX, ответственной за загрузку текстур. Функция, которая непосредственно загружает KTX-файлы, называется ktxLoadTextureM. Она позволяет загружать нужную текстуру из данных в памяти. Эта функция – часть библиотеки libktx, документацию по ней можно найти на сайте Khronos.
Вот фрагмент кода, который инициализирует текстуру и предоставляет поддержку MIP-карт для формата ETC (KTX).
// Создание обработчика (handle) и загрузка текстуры
GLuint handle = 0;
GLenum target;
GLboolean mipmapped;
KTX_error_code result = ktxLoadTextureM( pData, fileSize, &handle, &target, NULL, &mipmapped, NULL, NULL, NULL );
if( result != KTX_SUCCESS )
{
LOGI( "KTXLib couldn't load texture %s. Error: %d", TextureFileName, result );
return 0;
}
// Привязка текстуры
glBindTexture( target, handle );
Загрузка PVRTC
Поддержка MIP-карт для PVRTC-текстур – задачка чуть посложнее. После чтения заголовка определяется смещение, которое равняется сумме размеров заголовка и метаданных. Метаданные идут следом за заголовком, они не являются частью изображения. Для каждого сгенерированного уровня карты пиксели группируются в блоки (различия зависят от того, применяется ли кодировка 4 бита на пиксель или 2 бита – и тот и другой варианты подходят для PVRTC). Далее, происходит поиск границ, фиксируется ширина и высота блоков. Затем вызывается функция glCompressedTexImage(), она идентифицирует двумерное изображение в сжатом формате PVRTC. Далее, вычисляется размер пиксельных данных и то, что получилось, добавляется к ранее найденному смещению для того, чтобы сгруппировать набор пикселей для следующего фрагмента карты. Этот процесс повторяется до тех пор, пока не будут обработаны все текстуры, из которых состоит карта.
// Инициализация текстуры
unsigned int offset = sizeof(PVRHeaderV3) + pHeader->mMetaDataSize;
unsigned int mipWidth = pHeader->mWidth;
unsigned int mipHeight = pHeader->mHeight;
unsigned int mip = 0;
do
{
// Определение размера (ширина * высота * bbp/8), минимальный размер равен 32
unsigned int pixelDataSize = ( mipWidth * mipHeight * bitsPerPixel ) >> 3;
pixelDataSize = (pixelDataSize < 32) ? 32 : pixelDataSize;
// Выгрузка текстурных данных для фрагмента карты
glCompressedTexImage2D(GL_TEXTURE_2D, mip, format, mipWidth, mipHeight, 0, pixelDataSize, pData + offset);
checkGlError("glCompressedTexImage2D");
// Следующий фрагмент имеет в два раза меньший размер, минимум – 1
mipWidth = ( mipWidth >> 1 == 0 ) ? 1 : mipWidth >> 1;
mipHeight = ( mipHeight >> 1 == 0 ) ? 1 : mipHeight >> 1;
// Переходим к следующему фрагменту
offset += pixelDataSize;
mip++;
} while(mip < pHeader->mMipmapCount);
Загрузка S3TC
После загрузки файла, хранящего S3TC-текстуры, определяется его формат и выполняется чтение MIP-карты, расположенной за заголовком. Производится обход фрагмента карты, пиксели группируются в блоки. Затем, для идентификации двумерного изображения в сжатых данных, вызывается функция glCompressedTexImage(). Общий размер блока затем добавляется к смещению для того, чтобы можно было найти начало следующего фрагмента карты и выполнить те же действия. Это повторяется до тех пор, пока не будут обработаны все уровни карты. Вот фрагмент кода, который инициализирует текстуру и предоставляет поддержку MIP-карт для формата S3TC.
// Инициализация текстуры
// Выгрузка текстурных карт
unsigned int offset = 0;
unsigned int width = pHeader->mWidth;
unsigned int height = pHeader->mHeight;
unsigned int mip = 0;
do
{
// Определение размера
// В расширении определено: size = ceil(<w>/4) * ceil(<h>/4) * blockSize
unsigned int Size = ((width + 3) >> 2) * ((height + 3) >> 2) * blockSize;
glCompressedTexImage2D( GL_TEXTURE_2D, mip, format, width, height, 0, Size, (pData + sizeof(DDSHeader)) + offset );
checkGlError( "glCompressedTexImage2D" );
offset += Size;
if( ( width <<= 1 ) == 0) width = 1;
if( ( height <<= 1 ) == 0) height = 1;
mip++;
} while( mip < pHeader->mMipMapCount );
Выводы
В зависимости от конкретной ситуации, выбор наиболее подходящего формата хранения сжатых текстур может улучшить внешний вид изображений, серьёзно уменьшить размер приложения и значительно повысить производительность. Тщательный подбор оптимального метода сжатия текстур способен дать разработчикам и их приложениям серьёзные конкурентные преимущества. В приложении-примере Android Texture Compression показано, как работать с текстурами наиболее популярных в Android-среде форматов. Загружайте код и добавляйте в свои проекты поддержку наиболее подходящих для них форматов сжатия текстур.
Комментарии (13)
iOrange
29.01.2016 17:55В отличие от ETC и S3TC, алгоритм PVRTC не работает с фиксированными блоками пикселей.
Не совсем.
Для PVRTC4bpp — размер блока 4х4, для PVRTC2bpp — 8x4.
Мы на работе использовали данное свойство чтобы править «мух» на границах полу-прозрачных областей в уже сжатых файлах.
Это, кстати, самый огромный минус PVRTC. С удовольствием бы использовали тот же DXT5 (который сейчас принято называть BC3), но, к сожалению, на iOS-устройствах он не поддерживается.
Lure_of_Chaos
29.01.2016 21:50А что скажете о *.tga?
iOrange
30.01.2016 00:04А что можно сказать о Targa?
Формат очень простой, вот нереально простой, чем завоевал популярность у программистов.
Поддерживает черно-белые (1bpp), grayscale (как по русски правильно?), палитризированные (paletted), RGB и RGBA изображения.
Все это счастье еще и может быть пожато обычным RLE (в классическом варианте — строка RLE не должна пересекать ширину изображения)
Жмет, как вы уже поняли, плохо, зато быстро.
Т.к. писать-читать его легко и без всяких библиотек — широко используется как рабочий формат.
Если нет аллергии на сторонние библиотеки — лучше использовать PNG.
/Added:
Наши художники предпочитают, в качестве промежуточного формата, использовать TGA т.к. в фотошопе очень легко работать с его альфа-каналом. С PNG там позамороченнее.Lure_of_Chaos
30.01.2016 12:11Спасибо. Спросил Ваше мнение, потому что уж очень много в опыте реверс-инжиниринга встречал текстуры именно этого формата, а популярность объяснить не мог. Мол, неужто действительно такой хороший формат?
Но, благодаря опыту и Вашей статье, все же сделал вывод, что оптимальнее использовать PNG, его недостатки не столь велики по сравнению с другими знакомыми форматами (для текстур).iOrange
01.02.2016 01:10Не за что ;) Правда я не автор статьи.
Для текстур, все же, я бы советовал использовать hardware-compressed форматы, они и грузятся быстрее, и памяти меньше занимают.
PNG текстуры все равно распакуются и будут использовать памяти столько же, сколько и BMP, к примеру.
PNG /TGA / TIFF и иже с ними в геймдеве чаще всего используются как промежуточные, т.н. uncooked данные.
Nomad1
30.01.2016 01:37+4Никогда нельзя сравнивать размер PNG и GPU текстур! PNG это LZW архивный контейнер для формата RAW. К примеру, для несжатой текстуры 2048x2048x32 размер будет составлять 16777216 байт, на диске же она будет занимать столько, насколько сожмет компрессор или PNG конвертер, но в видеопамяти все те же 16 мегабайт. В то же время можно без особых проблем сжать каким-нибудь GZIP текстуру PVRTC 2048x2048x4bpp и получить на диске 300 килобайт вместо фиксированных 2097152 байт, которые все-равно она будет занимать в видеопамяти.
Затем, если уж вы рассматриваете текстуры «на все случаи жизни» (т.е. OpenGL ES 1.1-2.0), то обязательно надо учесть ATITC и 3DC.
Вообще, статья ну уж очень «для маленьких». Сравнение качества без метрик PSNR и SSIM не очень полезно, сравнение размера не актуально без таблиц. Подводные камни для больших файлов в assets вообще не упомянуты. Общий вывод-то для текстур на Android такой: для сжатых текстур без прозрачности можно использовать ETC1, для прозрачных — набор из PVRTC/S3TC/ATITC/3DC в зависимости от поддержки железом (можно разные билды выкладывать и параметрами Manifest ставить). Еще можно заморочиться с поддержкой raw 8-bit paletted, для некоторых игр подходит и занимает 8bpp, довольно удобно. Ну и если качество критично, то используем RGBA8888, в контейнере PNG, PVR, KTX и пр., или без оного вообще.
Ну и если у вас уже OpenGL ES 3.0, то тут надо смотреть на новые технологии — ETC2/EAC, ASTC и пр.
В конце-концов для самых-самых хитрых есть такие странности, как декодирование PVRTC или других текстур на ARM-Neon на лету, чтобы читать их на любом железе, собственные методы сжатия (н-р, храним текстуру 1024x1024 и таблицу, по которой достраивается до 2048x2048, если нужно такое разрешение) и т.д. По этим темам я давно хотел написать статьи и заполнить github различным кодом, но как-то руки не дошли.iOrange
30.01.2016 05:38Добрый день коллега.
Подозреваю что статья действительно писалась «для самых маленьких» — для тех кто далек от темы или только-только постигает азы.
То что не было метрик действительно странно (в статье про сжатие изображений то!).
Немного поправить вас хочу — в PNG используется Deflate алгоритм (не LZW), и поток т.н. raw-deflate — т.е. без zlib-маркеров.
Как я уже писал выше — тут так же упущены такие важные моменты как проблемы полупрозрачных текстур при сжатии в PVRTC (например для UI приходится хранить 2 текстуры — PVRTC4bpp для RGB и PVRTC2bpp для A), и делать 2 выборки в шейдере.
3DC это уже специфика — он больше для специфичных текстур (типа нормалмапов) подходит, и, по сути, является тем же DXT5 (BC3), только сбоку.
PS. А можно спросить у вас про raw 8-bit paletted — в железе поддержки нет, значит приходится эмулировать. Вы палитру передаете юниформом в шейдер (а хватит регистров?), или отдельной текстурой.
Никогда не заморачивался, но вот вы написали — и стало жутко интересно.Nomad1
30.01.2016 06:54На счет LZW я действительно приврал уже, ну то такое дело.
Для UI я бы вообще PVRTC не использовал, но это тоже уже по желанию. Кстати, в актуальных версиях PVRTexTool есть регрессия, из-за которой альфа канал жмется хуже, чем 2-3 года назад. Можно даже сравнить и ужаснуться — раньше еще хоть как-то для UI подходило.
Про 8-bit paletted все проще — он обязателен для стандарта OpenGL ES 1.0 — GL_OES_compressed_paletted_texture, а значит и может быть использован где-угодно. Технически, в железе его зачастую реализуют как эмуляцию, но довольно быструю, потому открытие такой текстуры занимает разумное время.
Для работы надо, чтобы первые 1024 байта занимала палитра из 256 элементов, затем изображение с 8bpp. Грузим как обычно через glCompressedTexImage2D (GL.GL_TEXTURE_2D, 0, GL.GL_PALETTE8_RGBA8_OES, width, height, 0, width*height + 1024, data);iOrange
01.02.2016 00:59Для UI я бы вообще PVRTC не использовал
К сожалению на iOS-девайсах это единственное что нам доступно, а учитывая разрешения последних iPad'ов — не жать огромные UI-атласы — просто непозволительно.
PS. Про paletted texture — спасибо, как-то упустил это расширение, правда с ходу не могу придумать куда нам это приспособить, но в багаже знаний пригодится ;)
Denai
31.01.2016 02:06Почему PNG даёт большой размер файлов? Да потому что используется не там где надо. Танчик со второй картинки в PNG как раз будет самым маленьким, нет?
6opoDuJIo
А можно посмотреть. как эти форматы сжимают градиенты?
Athari
А также резкие переходы.
Вообще, странный выбор текстур: пять текстур, при этом все в один-два основных цвета. Преимуществ и недостатков вообще не видать.