Я пишу приложение, которое отображает случайный остров, засаженный деревьями. Деревья в настоящее время представляют собой два четырехугольника, перекрещенные и нарисованные текстурами. Я планирую иметь более сложные сетки, которые формируют различные типы растений, например, пальму, дуб, траву и т.д ..
Проблема, с которой я сталкиваюсь, состоит в том, что, поскольку текстуры прозрачны, я должен нарисовать их сзади вперед. План-б состоит в том, чтобы вызвать использование discard в фрагментном шейдере, но z-порядок дает лучшие результаты:
uniform float uTreeAlpha;
uniform sampler2D uTexture;
varying vec2 vTexCoordOut;
void main (void)
{
vec4 colour = texture2D(uTexture, vTexCoordOut);
if (colour.a < 0.1) {
discard;
}
gl_FragColor = vec4(colour.rgb, colour.a * uTreeAlpha);
}
Вторая проблема заключается в том, что порядок меняется в зависимости от камеры и вида. Я не знаю эффективного способа нарисовать их в OpenGL за один вызов.
В настоящее время мой код рендеринга выглядит следующим образом:
if cameraChangedFromLastTime() then
sortTreesBackToFront();
end
for i = 0 to trees.size() -1
drawTree()
end
Где каждый drawTree () устанавливает некоторые формы, устанавливает текстуру, а затем вызывает glDrawArrays (). У меня есть некоторые оптимизации, чтобы пропустить установку текстуры или обновление текстурных координат, если последнее дерево и текущий совпадают, и установить некоторые общие формы вне цикла, и пропустить деревья, которые слишком далеко, но в основном, если у меня есть 3000 деревьев, я иди 3000 раз по кругу.
Рисование каждого дерева в отдельности является убийцей производительности. Если бы я мог нарисовать их одним вызовом или партиями (при сохранении Z-порядка), я бы, вероятно, сделал это в 1/10 времени.
Так как бы я это сделал. Имейте в виду, что мои деревья являются местозаполнителями, и в конечном итоге я получу:
- Разные сетки для разных деревьев
- Различные масштабы и углы для деревьев, чтобы дать больше разнообразия
- Различные текстуры для разных деревьев, потенциально несколько текстур, примененных к сетке (например, оставляет одну текстуру, ствол другой)
- Деревья все смешаны вместе, поэтому нет простого способа нарисовать один вид, а затем другой
- Некоторая форма простой циклической анимации (ветки качаются на ветру)
- Все текстуры будут находиться в одном атласе
Итак, что лучше подходит здесь? Возможно ли сделать рендеринг за один проход? Если бы я использовал glDrawElements, перестраивая индексы, но не вершины, могу ли я достичь этого?
источник
Ответы:
То, что вы хотите, это аппаратное копирование . Примечание: я сделал это в XNA (то есть DirectX), но я не очень разбираюсь в OpenGL. Я уверен, что есть сопоставимая особенность, хотя. По сути, это то, что он связывает вместе вершины вашей модели дерева с другим потоком вершин, который несет мировые координаты для каждого экземпляра.
источник
Прозрачность нужно заказывать только в том случае, если используется неаддитивное смешивание. Для тонны отдаленных рекламных щитов смешивание не нужно (вы действительно не можете видеть это). Рендеринг по крайней мере следующих с прозрачностью выреза (альфа только 1 или 0), и вам не нужно сортировать их.
Вы можете использовать лист спрайтов для визуализации различных типов деревьев с запеченными анимациями. Нарисуйте сетки для более близких деревьев, которые вы можете анимировать с большей точностью, основываясь на ветре или что угодно.
источник