WebGL - Рисование треугольника

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

WebGL - Drawing a Triangle

Что такое WebGL?

Прежде чем начать рисовать треугольники, давайте на минутку разберемся, что такое WebGL. WebGL (Web Graphics Library) — это API на JavaScript, который позволяет нам render 2D и 3D графику в веб-браузерах без использования каких-либо плагинов. Это как иметь суперсилу, которая позволяет создавать потрясающие визуальные эффекты прямо в вашем веб-браузере!

Шаги для рисования треугольника

Рисование треугольника в WebGL может показаться пугающей задачей, но не волнуйтесь! Мы разберем это на управляемые шаги. Вот что нам нужно сделать:

  1. Настроить HTML canvas
  2. Получить контекст WebGL
  3. Создать и скомпилировать вершины шейдера
  4. Создать и скомпилировать фрагментный шейдер
  5. Создать шейдерную программу
  6. Определить вершины треугольника
  7. Создать буфер и загрузить вершинные данные
  8. Связать атрибуты вершины
  9. Нарисовать треугольник

Теперь давайте рассмотрим каждый шаг подробно.

1. Настроить HTML canvas

Сначала нам нужно создать canvas в нашем HTML файле, где WebGL будет render наш треугольник. Вот как это сделать:

<canvas id="glCanvas" width="640" height="480"></canvas>

Этот код создает canvas с ID "glCanvas" и размерами 640x480 пикселей. Вы можете изменить эти размеры по мере необходимости.

2. Получить контекст WebGL

Теперь перейдем к JavaScript. Нам нужно получить контекст WebGL из нашего canvas:

const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('Unable to initialize WebGL. Your browser may not support it.');
return;
}

Этот код находит наш canvas, запрашивает контекст WebGL и проверяет, поддерживает ли ваш браузер WebGL.

3. Создать и скомпилировать вершины шейдера

Вершинный шейдер — это программа, которая обрабатывает вершинные данные. Вот как мы создаем один:

const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;

function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);

Этот код определяет источник вершинного шейдера и функцию для создания и компиляции шейдеров.

4. Создать и скомпилировать фрагментный шейдер

Фрагментный шейдер определяет цвет каждого пикселя. Вот как мы создаем один:

const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

Этот фрагментный шейдер окрасит наш треугольник в красный цвет.

5. Создать шейдерную программу

Теперь нам нужно связать наши шейдеры в программу:

const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return;
}

6. Определить вершины треугольника

Давайте определим вершины нашего треугольника:

const vertices = [
0.0,  0.5,  0.0,
-0.5, -0.5,  0.0,
0.5, -0.5,  0.0
];

Эти координаты определяют треугольник в рабочем пространстве, где каждое значение варьируется от -1 до 1.

7. Создать буфер и загрузить вершинные данные

Теперь нам нужно создать буфер и загрузить наши вершинные данные в него:

const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

8. Связать атрибуты вершины

Нам нужно tell WebGL, как интерпретировать наши вершинные данные:

const aVertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aVertexPosition);

9. Нарисовать треугольник

Наконец, мы можем нарисовать наш三角形:

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

Объединить все вместе

Вот наш полный код для рисования треугольника:

// Получить контекст WebGL
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('Unable to initialize WebGL. Your browser may not support it.');
return;
}

// Источник вершинного шейдера
const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;

// Источник фрагментного шейдера
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

// Функция создания шейдера
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

// Создать шейдеры
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

// Создать шейдерную программу
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
return;
}

// Определить вершины
const vertices = [
0.0,  0.5,  0.0,
-0.5, -0.5,  0.0,
0.5, -0.5,  0.0
];

// Создать буфер и загрузить вершинные данные
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// Связать атрибуты вершины
const aVertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aVertexPosition);

// Нарисовать треугольник
gl.useProgram(shaderProgram);
gl.drawArrays(gl.TRIANGLES, 0, 3);

И вот так вы нарисовали свой первый треугольник с помощью WebGL. Может показаться, что для простого треугольника много шагов, но помните, это основа для создания сложной 3D-графики. Каждый шаг, который мы прошли, crucial для более сложного рендеринга.

Заключение

Поздравляю с рисованием вашего первого треугольника в WebGL! Вы сделали первый шаг в увлекательный мир программирования компьютерной графики. Помните, каждый путь начинается с одного шага - или в нашем случае, одного треугольника. Продолжайте практиковаться, продолжайте исследовать, и sooner or later, вы будете создавать потрясающие 3D-графики, которые поразят людей!

Вот таблица, резюмирующая основные методы WebGL, которые мы использовали:

Метод Описание
getContext('webgl') Получает контекст WebGL
createShader() Создает объект шейдера
shaderSource() Устанавливает исходный код шейдера
compileShader() Компилирует шейдер
createProgram() Создает объект программы
attachShader() Прикрепляет шейдер к программе
linkProgram() Связывает объект программы
createBuffer() Создает объект буфера
bindBuffer() Привязывает объект буфера к цели
bufferData() Создает и инициализирует хранилище данных буфера
getAttribLocation() Возвращает местоположение атрибутной переменной
vertexAttribPointer() Указывает layout вершинных атрибутов
enableVertexAttribArray() Включает массив вершинных атрибутов
useProgram() Устанавливает указанную программу как часть текущего состояния рендеринга
drawArrays() Рендерит примитивы из массивных данных

Держите эту таблицу под рукой, когда продолжите свое путешествие в WebGL. Удачи в кодировании, и пусть ваши треугольники всегда будут perfectly rendered!

Credits: Image by storyset