Быстрый палитра экрана с 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);
}
Другие вопросы по тегам