У меня 5-мегапиксельная текстура, у меня возникли проблемы с обновлением. Текстура отображается на прямоугольнике, не отличающемся от видеопотока.OpenGL Texture Оценить слишком медленно?
Команды OpenGL выполняются быстро, но реальная скорость обновления текстур является суб оптимальной, возможно, всего 3 фактических кадра в секунду. При использовании меньшей текстуры (500x500) есть некоторые изменения, но не так сильно.
Машина имеет NVIDIA GTX 570
Мои первоначальные усилия были использовать glTexSubImage2D
и glBufferSubData
, но они выполнены несколько хуже, чем памяти отображаются схемы.
Есть ли способ заставить графическую карту обновлять текстуру? Как написано программное обеспечение для потоковой передачи видео?
Рендер Loop
void glStream::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
program1.bind();
program1.setUniformValue("texture", 0);
program1.enableAttributeArray(vertexAttr1);
program1.enableAttributeArray(vertexTexr1);
program1.setAttributeArray(vertexAttr1, vertices.constData());
program1.setAttributeArray(vertexTexr1, texCoords.constData());
//
glECheck();
glBindTexture(GL_TEXTURE_2D, textures[0]);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,pbos[0]);
void* memory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,GL_WRITE_ONLY);
device->fillBuffer((unsigned char *)memory,heightGL,widthGL); // takes 2ms (not long)
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,widthGL,heightGL,GL_LUMINANCE,GL_UNSIGNED_BYTE, NULL);
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
glBindTexture(GL_TEXTURE_2D,0);
//
program1.disableAttributeArray(vertexTexr1);
program1.disableAttributeArray(vertexAttr1);
program1.release();
glECheck();//no errors
}
текстуры Резервирование
void glStream::reserveTextures()
{
assert(numGLFrames>0);
assert(glGenBuffers);
displayBuff = (GLubyte*) calloc(numGLFrames*widthGL*heightGL,sizeof(GLubyte));//GL_RGB8
memset(displayBuff,100,numGLFrames*widthGL*heightGL*sizeof(GLubyte));
glGenBuffers(1,&pbos[0]);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbos[0]);
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
numGLFrames*widthGL*heightGL*sizeof(GLubyte),
&displayBuff[0], GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
glGenTextures(1,&textures[0]);
glBindTexture(GL_TEXTURE_2D,textures[0]);
glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,
widthGL,heightGL,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
glBindTexture(GL_TEXTURE_2D,0);
}
Инициализация
void glStream::initializeGL()
{
GLenum err = glewInit();
if (GLEW_OK != err)
{
const char * emssage = (const char*)glewGetErrorString(err);
QMessageBox::information(0, "OpenGL 3.x Context Example",
emssage);
exit(20);
}
glDisable(GL_DEPTH_TEST);
QGLShader *vshader1 = new QGLShader(QGLShader::Vertex, this);
const char *vsrc1 =
"attribute vec2 coord2d; \n"
"attribute mediump vec4 texCoord;\n"
"varying mediump vec4 texc;\n"
"void main() \n"
"{ \n"
" gl_Position = vec4(coord2d, 0.0, 1.0); \n"
" texc = texCoord;\n"
"} \n";
vshader1->compileSourceCode(vsrc1);
QGLShader *fshader1 = new QGLShader(QGLShader::Fragment, this);
const char *fsrc1 =
"uniform sampler2D texture;\n"
"varying mediump vec4 texc;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(texture, texc.st);\n"
"}\n";
fshader1->compileSourceCode(fsrc1);
program1.addShader(vshader1);
program1.addShader(fshader1);
program1.link();
vertexAttr1 = program1.attributeLocation("coord2d");
vertexTexr1 = program1.attributeLocation("texCoord");
// Create the vertex buffer.
vertices.clear();
float u=1;
#define AVEC -u,u
#define BVEC -u,-u
#define CVEC u,u
#define DVEC u,-u
vertices << QVector2D(AVEC);vertices << QVector2D(BVEC);
vertices << QVector2D(CVEC);vertices << QVector2D(BVEC);
vertices << QVector2D(DVEC);vertices << QVector2D(CVEC);
// Create the texture vertex buffer
#define TAVEC 0,1
#define TBVEC 0,0
#define TCVEC 1,1
#define TDVEC 1,0
texCoords << QVector2D(TAVEC);texCoords << QVector2D(TBVEC);
texCoords << QVector2D(TCVEC);texCoords << QVector2D(TBVEC);
texCoords << QVector2D(TDVEC);texCoords << QVector2D(TCVEC);
glECheck();
reserveTextures();
}
Редактировать 1
Я уверен, что заполняющий буфер содержит новую текстуру, потому что в какой-то другой части кода я пишу эту текстуру в файл, и это действительно другое. Это печальный день, когда мой файл IO быстрее, чем текстура OpenGL.
Edit 2 Я попробовал FRAPS, и я проверил, что делают цикл происходит при ~ 18 FPS, но видимые обновления медленнее (возможно, 3 FPS). Что может объяснить такое несоответствие?
Я не эксперт в этом сам, но так как вы упомянули о том, что у вас есть карта Nvidia и хотите, чтобы графическая карта говорила, чтобы напрямую обновить ваш буфер OpenGL: подумали ли вы об использовании Cuda? На странице разработчиков Nvidia существует довольно много примеров проектов, которые иллюстрируют именно это. – Yellow
Ваш выбор слов «реальная скорость обновления текстур» заставляет меня задаться вопросом, что именно означает это утверждение? Горячий, ты это измерил? Какой код вызывает ваши репликации? Как часто они происходят? В комментарии ниже вы сказали что-то о 20fps: вы говорите, что 'paintGL()' вызывается примерно 20 раз в секунду, но только 3 раза в секунду вы видите обновленную текстуру на экране? Если да: вы уверены, что 'fillBuffer()' придумывает «новую» текстуру каждый раз, когда вы ее вызываете? – axxel
@axxel Да, это именно то, что я имею в виду, я уверен, что буфер заполнения появляется с новой текстурой, потому что в какой-то другой части кода я пишу эту текстуру в файл, и это действительно так. Это печальный день, когда ваш файл IO быстрее, чем текстура OpenGL. – Mikhail