Закраска объекта

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

<script id="shader-fs" type="x-shader/x-fragment">
    varying lowp vec4 v_color;
    void main(void) {
         gl_FragColor = v_color;
     }
</script>
<script id="shader-vs" type="x-shader/x-vertex">
    attribute vec3 a_vertexPosition;
    attribute vec3 a_vertexColor;
    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;
    varying lowp vec4 v_color;
    void main(void) {
        gl_Position = uPMatrix * uMVMatrix * vec4(a_vertexPosition, 1.0);
        v_color = vec4(a_vertexColor, 1.0);
    }
</script>

В вершинный шейдер мы добавили атрибут a_vertexColor, который будет хранить цвет вершины. Вершинный шейдер будет передавать цвет вершины переменной v_color, которая определена в фрагментном шейдере. Во время закраски треугольника фрагментный шейдер для каждого фрагмента интерполирует цвет между тремя вершинами и выполняет закраску получившимся цветом. Передача значения переменной из вершинного шейдера во фрагментный осуществляется с помощью описателя varying. А описатель lowp сообщает о точности вычисления для типа vec3

Так же изменились функции initShader(), drawScene() и initBuffers().

function initShader() {
    var fragmentShader = getShader(gl, "shader-fs");
    var vertexShader = getShader(gl, "shader-vs");
    shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);
    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert("Не получилось инициилизировать шейдерную программу.");
    }
    gl.useProgram(shaderProgram);
    vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "a_vertexPosition");
    gl.enableVertexAttribArray(vertexPositionAttribute);
    vertexColorAttribute = gl.getAttribLocation(shaderProgram, "a_vertexColor");
    gl.enableVertexAttribArray(vertexColorAttribute);
}

Мы извлекли номер атрибута a_vertexColor и сохранили его, чтобы вытаскивать данные о цвете из буфера в этот атрибут.

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

    color_buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
    var colors = [
        0.5,  0.0,  0.5,  1.0,
        1.0,  0.0,  0.0,  1.0,
        0.0,  1.0,  0.0,  1.0,
        0.0,  0.0,  1.0,  1.0
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), 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, [0, 0, 1]);

    gl.bindBuffer(gl.ARRAY_BUFFER, vertices_buffer);
    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(vertexPositionAttribute);

    gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
    gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(vertexColorAttribute);

    setMatrixUniforms();
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

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

И наконец, указываем, как извлечь данные о цвете и использовать их.

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