OpenGL - быстрые текстурированные квады? - PullRequest
5 голосов
/ 02 октября 2011

Я пытаюсь отобразить как можно больше текстурированных квадов в произвольных положениях в трехмерном пространстве.По моему опыту, я не могу отобразить даже пару тысяч из них без значительного снижения частоты кадров ниже 30 (мой сценарий движения камеры становится запаздывающим).

Сейчас я следую древнему учебнику.После инициализации OpenGL:

glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0, 0, 0, 0);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

я устанавливаю точку обзора и перспективу:

glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

Затем загружаю несколько текстур:

glGenTextures(TEXTURE_COUNT, &texture[0]);
for (int i...){
    glBindTexture(GL_TEXTURE_2D, texture[i]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    gluBuild2DMipmaps(GL_TEXTURE_2D,3,TextureImage[0]->w,TextureImage[0]->h,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->pixels);
}

И, наконец, я рисую свой GL_QUADSиспользуя:

glBindTexture(GL_TEXTURE_2D, q);
glTranslatef(fDistanceX,fDistanceZ,-fDistanceY); 
glBegin(GL_QUADS);
    glNormal3f(a,b,c);
    glTexCoord2f(d, e); glVertex3f(x1, y1,  z1);
    glTexCoord2f(f, g); glVertex3f(x2, y2,  z2);
    glTexCoord2f(h, k); glVertex3f(x3, y3,  z3);
    glTexCoord2f(m, n); glVertex3f(x4, y4,  z4);
glEnd();
glTranslatef(-fDistanceX,-fDistanceZ,fDistanceY);

Я нахожу весь этот код самоочевидным.К сожалению, такой способ, насколько я знаю, устарел.Я прочитал некоторые расплывчатые вещи о PBO и vertexArrays в Интернете, но я не нашел учебника о том, как их использовать.Я даже не знаю, подходят ли эти объекты, чтобы понять, что я пытаюсь сделать здесь (миллиард квадратов на экране без задержки).Возможно, кто-нибудь здесь мог бы дать мне однозначное предложение о том, что я должен использовать для достижения результата?И если у вас есть еще одна минута свободного времени, не могли бы вы дать мне краткое описание того, как используются эти функции (так же, как я делал с устаревшими функциями выше)?

Ответы [ 2 ]

8 голосов
/ 02 октября 2011

Может быть, кто-нибудь здесь мог бы дать мне однозначное предложение о том, что я должен использовать для достижения результата?

Что такое "результат"? Вы не очень хорошо объяснили, что именно вы пытаетесь достичь. Все, что вы сказали, это то, что вы пытаетесь нарисовать много текстурированных четырехугольников. Что вы пытаетесь сделать с этими текстурированными квадраторами?

Например, вы, кажется, создаете одну и ту же текстуру, с той же шириной и высотой, учитывая одни и те же данные пикселей. Но вы храните их в разных текстурных объектах. OpenGL не знает, что они содержат одинаковые данные. Таким образом, вы тратите много времени на смену текстур без необходимости при рендеринге четырехугольников.

Если вы просто рисуете их для проверки производительности, тогда вопрос бессмысленный. Такие тесты бессмысленны, потому что они полностью искусственные. Они тестируют только этот искусственный сценарий, в котором вы меняете текстуры каждый раз, когда визуализируете квад.

Не зная, что вы пытаетесь в конечном итоге визуализировать, единственное, что я могу сделать, это дать общий совет по производительности. По порядку (то есть: сделать первое, прежде чем делать последующие):

  1. Хватит менять текстуры для каждого квадратора. Вы можете упаковать несколько изображений в одну и ту же текстуру, а затем визуализировать все четырехугольники, которые используют эту текстуру одновременно, всего одним вызовом glBindTexture. Координаты текстуры четырехугольника определяют, какое изображение в текстуре используется.

  2. Прекратите использовать glTranslate, чтобы расположить каждый отдельный квад. Вы можете использовать его для позиционирования групп четырехугольников, но вы должны сделать математику самостоятельно, чтобы вычислить позиции вершин четырехугольника. После того как эти glTranslate вызовы исчезли, вы можете поместить несколько четырехугольников в пространство одной пары glBegin/glEnd.

  3. Предполагая, что ваши квады статичны (фиксированная позиция в пространстве модели), рассмотрите возможность использования буферного объекта для хранения и визуализации с вашими данными квадрата.

Я прочитал в Интернете некоторые расплывчатые сведения о PBO и vertexArrays, но я не нашел учебника по их использованию.

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

7 голосов
/ 02 октября 2011

Я слышал, в современных играх миллиарды полигонов отображаются в режиме реального времени

На самом деле это в миллионах.Я предполагаю, что вы немец: «Milliarde» переводится как «Billion» на английском языке.

Сейчас я следую древнему учебнику.

Это ваша основная проблема,Современные приложения OpenGL не используют древние методы рендеринга.Вы используете непосредственный режим, что означает, что вы проходите несколько вызовов функций, чтобы просто отправить одну вершину.Это крайне неэффективно.Современные приложения, такие как игры, могут достичь такого большого числа треугольников, потому что они не тратят время своего ЦП на вызов многих функций, они не тратят пропускную способность ЦП → GPU на поток данных.

Чтобы достичь этогоПри большом количестве отображаемых треугольников в реальном времени вы должны поместить все данные геометрии в «быструю память», то есть в ОЗУ на видеокарте.Методика, предлагаемая OpenGL для этого, называется «Объекты буфера вершин».Используя VBO, вы можете рисовать большие партии геометрии с помощью одного вызова рисования (glDrawArrays, glDrawElements и их родственников).

После того, как вы избавитесь от геометрии, вы должны хорошо относиться к GPU.Графическим процессорам это не нравится, если вы часто переключаете текстуры или шейдеры.Переключение текстуры делает недействительным содержимое кэша (ов), переключение шейдера означает остановку конвейера графического процессора, но, что еще хуже, это делает недействительной статистику прогнозирования пути выполнения (графический процессор принимает статистику, какие пути выполнения шейдера наиболее вероятны для выполненияи какие шаблоны доступа к памяти он демонстрирует, это используется для итеративной оптимизации выполнения шейдера).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...