Создание массивов текстур в JavaScript и WebGL для карт тайлов и анимации

Текстурные массивы в WebGL очень полезны. Они отлично подходят для тайловых карт/атласов текстур или для циклического просмотра анимации. Однако я не смог найти никаких руководств, когда хотел добавить их в свой движок WebGL. Массивы текстур были введены только в более новом стандарте WebGL 2, что может объяснить отсутствие исходников.

Раньше я реализовывал массивы текстур на C++/OpenGL, но простое преобразование кода не сработало из-за некоторых ограничений в спецификациях WebGL. После того, как я понял, как использовать массивы текстур в WebGL, я решил создать краткое руководство.

Массивы текстур

Как упоминалось выше, массивы текстур можно использовать для циклического просмотра кадров анимации. В моем случае я хотел зациклить несколько кадров текстуры воды, но для проверки я сделал этот удивительный арт в Paint:

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

Начнем с загрузки изображения:

var image = new Image();
image.onload = () =>
{
    // see below
};
image.src = "image.png";

Когда изображение загружено, мы можем создать текстуру WebGL, определить некоторые полезные переменные на будущее и установить некоторые параметры текстуры по умолчанию. Это точно так же, как и для обычных текстур, за исключением использования gl.TEXTURE_2D_ARRAY вместо gl.TEXTURE_2D:

var texture = gl.createTexture();

var xTiles = 4;
var yTiles = 4;
var layerCount = xTiles*yTiles;
var tileWidth = image.width/xTiles;
var tileHeight = image.height/yTiles;

gl.bindTexture( gl.TEXTURE_2D_ARRAY , texture );
gl.texParameteri( gl.TEXTURE_2D_ARRAY , gl.TEXTURE_MIN_FILTER , gl.LINEAR );
gl.texParameteri( gl.TEXTURE_2D_ARRAY , gl.TEXTURE_MAG_FILTER , gl.LINEAR);
gl.texParameteri( gl.TEXTURE_2D_ARRAY , gl.TEXTURE_WRAP_S , gl.CLAMP_TO_EDGE );
gl.texParameteri( gl.TEXTURE_2D_ARRAY , gl.TEXTURE_WRAP_T , gl.CLAMP_TO_EDGE );