Данный метод загружает текстуру в GPU (графический процессор на видеокарте). Он имеет следующий синтаксис:
texImage2D(target, level, internalformat, format, type, elem)
target: указывает целевой объект для загрузки текстуры
level: уровень множественного отображения текстуры
internalformat и format: формат и внутренний формат. В WebGL должны иметь одно и то же
значение. Так, формат gl.RGBA
, к примеру, показывает, что для каждого текселя на текстуре должны
быть установлены цветовые каналы для красного, зеленого и синего цветов, а также альфа-канал.
type: тип данных, которых сохраняет все данные текселей текстуры. Например, gl.UNSIGNED_BYTE
указывает,
что для каждого цветового канала в gl.RGBA
для сохранения данных выделяется один байт.
elem: указывает на элемент, который содержит источник текстурирования. Это может быть элемент img или Image. Это также может быть элемент HTML5 video или canvas.
Все возможные сочетания форматов и типов:
Формат | Тип |
gl.RGBA | gl.UNSIGNED_BYTE |
gl.RGB | gl.UNSIGNED_BYTE |
gl.RGBA | gl.UNSIGNED_SHORT_4_4_4_4 |
gl.RGBA | gl.UNSIGNED_SHORT_5_5_5_1 |
gl.RGB | gl.UNSIGNED_SHORT_5_6_5 |
gl.LUMINANCE_ALPHA | gl.UNSIGNED_BYTE |
gl.LUMINANCE | gl.UNSIGNED_BYTE |
gl.ALPHA | gl.UNSIGNED_BYTE |
Я думаю, формат gl.RGBA
понятен: каждый тексель текстуры имеет канал красного, зеленого и синего цветов, а также альфа-канал.
Формат gl.RGB
- то же самое, только без альфа-канала.
Формат gl.LUMINANCE_ALPHA
имеет канал яркости и альфа-канал. И формат gl.LUMINANCE
имеет только канал яркости,
а формат gl.ALPHA
- только альфа-канал.
Например, настройка gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE_ALPHA, gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE, image);
даст
следующий эффект:
Касательно типов тоже все просто. Тип gl.UNSIGNED_BYTE
предоставляет по одному байту на каждый канал.
Тип gl.UNSIGNED_SHORT_4_4_4_4
предоставляет для каждого канала в формате RGBA по четыре байта.
Тип gl.UNSIGNED_SHORT_5_5_5_1
предоставляет для каждого каналов красного, зеленого и синего цветов в формате RGBA по пять байт,
а для альфа-канала - один байт.
И тип gl.UNSIGNED_SHORT_5_6_5
предоставляет для каналов красного и синего цветов по пять байт и для зеленого цвета - шесть байт в формате RGB.
Метод gl.texParameteri()
позволяет определить параметры текстуры. Он имеет следующий формальный синтаксис:
texParameteri(target, pname, param)
. Сочетания параметров бывают разными и могут влиять на используемые значения.
target: в зависимости от направления текстурирования может принимать значения gl.TEXTURE_2D
,
либо gl.TEXTURE_CUBE_MAP
pname: указывает на фильтр, который мы хотим установить. Может принимать следующие значения:
gl.TEXTURE_MAG_FILTER
, gl.TEXTURE_MIN_FILTER
, gl.TEXTURE_WRAP_S
и gl.TEXTURE_WRAP_T
param: предоставляет значение для фильтра pname. То есть в выражении gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
фильтру текстуры gl.TEXTURE_MAG_FILTER
устанавливается значение gl.NEAREST
.
Значения, передаваемые параметром param, разнообразны и позволяют создавать определенные эффекты, которые далее мы подробно разберем.
Зачем вообще нужна настройка этих параметров? В реальности текстуры имею определенные размеры, например, 128х128. Однако поверхность объекта, на которую накладывается текстура, может иметь как большие, так и меньшие размеры. Использование фильтра gl.TEXTURE_MAG_FILTER фактически помогает определить рендеринг текстуры, если она меньше размера объекта, то ее надо увеличить.
И фильтр gl.TEXTURE_MIN_FILTER, наоборот, указывает, каким образом надо проводить рендеринг, если размеры поверхности объекта меньше размеров текстуры.
Данное значение позволяет семплеру взять из текстуры цвет того текселя, центр которого находится ближе всего к точке, с которой семплер берет цветовые значения.
Это значение может быть установлено как для фильтра gl.TEXTURE_MIN_FILTER, так и для фильтра gl.TEXTURE_MAG_FILTER.
Данный фильтр возвращает средневзвешенное значение соседних четырех пикселей, центры которых находятся ближе всего к точке, с которой семплер берет цветовые значения. Это обеспечивает цветовую плавность, плавное смешивание цветов. В то же время, поскольку здесь для определения цвета нужны значения четырех пикселей, то и работать данный фильтр будет медленне, чем gl.NEAREST, но при этом более качественней.
Это значение может быть установлено как для фильтра gl.TEXTURE_MIN_FILTER, так и для фильтра gl.TEXTURE_MAG_FILTER.
Концепция mip-текстурирования предполагает использование нескольких копий одной текстуры, но с разной детализацией. Это позволяет увеличивать качество отображения, например, при удалении от объекта.
Mip-текстурирование в WebGL использует ряд фильтров. Подобные фильтры могут использоваться только в качестве значения для фильтра gl.TEXTURE_MIN_FILTER:
gl.NEAREST_MIPMAP_NEAREST: фильтр использует одну копию текстуры, которая наиболее подходит под размеры текстуры на экране. Выборка семплером значений происходит по алгоритму NEAREST. Самый быстрый способ текстурирования, но при этом менее качественный
gl.LINEAR_MIPMAP_NEAREST: фильтр использует одну копию текстуры, которая наиболее подходит под размеры текстуры на экране. Выборка семплером значений происходит по алгоритму LINEAR
gl.NEAREST_MIPMAP_LINEAR: фильтр использует две копии текстуры, которые наиболее подходят под размеры текстуры на экране. Выборка семплером значений происходит по алгоритму NEAREST. Выборка цвета пикселя идет параллельно сразу из двух копий, а финальное значение цвета представляет средневзвешенное значение двух выборок
gl.LINEAR_MIPMAP_LINEAR: фильтр использует две копии текстуры, которые наиболее подходят под размеры текстуры на экране. Выборка семплером значений происходит по алгоритму LINEAR. Выборка цвета пикселя идет параллельно сразу из двух копий, а финальное значение цвета представляет средневзвешенное значение двух выборок. Наиболее медленный способ, но при этом дающий наибольшее качество
Само использование этих значений для фильтров еще предполагает, что у нас будет использоваться mip-текстурирование. Перед этим нам надо
сгенерировать мипмапы, то есть копии текстуры, с помощью метода gl.generateMipmap(gl.TEXTURE_2D);
. Этот метод должен вызываться
после метода gl.texImage2D(). То есть, возьмем из ранее использованный примеров текстурирования функцию handleTextureLoaded
и изменим ее так, чтобы использовались мипмапы:
function handleTextureLoaded(image, texture) { gl.bindTexture(gl.TEXTURE_2D, texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); gl.generateMipmap(gl.TEXTURE_2D); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); }
Это даст нам следующий результат:
Надо отметить, что мип-текстурирование имеет некоторые ограничения: используемые изображения должны иметь размеры, которые равны степени двойки. Например, 16px, 32px, 64px, 128px и т.д. При этом необязательно, чтобы высота и ширина были равные, главное, чтобы их значения были равны степени двойки.
Еще один способ текстурирования называется texture wrapping. Этот термин можно перевести как обертывание текстурой. То есть данный способ определяет поведение семплера при отборе цветов пикселей с текстуры, если заданные координаты текстуры находятся вне диапазона [0.0, 1.0].
В данном случае нам потребуется установить значения для фильтров gl.TEXTURE_WRAP_S
и gl.TEXTURE_WRAP_T
, которые
отвечают за рендеринг текстуры вдоль осей s и t.
Например, у нас определены следующие координаты текстуры в буфере координат текстуры:
// Координаты текстуры var textureCoords = [ 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0 ];
А функция handleTextureLoaded
выглядела бы следующим образом:
function handleTextureLoaded(image, texture) { gl.bindTexture(gl.TEXTURE_2D, texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); gl.generateMipmap(gl.TEXTURE_2D); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); }
То мы можем получить следующий результат:
Для параметров мы можем использовать следующие значения:
gl.CLAMP_TO_EDGE: все координаты текстуры, которые больше 1 и меньше 0, сжимаются до диапазона [0, 1]
gl.REPEAT: происходит повторение текстуры после выхода вне диапазона [0, 1]
gl.MIRRORED_REPEAT: повторение текстуры с зеркальным отображением
Можно комбинировать данные значения, как в вышеприведенном примере, где одновременно используются gl.REPEAT и gl.CLAMP_TO_EDGE.