Дайте пару советов по OpenGL

lord2476

точнее по оптимизации, и получения большей скорости работы

al70

1. Почитать книжку по OpenGL.
2. Изучить исходники Q2.
А что конкретно-то интересует? Оптимизировать много чего можно.

NataNata

в каких-то nvidiевских доках читал, что быстре всего будет работать, если модель будешь передавать, как triangle_fan

foxie84

не любую модель можно представить в виде треугольного вентилятора

lord2476

1. гавносовет.
2. интересно
3. скорость работы приложения

lord2476

моделек нет.
рендер сцен состоит из более 5000 полигонов и текстуры 5000*1000*4 байт

NataNata

а в чем вопрос? неужели медленно? у меня lightwave3D в openGL крутит 5000 полигонов текстурированных полигонов с большим фпс-ом
и что значит - моделек нет? просто более-менее случайные полигоны в пространстве?

maddok

- Текстуру разбей на более мелкие: 256х256 или 512х512, в любом случае размер текстуры должен быть степенью двойки (можешь, конечно, воспользоваться расширением NV_texture_rectangle, но это снизит производительность, а текстурку все равно придется порезать на более мелкие, т.к. не все видеокарты поддерживают такие большие текстуры).
- Треугольников у тебя не очень много, поэтому можешь смело посылать ВСЕ на видеокарту и не отбрасывать отсекаемые пирамидой видимости части сцены. Пользуйся связными списками треугольников (GL_TRIANGLE_STRIP) или четырехугольников (GL_QUAD_STRIP).

- Используй Z-буфер и выводи сцену по частям, от ближнего к дальнему, тогда видеокарта не будет вычислять цвета тех текселей, которые не видны. Также для повышения производительности необходимо пользоваться mipmap'ами.

lord2476

как сделать второе?
первое в моей ситуации не дало эффекта, третье использую, т.к. прозрачности много

NataNata

всем большая просьба - если найдете кто-нибудь, киньте сюда или в приват алгоритм этот
спасибо заранее

NataNata

заодно можешь поискать в сети nvidia sdk. то ли в нем, то ли в окрестности была куча ppt-шников, и в них были рекомендации, как убыстрить работу

maddok

­Чтобы решить проблему, нужно ее себе четко представлять. Поэтому расскажу несколько ОБЩИХ принципов по выводу изображений при помощи OpenGL.
1. Порядок вывода элементов сцены.
Z-буфер хранит для каждого пикселя на экране расстояние от наблюдателя до объекта, занимающего этот пиксель. Если тест глубины пройден, то входящее значение глубины заменяет уже находящееся в буфере глубины.
В основном буфер глубины используется для удаления невидимых поверхностей. Если новый объект претендует на окраску пикселя, то цвет объекта вычисляется только в случае, когда соответствующий объект ближе, чем предыдущий. Цвет входящего элемента НЕ ВЫЧИСЛЯЕТСЯ, если тест глубины не пройден, что освобождает графическое ядро от лишней работы.
Конечно, чтобы определить расстояние до объекта необходимо сначала отправить на видеокарту координаты вершин, из которых он состоит (а возможно и нормали к вершинам, и их цвета, и текстурные координаты). Если объект достаточно сложный, но при этом никакая его часть не видна, то мы только зря заставим графическое ядро обрабатывать эти вершины. Налицо явная потеря производительности.
Суммируя вышесказанное, получаем следующий порядок работы со сценой:
  • Отбрасываем крупные элементы сцены (состоящие из большого количества примитивов) не попадающие в область видимости. Один из способов — это использование ограничивающих тел для объектов и частей сцены, объединение их в иерархические структуры и последующая проверка на пересечение их с областью видимости.
  • Включаем тест глубины и выводим НЕПРОЗРАЧНЫЕ элементы сцены в порядке от ближнего к дальнему.
  • Если у нас есть прозрачные объекты, то их выводим ПОСЛЕ непрозрачных. При этом отправляем их на видеокарту в порядке ОТ ДАЛЬНЕГО К БЛИЖНЕМУ.

2. Эффективная передача геометрических данных на видеокарту.
Каждый объект задается некоторым множеством вершин, но OpenGL рисует примитивами: треугольниками и четырехугольниками, поэтому нельзя просто послать графической системе массив вершин — ей нужна последовательность примитивов. Другое дело, что они (примитивы) задаются вершинами.
Чтобы нарисовать четырехугольник (далее квадрат используется следующий код:
glBegin(GL_QUADS);
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v3);
glVertex3fv(v2);
glEnd;
Если рядом с первым четырехугольником находится второй, использующий две вершины первого — v2 и v3, то для того чтобы нарисовать их оба используем следующий код:
glBegin(GL_QUADS);
// рисуем 1-ый
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v3);
glVertex3fv(v2);
// рисуем 2-ой
glVertex3fv(v2);
glVertex3fv(v3);
glVertex3fv(v5);
glVertex3fv(v4);
// и т. д..
glEnd;
Если у нас достаточно длинный список связанных таким образом квадратов, то мы посылаем графической системе в 2 раза больше вершин, чем это необходимо для полного описания этого списка. Таким образом, при стандартном подходе получаем избыточную обработку вершин между смежными многоугольниками.
Для рисования связанной полосы четырехугольников в качестве параметра команде glBegin необходимо передать параметр GL_QUAD_STRIP. Ниже приводится код для вывода трех последовательных квадратов:
glBegin(GL_QUAD_STRIP);
// рисуем 1-ый
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v2);
glVertex3fv(v3);
// рисуем 2-ой, используя две предыдущие вершины
glVertex3fv(v4);
glVertex3fv(v5);
// рисуем 3-ий, используя две предыдущие вершины
glVertex3fv(v6);
glVertex3fv(v7);
glEnd;
Получаем более эффективную, чем во втором случае передачу данных, т.к. каждая вершина обрабатывается 1 раз.
Вариантов эффективной подачи данных на видеокарту существует довольно много, поэтому, резюмируя, коротко о самых основных:
  • Если в объекте (или какой-либо части сцены) полигоны связаны смежными вершинами, то при передаче данных используем примитивы GL_TRIANGLE_STRIP, GL_QUAD_STRIP или GL_TRIANGLE_FAN.
  • Если у нас имеется набор несвязанных общими вершинами четырехугольников (например система частиц то для их отображения используйте единственный вызов glBegin(GL_QUADS) вместо использования множества вызовов glBegin(GL_QUADS). Все вышесказанное в равной мере относится и к треугольникам.
  • Если геометрия статическая, то использование дисплейных списков может значительно повысить скорость обработки вершин.
  • Возможно еще большее увеличение производительности при сохранении данных вершин в массивах вершин и дальнейшая передача этих данных при помощи команд glDrawElements и glDrawArrays.

Для заинтересовавшихся оптимизацией всерьез:



Если есть вопросы — пишите, постараюсь ответить.
Оставить комментарий
Имя или ник:
Комментарий: