Вывод примитивов
В WebGL есть две команды вывода примитивов: drawArrays() и drawElements(). Команда drawArrays(mode, first, count) выводит примитивы типа mode, используя вершины, начиная с first и заканчивая first+count-1.
Параметр mode может принимать одно из следующих значений: POINTS, LINES, LINE_STRIP, LINE_LOOP, TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN.
Вызов drawArrays(gl.TRIANGLE_STRIP, 0, 4), который мы использовали в предыдущих статьях, нарисует два треугольника: один, с индексами (0, 1, 2), и другой с индексами (2, 1, 3). Команда drawArrays() очень удобна, если у нас есть объект, вершины которого не переиспользуются.
Однако вершины объектов обычно принадлежат сразу нескольким треугольникам. Если мы захотим вывести куб при помощи drawArrays(), то мы получим следующий код:
vertex_position_index = 0; faces_count = 6; vertices = [...]; // координаты для каждой вершины gl.enableVertexAttribArray(vertex_position_index); gl.vertexAttribPointer(vertex_position_index, 3, gl.FLOAT, false, 0, vertices); for ( i = 0; i < faces_count; i++ ) { gl.drawArrays( gl.TRIANGLE_FAN, i * 4, 4 ); } // или вместо for можно использовать gl.drawArrays( gl.TRIANGLES, 0, 36 );
Для вывода куба нам нужно вызвать drawArrays() для каждой его грани. Хранящиеся вершины должны быть заданы по нескольку раз. Данный подход не эффективен. При помощи drawElements() этот же куб можно вывести следующим образом:
vertex_position_index = 0; vertices = [...]; // координаты для каждой вершины indices = [ 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 1, 7, 1, 6, 7, 2, 1, 7, 5, 4, 7, 6, 5, 7, 3, 2, 7, 4, 3 ]; gl.enableVertexAttribArray( vertex_position_index ); gl.vertexAttribPointer( vertex_position_index, 3, gl.FLOAT, false, 0, vertices ); gl.drawElements( gl.TRIANGLES, indices.length(), gl.UNSIGNED_BYTE, indices );
Последний вариант будет быстрее первого по ряду причин. Во-первых, размер данных с атрибутами будет меньше, так как вершины используются повторно. Во-вторых, потребляется меньше памяти и требует меньшей пропускной способности от памяти.