WebGL -Cube Rotation
Привет, будущие маги WebGL! Сегодня мы отправляемся в увлекательное путешествие в мир 3D-графики. К концу этого урока вы сможете создать вращающийся куб с помощью WebGL. Это же здорово, не так ли? Погружаемся!
Понимание основ
Прежде чем мы начнем крутить кубы как DJ, давайте разберемся с некоторыми основными концепциями.
Что такое WebGL?
WebGL (Web Graphics Library) - это API на JavaScript, который позволяет нам рендерить 3D-графику в браузере. Это как дать вашему браузеру парочку 3D-очков!
Почему куб?
Вы можете задаться вопросом: "Почему мы начинаем с куба?" Ну, мои дорогие студенты, куб - это как "Привет, мир" в 3D-графике. Он достаточен прост, чтобы его понять, но достаточен сложен, чтобы научить нас важным концепциям. Да и кто не любит хороший куб?
Настройка нашего окружения WebGL
HTML Canvas
Перво-наперво, нам需要一个 подиум для нашего куба. В WebGL этот подиум называется канвой. Давайте настроим его:
<canvas id="glcanvas" width="640" height="480">
Ваш браузер не поддерживает HTML5 canvas
</canvas>
Это создает канву размером 640x480 пикселей. Если вы его не видите, не волнуйтесь - это как невидимая танцплощадка прямо сейчас.
Инициализация WebGL
Теперь давайте подготовим WebGL к party:
var canvas = document.getElementById('glcanvas');
var gl = canvas.getContext('webgl');
if (!gl) {
console.log('WebGL не поддерживается, переходим на experimental-webgl');
gl = canvas.getContext('experimental-webgl');
}
if (!gl) {
alert('Ваш браузер не поддерживает WebGL');
}
Этот код получает наш контекст WebGL. Если ваш браузер не поддерживает WebGL, это как пытаться играть DVD на ВHS-плеере - это просто не работает!
Создание нашего 3D-куба
Определение вершин
Куб имеет 8 углов (вершин). Мы должны tell WebGL, где эти углы находятся:
var vertices = [
// Лицевая сторона
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Задняя сторона
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Верхняя сторона
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// Нижняя сторона
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// Правая сторона
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// Левая сторона
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
];
Каждая тройка чисел представляет собой угол нашего куба в 3D-пространстве. Это как дать WebGL карту нашего куба!
Создание буфера
Теперь нам нужно отправить эти данные на GPU:
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
Это как упаковать наш куб в чемодан (буфер) и отправить его на GPU.
Шейдеры - маги WebGL
Вершинный шейдер
Вершинный шейдер определяет положение наших вершин:
var vertexShaderSource = `
attribute vec3 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
}
`;
Этот шейдер принимает каждую вершину и применяет наши матрицы трансформации. Это как маг, передвигающий углы нашего куба!
Фрагментный шейдер
Фрагментный шейдер закрашивает наш куб:
var fragmentShaderSource = `
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
Этот простой шейдер просто закрашивает все белым. Это как покрасить наш куб!
Компиляция и liênирование шейдеров
Теперь нам нужно скомпилировать наши шейдеры и связать их в программу:
function getShader(gl, source, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('Произошла ошибка при компиляции шейдеров: ' + gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var vertexShader = getShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
var fragmentShader = getShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('Не удалось инициализировать шейдерную программу: ' + gl.getProgramInfoLog(shaderProgram));
}
gl.useProgram(shaderProgram);
Это как научить наших магов (шейдеров) их трюков и затем пустить их на сцену!
Делаем наш куб вращаться
Настройка вращения
Чтобы сделать наш куб вращающимся, мы должны обновлять его angle вращения со временем:
var cubeRotation = 0.0;
function render(now) {
now *= 0.001; // преобразовать в секунды
const deltaTime = now - then;
then = now;
cubeRotation += deltaTime;
drawScene();
requestAnimationFrame(render);
}
Эта функция вызывается многократно, обновляя вращение нашего куба каждый раз.
Рисование сцены
Теперь давайте соберем все вместе и нарисуем наш вращающийся куб:
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, 45 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.1, 100.0);
const modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]);
mat4.rotate(modelViewMatrix, modelViewMatrix, cubeRotation, [0, 1, 1]);
gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'), false, projectionMatrix);
gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'), false, modelViewMatrix);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 36);
}
Эта функция очищает канву, настраивает перспективу, применяет вращение иfinally рисует наш куб.
Заключение
И вот оно,folks! Мы создали вращающийся 3D-куб с помощью WebGL. Помните, что овладение WebGL похоже на обучение жонглированию - это требует практики, но как только вы это освоите, вы сможете делать удивительные вещи!
Вот таблица, резюмирующая основные методы, которые мы использовали:
Метод | Описание |
---|---|
gl.createBuffer() |
Создает новый буферный объект |
gl.bindBuffer() |
Связывает буферный объект с целевым |
gl.bufferData() |
Создает и иницииализирует хранилище данных буферного объекта |
gl.createShader() |
Создает шейдерный объект |
gl.shaderSource() |
Устанавливает исходный код шейдерного объекта |
gl.compileShader() |
Компилирует шейдерный объект |
gl.createProgram() |
Создает объект программы |
gl.attachShader() |
Прикрепляет шейдерный объект к объекту программы |
gl.linkProgram() |
Связывает объект программы |
gl.useProgram() |
Устанавливает указанный объект программы как часть текущего состояния рендеринга |
gl.clear() |
Очищает буферы до预设ных значений |
gl.uniformMatrix4fv() |
Указывает значение переменной uniform для текущего объекта программы |
gl.drawArrays() |
Рендерит примитивы из массива данных |
Продолжайте практиковаться, продолжайте программировать, и скоро вы сможете создавать удивительную 3D-графику в вашем браузере. Счастливого кодирования!
Credits: Image by storyset