glReadPixels () действительно медленное, лучшее решение для получения координат OpenGL с позиции мыши? - PullRequest
5 голосов
/ 06 февраля 2010

Это мой код, который я использую для определения положения мыши в 3D-сцене:

void GetOGLPos(int x, int y, GLdouble &pX, GLdouble &pY, GLdouble &pZ){
 GLint viewport[4];
 GLdouble modelview[16];
 GLdouble projection[16];
 GLfloat winX, winY, winZ;

 glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
 glGetDoublev(GL_PROJECTION_MATRIX, projection);
 glGetIntegerv(GL_VIEWPORT, viewport);

 winX = (float)x;
 winY = (float)viewport[3]-(float)y;
 glReadPixels(x, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);

 gluUnProject(winX, winY, winZ, modelview, projection, viewport, &pX, &pY, &pZ);
}

Но я заметил одну плохую вещь ... 1-2 вызова этой функции на кадр делают загрузку процессора 100%, 3 или более вызовов 200% загрузки процессора (у меня 4 ядра, 1-2 вызова = 25%, 3 или больше звонков = 50%, я не могу сделать это выше, чем 50%, я думаю ..)

Есть ли другой способ сделать это эффективно? Я использую 4 вызова этой функции в каждом кадре, поэтому я знаю, какие области я должен отрисовать для моей сцены (я беру их с каждого угла экрана).

Также я использую это, чтобы знать, на какое место я указываю мышью, поэтому мне это нужно в режиме реального времени, но я бы хотел использовать меньше ЦП, потому что даже один вызов делает его 100% -ным использованием для одноядерных систем.

РЕДАКТИРОВАТЬ

Я пробовал метод glPushName (), но он даже медленнее, скорее, медленнее в моем GPU, чем в CPU. Кроме того, загрузка моего процессора составляет всего 0-1%, когда в моей программе не используется ни один вызов glReadPixels (). Странно то, что у меня высокая загрузка ЦП, но это не делает программу запаздывающей, как можно было ожидать при 100% использовании ... проблема возникает только тогда, когда я использую другие программы, когда моя программа включена, и их использование отстает .

Ответы [ 3 ]

1 голос
/ 06 февраля 2010

Похоже, вы пытаетесь делать отбор в OpenGL.

Изучите этот учебник, он должен иметь меньше потерь производительности, чем ваш подход: http://gpwiki.org/index.php/OpenGL:Tutorials:Picking

В этом месте упоминаются другие способы выбора в OpenGL: http://www.opengl.org/resources/faq/technical/selection.htm

0 голосов
/ 18 января 2013

glReadPixels будет использовать CPU для преобразования данных, считываемых из кадрового буфера, даже когда вы пытаетесь использовать PBO. Например, если вы попытаетесь прочитать данные о цвете с помощью PBO, только если для параметра установлено значение GL_BGRA, функция не будет преобразовывать данные и немедленно вернется. В противном случае, если вы установите параметр в GL_RGBA, загрузка процессора будет занята. Я также пытаюсь прочитать данные о глубине из кадрового буфера, но glReadPixels определенно преобразует данные независимо от установки параметра

0 голосов
/ 05 марта 2010

Вы абсолютно уверены, что эта единственная функция вызывает проблему? Вы пробовали инструмент профилирования для подтверждения? Не то чтобы я хотел сомневаться в вас, я просто хочу, чтобы вы были уверены, прежде чем вы начнете испытывать проблемы с отладкой или изменением больших битов вашего кода.

Я довольно удивлен, что вызов OpenGL (чтобы прочитать один пиксель, не меньше) занимает CPU время. Во всяком случае, я думаю, что это покажет 0 загрузки процессора, но имеет медленную частоту кадров. Но я едва знаю достаточно об OpenGL, чтобы подозревать, что с этим что-то действительно не так. Кажется, это просто кажется не интуитивным.

В сообщении на форуме о производительности glReadPixels указывается, что некоторые графические карты (особенно старые) просто неэффективны при перемещении данных с графического процессора на процессор. Можете ли вы запустить свой код на другом компьютере, чтобы увидеть, если это только ваша видеокарта? Это был бы лучший способ начать, особенно если у вас есть карта ATI и вы используете ее на карте NVIDIA друга или наоборот.

В сообщении также упоминается, что тип данных может иметь значение. Я не вижу в этом большого значения, но кто знает.

Еще одна вещь, которую вы можете попробовать: если вы вызываете функцию четыре раза подряд, у вас есть три лишних набора вызовов для чтения текущих матриц. Попробуйте вместо этого взять матрицы через параметры. Но я сомневаюсь, что glGetDoublev / glGetIntegerv действительно занимают много времени.

В зависимости от того, что вы делаете, вы, возможно, захотите прочитать об отбраковке фруструма. Это похоже на то, что вы пытаетесь сделать, получая четыре угла экрана. Для вас может быть дешевле реализовать математику самостоятельно, чем использовать glUnProject.

...