Бърз палетиран екран с OpenGL

Една игра използва софтуерно изобразяване, за да начертае палетирано (8-битово) изображение на цял екран в паметта.

Кой е най-бързият начин да поставите това изображение на екрана с помощта на OpenGL?

Неща, които съм пробвал:

  • glDrawPixels с glPixelMap за указване на палитрата и оставяне на OpenGL да направи картографирането на палитрата. Производителността беше ужасяваща (~5 FPS).
  • Извършване на картографиране на палитри (индексирано -> BGRX) в софтуера, след което чертаене с помощта на glDrawPixels. Производителността беше по-добра, но използването на процесора все още е много по-високо от използването на 32-битов DirectDraw със същото картографиране на софтуерната палитра.

Трябва ли вместо това да използвам някаква текстура?


person Vladimir Panteleev    schedule 21.09.2012    source източник
comment
Определено. Заредете изображението като текстурен обект, след което нарисувайте четириъгълник (или два триъгълника), текстуриран с това изображение.   -  person Ben Zotto    schedule 21.09.2012
comment
Въпреки че изображението ще се променя всеки кадър?   -  person Vladimir Panteleev    schedule 21.09.2012
comment
@CyberShadow: Е, какво друго ще правиш? Данните за вашето изображение са в паметта на клиента, а не в GPU. Преди графичният процесор да може да го изобрази, той трябва да стигне до графичния процесор. Например като го поставите в текстура.   -  person Nicol Bolas    schedule 21.09.2012
comment
Благодаря. Предполагам, че ми е просто контраинтуитивно, че създаването на текстура (с всичките й режийни) ще бъде по-бързо от простото извикване на функция, специално предназначена за тази задача.   -  person Vladimir Panteleev    schedule 21.09.2012
comment
И все пак можете да ускорите качването на текстури, като използвате Async DMA трансфер с PBOs ping-pong. Google за това. Ето един от ресурсите: songho.ca/opengl/gl_pbo.html. Можете да спечелите x10 -x16 време за зареждане (вашата текстура трябва да се чете от паметта, а не от IO)   -  person Michael IV    schedule 21.09.2012
comment
@CyberShadow Не създавате текстура на всеки кадър (което наистина носи някои допълнителни разходи). Вие просто актуализирате изображението му, като използвате glTexSubImage2DSub там е важно). И разбира се Майкъл е прав за използването на PBO във ваша полза. Но glDrawPixels е най-бавното нещо, което можете да направите.   -  person Christian Rau    schedule 21.09.2012


Отговори (1)


  • glDrawPixels с glPixelMap за указване на палитрата и оставяне на OpenGL да направи картографирането на палитрата. Производителността беше ужасяваща (~5 FPS).

Това не е изненада. glDrawPixels не е много бърз като начало и glPixelMap ще направи преобразуването на индекс/палета → RGB на процесора в със сигурност не много оптимизиран кодов път.

  • Извършване на картографиране на палитри (индексирано -> BGRX) в софтуера, след което рисуване с помощта на glDrawPixels.

glDrawPixels е една от най-бавните функции в OpenGL. Това има две основни причини: първо, това е кодов пач, който не е много оптимизиран, второ, той записва директно в целевия буфер на кадри, като по този начин принуждава конвейера да се синхронизира всеки път, когато бъде извикан. Освен това на повечето графични процесори той не е подкрепен от никакъв кеш.

Това, което предлагам, е да поставите вашето индексирано изображение в едноканална текстура, напр. GL_R8 (за OpenGL-3 или по-късно) или GL_LUMINANCE8 и вашата палитра в 1D RGB текстура, така че индексът, използван като текстурна координата, да търси цвета. Използването на текстура като LUT е напълно нормално. С тази комбинация използвате фрагментен шейдър за преобразуване на индекс на палитра в цвят на място.

Фрагментният шейдър ще изглежда така

#version 330

uniform sampler2D image;
uniform sampler1D palette;

in vec2 texcoord;

void main()
{
    float index = tex2D(image, texcoord).r * 255.f; // 255 for a 8 bit palette
    gl_FragColor = texelFetch(palette, index, 0);
}
person datenwolf    schedule 21.09.2012