WebGL - Рисование треугольника
Здравствуйте, будущие маги WebGL! Сегодня мы отправляемся в увлекательное путешествие в мир компьютерной графики. Мы будем учиться рисовать треугольник с помощью WebGL, что может показаться простым, но поверьте мне, это основа всех потрясающих 3D-график, которые вы видите в играх и фильмах. Так что пристегнитесь и погружайтесь с нами!
Что такое WebGL?
Прежде чем начать рисовать треугольники, давайте на минутку разберемся, что такое WebGL. WebGL (Web Graphics Library) — это API на JavaScript, который позволяет нам render 2D и 3D графику в веб-браузерах без использования каких-либо плагинов. Это как иметь суперсилу, которая позволяет создавать потрясающие визуальные эффекты прямо в вашем веб-браузере!
Шаги для рисования треугольника
Рисование треугольника в WebGL может показаться пугающей задачей, но не волнуйтесь! Мы разберем это на управляемые шаги. Вот что нам нужно сделать:
- Настроить HTML canvas
- Получить контекст WebGL
- Создать и скомпилировать вершины шейдера
- Создать и скомпилировать фрагментный шейдер
- Создать шейдерную программу
- Определить вершины треугольника
- Создать буфер и загрузить вершинные данные
- Связать атрибуты вершины
- Нарисовать треугольник
Теперь давайте рассмотрим каждый шаг подробно.
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