Задание цвета вершинам
Как правило, в GL объекты строятся с использованием наборов каких-то вершин, для которых задаётся не только положение в пространстве, но и цвет. Цвета же всех остальных пикселей, по умолчанию, вычисляются с помощью линейной интерполяции, автоматически делая плавный градиент.
Допустим, мы не хотим, чтобы фрагментный шейдер назначал нашему рисунку (в качестве примера будем использовать квадрат) фиксированный белый цвет для каждого пикселя. Мы хотим сделать плавный градиент с использованием разных цветов: синий, зелёный, красный и белый.
Поэтому, первое, что необходимо будет сделать – это назначить перечисленные цвета четырём вершинам. Чтобы сделать это, необходимо для начала создать нужный массив цветов вершин и сохранить его в WebGl буфер, добавив код в функцию initBuffers():
var colors = [ 1.0, 1.0, 1.0, 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 // синий ]; squareVerticesColorBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); }
Начало кода –JavaScript массив, содержащий в себе четыре вектора с четырьмя значениями каждый – по одному вектору для задания цвета каждой вершине.
Затем – новый WebGl буфер выделяет место в памяти хранения этих цветов и массив приводится к вещественному формату WebGl и сохраняется в буфер.
Далее, для использования этих цветов, вершинному шейдеру необходимо будет произвести обновление, помещая соответствующий цвет из буфера цвета:
<script id="shader-vs" type="x-shader/x-vertex"> attribute vec3 aVertexPosition; attribute vec4 aVertexColor; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying lowp vec4 vColor; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vColor = aVertexColor; } </script>
Ключевым отличием будет является то, что для каждой вершины, мы задаём цвет на соответствующее значение из массива цвета.
Окраска фрагментов
Чтобы напомнить, как фрагментный шейдер выглядел ранее, ниже приведён его код:
< script id="shader-fs" type="x-shader/x-fragment"> void main(void) { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } </script>
Чтобы подобрать интерполируемый цвет каждому пикселю,необходимо просто изменить его, получив значение из переменной vColor:
<script id="shader-fs" type="x-shader/x-fragment"> varying lowp vec4 vColor; void main(void) { gl_FragColor = vColor; } </script>
Такое простое изменение, однако, с его помощью каждый фрагмент вместо фиксированного значения получает значение интерполируемого цвета на основе его расположения относительно вершин.
Отрисовка с использованием цветов
Далее добавляем код в initShaders() для задания значений атрибута цвета для шейдерной программы:
vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor"); gl.enableVertexAttribArray(vertexColorAttribute);
Следом, drawScene() можно исправить на фактическое использование этих цветов при отрисовке квадрата:
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer); gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
Полученное изображение (в качестве примера) можно увидеть ниже, а с исходным кодом ознакомиться в прикреплённом файле.
Прикрепленный файл | Размер |
---|---|
WebGl_color_Griniova.rar | 2.72 кб |