Мне нужно очень быстро смешать тысячи пар изображений.
В настоящее время мой код делает следующее: _apply — это указатель на функцию, подобную Blend. Это одна из многих функций, которые мы можем передать, но не единственная. Любая функция принимает два значения и выводит третье, и это делается на каждом канале для каждого пикселя. Я бы предпочел решение, которое является общим для любой такой функции, а не конкретное решение для смешивания.
typedef byte (*Transform)(byte src1,byte src2);
Transform _apply;
for (int i=0 ; i< _frameSize ; i++)
{
source[i] = _apply(blend[i]);
}
byte Blend(byte src, byte blend)
{
int resultPixel = (src + blend)/2;
return (byte)resultPixel;
}
Я делал это на процессоре, но производительность ужасна. Насколько я понимаю, делать это на GPU очень быстро. Моя программа должна работать на компьютерах с графическими процессорами Nvidia или Intel, поэтому любое решение, которое я использую, должно быть независимым от поставщика. Если я использую графический процессор, он также должен быть OpenGL, чтобы быть независимым от платформы.
Я думаю, что использование пиксельного шейдера GLSL помогло бы, но я не знаком с пиксельными шейдерами или с тем, как использовать их для 2D-объектов (например, моих изображений).
Это разумное решение? Если да, то как это сделать в 2D? Если есть библиотека, которая уже делает это, тоже полезно знать.
РЕДАКТИРОВАТЬ: я получаю пары изображений из разных источников. Один всегда исходит из компонента 3D-графики в opengl (то есть изначально в GPU). Другой исходит из системной памяти либо из сокета (в сжатом видеопотоке), либо из файла с отображением памяти. «Стоком» результирующего изображения является экран. Ожидается, что я покажу изображения на экране, поэтому для их отображения можно использовать GPU или что-то вроде SDL.
Функция смешивания, которая будет выполняться чаще всего, это
byte Patch(byte delta, byte lo)
{
int resultPixel = (2 * (delta - 127)) + lo;
if (resultPixel > 255)
resultPixel = 255;
if (resultPixel < 0)
resultPixel = 0;
return (byte)resultPixel;
}
РЕДАКТИРОВАТЬ 2: Изображение, поступающее с земли GPU, происходит таким образом. От FBO к PBO к системной памяти
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
glReadBuffer( GL_COLOR_ATTACHMENT0 );
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glReadPixels(0,0,width,height,GL_BGR,GL_UNSIGNED_BYTE,0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
void* mappedRegion = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
Похоже, что лучше просто работать в памяти графического процессора. Другое растровое изображение может поступать из системной памяти. В конечном итоге мы можем получить его и из видеодекодера в памяти графического процессора.
Редактировать 3: одно из моих изображений будет получено из D3D, а другое - из OpenGL. Кажется, что-то вроде Thrust или OpenCL — лучший вариант