Готовый перевод WebGL Lesson 1 – A triangle and a square / WebGL Урок 1 - треугольник и квадрат: WebGL Урок 1 - треугольник и квадрат

Внимание! Этот перевод, возможно, ещё не готов, так как модераторы установили для него статус «идёт перевод»

Приветствую в моём первом WebGL учебнике! Этот первый урок основан на втором номере учебника NeHe OpenGL, который очень популярен в изучении 3D графике для создания игр.

Урок покажет вам как нарисовать треугольник и квадрат на web-странице

Может это не так интересно само по себе, но это превосходное введение по основам WebGL; если вы поймете как это работает, все остальное для вас будет легким...

Предупреждение: эти уроки предназначены для людей с обширным программистским опытом, но не имеющих навыков в 3D графике; советуем вам приступать, если вы хорошо разбираетесь, что происходит в коде, только тогда вы сможете сделать ваши собственные 3D web-страницы настолько быстро, как это только возможно

Я пишу, как изучал WebGL сам, и мог допустить (и скорее всего допустил) ошибки; используйте на свой страх и риск.

Однако, я устраняю ошибки и корректирую (заблуждения), когда я услышу их, если Вы заметите любые ошибки то, пожалуйста дайте мне знать в комментариях.

Пример этого кода Вы можете получить двумя путями. Нажав нажав "Просмотреть исходный код", при просмотре примера в браузере, или если Вы используете GitHub, Вы можете скопировать (и будущие уроки тоже) из репозитория. В любом случае, если у вас есть код, загрузите его в вашем любимом текстовом редакторе и посмотрите его.

Это довольно сложно на первый взгляд, даже если Вы знакомы с основами OpenGL на уровне основ.

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

Это всё тело страницы — всё прочее написано на JavaScript (хотя, если вы получили код с помощью вызова пункта меню "Просмотреть исходный код", вы увидите кое-какой дополнительный код необходимый для аналитики моего сайта. Этот код можете не рассматривать.

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

Канвасы это новшество появившееся в HTML 5.0 — с их помощью поддерживаются новые типы элементов отображаемых в web-страницах с помощью JavaScript, как 2D, так и (средствами WebGL) 3D-элементов.

В тэге канваса мы не определяем ничего кроме простых свойств определяющих его расположение, а весь код по настройке WebGL мы разместим в JavaScript функции webGLStart, которая как вы можете видеть вызывается при загрузке страницы.

Давайте взглянем на эту функцию:

function webGLStart() {
var canvas = document.getElementById("lesson01-canvas");
initGL(canvas);
initShaders();
initBuffers();
//
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0)
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
//
setInterval(drawScene, 15);
}

Она вызывает функции для инициализации WebGL и шейдеров, о которых я ранее упоминал, передавая их в элемент canvas, в котором мы хотим нарисовать наши 3D-штуковины, а затем она инициализирует некоторые буферы используя initBuffers. Буферы используются для хранения информации о треугольнике и квадрате, которые мы собираемся рисовать,— о них мы поговорим через секунду.

var triangleVertexPositionBuffer;
var squareVertexPositionBuffer;

function initBuffers() {
triangleVertexPositionBuffer = gl.createBuffer();

var vertices = [
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0
];

gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(vertices), gl.STATIC_DRAW);

triangleVertexPositionBuffer.itemSize = 3;
triangleVertexPositionBuffer.numItems = 3;

squareVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
vertices = [
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(vertices), gl.STATIC_DRAW);
squareVertexPositionBuffer.itemSize = 3;
squareVertexPositionBuffer.numItems = 4;
}

function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);

loadIdentity();

7 mvTranslate([-1.5, 0.0, -7.0]);

gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

setMatrixUniforms();

gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);

}

…

var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch(e) {
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
}

var mvMatrix;

function loadIdentity() {
mvMatrix = Matrix.I(4);
}

function multMatrix(m) {
mvMatrix = mvMatrix.x(m);
}

function mvTranslate(v) {
var m = Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4();
multMatrix(m);
}

var pMatrix;
function perspective(fovy, aspect, znear, zfar) {
pMatrix = makePerspective(fovy, aspect, znear, zfar);
}

var shaderProgram;
function initShaders() {
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
//
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
//
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
//
gl.useProgram(shaderProgram);

shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}

function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
//
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3)
str += k.textContent;
k = k.nextSibling;
}
//
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
//
gl.shaderSource(shader, str);
gl.compileShader(shader);
//
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
//
return shader;
}

function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, new WebGLFloatArray(pMatrix.flatten()));
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, new WebGLFloatArray(mvMatrix.flatten()));
}

Внимание! Этот перевод, возможно, ещё не готов.
Его статус: идёт перевод

Переведено на Нотабеноиде
http://notabenoid.org/book/10096/31213

Переводчики: Torna, realgaa, undefiened

Настройки

Готово:

24.43% КП = 1.0

Непереведённые фрагменты будут пропущены.