Дайте пару советов по OpenGL
2. Изучить исходники Q2.
А что конкретно-то интересует? Оптимизировать много чего можно.
в каких-то nvidiевских доках читал, что быстре всего будет работать, если модель будешь передавать, как triangle_fan
не любую модель можно представить в виде треугольного вентилятора
2. интересно
3. скорость работы приложения
рендер сцен состоит из более 5000 полигонов и текстуры 5000*1000*4 байт
и что значит - моделек нет? просто более-менее случайные полигоны в пространстве?
- Треугольников у тебя не очень много, поэтому можешь смело посылать ВСЕ на видеокарту и не отбрасывать отсекаемые пирамидой видимости части сцены. Пользуйся связными списками треугольников (GL_TRIANGLE_STRIP) или четырехугольников (GL_QUAD_STRIP).
- Используй Z-буфер и выводи сцену по частям, от ближнего к дальнему, тогда видеокарта не будет вычислять цвета тех текселей, которые не видны. Также для повышения производительности необходимо пользоваться mipmap'ами.
первое в моей ситуации не дало эффекта, третье использую, т.к. прозрачности много
спасибо заранее
заодно можешь поискать в сети nvidia sdk. то ли в нем, то ли в окрестности была куча ppt-шников, и в них были рекомендации, как убыстрить работу
1. Порядок вывода элементов сцены.
Z-буфер хранит для каждого пикселя на экране расстояние от наблюдателя до объекта, занимающего этот пиксель. Если тест глубины пройден, то входящее значение глубины заменяет уже находящееся в буфере глубины.
В основном буфер глубины используется для удаления невидимых поверхностей. Если новый объект претендует на окраску пикселя, то цвет объекта вычисляется только в случае, когда соответствующий объект ближе, чем предыдущий. Цвет входящего элемента НЕ ВЫЧИСЛЯЕТСЯ, если тест глубины не пройден, что освобождает графическое ядро от лишней работы.
Конечно, чтобы определить расстояние до объекта необходимо сначала отправить на видеокарту координаты вершин, из которых он состоит (а возможно и нормали к вершинам, и их цвета, и текстурные координаты). Если объект достаточно сложный, но при этом никакая его часть не видна, то мы только зря заставим графическое ядро обрабатывать эти вершины. Налицо явная потеря производительности.
Суммируя вышесказанное, получаем следующий порядок работы со сценой:
- Отбрасываем крупные элементы сцены (состоящие из большого количества примитивов) не попадающие в область видимости. Один из способов — это использование ограничивающих тел для объектов и частей сцены, объединение их в иерархические структуры и последующая проверка на пересечение их с областью видимости.
- Включаем тест глубины и выводим НЕПРОЗРАЧНЫЕ элементы сцены в порядке от ближнего к дальнему.
- Если у нас есть прозрачные объекты, то их выводим ПОСЛЕ непрозрачных. При этом отправляем их на видеокарту в порядке ОТ ДАЛЬНЕГО К БЛИЖНЕМУ.
2. Эффективная передача геометрических данных на видеокарту.
Каждый объект задается некоторым множеством вершин, но OpenGL рисует примитивами: треугольниками и четырехугольниками, поэтому нельзя просто послать графической системе массив вершин — ей нужна последовательность примитивов. Другое дело, что они (примитивы) задаются вершинами.
Чтобы нарисовать четырехугольник (далее квадрат используется следующий код:
glBegin(GL_QUADS);Если рядом с первым четырехугольником находится второй, использующий две вершины первого — v2 и v3, то для того чтобы нарисовать их оба используем следующий код:
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v3);
glVertex3fv(v2);
glEnd;
glBegin(GL_QUADS);Если у нас достаточно длинный список связанных таким образом квадратов, то мы посылаем графической системе в 2 раза больше вершин, чем это необходимо для полного описания этого списка. Таким образом, при стандартном подходе получаем избыточную обработку вершин между смежными многоугольниками.
// рисуем 1-ый
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v3);
glVertex3fv(v2);
// рисуем 2-ой
glVertex3fv(v2);
glVertex3fv(v3);
glVertex3fv(v5);
glVertex3fv(v4);
// и т. д..
glEnd;
Для рисования связанной полосы четырехугольников в качестве параметра команде glBegin необходимо передать параметр GL_QUAD_STRIP. Ниже приводится код для вывода трех последовательных квадратов:
glBegin(GL_QUAD_STRIP);Получаем более эффективную, чем во втором случае передачу данных, т.к. каждая вершина обрабатывается 1 раз.
// рисуем 1-ый
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v2);
glVertex3fv(v3);
// рисуем 2-ой, используя две предыдущие вершины
glVertex3fv(v4);
glVertex3fv(v5);
// рисуем 3-ий, используя две предыдущие вершины
glVertex3fv(v6);
glVertex3fv(v7);
glEnd;
Вариантов эффективной подачи данных на видеокарту существует довольно много, поэтому, резюмируя, коротко о самых основных:
- Если в объекте (или какой-либо части сцены) полигоны связаны смежными вершинами, то при передаче данных используем примитивы GL_TRIANGLE_STRIP, GL_QUAD_STRIP или GL_TRIANGLE_FAN.
- Если у нас имеется набор несвязанных общими вершинами четырехугольников (например система частиц то для их отображения используйте единственный вызов glBegin(GL_QUADS) вместо использования множества вызовов glBegin(GL_QUADS). Все вышесказанное в равной мере относится и к треугольникам.
- Если геометрия статическая, то использование дисплейных списков может значительно повысить скорость обработки вершин.
- Возможно еще большее увеличение производительности при сохранении данных вершин в массивах вершин и дальнейшая передача этих данных при помощи команд glDrawElements и glDrawArrays.
Для заинтересовавшихся оптимизацией всерьез:
Если есть вопросы — пишите, постараюсь ответить.
Оставить комментарий
lord2476
точнее по оптимизации, и получения большей скорости работы