Основы WebGL: разбираемся в магическом коде и заливаем на хостинг

WebGL — технология, которая «создает магию» в 2D-canvas’е HTML5. Рассказываем, как за счет градиента добиться такого интересного 3D-эффекта, как выпуклость, не используя дополнительных библиотек и подробно объяснив всю «магию». По завершению работы с кодом мы зальем наш проект на хостинг GPDHOST, чтобы вы могли поделиться результатом со знакомыми.

Код

Начнем с примера: нарисуем прямоугольник на экране. Этот код должен срендерить прямоугольник с градиентом:

На самом деле, код рисует два треугольника, X и Y координаты каждого пикселя используются как R и G значения цвета, а цвета внутри треугольников экстраполируются и в результате получается прямоугольник с градиентом.

Что происходит?

Мы создаем canvas объект, который используется для рендеринга, а также два «странных» тега script. В качестве типа у этих тегов вы можете указать все, что угодно — главное, чтобы вы могли затем как-то извлечь эти элементы из DOM через JS. Важно указать такой тип, который не будет распознаваться браузерами как «javascript». Это позволит нам добавить невидимое многострочное содержимое в документ, с которым мы сможем работать позже. В общем, эти теги не имеют какого-то специального значения, это просто такой трюк, чтобы добавить нужную нам информацию в JS.

В коде мы видим два таких тега script. Их содержимое принадлежит двум разным шейдерам, с помощью которых мы будем «делать магию».

О шейдерах

Простыми словами, шейдеры позволяют сопоставлять входные пиксели с выходными пикселями и пиксели с выходными цветами. В нашем случае есть два шейдера: вершинный (vertex) шейдер, который сопоставляет входные пиксели их координатам, и фрагментный (fragment) шейдер, который сопоставляет пиксели с их цветами.

В шейдерах существует 4 основных типа «переменных». Первый — это uniform. Вы можете определить такую переменную с помощью JS, но в шейдере она будет read-only. Второй тип это attribute, который, условно говоря, используется для получения определенных атрибутов точки. Третий — varying тип, он позволяет нам пересылать данные с одного шейдера в другой. Четвертый и последний это const, он позволяет создавать константы.

Кроме них есть ещё float для чисел с плавающей запятой, есть типы vec1, vec2, vec3 и vec4 для векторов, которые на самом деле являются просто списком чисел с плавающей запятой. Есть также типы xyz, rgba и тд. Очевидно, они не имеют особых различий, поэтому не будем рассматривать их подробно.

Как работает написанный выше код

JS-код начинается с простой инициализации и начальной загрузки: получения canvas, получения gl-контекста и т.д.

Сначала мы компилируем оба шейдеры в одну «программу»:

После компиляции проверяем, скомпилировались шейдеры или нет. Вы можете использовать что-то вроде:

Так вы сможете получить больше информации о том, почему компиляция завершилась неуспешно. Для отладки желательно использовать Firefox, так как он выдает больше подробностей об ошибке, чем Chrome.

Функции main шейдеров не возвращают каких-либо значений. Вместо этого они должны устанавливать переменную, которую перехватит WebGL. Тем не менее, для удобства будем называть эту переменную возвращаемым значением функции. Например, вершинный шейдер должен установить переменную gl_Position, чтобы сообщить WebGL, какой именно пиксель canvas’а мы сейчас рисуем. Фрагментный шейдер должен установить переменную fl_FragColor, которая назначает цвет пикселя в формате RGBA. Устанавливаемое значение этих переменных может быть любым в диапазоне от −1.0 до 1.0.

var positionLocation = gl.getAttribLocation(program, "a_pos"); — это получение побайтового смещения для переменной a_pos в скомпилированной программе, которое нужно для установления значения positionLocation.

Далее создается буфер из точек, которые мы будем использовать в качестве параметров для рисования. Мы помещаем эти точки в буфер и говорим WebGL, как их интерпретировать:

Эта «строка» кода помещает координаты двух прямоугольников в буфер. Экранные координаты перечислены от −1 к 1, с верхнего левого угла к нижнему правому. То есть 12 значений выше — это, на самом деле, 6 координат вершин (<-1,-1>, <1,-1>, <-1,1>, <-1,1>, <1,-1>, <1,1>). STATIC_DRAW — это параметр для оптимизации, который для нас пока не очень важен.

Теперь мы сообщим WebGL, как использовать эти точки:

Здесь мы связываем каждую точку с a_post и переводим каждые два числа в число с плавающей запятой.

Само рисование треугольников происходит в последней строке: gl.drawArrays(gl.TRIANGLES, 0, 6);. Здесь три каждые три вектора объединяются в треугольники. Разберемся подробнее непосредственно в процедуре рисования.

Как WebGL «рисует»

Метод drawArrays работает с буфером, который мы подготовили: рисует из треугольник из трех пар координат.

Во время этого он применяет main-функцию каждого шейдера для каждой из координат. Вершинный шейдер передает эти координаты в gl_Position, устанавливая z равным 0 и w равным 1. Он также кладет координаты в varying переменные для использования во фрагментном шейдере. Фрагментный шейдер использует входные координаты, чтобы установить RGBA-значение переменной gl_FragColor: он берет vec2-координаты и создает из них vec4 для применения в качестве RGBA значения (r=x, g=y, b=0, a=1).

На самом деле мы всего лишь сообщаем WebGL, что нужно нарисовать те 6 точек (3 на каждый треугольник) и экстраполировать цвета между каждой, чтобы получить градиент. Та как мы рисуем три треугольника, они заполняют всю область просмотра. Никто реально не рисует прямоугольники, а составляет их из треугольников — это полезно для простоты и оптимизации.

Вот так будет выглядеть результат выполнения нашего кода:

Результат выполнения кода

Давайте теперь поделимся своим успехом с миром и зальем наше творчество на хостинг!

Размещение проекта на хостинге

Чтобы разместить наш проект, воспользуемся хостингом GPDHOST. Для нашего несложного эксперимента нам подойдет план Starter. Для удобства войдите на сайт — например, через аккаунт Google, а затем добавьте план Starter в корзину. Далее вам будет предложено выбрать доменное имя — выберите понравившееся вам. Любой один домен в зоне .site, .party или .pro предоставляется GPDHOST бесплатно.

После получения доступа к контрольной панели хостинга, можете переходить к размещению веб-страницы с JS-кодом на сайте. В разделе «Quick Server Logins» кликните по имени выбранного вами домена, и далее в «Quick Shortcuts» выберите пункт «File Manager». Вам откроется такое окно:

«Видимые» посетителям вашего сайта HTML-страницы должны располагаться в папке public_html, выберите ее в дереве каталогов слева. Далее кликните на «Upload» в верхней части страницы и загрузите файл index.html. Чтобы он корректно отображался при открытии вашего сайта, он должен называться именно index.html. Затем вернитесь на страницу, где был расположен раздел «Quick Shortcuts», и чуть выше этого раздела кликните «Visit Website» — теперь вы увидите на главной странице вашего сайта canvas с эффектом выпуклости.

Посмотреть результат вы можете в этом примере.

Поздравляем, теперь вы можете поделиться своим проектом! Продолжайте изучать тему, чтобы дать своему проекту интересные пути развития.

По мотивам «Barrel distortion in WebGL»