Содержание

WebGL2Fundamentals.org

Fix, Fork, Contribute

WebGL2 Точки, линии и треугольники

Большинство этого сайта рисует все треугольниками. Это аргументированно нормальная вещь, которую делают 99% WebGL программ. Но, ради полноты, давайте рассмотрим несколько других случаев.

Как упоминалось в первой статье, WebGL рисует точки, линии и треугольники. Он делает это, когда мы вызываем gl.drawArrays или gl.drawElements. Мы предоставляем вершинному шейдеру координаты clip space, и затем, на основе первого аргумента к gl.drawArrays или gl.drawElements, WebGL будет рисовать точки, линии или треугольники.

Допустимые значения для первого аргумента gl.drawArrays и gl.drawElements:

  • POINTS

    Для каждой вершины clip space, выводимой вершинным шейдером, рисуется квадрат, центрированный над этой точкой. Размер квадрата указывается установкой специальной переменной gl_PointSize внутри вершинного шейдера в размер, который мы хотим для этого квадрата в пикселях.

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

      const [minSize, maxSize] = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
    

    Также см. другую проблему здесь.

  • LINES

    Для каждых 2 вершин clip space, выводимых вершинным шейдером, рисуется линия, соединяющая 2 точки. Если у нас были точки A,B,C,D,E,F, то мы получили бы 3 линии.

    Спецификация говорит, что мы можем установить толщину этой линии, вызвав gl.lineWidth и указав ширину в пикселях. В реальности, однако, максимальная ширина зависит от реализации, и для большинства реализаций максимальная ширина равна 1.

      const [minSize, maxSize] = gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE);
    

    Это в основном потому, что значения > 1 были устаревшими в основном Desktop OpenGL.

  • LINE_STRIP

    Для каждой вершины clip space, выводимой вершинным шейдером, рисуется линия от предыдущей точки, выводимой вершинным шейдером.

    Итак, если вы выводите вершины clip space A,B,C,D,E,F, вы получите 5 линий.

  • LINE_LOOP

    Это то же самое, что и LINE_STRIP, но еще одна линия рисуется от последней точки к первой точке.

  • TRIANGLES

    Для каждых 3 вершин clip space, выводимых вершинным шейдером, рисуется треугольник из 3 точек. Это наиболее используемый режим.

  • TRIANGLE_STRIP

    Для каждой вершины clip space, выводимой вершинным шейдером, рисуется треугольник из последних 3 вершин. Другими словами, если вы выводите 6 точек A,B,C,D,E,F, то будет нарисовано 4 треугольника. A,B,C затем B,C,D затем C,D,E затем D,E,F

  • TRIANGLE_FAN

    Для каждой вершины clip space, выводимой вершинным шейдером, рисуется треугольник из первой вершины и последних 2 вершин. Другими словами, если вы выводите 6 точек A,B,C,D,E,F, то будет нарисовано 4 треугольника. A,B,C затем A,C,D затем A,D,E и наконец A,E,F

Я уверен, что некоторые другие не согласятся, но по моему опыту TRIANGLE_FAN и TRIANGLE_STRIP лучше избегать. Они подходят только для нескольких исключительных случаев, и дополнительный код для обработки этих случаев не стоит того, чтобы просто делать все треугольниками с самого начала. В частности, возможно, у вас есть инструменты для построения нормалей или генерации координат текстуры или выполнения любого другого количества вещей с данными вершин. Придерживаясь только TRIANGLES, ваши функции просто будут работать. Как только вы начнете добавлять TRIANGLE_FAN и TRIANGLE_STRIP, вам понадобятся дополнительные функции для обработки большего количества случаев. Вы свободны не соглашаться и делать все, что хотите. Я просто говорю, что это мой опыт и опыт нескольких AAA разработчиков игр, которых я спрашивал.

Аналогично LINE_LOOP и LINE_STRIP не так полезны и имеют аналогичные проблемы. Как TRIANGLE_FAN и TRIANGLE_STRIP, ситуации для их использования редки. Например, вы можете подумать, что хотите нарисовать 4 соединенные линии, каждая из которых состоит из 4 точек.

Если вы используете LINE_STRIP, вам нужно будет сделать 4 вызова к gl.drawArrays и больше вызовов для настройки атрибутов для каждой линии, тогда как если вы просто используете LINES, то вы можете вставить все точки, необходимые для рисования всех 4 наборов линий одним вызовом к gl.drawArrays. Это будет намного намного быстрее.

Кроме того, LINES могут быть отличными для использования для отладки или простых эффектов, но учитывая их ограничение в 1 пиксель ширины на большинстве платформ, это часто неправильное решение. Если вы хотите нарисовать сетку для графика или показать контуры многоугольников в программе 3D моделирования, использование LINES может быть отличным, но если вы хотите нарисовать структурированную графику, такую как SVG или Adobe Illustrator, то это не будет работать, и вам придется рендерить ваши линии каким-то другим способом, обычно из треугольников.

Есть предложения или замечания? Создайте issue на GitHub.
comments powered by Disqus