Быстрый палитра экрана с OpenGL
Игра использует программный рендеринг для рисования полноэкранного палитрового (8-битного) изображения в памяти.
Какой самый быстрый способ вывести это изображение на экран, используя OpenGL?
Вещи, которые я пробовал:
glDrawPixels
сglPixelMap
указать палитру и позволить OpenGL сделать отображение палитры. Производительность была ужасной (~5 FPS).- Выполнение отображения палитры (indexed -> BGRX) в программном обеспечении, затем рисование, используя
glDrawPixels
, Производительность была лучше, но загрузка процессора все еще намного выше, чем при использовании 32-битнойDirectDraw
с тем же программным обеспечением отображения палитры.
Должен ли я использовать какую-то текстуру вместо этого?
1 ответ
- glDrawPixels с glPixelMap, чтобы указать палитру, и позволить OpenGL сделать отображение палитры. Производительность была ужасной (~5 FPS).
Это не удивительно. С самого начала glDrawPixels работает не очень быстро, и glPixelMap выполняет преобразование индекса / палитры → RGB на ЦП в явно не очень оптимизированном пути кода.
- Выполнение отображения палитры (indexed -> BGRX) в программном обеспечении, затем рисование с использованием glDrawPixels.
glDrawPixels - одна из самых медленных функций в OpenGL. Это имеет две основные причины: во-первых, это не очень оптимизированная кодовая заплатка, во-вторых, она записывает непосредственно в целевой кадровый буфер, следовательно, заставляет конвейер синхронизироваться каждый раз, когда он вызывается. Также на большинстве графических процессоров он не поддерживается ни одним кешем.
Я предлагаю вам поместить ваше индексированное изображение в одноканальную текстуру, например, GL_R8 (для OpenGL-3 или новее) или GL_LUMINANCE8, и свою палитру в 1D RGB-текстуру, чтобы индекс, используемый в качестве координаты текстуры, действительно искал цвет. Использование текстуры в качестве LUT совершенно нормально. В этой комбинации вы используете фрагментный шейдер для преобразования палитры in-situ в цвет.
Фрагмент шейдера будет выглядеть так
#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);
}