Оптимизация

Обычно используют два метода для хранения данных в вершинах: массив структур и структура массивов. Массив структур хранит вершинные атрибуты в одном массиве. А структура массивов хранит каждый атрибут в отдельном буфере.

Возникает вопрос: какой способ более эффективен? В большинстве случаев это массив структур. Это объясняется тем, что данные могут читаться последовательно. Но у него есть недостаток, например, когда необходимо изменить определённые атрибуты.

В предыдущих статьях мы использовали структуру массивов. Поэтому сейчас рассмотрим, как изменится программа, если применить массив структур.

function initBuffers() {
    vertices_buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertices_buffer);
    var vertices = [
        -1.0, -1.0,  1.0,
         0.0,  0.0,
         1.0, -1.0,  1.0,
         1.0,  0.0,
         1.0,  1.0,  1.0,
         1.0,  1.0,
        -1.0,  1.0,  1.0,
         0.0,  1.0,

        -1.0, -1.0, -1.0,
         0.0,  0.0,
        -1.0,  1.0, -1.0,
         1.0,  0.0,
         1.0,  1.0, -1.0,
         1.0,  1.0,
         1.0, -1.0, -1.0,
         0.0,  1.0,

        -1.0,  1.0, -1.0,
         0.0,  0.0,
        -1.0,  1.0,  1.0,
         1.0,  0.0,
         1.0,  1.0,  1.0,
         1.0,  1.0,
         1.0,  1.0, -1.0,
         0.0,  1.0,

        -1.0, -1.0, -1.0,
         0.0,  0.0,
         1.0, -1.0, -1.0,
         1.0,  0.0,
         1.0, -1.0,  1.0,
         1.0,  1.0,
        -1.0, -1.0,  1.0,
         0.0,  1.0,

         1.0, -1.0, -1.0,
         0.0,  0.0,
         1.0,  1.0, -1.0,
         1.0,  0.0,
         1.0,  1.0,  1.0,
         1.0,  1.0,
         1.0, -1.0,  1.0,
         0.0,  1.0,

        -1.0, -1.0, -1.0,
         0.0,  0.0,
        -1.0, -1.0,  1.0,
         1.0,  0.0,
        -1.0,  1.0,  1.0,
         1.0,  1.0,
        -1.0,  1.0, -1.0,
         0.0,  1.0
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

    index_buffer = gl.createBuffer();
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, index_buffer );
    var indices = [
        0,  1,  2,      0,  2,  3,
        4,  5,  6,      4,  6,  7,
        8,  9,  10,     8,  10, 11,
        12, 13, 14,     12, 14, 15,
        16, 17, 18,     16, 18, 19,
        20, 21, 22,     20, 22, 23
    ];
    gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW );
}

Обратите внимание на то, как мы сгруппировали данные. Сначала идут три компоненты описывающие положение вершины, а затем идут две компоненты описывающие координаты текстуры. Так же мы избавились от трёх команд, так как мы объединили два массива в один.

function drawScene(delta) {
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    perspectiveMatrix = makePerspective(45, 600.0/400.0, 0.1, 100.0);
    loadIdentity();
    mvPushMatrix();
    mvTranslate([-0.0, 0.0, -6.0]);
    mvRotate(sqrRot, [1, 0, 0.6]);

    gl.bindBuffer(gl.ARRAY_BUFFER, vertices_buffer);

    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 20, 0);
    gl.enableVertexAttribArray(vertexPositionAttribute);

    gl.vertexAttribPointer(vertexCoordAttribute, 2, gl.FLOAT, false, 20, 12);
    gl.enableVertexAttribArray(vertexCoordAttribute);

    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, index_buffer );

    setMatrixUniforms();

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.uniform1i(samplerUniform, 0);

    var vertices = 36;
    gl.drawElements( gl.TRIANGLES, vertices, gl.UNSIGNED_SHORT, 0 );

    mvPopMatrix();
    sqrRot -= delta * 40;
}

Обратите внимание на то, как изменились параметры команд vertexAttribPointer(). Так как данные хранятся как тип float, то каждая компонента занимает 4 байта. Одну вершину описывает 5 компонент. Отсюда следует, что вершина описывается 20 байтами. Следующий параметр сообщает о смещении. Так как сначала описывается положение, то смещение равно 0. А для координат текстуры смещение будет равно 12, так как перед ними стоят 3 компоненты описывающие положение вершины.

Please use a browser that supports "canvas"
  < НАЗАД >