WebGL - Режимы рисования

Здравствуйте, будущие маги WebGL! ? Сегодня мы окунемся в захватывающий мир режимов рисования в WebGL. Как ваш доброжелательный сосед-преподаватель информатики, я здесь, чтобы провести вас через это путешествие, даже если вы еще не писали ни строчки кода. Так что возьмите свою виртуальную кисть, и давайте создадимdigitальные шедевры!

WebGL - Modes of Drawing

Параметр mode

Прежде чем приступить к рисованию, давайте поговорим о звезде нашего шоу: параметре mode. Представьте его как магическую палочку, которая говорит WebGL, как соединять точки (или в нашем случае, вершины) для создания разных фигур и узоров.

В WebGL, когда мы вызываем функцию gl.drawArrays() или gl.drawElements(), нам нужно указать параметр mode. Этот параметр похож на то, как давать инструкции для головоломки "Соедини точки" - он tells WebGL, как соединять точки, которые мы определили.

Вот таблица с различными режимами рисования, доступными в WebGL:

Режим Описание
gl.POINTS Рисует одну точку для каждого вершины
gl.LINES Рисует линию между каждой парой вершин
gl.LINE_STRIP Рисует непрерывную линию, соединяющую вершины
gl.LINE_LOOP Подобно LINE_STRIP, но замыкает форму
gl.TRIANGLES Рисует треугольник для каждой тройки вершин
gl.TRIANGLE_STRIP Рисует connected группу треугольников
gl.TRIANGLE_FAN Рисует веерообразную форму из соединенных треугольников

Не волнуйтесь, если это покажется вам сложным сейчас. Мы рассмотрим каждый из них с примерами по мере продвижения!

Пример - Рисование трех параллельных линий

Давайте начнем с простого примера: рисование трех параллельных линий. Это поможет нам понять, как работает параметр mode на практике.

// Сначала настроим наш контекст WebGL
const canvas = document.getElementById('myCanvas');
const gl = canvas.getContext('webgl');

// Теперь определим наш vertex shader
const vertexShaderSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
`;

// И наш fragment shader
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Красный цвет
}
`;

// Создаем и компилируем шейдеры (не волнуйтесь, мы рассмотрим это подробнее в будущих уроках)
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

// Создаем программу и связываем шейдеры
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// Определяем позиции наших линий
const positions = new Float32Array([
-0.8, -0.8,  // Начало первой линии
-0.8,  0.8,  // Конец первой линии
-0.3, -0.8,  // Начало второй линии
-0.3,  0.8,  // Конец второй линии
0.2, -0.8,  // Начало третьей линии
0.2,  0.8   // Конец третьей линии
]);

// Создаем буфер и кладем в него позиции
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

// Говорим WebGL, как читать буфер и атрибутить его к `a_position`
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

// Очищаем холст
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

// Рисуем линии
gl.drawArrays(gl.LINES, 0, 6);

Теперь разберем это:

  1. Мы настраиваем наш контекст WebGL и определяем наши шейдеры. Не волнуйтесь о этом сейчас; мы рассмотрим шейдеры подробнее в будущих уроках.

  2. Мы создаем программу и связываем наши шейдеры с ней. Это как подготовка нашей цифровой кисти.

  3. Мы определяем позиции наших линий. Каждая линия определяется двумя точками (ее началом и концом), и каждая точка определяется двумя координатами (x и y). Так что у нас есть 6 точек для наших 3 линий.

  4. Мы создаем буфер и кладем наши позиции в него. Представьте это как загрузку краски на кисть.

  5. Мы говорим WebGL, как читать этот буфер и ассоциировать его с атрибутом a_position в нашем vertex шейдере.

  6. Наконец, мы вызываем gl.drawArrays(gl.LINES, 0, 6). Вот где происходит магия!

  • gl.LINES是我们的模式。 Он говорит WebGL рисовать линии между парами вершин.
  • 0 - это начальный индекс в нашем массиве позиций.
  • 6 - это количество вершин, которые нужно учитывать (помните, у нас 6 точек для наших 3 линий).

Запустите этот код, и voila! Вы должны увидеть три красные параллельные линии на черном фоне. Поздравляю, вы только что создали свое первое рисование в WebGL! ?

Режимы рисования

Теперь, когда мы видели gl.LINES в действии, давайте рассмотрим другие режимы рисования. Мы будем использовать тот же набор, что и раньше, но изменим наши позиции и режим рисования.

gl.POINTS

Давайте начнем с самого простого режима: gl.POINTS. Этот режим рисует одну точку для каждой вершины.

// ... (предыдущий код настройки)

const positions = new Float32Array([
-0.5, 0.5,
0.0, 0.0,
0.5, -0.5
]);

// ... (код настройки буфера)

gl.drawArrays(gl.POINTS, 0, 3);

Это нарисует три красные точки на вашем холсте. Просто, правда?

gl.LINE_STRIP

Теперь давайте попробуем gl.LINE_STRIP. Этот режим рисует непрерывную линию, соединяющую каждую вершину с следующей.

// ... (предыдущий код настройки)

const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);

// ... (код настройки буфера)

gl.drawArrays(gl.LINE_STRIP, 0, 3);

Вы должны увидеть V-образную линию, соединяющую три точки.

gl.LINE_LOOP

gl.LINE_LOOP подобен LINE_STRIP, но он замыкает форму, соединяя последнюю вершину с первой.

// ... (предыдущий код настройки)

const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);

// ... (код настройки буфера)

gl.drawArrays(gl.LINE_LOOP, 0, 3);

Это нарисует контур треугольника.

gl.TRIANGLES

Теперь давайте перейдем к заполнению фигур с помощью gl.TRIANGLES. Этот режим рисует отдельный треугольник для каждой тройки вершин.

// ... (предыдущий код настройки)

const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
0.0, 0.5
]);

// ... (код настройки буфера)

gl.drawArrays(gl.TRIANGLES, 0, 3);

Вы должны увидеть красный треугольник.

gl.TRIANGLE_STRIP

gl.TRIANGLE_STRIP немного сложнее. Он рисует connected группу треугольников, где каждый треугольник делит два вершины с предыдущим.

// ... (предыдущий код настройки)

const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
0.5, 0.5
]);

// ... (код настройки буфера)

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

Это нарисует два соединенных треугольника, forming矩形.

gl.TRIANGLE_FAN

Наконец, рассмотрим gl.TRIANGLE_FAN. Этот режим рисует веерообразную форму, где все треугольники делят первую вершину.

// ... (предыдущий код настройки)

const positions = new Float32Array([
0.0, 0.0,    // Центральная точка
0.5, 0.0,    // Точка 1
0.35, 0.35,  // Точка 2
0.0, 0.5,    // Точка 3
-0.35, 0.35  // Точка 4
]);

// ... (код настройки буфера)

gl.drawArrays(gl.TRIANGLE_FAN, 0, 5);

Это нарисует форму, которая resemblesчетверть круга.

И вот и все! Мы рассмотрели все режимы рисования в WebGL. Помните, ключ к их освоению - это практика. Попробуйте combine разные режимы, change цвета и experiment с положениями вершин. Before you know it, вы будете создавать сложные сцены WebGL с легкостью!

В следующем уроке мы углубимся в шейдеры и научимся добавлять немного пышности нашим рисункам с помощью цветов и текстур. Пока что, счастливого кодирования, будущие художники WebGL! ??‍??‍?

Credits: Image by storyset