Я имею в виду сцену типа Minecraft, где под вокселем вы подразумеваете мир блоков, которые на самом деле визуализируются с использованием полигонов:
Если вы используете геометрический шейдер, вам будет трудно избежать ровно трех граней (или чего-то еще) на воксель.
Если у вас есть много смежных блоков, которые имеют одинаковую текстуру, вы можете использовать мозаику текстур, чтобы иметь гораздо меньше треугольников в вашей (вырожденной) полосе в подходе VBO. Я имею в виду, что если есть хороший большой плоский участок 6x6 вокселей травы, вы можете нарисовать всю вершину всего за 2 треугольника, а не за 64.
При подходе GS вы не можете выполнять тривиальный отбор граней, перекрытых соседними вокселями, что также очень просто при подходе VBO.
Я не пробовал подход GS, но могу сказать, что подход VBO с объединением повторяющихся соседних плиток работает очень хорошо. Я обнаружил, что возиться с индексами элементов гораздо медленнее, чем просто повторять вершины. Если вы разделите свой мир на маленькие кубики, вы обычно можете использовать только один байт на компонент для каждой вершины и даже упаковать информацию о текстуре и нормали (у грани на выровненном по оси кубе есть только 3 возможных нормали) и т. Д. В четвертый байт, чтобы сделать 4 байта на вершину, что приятно и быстро.
Я использовал отдельные VBO для каждой из 6 граней - вам, очевидно, нужно всего лишь нарисовать не более 3 из них. Это прекрасно согласуется с различными текстурами, обычно используемыми в верхних частях вокселей в стиле Minecraft. Потому что для каждого набора нормальное и таковое тогда одинаково.
С использованием вертикально-мозаичных растровых изображений в атласе с GL_REPEAT
горизонтальной осью и с поворотными на 90 градусов версиями растровых изображений в одном и том же атласе я обнаружил, что могу рисовать огромное количество явно разных блоков, используя один и тот же VBO в одном вызове. В примере с площадью травы 6х6 я бы разбил это на 12 треугольников, поскольку я повторял только одно измерение в моем атласе.
Я в основном заставлял это работать на самом низком уровне интегрированных графических чипов и мобильных устройств, где GS - это просто то, о чем я могу мечтать, играя однажды.
Как насчет третьего варианта, использующего инстансированные массивы? По сути, вы рисуете множество блоков (сделанных из простого 8-вершинного куба) одним вызовом отрисовки, выбирая позиции (и другие данные) в качестве атрибутов для каждого экземпляра из VBO Voxel-data (
glVertexAttribDivisor
я уверен, используя OpenGL) У DX это тоже есть). Это может быть быстрее, чем подход геометрического шейдера, хотя код приложения (не шейдер) должен быть довольно похожим, поскольку я помню, что геометрические шейдеры имеют репутацию медленных, хотя у меня нет опыта работы с ними (или создания экземпляров), так как я до сих пор сижу на 2.1 аппаратно.Но в любом случае, либо геометрические шейдеры, либо экземпляры массивов должны быть более подходящими, чем встроенная в CPU геометрия вокселей, особенно когда данные вокселей подвержены изменениям. В сочетании с обратной связью с преобразованием (вывод потока в DX?) Вы можете установить хорошую методику отбора на основе графического процессора.
источник
Геометрия шейдерной версии звучит для меня намного лучше. Вы можете иметь только точку VBO и поле построения на лету (точка входа, поток выходного треугольника). Он будет быстрым (даже быстрее, если вы будете использовать модуль тесселяции в шейдерной модели 5 экв. DX11) и значительно сократит полосу пропускания, это будет хорошим и чистым решением.
О ГС. Он помещается между вершинным шейдером и пиксельным шейдером и изменяет исходящий поток вершин (примитивов). В то время как вершинный шейдер работает только с вершинами, геометрический шейдер работает с целыми примитивами. Вывод этого потока идет только в пиксельный шейдер (и перед этим растеризуется, конечно же, :)), и сохранить его невозможно. (Может быть, с помощью какого-то сумасшедшего рендеринга в текстуру и последующего синтаксического анализа ... но реальной возможности нет)
Замечание по производительности: Вы должны быть способны ко всему в геометрическом шейдере и пропустить (просто передать данные) вершинный шейдер. Но это не лучший способ. Лучше (быстрее) выполнить большинство возможных преобразований в вершинном шейдере и попытаться свернуть программу геометрического шейдера. Не бойтесь использовать для цикла, если он вам понадобится (например, для создания коробки). Компилятор развернет его для вас.
источник