aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/api/webgl_api
diff options
context:
space:
mode:
Diffstat (limited to 'files/ru/web/api/webgl_api')
-rw-r--r--files/ru/web/api/webgl_api/index.html106
-rw-r--r--files/ru/web/api/webgl_api/tutorial/adding_2d_content_to_a_webgl_context/index.html223
-rw-r--r--files/ru/web/api/webgl_api/tutorial/animating_objects_with_webgl/index.html123
-rw-r--r--files/ru/web/api/webgl_api/tutorial/getting_started_with_webgl/index.html104
-rw-r--r--files/ru/web/api/webgl_api/tutorial/index.html39
-rw-r--r--files/ru/web/api/webgl_api/tutorial/lighting_in_webgl/index.html225
-rw-r--r--files/ru/web/api/webgl_api/tutorial/using_shaders_to_apply_color_in_webgl/index.html95
-rw-r--r--files/ru/web/api/webgl_api/tutorial/using_textures_in_webgl/index.html277
-rw-r--r--files/ru/web/api/webgl_api/tutorial/создание_3d_объектов_с_помощью_webgl/index.html131
-rw-r--r--files/ru/web/api/webgl_api/webgl_best_practices/index.html46
10 files changed, 1369 insertions, 0 deletions
diff --git a/files/ru/web/api/webgl_api/index.html b/files/ru/web/api/webgl_api/index.html
new file mode 100644
index 0000000000..6a35a2dda3
--- /dev/null
+++ b/files/ru/web/api/webgl_api/index.html
@@ -0,0 +1,106 @@
+---
+title: WebGL
+slug: Web/API/WebGL_API
+tags:
+ - WebGL
+translation_of: Web/API/WebGL_API
+---
+<div>{{WebGLSidebar}}</div>
+
+<p class="summary">WebGL (Web Graphics Library) - программная библиотека для языка JavaScript предназначенная для визуализации интерактивной трехмерной графики и двухмерной графики в пределах совместимости веб-браузера без использования плагинов. WebGL приносит в веб трехмерную графику, вводя API, который построен на основе OpenGL ES 2.0, что позволяет его использовать в элементах <a href="/en-US/docs/HTML/Canvas" title="en-US/docs/html/canvas"><code> canvas</code></a> HTML5 .</p>
+
+<p>Поддержка WebGL присутствует в <a href="/en-US/Firefox" title="Firefox 4 for developers">Firefox</a> 4+, <a href="http://www.google.com/chrome/" title="http://www.google.com/chrome/">Google Chrome</a> 9+, <a href="http://www.opera.com/" title="http://www.opera.com/">Opera</a> 12+, <a href="http://www.apple.com/safari/" title="http://www.apple.com/fr/safari/">Safari </a>5.1+ и <a href="http://windows.microsoft.com/en-us/internet-explorer/browser-ie" title="http://windows.microsoft.com/en-us/internet-explorer/download-ie">Internet Explorer</a> 11+. Однако помимо поддержки WebGL браузером, необходима также его поддержка графическим процессором клиента.</p>
+
+<table class="topicpage-table">
+ <tbody>
+ <tr>
+ <td>
+ <h2 class="Documentation" id="Разработка">Разработка</h2>
+
+ <dl>
+ <dt><a href="/ru/docs/Web/WebGL/Getting_started_with_WebGL" title="en-US/docs/WebGL/Getting started with WebGL">Начало работы с WebGL</a></dt>
+ <dd>Как настроить контекст WebGL .</dd>
+ <dt><a href="/ru/docs/Web/WebGL/Adding_2D_content_to_a_WebGL_context" title="en-US/docs/WebGL/Adding 2D content to a WebGL context">Добавление 2D контента в контекст WebGL</a></dt>
+ <dd>Как отобразить простую плоскую фигуру с помощью WebGL.</dd>
+ <dt><a href="/ru/docs/Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL" title="en-US/docs/WebGL/Using shaders to apply color in WebGL">Использование шейдеров для назначения цвета в WebGL</a></dt>
+ <dd>Демонстрирует как добавить цвет фигурам, используя шейдеры.</dd>
+ <dt><a href="/ru/docs/Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL" title="en-US/docs/WebGL/Animating objects with WebGL">Анимация объектов с помощью WebGL</a></dt>
+ <dd>Показывает как повернуть и перемещать объекты для создания простой анимации.</dd>
+ <dt><a href="/en-US/docs/WebGL/Creating_3D_objects_using_WebGL" title="en-US/docs/WebGL/Creating 3D objects using WebGL">Создание 3D объектов с помощью WebGL</a></dt>
+ <dd>Показывает как создавать и анимировать 3D объект (в данном случае куб).</dd>
+ <dt><a href="/en-US/docs/WebGL/Using_textures_in_WebGL" title="en-US/docs/WebGL/Using textures in WebGL">Использование текстур в WebGL</a></dt>
+ <dd>Демонстрирует как разместить текстуры на гранях объекта.</dd>
+ <dt><a href="/en-US/docs/WebGL/Lighting_in_WebGL" title="en-US/docs/WebGL/Lighting in WebGL">Освещение в WebGL</a></dt>
+ <dd>Как имитировать эффекты освещения в контексте WebGL .</dd>
+ <dt><a href="/en-US/docs/WebGL/Animating_textures_in_WebGL" title="en-US/docs/WebGL/Animating textures in WebGL">Анимация текстур в WebGL</a></dt>
+ <dd>Показывает как анимировать текстуры; в данном случае путём размещения видео Ogg на гранях вращающегося куба.</dd>
+ <dt><a href="/en-US/docs/WebGL/WebGL_best_practices" title="en-US/docs/WebGL/WebGL best practices">WebGL: советы по применению на практике</a></dt>
+ <dd>Советы и предложения по улучшению контента, созданного вами при помощи WebGL.</dd>
+ <dt><a href="/en-US/docs/WebGL/Cross-Domain_Textures" title="en-US/docs/WebGL/Cross-Domain Textures">Текстуры с других доменов</a></dt>
+ <dd>Информация о загрузке текстур с других доменов, отличных от того, с которого загружается ваш контент.</dd>
+ <dt><a href="/en-US/docs/WebGL/Using_Extensions" title="en-US/docs/WebGL/Using_Extensions">Использование расширений</a></dt>
+ <dd>Как использовать расширения, доступные в WebGL.</dd>
+ </dl>
+ </td>
+ <td>
+ <h2 class="Related_Topics" id="Ресурсы">Ресурсы</h2>
+
+ <dl>
+ <dt><a class="link-https" href="https://www.khronos.org/registry/webgl/specs/1.0/" title="https://www.khronos.org/registry/webgl/specs/1.0/">Спецификация WebGL</a></dt>
+ <dd>Спецификация WebGL.</dd>
+ <dt><a class="external" href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">Официальный сайт WebGL</a></dt>
+ <dd>Веб-сайт разработчиков WebGL - Khronos Group.</dd>
+ <dt><a class="external" href="http://learningwebgl.com/blog/" title="http://learningwebgl.com/blog/">Изучение WebGL</a></dt>
+ <dd>Веб-сайт с уроками, посвященными использованию WebGL.</dd>
+ <dt><a href="http://www.html5rocks.com/en/tutorials/webgl/webgl_fundamentals/" title="http://www.html5rocks.com/en/tutorials/webgl/webgl_fundamentals/">Основы WebGL</a></dt>
+ <dd>Учебные материалы по основным возможностям WebGL.</dd>
+ <dt><a href="http://games.greggman.com/game/webgl-2d-matrices/">Матрицы в WebGL</a></dt>
+ <dd>Введение в использование матриц в двухмерной графике на WebGL. На этом ресурсе объясняется математическая основа перспективы в трехмерной графике.</dd>
+ <dt><a class="external" href="http://learningwebgl.com/cookbook/index.php/" title="http://learningwebgl.com/cookbook/index.php/">Советы по использованию WebGL</a></dt>
+ <dd>Веб-сайт с советами по написанию кода на WebGL.</dd>
+ <dt><a class="external" href="http://code.google.com/p/ewgl-matrices/" title="http://code.google.com/p/ewgl-matrices/">ewgl-matrices</a></dt>
+ <dd>Библиотека для работы с матрицами для WebGL</dd>
+ <dt><a class="link-https" href="https://github.com/toji/gl-matrix" title="https://github.com/toji/gl-matrix">glMatrix</a></dt>
+ <dd>Библиотека для работы с матрицами и векторами, написанная на JavaScript, предназначенная для высокопроизводительных приложений на WebGL</dd>
+ <dt><a class="external" href="http://code.google.com/p/webgl-mjs/" title="http://code.google.com/p/webgl-mjs/">mjs</a></dt>
+ <dd><span>Математическая библиотека для работы с векторами и матрицами, написанная на JavaScript, оптимизированная для использования с WebGL.</span></dd>
+ <dt><a class="external" href="http://sylvester.jcoglan.com/" title="http://sylvester.jcoglan.com/">Sylvester</a></dt>
+ <dd>Библиотека с открытым исходным кодом для работы с векторами и матрицами. Не оптимизирована для WebGL, но производительная.</dd>
+ <dt><a class="external" href="http://webglplayground.net" title="http://webglplayground.net">WebGL площадка</a></dt>
+ <dd>Онлайн инструмент для создания и публикации проектов на WebGL. Удобна для быстрого прототипирования и экспериментирования.</dd>
+ <dt><a href="http://www.webglacademy.com" title="http://www.webglacademy.com">Академия WebGL</a></dt>
+ <dd>Редактор HTML/Javascript с учебными материалами для обучения основам программирования на webgl.</dd>
+ </dl>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2>
+
+<h3 id="WebGL_1">WebGL 1</h3>
+
+<div>
+
+
+<p>{{Compat("api.WebGLRenderingContext", 0)}}</p>
+
+<h3 id="WebGL_2">WebGL 2</h3>
+</div>
+
+<div class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div>
+
+<p>{{Compat("api.WebGL2RenderingContext", 0)}}</p>
+
+<h3 id="Замечания_по_Gecko">Замечания по Gecko</h3>
+
+<h4 id="Отладка_и_тестирование_WebGL">Отладка и тестирование WebGL</h4>
+
+<p>Начиная с Gecko 10.0 {{geckoRelease("10.0")}}, имеются две настройки, позволяющие вам управлять возможностями WebGL для тестирования своего кода:</p>
+
+<dl>
+ <dt><code>webgl.min_capability_mode</code></dt>
+ <dd>Свойство типа Boolean которое, при значении <code>true</code> позволяет запускать режим минимальных функциональных возможностей. В этом режиме WebGL сконфигурирован осуществлять поддержку минимального набора функциональных возможностей, поддержка которых обязательна по спецификации WebGL. Это позволяет вам убедиться в том, что ваш код на WebGL будет работать на любом устройстве или браузере, независимо от их возможностей. Значением по умолчанию для это свойства является значение <code>false</code>.</dd>
+ <dt><code>webgl.disable_extensions</code></dt>
+ <dd>Свойство типа Boolean которое, при значении <code>true</code> отключает все расширения WebGL. Значением по умолчанию для это свойства является значение <code>false</code>.</dd>
+</dl>
diff --git a/files/ru/web/api/webgl_api/tutorial/adding_2d_content_to_a_webgl_context/index.html b/files/ru/web/api/webgl_api/tutorial/adding_2d_content_to_a_webgl_context/index.html
new file mode 100644
index 0000000000..98198d8f7e
--- /dev/null
+++ b/files/ru/web/api/webgl_api/tutorial/adding_2d_content_to_a_webgl_context/index.html
@@ -0,0 +1,223 @@
+---
+title: Добавление двухмерного контента в контекст WebGL
+slug: Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context
+tags:
+ - WebGL
+translation_of: Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context
+---
+<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL", "Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL")}}</p>
+
+<p>После того, как вы успешно <a href="/ru/docs/Web/WebGL/Getting_started_with_WebGL" title="en/WebGL/Getting started with WebGL">создали контекст WebGL</a>, вы можете начинать отображать в нем графические объекты. Простейшая вещь, которую вы можете сделать - отрисовать простой квадрат без текстуры. Итак, начнём построение кода для отрисовки квадрата.</p>
+
+<h2 id="Отрисовка_сцены">Отрисовка сцены</h2>
+
+<p>На данном этапе очень важно понять одну вещь: не смотря на то, что мы в этом примере отрисовываем двухмерный объект, мы по-прежнему отрисовываем его в трехмерном пространстве. По существу, нам по-прежнему необходимо создать шейдеры, которые будут освещать нашу простую сцену,  и отрисовать наш объект. На данном шаге определим как квадрат будет освещаться.</p>
+
+<h3 id="Инициализация_шейдеров">Инициализация шейдеров</h3>
+
+<p>Шейдеры задаются при помощи языка высокого уровня для программирования шейдеров - <a class="external" href="http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf" title="http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf">OpenGL ES Shading Language</a>. Для того, чтобы сделать проще процесс поддержки и обновления нашего контента, мы можем фактически написать наш код, загружающий шейдеры и помещающий их в HTML документ, вместо того, чтобы встраивать его весь в JavaScript. Давайте рассмотрим нашу процедуру <code>initShaders()</code>, которая выполнит эту задачу:</p>
+
+<pre class="brush: js">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("Unable to initialize the shader program.");
+ }
+
+ gl.useProgram(shaderProgram);
+
+ vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
+ gl.enableVertexAttribArray(vertexPositionAttribute);
+}
+
+</pre>
+
+<p>Этой процедурой загружаются две шейдерные программы. Первая - фрагментный шейдер, загружается из элемента <a href="/en/HTML/Element/Script" title="En/HTML/Element/Script"><code>script</code></a> с ID "shader-fs". Вторая - вершинный шейдер, загружается из элемента <a href="/en/HTML/Element/Script" title="En/HTML/Element/Script"><code>script</code></a> с ID "shader-vs". Мы рассмотрим функцию <code>getShader()</code> чуть ниже. Эта процедура фактически отвечает за извлечение шейдерных программ из DOM.</p>
+
+<p>Затем мы создаем шейдерную программу, вызывая функцию <code>createProgram()</code> объекта WebGL, присоединяя два шейдера к нему, и связывая шейдерную программу. После выполнения этого, проверяется значение параметра <code>LINK_STATUS</code> объекта <code>gl</code> для того, чтобы убедиться, что программа успешно скомпанована. Если это так, мы активируем новую шейдерную программу.</p>
+
+<h3 id="Загрузка_шейдеров_из_DOM">Загрузка шейдеров из DOM</h3>
+
+<p>Функция <code>getShader()</code> получает из DOM шейдерную программу с определенным именем, возвращая скомпилированную шейдерную программу вызывающему, или значение null, если шейдерная программа не может быть загружена или скомпилирована.</p>
+
+<pre class="brush: js">function getShader(gl, id) {
+ var shaderScript, theSource, currentChild, shader;
+
+  shaderScript = document.getElementById(id);
+
+  if (!shaderScript) {
+    return null;
+  }
+
+  theSource = "";
+  currentChild = shaderScript.firstChild;
+
+  while(currentChild) {
+    if (currentChild.nodeType == currentChild.TEXT_NODE) {
+     theSource += currentChild.textContent;
+    }
+
+ currentChild = currentChild.nextSibling;
+  }
+</pre>
+
+<p>Как только элемент с указанным ID найден, его текст помещается в переменную <code>theSource</code>.</p>
+
+<pre class="brush: js"> 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;
+  }</pre>
+
+<p>После того, как код для шейдера считан, мы проверяем MIME тип шейдерного объекта, чтобы определить является он вершинным (MIME type "x-shader/x-vertex") или фрагментным (MIME type "x-shader/x-fragment") шейдером, а затем создаем соответствующий тип шейдера из полученного исходного кода.</p>
+
+<pre class="brush: js"> gl.shaderSource(shader, theSource);
+
+  // скомпилировать шейдерную программу
+  gl.compileShader(shader);
+
+  // Проверить успешное завершение компиляции
+  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
+      alert("An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader));
+      return null;
+  }
+
+  return shader;
+}
+</pre>
+
+<p>В результате, исходный код, передан в переменную shader и скомпилирован. Если произошли ошибки во время компиляции кода шейдера, мы отображаем окно с предупреждением и возвращаем значение null; Иначе, возвращается новый скомпилированный шейдер.</p>
+
+<h3 id="Шейдеры">Шейдеры</h3>
+
+<p>После этого нам необходимо добавить шейдерные программы в HTML описывающий наш документ. Подробная информация о том, как работают шейдеры выходит за рамки этой статьи, как и впрочем описание синтаксиса языка программирования шейдеров.</p>
+
+<h4 id="Фрагментный_шейдер">Фрагментный шейдер</h4>
+
+<p>Каждый пиксель в полигоне называется <strong>фрагментом</strong> в языке GL. Фрагментные шейдеры необходимы для назначения цвета для каждого пикселя. В данном случае, мы просто назначаем белый цвет каждому пикселю.</p>
+
+<p><code>gl_FragColor</code> - встроенная переменная GL, используемая для управления цветом фрагментов. Устанавливая ее значение назначаем цвет пикселям. Ниже приведен пример этого.</p>
+
+<pre class="brush: html">&lt;script id="shader-fs" type="x-shader/x-fragment"&gt;
+  void main(void) {
+    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
+  }
+&lt;/script&gt;
+</pre>
+
+<h4 id="Вершинный_шейдер">Вершинный шейдер</h4>
+
+<p>Вершинный шейдер определяет положение и форму каждой вершины.</p>
+
+<pre class="brush: html">&lt;script id="shader-vs" type="x-shader/x-vertex"&gt;
+  attribute vec3 aVertexPosition;
+
+  uniform mat4 uMVMatrix;
+  uniform mat4 uPMatrix;
+
+  void main(void) {
+    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
+  }
+&lt;/script&gt;
+</pre>
+
+<h2 id="Создание_объекта">Создание объекта</h2>
+
+<p>Перед тем, как мы отрисуем наш квадрат, нам необходимо создать буфер, который содержит его вершины. Мы сделаем это,  вызвав функцию <code>initBuffers().</code> По мере ознакомления с другими концепциями WebGL, эта функция будет усложняться при создании более сложных трехмерных объектов.</p>
+
+<pre class="brush: js">var horizAspect = 480.0/640.0;
+
+function initBuffers() {
+ squareVerticesBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+
+ var 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 Float32Array(vertices), gl.STATIC_DRAW);
+}
+</pre>
+
+<p>В этом примере эта функция упрощена и дает оценить основную суть сцены. Она начинает работу с вызова метода <code>createBuffer()</code> объекта <code>gl</code> для получения буфера, в котором мы будем хранить вершины. Затем он привязывается к контексту, вызовом метода <code>bindBuffer()</code>.</p>
+
+<p>После того, как мы это сделали, мы создаем JavaScript массив, содержащий координаты для каждой вершины квадрата. Затем этот массив преобразуется в массив вещественных чисел WebGL и передается в метод <code>bufferData()</code> объекта <code>gl</code> для назначения вершин объекту.</p>
+
+<h2 id="Отрисовка_сцены_2">Отрисовка сцены</h2>
+
+<p>Как только шейдеры установлены и объект создан, мы можем действительно отрисовать сцену. Поскольку в этом примере нет какой-либо анимации, наша функция <code>drawScene()</code> имеет очень простой вид. Она использует несколько утилитарных процедур, которые мы кратко рассмотрим ниже.</p>
+
+<pre class="brush: js">function drawScene() {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ perspectiveMatrix = makePerspective(45, 640.0/480.0, 0.1, 100.0);
+
+ loadIdentity();
+ mvTranslate([-0.0, 0.0, -6.0]);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
+ gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
+ setMatrixUniforms();
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+}
+</pre>
+
+<p>Первый шаг - очистка цветом фона сцены контекста. Затем мы устанавливаем перспективу камеры. Мы устанавливаем угол обзора в 45°, с соотношением ширины к высоте равным 640/480 (размеры нашего объекта canvas). Мы также определяем, что мы хотим видеть отрисованными объекты на расстоянии от 0.1 до 100 единиц от камеры.</p>
+
+<p>Затем мы устанавливаем позицию квадрата, загружая определенную позицию и размещая ее от камеры на 6 единиц. После этого, мы привязываем буфер, содержащий вершины квадрата к контексту, настраиваем его, и отрисовываем объект, вызывая метод <code>drawArrays()</code>.</p>
+
+<p>Вы можете <a href="/samples/webgl/sample2" title="https://developer.mozilla.org/samples/webgl/sample2">посмотреть как это работает щелкнув по этой ссылке</a>. Но это только в том случае, если используемый браузер осуществляет поддержку WebGL.</p>
+
+<h2 id="Операции_над_матрицами">Операции над матрицами</h2>
+
+<p>Операции над матрицами достаточно сложны. Никому бы не хотелось самому писать весь код для работы с ними. К счастью, есть <a class="external" href="http://sylvester.jcoglan.com/" title="http://sylvester.jcoglan.com/">Sylvester</a> - очень удобная библиотека для выполнения операций над векторами и матрицами, написанная на JavaScript.</p>
+
+<p>Файл <code>glUtils.js</code>, используемый в этом примере, используется большинством примеров на WebGL, размещенных в сети интернет. Никто не знает точно откуда он появился. Он просто используется Sylvester и он даже пополняется методами для построения специальных типов матриц, а также вывода HTML для их отображения.</p>
+
+<p>Также, этот пример определяет несколько полезных процедур взаимодействия с этими библиотеками для выполнения определенных задач. Пояснения относительно того, что делает каждая из приведенных функций, выходят за рамки этого примера, но в сети есть много хороших материалов об операциях над матрицами. Чуть {{ anch("ниже") }} есть список некоторых из них.</p>
+
+<pre class="brush: js">function loadIdentity() {
+ mvMatrix = Matrix.I(4);
+}
+
+function multMatrix(m) {
+ mvMatrix = mvMatrix.x(m);
+}
+
+function mvTranslate(v) {
+ multMatrix(Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4());
+}
+
+function setMatrixUniforms() {
+ var pUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
+ gl.uniformMatrix4fv(pUniform, false, new Float32Array(perspectiveMatrix.flatten()));
+
+ var mvUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
+ gl.uniformMatrix4fv(mvUniform, false, new Float32Array(mvMatrix.flatten()));
+}
+</pre>
+
+<h2 id="Смотрите_также">Смотрите также</h2>
+
+<ul>
+ <li><a class="external" href="http://mathworld.wolfram.com/Matrix.html" title="http://mathworld.wolfram.com/Matrix.html">Матрицы</a> на Wolfram MathWorld</li>
+ <li><a class="external" href="http://en.wikipedia.org/wiki/Matrix_(mathematics)" title="http://en.wikipedia.org/wiki/Matrix_(mathematics)">Матрица</a> (Wikipedia)</li>
+</ul>
+
+<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL", "Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL")}}</p>
diff --git a/files/ru/web/api/webgl_api/tutorial/animating_objects_with_webgl/index.html b/files/ru/web/api/webgl_api/tutorial/animating_objects_with_webgl/index.html
new file mode 100644
index 0000000000..6d18ab5490
--- /dev/null
+++ b/files/ru/web/api/webgl_api/tutorial/animating_objects_with_webgl/index.html
@@ -0,0 +1,123 @@
+---
+title: Оживление объектов при помощи WebGL
+slug: Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL
+tags:
+ - WebGL
+translation_of: Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL
+---
+<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL", "Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL") }}</p>
+
+<p>Наш код оставшийся от предыдущего примера уже насроен на перерисовку нашей WebGL сцены каждые 15 миллисекунд. До сих пор мы просто отрисовывали в точности одно и то же каждый раз. Пришло время изменить это так, чтобы наш квадрат начал двигаться.</p>
+
+<p>В этом примере мы заставим наш двумерный квадрат вращаться и двигаться во всех трёх направлениях. Это докажет, что не смотря на то, что мы создавали всего-лишь двумерный объект, он всё ещё существует в трёхмерном пространстве.</p>
+
+<h2 id="Заставим_квадрат_вращаться">Заставим квадрат вращаться</h2>
+
+<p>Давайте начнём с того, что заставим квадрат вращаться. Для начала нам понадобится переменная значение в которой будет отражать текущий угол поворота нашего квадрата:</p>
+
+<pre class="brush: js">var squareRotation = 0.0;
+</pre>
+
+<p>Теперь нам надо изменить процедуру <code>drawScene()</code> и добавить в неё код, который бы учитывал этот угол поворота при отрисовке квадрата в нашей сцене. После первоначального рассчёта матрицы положения для квадрата мы применяем условия поворота следующим образом:</p>
+
+<pre class="brush: js">mvPushMatrix();
+mvRotate(squareRotation, [1, 0, 1]);
+</pre>
+
+<p>Этот код сохраняет матрицу текущего положения, затем поворачивает матрицу на текущее значение переменной <code>squareRotation</code> вокруг осей X и Z.</p>
+
+<p>После отрисовки мы восстанавливаем изначальное состояние матрицы положения:</p>
+
+<pre class="brush: js"> mvPopMatrix();
+</pre>
+
+<p>Мы сохраняем и восстанавливаем состояние матрицы положения чтобы избежать влияние поворота на другие объекты, которые мы можем захотеть отобразить.</p>
+
+<p>Чтобы заставить квадрат крутиться нам нужно добавить в программу код, который будет изменять значение переменной <code>squareRotation</code> во времени. Для этого мы заведём ещё одну переменную в которую будем записывать время последней отрисовки (давайте назовём её <code>lastSquareUpdateTime</code>), затем добавим следующий код в конец нашей процедуры <code>drawScene()</code>:</p>
+
+<pre class="brush: js"> var currentTime = (new Date).getTime();
+ if (lastSquareUpdateTime) {
+ var delta = currentTime - lastSquareUpdateTime;
+
+ squareRotation += (30 * delta) / 1000.0;
+ }
+
+ lastSquareUpdateTime = currentTime;
+</pre>
+
+<p>Этот код использует количество времени прошедшего с момента, когда мы в последний раз изменяли значение переменной <code>squareRotation</code> чтобы определить как сильно нужно повернуть квадрат.</p>
+
+<h2 id="Сделаем_так_чтобы_квадрат_начал_двигаться">Сделаем так, чтобы квадрат начал двигаться</h2>
+
+<p>Мы можем также заставить наш квадрат двигаться изменяя его позицию перед отрисовкой. Этим примером мы собираемся продемонстрировать самые основные движения, очевидно, что в реальном мире вы бы сделали что-нибудь менее безумное.</p>
+
+<p>Давайте отслеживать сдвиг положения квадрата по каждой оси в новых переменных:</p>
+
+<pre class="brush: js">var squareXOffset = 0.0;
+var squareYOffset = 0.0;
+var squareZOffset = 0.0;
+</pre>
+
+<p>И расстояние на которое нужно сместить квадрат по каждой из осей в следующих переменных:</p>
+
+<pre class="brush: js">var xIncValue = 0.2;
+var yIncValue = -0.4;
+var zIncValue = 0.3;
+</pre>
+
+<p>Теперь мы можем просто добавить следующий код к уже написанному, который обновляет положение угла поворота:</p>
+
+<pre class="brush: js"> squareXOffset += xIncValue * ((30 * delta) / 1000.0);
+ squareYOffset += yIncValue * ((30 * delta) / 1000.0);
+ squareZOffset += zIncValue * ((30 * delta) / 1000.0);
+
+ if (Math.abs(squareYOffset) &gt; 2.5) {
+ xIncValue = -xIncValue;
+ yIncValue = -yIncValue;
+ zIncValue = -zIncValue;
+ }
+</pre>
+
+<p>И, наконец, мы добавляем в процедуру <code>drawScene()</code> следующий код:</p>
+
+<pre class="brush: js">mvTranslate([squareXOffset, squareYOffset, squareZOffset]);</pre>
+
+<p>Это заставит наш квадрат двигаться по экрану, приближаясь и удаляясь от наблюдателя и при этом ещё и вращаться. Это похоже на работу заставки</p>
+
+<p>Если ваш браузер поддерживает работу с WebGL, <a href="/samples/webgl/sample4/index.html" title="https://developer.mozilla.org/samples/webgl/sample4/index.html">проследуйте по этой ссылке, чтобы посмотреть на этот пример</a> в действии.</p>
+
+<h2 id="Больше_операций_с_матрицами">Больше операций с матрицами</h2>
+
+<p>Этот пример использует несколько дополнительных операций над матрицами включая две утилиты для работы со стэком состояния матриц и одну, поворачивающую матрицу положения на заданное количество градусов. Далее приведён код для вашего удобства:</p>
+
+<pre class="brush: js">var mvMatrixStack = [];
+
+function mvPushMatrix(m) {
+ if (m) {
+ mvMatrixStack.push(m.dup());
+ mvMatrix = m.dup();
+ } else {
+ mvMatrixStack.push(mvMatrix.dup());
+ }
+}
+
+function mvPopMatrix() {
+ if (!mvMatrixStack.length) {
+ throw("Can't pop from an empty matrix stack.");
+ }
+
+ mvMatrix = mvMatrixStack.pop();
+ return mvMatrix;
+}
+
+function mvRotate(angle, v) {
+ var inRadians = angle * Math.PI / 180.0;
+
+ var m = Matrix.Rotation(inRadians, $V([v[0], v[1], v[2]])).ensure4x4();
+ multMatrix(m);
+}
+</pre>
+
+<p>Эти утилиты были заимствованы из примера разработанного Владом Вукицевичем (Vlad Vukićević).</p>
+
+<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL", "Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL") }}</p>
diff --git a/files/ru/web/api/webgl_api/tutorial/getting_started_with_webgl/index.html b/files/ru/web/api/webgl_api/tutorial/getting_started_with_webgl/index.html
new file mode 100644
index 0000000000..0e50af82fa
--- /dev/null
+++ b/files/ru/web/api/webgl_api/tutorial/getting_started_with_webgl/index.html
@@ -0,0 +1,104 @@
+---
+title: Начало работы с WebGL
+slug: Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL
+tags:
+ - WebGL
+translation_of: Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL
+---
+<p>{{WebGLSidebar("Tutorial")}} {{Next("Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context")}}</p>
+
+<p><a class="external" href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">WebGL</a> позволяет веб-контенту использовать API, основанный на <a class="external" href="http://www.khronos.org/opengles/" title="http://www.khronos.org/opengles/">OpenGL ES</a> 2.0, для визуализации трехмерной графики без использования плагинов в HTML элементе <a class="internal" href="/en/HTML/Canvas" title="en/HTML/Canvas"><code>canvas</code></a> в браузерах, которые осуществляют его поддержку. WebGL программы состоят из кода управления, написанном на JavaScript и кода специальных эффектов (шейдерного кода), который выполняется на графическом процессоре. WebGL элементы могут быть смешаны с другими HTML элементами и собраны с другими частями веб-страницы или фоном веб-страницы.</p>
+
+<p>Эта статья знакомит вас с основами использования WebGL. Предполагается, что вы уже знакомы с математическими основами трехмерной графики. Данная статья не обучит вас OpenGL.</p>
+
+<h2 id="Подготовка_к_визуализации_в_3D">Подготовка к визуализации в 3D</h2>
+
+<p>Первое, что вам понадобится для использования WebGL для визуализации в 3D - это элемент canvas. Фрагмент на HTML ниже содержит элемент canvas и определяет обработчик события <code>onload</code>, которое инициализирует наш контекст WebGL.</p>
+
+<pre class="brush: html">&lt;body onload="start()"&gt;
+ &lt;canvas id="glcanvas" width="640" height="480"&gt;
+ Your browser doesn't appear to support the HTML5 &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element.
+ &lt;/canvas&gt;
+&lt;/body&gt;
+</pre>
+
+<h3 id="Подготовка_контекста_WebGL">Подготовка контекста WebGL</h3>
+
+<p>Функция <code>start()</code>, в нашем JavaScript коде вызывается после загрузки документа. Ее назначение - настройка контекста WebGL и начать отрисовку содержимого.</p>
+
+<pre class="brush: js">var gl; // глобальная переменная для контекста WebGL
+
+function start() {
+ var canvas = document.getElementById("glcanvas");
+
+ gl = initWebGL(canvas); // инициализация контекста GL
+
+ // продолжать только если WebGL доступен и работает
+
+ if (gl) {
+ gl.clearColor(0.0, 0.0, 0.0, 1.0); // установить в качестве цвета очистки буфера цвета черный, полная непрозрачность
+ gl.enable(gl.DEPTH_TEST); // включает использование буфера глубины
+ gl.depthFunc(gl.LEQUAL); // определяет работу буфера глубины: более ближние объекты перекрывают дальние
+ gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT); // очистить буфер цвета и буфер глубины.
+  }
+}
+</pre>
+
+<p>Первое, что мы здесь делаем - получаем ссылку на элемент canvas, помещаем ее в переменную <code>canvas</code>. Очевидно, что если вам не требуется многократно получать ссылку на canvas, вы должны избежать сохранения этого значения глобально, а только сохранить ее в локальной переменной или в поле объекта.</p>
+
+<p>Как только мы получили ссылку на canvas, мы вызываем функцию <code>initWebGL()</code>; Эту функцию мы определяем незамедлительно, ее работа - инициализировать контекст WebGL.</p>
+
+<p>Если контекст успешно инициализирован, в <code>gl</code> будет содержаться ссылка на него. В этом случае, мы устанавливаем цвет очистки буфера цвета (цвет фона) на черный, затем очищаем контекст этим цветом. После этого, контекст конфигурируется параметрами настройки. В данном случае, мы включаем буфер глубины и определяем, что более близкие объекты будут перекрывать более дальние.</p>
+
+<p>Всё вышеперечисленное необходимо сделать только для первоначальной инициализации. Чуть позже мы увидим работу по визуализации трехмерных объектов.</p>
+
+<h3 id="Создание_контекста_WebGL">Создание контекста WebGL</h3>
+
+<p>Функция <code>initWebGL()</code> выглядит следующим образом:</p>
+
+<pre class="brush: js">function initWebGL(canvas) {
+ gl = null;
+
+ try {
+    // Попытаться получить стандартный контекст. Если не получится, попробовать получить экспериментальный.
+    gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
+  }
+  catch(e) {}
+
+ // Если мы не получили контекст GL, завершить работу
+ if (!gl) {
+ alert("Unable to initialize WebGL. Your browser may not support it.");
+ gl = null;
+ }
+
+ return gl;
+}
+
+</pre>
+
+<p>Чтобы получить контекст WebGL для canvas, мы запрашиваем у элемента canvas контекст именуемый как "webgl". Если данная попытка завершается неудачно, мы пытаемся получить контекст, именуемый как "experimental-webgl". Если данная попытка также завершается неудачно, мы отображаем окно с предупреждением, позволяющим пользователю понять, что его браузер не поддерживает WebGL. Это всё, что необходимо сделать. На данном этапе мы будем иметь в переменной <code>gl</code> либо значение null (означающее, что контекст WebGL не доступен), либо ссылку на контекст WebGL в котором, мы будем производить отрисовку.</p>
+
+<div class="note"><strong>Обратите внимание:</strong> Контекст, именуемый как "experimental-webgl" - это временное имя для контекста, используемое на время процесса разработки спецификации. После того, как спецификация будет полностью разработана будет использоваться только имя контекста "webgl".</div>
+
+<p>На данном этапе этого кода достаточно, чтобы успешно инициализировать контекст WebGL, и вы увидите пустой черный блок, готовый к заполнению контентом.</p>
+
+<p>Если ваш браузер поддерживает WebGL, то вы можете посмотреть результат выполнения приведенного выше кода, щелкнув по этой <a href="/samples/webgl/sample1/index.html" title="https://developer.mozilla.org/samples/webgl/sample1/index.html">ссылке</a>.</p>
+
+<h3 id="Изменение_размера_контекста_WebGL">Изменение размера контекста WebGL</h3>
+
+<p>Новый контекст WebGL будет иметь возможность задания размеров области отображения в момент получения контекста путем задания высоты и ширины элемента canvas, без использования CSS. Редактирование стиля элемента canvas будет изменять его отображаемый размер, без изменения размеров области отрисовки. Редактирование атрибутов ширины и высоты элемента canvas после создания контекста не будет также изменять число пикселей для отрисовки. Чтобы изменить размер области отрисовки, с которой WebGL производит работу, например, когда пользователь изменяет размер окна на весь экран или когда вам необходимо менять настройки графики в самом приложении, вам необходимо вызвать контекстную функцию WebGL <code>viewport()</code>, чтобы подтвердить изменения.</p>
+
+<p>Чтобы изменить размер области отрисовки контекста WebGL с переменными <code>gl</code> и <code>canvas</code>, использующимися в примере выше:</p>
+
+<pre class="brush: js">gl.viewport(0, 0, canvas.width, canvas.height);</pre>
+
+<p>Элемент canvas будет изменять размер, в случае, если его отрисовать с другими размерами области отрисовки, чем те, что указаны в его стилях CSS, согласно которым он занимает место на экране. Изменение размера с помощью CSS наиболее полезно для сохранения ресурсов, отрисовывая с низким разрешением и позволяя браузеру растягивать полученный результат; сжимать возможно при использовании эффекта избыточной выборки сглаживания ( super sample antialiasing - SSAA) (приводит к менее приемлемым результатам и серьезным потерям производительности). В большинстве случаев лучше полагаться на множественную выборку сглаживания (<abbr style="line-height: 24px;" title='"Multisample'>MSAA) и </abbr>на реализацию алгоритмов фильтрации текстур, которые поддерживаются браузером пользователя, чем делать то же самое посредством грубой силы и надеяться, что алгоритм масштабирования изображений, используемый браузером, выдаст красивый результат.</p>
+
+<h3 id="Смотрите_также">Смотрите также</h3>
+
+<ul>
+ <li><a href="https://dev.opera.com/articles/introduction-to-webgl-part-1/">Введение в WebGL</a> - Автор: Luz Caballero Ресурс: DEV.OPERA. Эта статья адресована тем, кто хочет узнать что такое WebGL, как работает WebGL и как устроена концепция конвейера визуализации и знакомит с некоторыми библиотеками WebGL.</li>
+ <li><a href="http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html">Введение в современный OpenGL</a> - Серия хороших статей о OpenGL, написанная Joe Groff. В них дана вводная информация о OpenGL, начиная с истории возникновения и заканчивая важной концепцией графического конвейера. Весь материал сопровождается примерами с демонстрацией работы OpenGL. Если вы не знакомы с OpenGL, этот материал будет вам полезен.</li>
+</ul>
+
+<p>{{Next("Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context")}}</p>
diff --git a/files/ru/web/api/webgl_api/tutorial/index.html b/files/ru/web/api/webgl_api/tutorial/index.html
new file mode 100644
index 0000000000..6f689fa9c3
--- /dev/null
+++ b/files/ru/web/api/webgl_api/tutorial/index.html
@@ -0,0 +1,39 @@
+---
+title: WebGL tutorial
+slug: Web/API/WebGL_API/Tutorial
+tags:
+ - WebGL
+translation_of: Web/API/WebGL_API/Tutorial
+---
+<div>{{WebGLSidebar}}</div>
+
+<div class="summary">
+<p><a class="external" href="http://www.khronos.org/webgl/" title="http://www.khronos.org/webgl/">WebGL</a> позволяет использовать API, основанную на <a class="external" href="http://www.khronos.org/opengles/" title="http://www.khronos.org/opengles/">OpenGL ES</a> 2.0  для осуществления 3D рендеринга в HTML {{HTMLElement("canvas")}} в браузерах, которые его поддерживают без использования плагинов. WebGL программы состоят из программ, написанных на JavaScript, и специального кода шейдеров, который выполняется на видеокарте. WebGL элементы  могут использоваться с HTML элементами и скомпонованы с другими частями страницы или бэкграунда страницы.</p>
+</div>
+
+<p><span class="seoSummary">В этом руководстве с нуля рассказывается о том, как использовать элемент<code>&lt;canvas&gt;</code> для отрисовки WebGL. Предоставленные примеры помогут вам понять, как можно использовать WebGL, также вы сможете использовать код из примеров как сниппеты для ваших разработок.</span></p>
+
+<h2 id="Перед_тем_как_начать">Перед тем как начать</h2>
+
+<p>Использование элемента <code>&lt;canvas&gt;</code>  - это не сложно, но вы должны понимать основы <a href="/en-US/docs/Web/HTML" title="HTML">HTML</a> и <a href="/en-US/docs/Web/JavaScript" title="JavaScript">JavaScript</a>. <code>&lt;canvas&gt;</code> и WebGL не поддерживаются в некоторых старых браузерах, но поддерживаются в последних версиях всех основных. Чтобы рисовать графику на canvas нужно использовать объекты контекста JavaScript, который создает графику на лету.</p>
+
+<h2 id="В_этом_руководстве">В этом руководстве</h2>
+
+<dl>
+ <dt><a href="/en-US/docs/Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL">Начало работы с WebGL</a></dt>
+ <dd>Как настроить WebGL контекст.</dd>
+ <dt><a href="/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context">Добавление 2D контекста в WebGL контекст</a></dt>
+ <dd>Как визуализировать простые плоские фигуры используя WebGL.</dd>
+ <dt><a href="/en-US/docs/Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL">Использование шейдеров для добавления цвета в WebGL</a></dt>
+ <dd>Демонстрация того, как добавить цвет фигурам используя шейдеры.</dd>
+ <dt><a href="/en-US/docs/Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL">Анимирование объектов с WebGL</a></dt>
+ <dd>Как поворачивать и передвигать объекты для создания простых анимаций.</dd>
+ <dt><a href="/en-US/docs/Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL">Создание 3D объектов с WebGL</a></dt>
+ <dd>Как создать и анимировать 3D объект (куб).</dd>
+ <dt><a href="/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL">Использование текстур в WebGL</a></dt>
+ <dd>Как перевести текстуру на поверхность объекта.</dd>
+ <dt><a href="/en-US/docs/Web/API/WebGL_API/Tutorial/Lighting_in_WebGL">Освещение объектов в WebGL</a></dt>
+ <dd>Как симулировать эффект света в контексте WebGL.</dd>
+ <dt><a href="/en-US/docs/Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL">Анимирование текстур в WebGL</a></dt>
+ <dd>Как анимировать текстуры; здесь путем отображения Ogg видео на поверхность вращающегося куба.</dd>
+</dl>
diff --git a/files/ru/web/api/webgl_api/tutorial/lighting_in_webgl/index.html b/files/ru/web/api/webgl_api/tutorial/lighting_in_webgl/index.html
new file mode 100644
index 0000000000..57c1b21e35
--- /dev/null
+++ b/files/ru/web/api/webgl_api/tutorial/lighting_in_webgl/index.html
@@ -0,0 +1,225 @@
+---
+title: Lighting in WebGL
+slug: Web/API/WebGL_API/Tutorial/Lighting_in_WebGL
+translation_of: Web/API/WebGL_API/Tutorial/Lighting_in_WebGL
+---
+<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL", "Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL")}}</p>
+
+<p>Вам уже должно быть понятно,что у WebGL нет много "встроенного знания". Он просто выполняет две функции, которые вы написали - вершинный шейдер и фрагментный шейдер, а функции, которые рисуют сцену должны написать вы сами. Другими словами, если вы хотите добавить освещение, то вы должны рассчитать его самостоятельно. К счастью, сделать это не сложно. В этой статье мы опишем некоторые основы.</p>
+
+<h2 id="Симуляция_освещения_и_затенения_в_3D">Симуляция освещения и затенения в  3D</h2>
+
+<p>Хотя детали теории, лежащей в основе симуляции освещения в 3D-графике лежат далеко за пределами этой статьи, будет полезным немного узнать о том, как это работает. Посмотрите статью <a class="external" href="http://en.wikipedia.org/wiki/Phong_shading" title="http://en.wikipedia.org/wiki/Phong_shading">Затенение по Фонгу</a> в Википедии, чтобы получить хороший обзор наиболее часто используемых моделей освещения. А <a href="https://webglfundamentals.org/webgl/lessons/webgl-3d-lighting-point.html">в этой статье</a> вы можете посмотреть объяснение, основанное на WebGL.</p>
+
+<p>Существует три основных типа источников света:</p>
+
+<p><strong>Окружающий свет</strong> освещает всю сцену. Он не направленный и освещает все грани всех объектов одинаково, не зависимо от ориентации граней.</p>
+
+<p><strong>Направленный свет</strong> исходит из определенного направления. Этот свет приходит от настолько удаленного источника, что все фотоны летят параллельно друг другу. К примеру, солнечный свет можно считать.</p>
+
+<p><strong>Точечный свет</strong> исходит из одной точки во всех направлениях. В реальном мире многие источники освещения являются точечными, например электрическая лампочка.</p>
+
+<p>В этой статье мы упростим модель освещения и будем использовать только простой направленный и окружающий свет. Мы не будем создавать блики на поверхности объектов ({{interwiki("wikipedia", "specular highlights")}}) и точечные источники света. Вместо этого мы добавим окружающий свет и направленный свет в сцену с вращающимся кубом из <a href="/ru/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL">предыдущего примера</a>.</p>
+
+<p>Если оставить в стороне блики и точечные источники света, то останутся два пункта, которые нужно изучить по порядку:</p>
+
+<ol>
+ <li>Мы должны привязать <strong>нормаль поверхности</strong> к каждой вершине. Это вектор, который направлен перпендикулярно грани в данной вершине.</li>
+ <li>Нам нужно знать направление, в котором распространяется свет. Оно определяется <strong>вектором направления</strong>.</li>
+</ol>
+
+<p>Затем мы обновим вершинный шейдер, чтобы скорректировать цвет каждой вершины в зависимости от окружающего и направленного освещения с учетом угла падения на грань. Мы увидим, как это делается, когда посмотрим на код шейдера.</p>
+
+<h2 id="Построение_нормали_для_вершин">Построение нормали для вершин</h2>
+
+<p>Сначала нам нужно создать массив нормалей для всех вершин, из которых состоит наш куб. Это будет просто, потому что куб очень простой объект. Очевидно, что для более сложных объектов расчет нормалей будет более затратным.</p>
+
+<pre class="brush: js">  const normalBuffer = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
+
+  const vertexNormals = [
+    // Front
+     0.0,  0.0,  1.0,
+     0.0,  0.0,  1.0,
+     0.0,  0.0,  1.0,
+     0.0,  0.0,  1.0,
+
+    // Back
+     0.0,  0.0, -1.0,
+     0.0,  0.0, -1.0,
+     0.0,  0.0, -1.0,
+     0.0,  0.0, -1.0,
+
+    // Top
+     0.0,  1.0,  0.0,
+     0.0,  1.0,  0.0,
+     0.0,  1.0,  0.0,
+     0.0,  1.0,  0.0,
+
+    // Bottom
+     0.0, -1.0,  0.0,
+     0.0, -1.0,  0.0,
+     0.0, -1.0,  0.0,
+     0.0, -1.0,  0.0,
+
+    // Right
+     1.0,  0.0,  0.0,
+     1.0,  0.0,  0.0,
+     1.0,  0.0,  0.0,
+     1.0,  0.0,  0.0,
+
+    // Left
+    -1.0,  0.0,  0.0,
+    -1.0,  0.0,  0.0,
+    -1.0,  0.0,  0.0,
+    -1.0,  0.0,  0.0
+  ];
+
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexNormals),
+                gl.STATIC_DRAW);
+
+...
+
+  return {
+    position: positionBuffer,
+    normal: normalBuffer,
+    textureCoord: textureCoordBuffer,
+    indices: indexBuffer,
+  };
+
+</pre>
+
+<p>Код уже должен выглядеть узнаваемо. Мы создаем новый буфер, связываем его с рабочим буфером и записываем в него массив нормалей к вершинам при помощи <code>bufferData()</code>.</p>
+
+<p>Затем добавим в <code>drawScene()</code> код, который свяжет массив нормалей с атрибутом шейдера. Таким образом шейдер сможет получить к нему доступ:</p>
+
+<pre class="brush: js">  // Указываем WebGL как извлекать нормали из
+  // буфера нормалей в атрибут vertexNormal.
+  {
+    const numComponents = 3;
+    const type = gl.FLOAT;
+    const normalize = false;
+    const stride = 0;
+    const offset = 0;
+    gl.bindBuffer(gl.ARRAY_BUFFER, buffers.normal);
+    gl.vertexAttribPointer(
+        programInfo.attribLocations.vertexNormal,
+        numComponents,
+        type,
+        normalize,
+        stride,
+        offset);
+    gl.enableVertexAttribArray(
+        programInfo.attribLocations.vertexNormal);
+  }
+</pre>
+
+<p>В конце нужно обновить код, который строит матрицы для uniform-переменных, чтобы создать и передать в шейдер <strong>матрицу нормалей</strong>, которая используется для трансформации нормалей при расчете ориентации куба относительно направления на источник света:</p>
+
+<pre class="brush: js">  const normalMatrix = mat4.create();
+  mat4.invert(normalMatrix, modelViewMatrix);
+  mat4.transpose(normalMatrix, normalMatrix);
+
+...
+
+  gl.uniformMatrix4fv(
+      programInfo.uniformLocations.normalMatrix,
+      false,
+      normalMatrix);
+</pre>
+
+<h2 id="Обновление_шейдеров">Обновление шейдеров</h2>
+
+<p>Теперь у нас есть все данные для шейдеров. Пора обновить код самих шейдеров.</p>
+
+<h3 id="Вершинный_шейдер">Вершинный шейдер</h3>
+
+<p>Сначала обновим вершинный шейдер, чтобы он рассчитывал значение освещения для каждой вершины на основе окружающего и направленного света. Посмотрим на код:</p>
+
+<pre class="brush: html">  const vsSource = `
+    attribute vec4 aVertexPosition;
+    attribute vec3 aVertexNormal;
+    attribute vec2 aTextureCoord;
+
+    uniform mat4 uNormalMatrix;
+    uniform mat4 uModelViewMatrix;
+    uniform mat4 uProjectionMatrix;
+
+    varying highp vec2 vTextureCoord;
+    varying highp vec3 vLighting;
+
+    void main(void) {
+      gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
+      vTextureCoord = aTextureCoord;
+
+      // Применяем эффект освещения
+
+      highp vec3 ambientLight = vec3(0.3, 0.3, 0.3);
+      highp vec3 directionalLightColor = vec3(1, 1, 1);
+      highp vec3 directionalVector = normalize(vec3(0.85, 0.8, 0.75));
+
+      highp vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0);
+
+      highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0);
+      vLighting = ambientLight + (directionalLightColor * directional);
+    }
+  `;
+</pre>
+
+<p>После расчета позиции вершины мы передаем координаты текселя ({{Glossary("texel")}}), соответствующего вершине, во фрагментный шейдер, и начинаем расчет освещения вершины.</p>
+
+<p>Сначала нужно преобразовать нормаль, основываясь на текущей ориентации куба - умножив нормаль вершины на матрицу нормалей. Затем мы можем рассчитать количество света от направленного источника, которое приходит в вершину, посчитав скалярное произведение преобразованной нормали и вектора направления (направления, с которого приходит свет). Если скалярное произведение меньше нуля, то мы принимаем его за ноль, потому что количество света не может быть меньше 0.</p>
+
+<p>После расчета количества падающего направленного света мы можем посчитать финальное освещение, сложив окружающий свет и произведение количества направленного света на его цвет. В результате получается значение RGB, которое используется фрагментным шейдером для изменения цвета каждого пикселя.</p>
+
+<h3 id="Фрагментный_шейдер">Фрагментный шейдер</h3>
+
+<p>Фрагментный шейдер должен быть обновлен таким образом, чтобы он учитывал в значение освещения, рассчитанное в вершинном шейдере:</p>
+
+<pre class="brush: js">  const fsSource = `
+    varying highp vec2 vTextureCoord;
+    varying highp vec3 vLighting;
+
+    uniform sampler2D uSampler;
+
+    void main(void) {
+      highp vec4 texelColor = texture2D(uSampler, vTextureCoord);
+
+      gl_FragColor = vec4(texelColor.rgb * vLighting, texelColor.a);
+    }
+  `;
+</pre>
+
+<p>Здесь мы получаем цвет текселя, как и в предыдущем примере, но перед тем, как установить цвет фрагмента, мы умножаем цвет текселя на значение освещения, чтобы учесть влияние источников света.</p>
+
+<p>Осталось только посмотреть на определение атрибута <code>aVertexNormal</code> и uniform-переменной <code>uNormalMatrix</code>.</p>
+
+<pre class="brush: js">  const programInfo = {
+    program: shaderProgram,
+    attribLocations: {
+      vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
+      vertexNormal: gl.getAttribLocation(shaderProgram, 'aVertexNormal'),
+      textureCoord: gl.getAttribLocation(shaderProgram, 'aTextureCoord'),
+    },
+    uniformLocations: {
+      projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
+      modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
+      normalMatrix: gl.getUniformLocation(shaderProgram, 'uNormalMatrix'),
+      uSampler: gl.getUniformLocation(shaderProgram, 'uSampler'),
+    },
+  };
+</pre>
+
+<p>И это всё!</p>
+
+<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample7/index.html', 670, 510) }}</p>
+
+<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample7">Посмотреть код примера полностью</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample7/">Открыть демо в новом окне</a></p>
+
+<h2 id="Самостоятельные_упражнения">Самостоятельные упражнения</h2>
+
+<p>Очевидно, что это простой пример, показывающий базовое вершинное освещение. В более продвинутой графике вам наверняка захочется сделать попиксельное освещение.</p>
+
+<p>Также вы можете поэкспериментировать с направлением на источник света, цветами окружающего и направленного света, и т. д.</p>
+
+<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL", "Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL")}}</p>
diff --git a/files/ru/web/api/webgl_api/tutorial/using_shaders_to_apply_color_in_webgl/index.html b/files/ru/web/api/webgl_api/tutorial/using_shaders_to_apply_color_in_webgl/index.html
new file mode 100644
index 0000000000..74299aa620
--- /dev/null
+++ b/files/ru/web/api/webgl_api/tutorial/using_shaders_to_apply_color_in_webgl/index.html
@@ -0,0 +1,95 @@
+---
+title: Использование шейдеров для задания цвета в WebGL
+slug: Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL
+tags:
+ - WebGL
+translation_of: Web/API/WebGL_API/Tutorial/Using_shaders_to_apply_color_in_WebGL
+---
+<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context", "Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL")}}</p>
+
+<p>В <a href="/ru/docs/Web/WebGL/Adding_2D_content_to_a_WebGL_context" title="en/WebGL/Adding 2D content to a WebGL context">предыдущей статье</a> мы создали квадрат, следующим шагом будет добавление ему цвета. Мы можем сделать это, используя шейдеры.</p>
+
+<h2 id="Задание_цвета_вершинам">Задание цвета вершинам</h2>
+
+<p>В GL, объекты строятся с использованием наборов вершин, для каждой из которых задается положение в пространстве и цвет. По умолчанию, цвета всех остальных пикселей (и все их другие атрибуты, включая положение в пространстве) вычисляются с использованием линейной интерполяции, автоматически создавая плавный градиент. В прошлый раз наш вершинный шейдер не задавал определенных цветов вершинам, а фрагментный шейдер назначил фиксированный белый цвет каждому пикселю, поэтому квадрат целиком был отрисован белым цветом.</p>
+
+<p>Предположим, что мы хотим отрисовать градиент, в котором каждый угол квадрата разного цвета: красного, синего, зеленого и белый. Первое, что необходимо сделать - назначить эти цвета четырем вершинам. Чтобы сделать это, нам сначала необходимо создать массив цветов вершин, а затем сохранить его в WebGL буфер. Мы сделаем это, добавив следующий код в нашу функцию <code>initBuffers()</code>:</p>
+
+<pre class="brush: js"> var colors = [
+ 1.0, 1.0, 1.0, 1.0, // белый
+ 1.0, 0.0, 0.0, 1.0, // красный
+ 0.0, 1.0, 0.0, 1.0, // зеленый
+ 0.0, 0.0, 1.0, 1.0 // синий
+ ];
+
+ squareVerticesColorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
+}
+</pre>
+
+<p>Этот код начинается с создания JavaScript массива, содержащего четыре вектора, содержащих по четыре значения каждый - по одному вектору для задания цвета каждой вершине. Затем новый WebGL буфер выделяет место в памяти для хранения этих цветов и массив приводится к вещественному формату WebGL и сохраняется в буфер.</p>
+
+<p>Чтобы теперь использовать эти цвета, вершинному шейдеру необходимо обновиться, поместив соответствующий цвет из буфера цвета:</p>
+
+<pre class="brush: html"> &lt;script id="shader-vs" type="x-shader/x-vertex"&gt;
+ attribute vec3 aVertexPosition;
+ attribute vec4 aVertexColor;
+
+ uniform mat4 uMVMatrix;
+ uniform mat4 uPMatrix;
+
+      varying lowp vec4 vColor;
+
+ void main(void) {
+ gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
+        vColor = aVertexColor;
+ }
+ &lt;/script&gt;
+</pre>
+
+<p>Ключевым отличием здесь является то, что для каждой вершины, мы задаем цвет на соответствующее значение из массива цвета.</p>
+
+<h2 id="Окраска_фрагментов">Окраска фрагментов</h2>
+
+<p>Чтобы напомнить, как фрагментный шейдер выглядел ранее, ниже приведен его код:</p>
+
+<pre class="brush: html"> &lt;script id="shader-fs" type="x-shader/x-fragment"&gt;
+      void main(void) {
+        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
+      }
+    &lt;/script&gt;
+</pre>
+
+<p>Для того, чтобы подобрать интерполируемый цвет каждому пикселю, нам просто необходимо изменить его, получив значение из переменной <code>vColor</code>:</p>
+
+<pre class="brush: html"> &lt;script id="shader-fs" type="x-shader/x-fragment"&gt;
+ varying lowp vec4 vColor;
+
+ void main(void) {
+ gl_FragColor = vColor;
+ }
+ &lt;/script&gt;
+</pre>
+
+<p>Это простое изменение, но с помощью него каждый фрагмент вместо фиксированного значения получает значение интерполируемого цвета на основе его расположения относительно вершин.</p>
+
+<h2 id="Отрисовка_с_использованием_цветов">Отрисовка с использованием цветов</h2>
+
+<p>Далее, необходимо добавить код в процедуру <code>initShaders()</code> для задания значений атрибута цвета для шейдерной программы:</p>
+
+<pre class="brush: js"> vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
+ gl.enableVertexAttribArray(vertexColorAttribute);
+</pre>
+
+<p>Затем, drawScene() может быть исправлен на фактическое использование этих цветов при отрисовке квадрата:</p>
+
+<pre class="brush: js"> gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer);
+ gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
+</pre>
+
+<p>На этом этапе, вы можете посмотреть <a href="/samples/webgl/sample3/index.html" title="https://developer.mozilla.org/samples/webgl/sample3/index.html">результат работы написанного кода</a>, если используете браузер, поддерживающий WebGL. Вы увидете нечто похожее на следующий рисунок (расположенный по центру в большом черном поле):</p>
+
+<p><img alt="screenshot.png" class="default internal" src="/@api/deki/files/4081/=screenshot.png"></p>
+
+<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context", "Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL")}}</p>
diff --git a/files/ru/web/api/webgl_api/tutorial/using_textures_in_webgl/index.html b/files/ru/web/api/webgl_api/tutorial/using_textures_in_webgl/index.html
new file mode 100644
index 0000000000..adbc0ff443
--- /dev/null
+++ b/files/ru/web/api/webgl_api/tutorial/using_textures_in_webgl/index.html
@@ -0,0 +1,277 @@
+---
+title: Using textures in WebGL
+slug: Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL
+translation_of: Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL
+---
+<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL", "Web/API/WebGL_API/Tutorial/Lighting_in_WebGL")}}</p>
+
+<p>Сейчас наша программа рисует вращающийся объемный куб - давайте натянем на него текстуру вместо заливки граней одним цветом.</p>
+
+<h2 id="Загрузка_текстур">Загрузка текстур</h2>
+
+<p>Сначала нужно добавить код для загрузки текстур. В нашем случае мы будем использовать одну текстуру, натянутую на все шесть граней вращающегося куба, но этот подход может быть использован для загрузки любого количества текстур.</p>
+
+<div class="blockIndicator note">
+<p><strong>Обратите внимание:</strong> Важно помнить, что загрузка текстур следует <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS">правилам кросс-доменности</a>, что означает, что вы можете загружать текстуры только с сайтов, для которых ваш контент является CORS доверенным. См. подробности в секции "Кросс-доменные текстуры" ниже.</p>
+</div>
+
+<p>Код для загрузки текстур выглядит так::</p>
+
+<pre><code>//
+// Инициализация текстуры и загрузка изображения.
+// Когда загрузка изображения завершена - копируем его в текстуру.
+//
+function loadTexture(gl, url) {
+ const texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ // Так как изображение будет загружено из интернета,
+ // может потребоваться время для полной загрузки.
+ // Поэтому сначала мы </code>помещаем <code>в текстуру единственный пиксель, чтобы
+ // её можно было использовать сразу. После завершения загрузки
+  // изображения мы обновим текстуру.
+ const level = 0;
+ const internalFormat = gl.RGBA;
+ const width = 1;
+ const height = 1;
+ const border = 0;
+ const srcFormat = gl.RGBA;
+ const srcType = gl.UNSIGNED_BYTE;
+ const pixel = new Uint8Array([0, 0, 255, 255]); // непрозрачный синий
+ gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
+ width, height, border, srcFormat, srcType,
+ pixel);
+
+ const image = new Image();
+ image.onload = function() {
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
+ srcFormat, srcType, image);
+
+ // У WebGL1 иные требования к изображениям, имеющим размер степени 2,
+ // и к не имеющим размер степени 2, поэтому проверяем, что изображение
+  // имеет размер степени 2 в обеих измерениях.
+ if (isPowerOf2(image.width) &amp;&amp; isPowerOf2(image.height)) {
+ // Размер соответствует степени 2. Создаем MIP'ы.
+ gl.generateMipmap(gl.TEXTURE_2D);
+ } else {
+ // Размер не соответствует степени 2.
+ // Отключаем MIP'ы и устанавливаем натяжение по краям
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ }
+ };
+ image.src = url;
+
+ return texture;
+}
+
+function isPowerOf2(value) {
+ return (value &amp; (value - 1)) == 0;
+}</code></pre>
+
+<p>Функция <code>loadTexture()</code> начинается с создания объекта WebGL <code>texture</code> вызовом функции {{domxref("WebGLRenderingContext.createTexture()", "createTexture()")}}. Сначала функция создает текстуру из единственного голубого пикселя, используя {{domxref("WebGLRenderingContext.texImage2D()", "texImage2D()")}}. Таким образом текстура может быть использована сразу (как сплошной голубой цвет) при том, что загрузка изображения может занять некоторое время.</p>
+
+<p>Чтобы загрузить текстуру из файла изображения, функция создает объект <code>Image</code> и присваивает атрибуту <code>src</code> адрес, с которого мы хотим загрузить текстуру. Функция, которую мы назначили на событие <code>image.onload</code>,будет вызвана после завершения загрузки изображения. В этот момент мы вызываем {{domxref("WebGLRenderingContext.texImage2D()", "texImage2D()")}}, используя загруженное изображение как исходник для текстуры. Затем мы устанавливаем фильтрацию и натяжение, исходя из того, является ли размер изображения степенью 2 или нет.</p>
+
+<p>В WebGL1 изображения размера, не являющегося степенью 2, могут использовать только <code>NEAREST</code> или <code>LINEAR</code> фильтрацию, и для них нельзя создать mipmap. Также для таких изображений мы должны установить натяжение <code>CLAMP_TO_EDGE</code>. С другой стороны, если изображение имеет размер степени 2 по обеим осям, WebGL может производить более качественную фильтрацию, использовать mipmap и режимы натяжения <code>REPEAT</code> или <code>MIRRORED_REPEAT</code>.</p>
+
+<p>Примером повторяющейся текстуры является изображение нескольких кирпичей, которое размножается для покрытия поверхности и создания изображения кирпичной стены.</p>
+
+<p>Мипмаппинг и UV-повторение могут быть отключены с помощью {{domxref("WebGLRenderingContext.texParameter()", "texParameteri()")}}. Так вы сможете использовать текстуры с размером, не являющимся степенью 2 (NPOT - non-power-of-two), ценой отключения мипмаппинга, UV-натяжения, UV-повторения, и вам самому придется контролировать, как именно устройство будет обрабатывать текстуру.</p>
+
+<pre><code>// также разрешено gl.NEAREST вместо gl.LINEAR, но не mipmap.
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+// Не допускаем повторения по s-координате.
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+// Не допускаем повторения по t-координате.
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);</code></pre>
+
+<p>Повторим, что с этими параметрами совместимые WebGL устройства будут допускать использование текстур с любым разрешением (вплоть до максимального). Без подобной настройки WebGL потерпит неудачу при загрузке NPOT-текстур, и вернёт прозрачный черный цвет <code>rgba(0,0,0,0)</code>.</p>
+
+<p>Для загрузки изображения добавим вызов <code>loadTexture()</code> в функцию <code>main()</code>. Код можно разместить после вызова <code>initBuffers(gl)</code>.</p>
+
+<pre><code>// Загрузка текстуры
+const texture = loadTexture(gl, 'cubetexture.png');</code></pre>
+
+<h2 id="Отображение_текстуры_на_гранях">Отображение текстуры на гранях</h2>
+
+<p>Сейчас текстура загружена и готова к использованию. Но сначала мы должны установить соответствие между координатами текстуры и гранями нашего куба. Нужно заменить весь предыдущий код, который устанавливал цвета граней в <code>initBuffers()</code>.</p>
+
+<pre><code> const textureCoordBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordBuffer);
+
+ const textureCoordinates = [
+ // Front
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Back
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Top
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Bottom
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Right
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Left
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ ];
+
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates),
+ gl.STATIC_DRAW);
+
+...
+ return {
+ position: positionBuffer,
+ textureCoord: textureCoordBuffer,
+ indices: indexBuffer,
+ };</code></pre>
+
+<p>Сначала мы создаем WebGL буфер, в котором сохраняем координаты текстуры для каждой грани, затем связываем его с массивом, в который будем записывать значения.</p>
+
+<p>Массив <code>textureCoordinates</code> определяет координаты текстуры, соответствующие каждой вершине каждой грани. Заметьте, что координаты текстуры лежат в промежутке между 0.0 и 1.0. Размерность текстуры нормализуется в пределах между 0.0 и 1.0, независимо от реального размера изображения.</p>
+
+<p>После опредения массива координат текстуры, мы копируем его в буфер, и теперь WebGL имеет данные для отрисовки.</p>
+
+<h2 id="Обновление_шейдеров">Обновление шейдеров</h2>
+
+<p>Мы должны обновить шейдерную программу, чтобы она использовала текстуру, а не цвета.</p>
+
+<h3 id="Вершинный_шейдер">Вершинный шейдер</h3>
+
+<p>Заменяем вершинный шейдер, чтобы он получал координаты текстуры вместо цвета.</p>
+
+<pre><code> const vsSource = `
+ attribute vec4 aVertexPosition;
+ attribute vec2 aTextureCoord;
+
+ uniform mat4 uModelViewMatrix;
+ uniform mat4 uProjectionMatrix;
+
+ varying highp vec2 vTextureCoord;
+
+ void main(void) {
+ gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
+ vTextureCoord = aTextureCoord;
+ }
+ `;</code></pre>
+
+<p>Ключевое изменение в том, что вместо получения цвета вершины, мы получаем координаты текстуры и передаем их в вершинный шейдер, сообщая положение точки внутри текстуры, которая соответствует вершине.</p>
+
+<h3 id="Фрагментный_шейдер">Фрагментный шейдер</h3>
+
+<p>Также нужно обновить фрагментный шейдер:</p>
+
+<pre><code> const fsSource = `
+ varying highp vec2 vTextureCoord;
+
+ uniform sampler2D uSampler;
+
+ void main(void) {
+ gl_FragColor = texture2D(uSampler, vTextureCoord);
+ }
+ `;</code></pre>
+
+<p>Вместо задания цветового значения цвету фрагмента, цвет фрагмента рассчитывается из <strong>текселя</strong> (пикселя внутри текстуры), основываясь на значении <code>vTextureCoord</code>, которое интерполируется между вершинами (как ранее интерполировалось значение цвета).</p>
+
+<h3 id="Атрибуты_и_uniform-переменные">Атрибуты и uniform-переменные</h3>
+
+<p>Так как мы изменили атрибуты и добавили uniform-переменные, нам нужно получить их расположение</p>
+
+<pre><code> const programInfo = {
+ program: shaderProgram,
+ attribLocations: {
+ vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
+ textureCoord: gl.getAttribLocation(shaderProgram, 'aTextureCoord'),
+ },
+ uniformLocations: {
+ projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
+ modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
+ uSampler: gl.getUniformLocation(shaderProgram, 'uSampler'),
+ },
+ };</code></pre>
+
+<h2 id="Рисование_текстурированного_куба">Рисование текстурированного куба</h2>
+
+<p>Сделаем несколько простых изменений в функции <code>drawScene()</code>.</p>
+
+<p>Во-первых, удаляем код, который определял цветовые буферы, и заменяем его на:</p>
+
+<pre><code>// Указываем WebGL, как извлечь текстурные координаты из буффера
+{
+ const num = 2; // каждая координата состоит из 2 значений
+ const type = gl.FLOAT; // данные в буфере имеют тип 32 bit float
+ const normalize = false; // не нормализуем
+ const stride = 0; // сколько байт между одним набором данных и следующим
+ const offset = 0; // стартовая позиция в байтах внутри набора данных
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffers.textureCoord);
+ gl.vertexAttribPointer(programInfo.attribLocations.textureCoord, num, type, normalize, stride, offset);
+ gl.enableVertexAttribArray(programInfo.attribLocations.textureCoord);
+}</code></pre>
+
+<p>Затем добавляем код, который отображает текстуру на гранях, прямо перед отрисовкой:</p>
+
+<pre><code> // Указываем WebGL, что мы используем текстурный регистр 0
+ gl.activeTexture(gl.TEXTURE0);
+
+ // Связываем текстуру с регистром 0
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+
+ // Указываем шейдеру, что мы связали текстуру с текстурным регистром 0
+ gl.uniform1i(programInfo.uniformLocations.uSampler, 0);</code></pre>
+
+<p>WebGL имеет минимум 8 текстурных регистров; первый из них <code>gl.TEXTURE0</code>. Мы указываем, что хотим использовать регистр 0. Затем мы вызываем функцию {{domxref("WebGLRenderingContext.bindTexture()", "bindTexture()")}}, которая связывает текстуру с <code>TEXTURE_2D</code> регистра 0. Наконец мы сообщаем шейдеру, что для <code>uSampler</code> используется текстурный регистр 0.</p>
+
+<p>В завершение, добавляем аргумент <code>texture</code> в функцию <code>drawScene()</code>.</p>
+
+<pre><code>drawScene(gl, programInfo, buffers, texture, deltaTime);
+...
+function drawScene(gl, programInfo, buffers, texture, deltaTime) {</code></pre>
+
+<p>Сейчас вращающийся куб должен именть текстуру на гранях.</p>
+
+
+
+<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample6/index.html', 670, 510) }}</p>
+
+<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample6">Посмотреть код примера полностью</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample6/">Открыть демо в новом окне</a></p>
+
+<h2 id="Кросс-доменные_текстуры">Кросс-доменные текстуры</h2>
+
+<p>Загрузка кросс-доменных текстур контролируется правилами кросс-доменного доступа. Чтобы загрузить текстуру с другого домена, она должна быть CORS доверенной. См. детали в статье <a href="https://developer.mozilla.org/ru/docs/Web/HTTP/CORS">HTTP access control</a>.</p>
+
+<p><a href="http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/">В статье на hacks.mozilla.org</a> есть объяснение с <a href="http://people.mozilla.org/~bjacob/webgltexture-cors-js.html">примером</a>, как использовать изображения CORS для создания WebGL текстур.</p>
+
+<div class="blockIndicator note">
+<p><strong>Обратите внимание:</strong> Поддержка CORS для текстур WebGL и атрибут <code>crossOrigin</code> для элементов изображений реализованы в {{Gecko("8.0")}}.</p>
+</div>
+
+<p>Tainted (только-для-записи) 2D canvas нельзя использовать в качестве текстур WebGL. Например, 2D {{ HTMLElement("canvas") }} становится "tainted", когда на ней отрисовано кросс-доменное изображение.</p>
+
+<div class="blockIndicator note">
+<p><strong>Обратите внимание:</strong> Поддержка CORS для Canvas 2D <code>drawImage</code> реализована в  {{Gecko("9.0")}}. Это значит, что использование CORS доверенных кросс-доменных изображений больше не делает 2D canvas "tained" (только-для-записи),  и вы можете использовать такую 2D canvas как исходник для текстур WebGL.</p>
+</div>
+
+<div class="blockIndicator note">
+<p><strong>Обратите внимание:</strong> Поддрежка CORS для кросс-доменного видео и атрибут <code>crossorigin</code> для HTML-элемента {{ HTMLElement("video") }} реализованы в {{Gecko("12.0")}}.</p>
+</div>
+
+<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL", "Web/API/WebGL_API/Tutorial/Lighting_in_WebGL")}}</p>
diff --git a/files/ru/web/api/webgl_api/tutorial/создание_3d_объектов_с_помощью_webgl/index.html b/files/ru/web/api/webgl_api/tutorial/создание_3d_объектов_с_помощью_webgl/index.html
new file mode 100644
index 0000000000..b5abccbe14
--- /dev/null
+++ b/files/ru/web/api/webgl_api/tutorial/создание_3d_объектов_с_помощью_webgl/index.html
@@ -0,0 +1,131 @@
+---
+title: Создание 3D объектов с помощью WebGL
+slug: Web/API/WebGL_API/Tutorial/Создание_3D_объектов_с_помощью_WebGL
+tags:
+ - WebGL
+ - Урок
+translation_of: Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_WebGL
+---
+<p>{{WebGLSidebar("Tutorial")}} {{PreviousNext("Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL", "Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL")}}</p>
+
+<p>Давайте поместим наш квадрат в трехмерное пространство, добавив еще 5 граней, чтобы получить куб. Чтобы сделать это наиболее продуктивно, вместо рисования вершин непосредственным вызовом метода {{domxref("WebGLRenderingContext.drawArrays()", "gl.drawArrays()")}} , мы будем использовать массив вершин в виде таблицы и ссылаться на каждую вершину в этой таблице, чтобы определить положение каждой вершины грани, вызывая {{domxref("WebGLRenderingContext.drawElements()", "gl.drawElements()")}}.</p>
+
+<p>Заметим: чтобы определить каждую грань необходимо четыре вершины, но каждая вершина принадлежит трем граням. Мы можем передавать намного меньше данных, построив список всех 24-х вершин, затем ссылаться на каждую из них в этом списке по её индексу, вместо того чтобы передавать все множество вершин. Если вы удивлены, почему нам нужны 24 вершины, а не только 8, так это потому, что каждое ребро принадлежит трем граням разных цветов, и каждая отдельная вершина должна иметь конкретный отдельный цвет - поэтому мы создадим 3 копии каждой вершины трех разных цветов, по одной для каждой грани.</p>
+
+<h2 id="Определение_позиций_вершин_куба">Определение позиций вершин куба</h2>
+
+<p>Во первых, давайте построим буффер позиций вершин куба, обновив код в <code>initBuffers()</code>. Это в значительной степени то же самое как это было для квадрата, но несколько длиннее, так как здесь 24 вершины (4 с каждой стороны):</p>
+
+<pre class="brush: js">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
+];
+</pre>
+
+<h2 id="Определение_цветов_вершин">Определение цветов вершин</h2>
+
+<p>Нам также нужно построить массив цветов для каждой из 24-х вершин. Этот код начинается с определения цветов для каждой грани, затем используется цикл для составления массива все всех цветов для каждой из вершин.</p>
+
+<pre class="brush: js">var colors = [
+ [1.0, 1.0, 1.0, 1.0], // Front face: white
+ [1.0, 0.0, 0.0, 1.0], // Back face: red
+ [0.0, 1.0, 0.0, 1.0], // Top face: green
+ [0.0, 0.0, 1.0, 1.0], // Bottom face: blue
+ [1.0, 1.0, 0.0, 1.0], // Right face: yellow
+ [1.0, 0.0, 1.0, 1.0] // Left face: purple
+];
+
+var generatedColors = [];
+
+for (j=0; j&lt;6; j++) {
+ var c = colors[j];
+
+ for (var i=0; i&lt;4; i++) {
+ generatedColors = generatedColors.concat(c);
+ }
+}
+
+cubeVerticesColorBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesColorBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(generatedColors), gl.STATIC_DRAW);
+</pre>
+
+<h2 id="Определение_массива_элементов">Определение массива элементов</h2>
+
+<p>Как только массив вершин сгенерирован, нам нужно построить массив элементов.</p>
+
+<pre class="brush: js">cubeVerticesIndexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
+
+// Этот массив определяет каждую грань как два треугольника,
+// используя индексы в массиве вершин, чтобы определить позицию
+// каждого треугольника.
+
+var cubeVertexIndices = [
+ 0, 1, 2, 0, 2, 3, // front
+ 4, 5, 6, 4, 6, 7, // back
+ 8, 9, 10, 8, 10, 11, // top
+ 12, 13, 14, 12, 14, 15, // bottom
+ 16, 17, 18, 16, 18, 19, // right
+ 20, 21, 22, 20, 22, 23 // left
+];
+
+// Теперь отправим массив элементов в GL
+
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
+ new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
+</pre>
+
+<p>Массив <code>cubeVertexIndices</code> определяет каждую грань как пару треугольников, сопоставляя каждой вершине треугольника индекс в массиве вершин куба. Таким образом куб можно представить как набор из 12 треугольников.</p>
+
+<h2 id="Рисование_куба">Рисование куба</h2>
+
+<p>Далее нам нужно обновить код нашей функции <code>drawScene()</code> , чтобы рисовать, используя буффер индексов куба, добавив новые вызовы {{domxref("WebGLRenderingContext.bindBuffer()", "gl.bindBuffer()")}} и {{domxref("WebGLRenderingContext.drawElements()", "gl.drawElements()")}}:</p>
+
+<pre class="brush: js">gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
+setMatrixUniforms();
+gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
+</pre>
+
+<p>Поскольку каждая грань нашего куба состоит из двух треугольников, где 6 вершин на каждой грани, или всего 36 вершин во всем кубе, даже если многие из них дублируются. Однако, поскольку наш массив индексов состоит из целых чисел, это не чрезмерное количество данных, посылаемых для каждого кадра анимации.</p>
+
+<p>В данный момент у нас есть анимированный куб с гранями 6 разных цветов, который прыгает и вращается.</p>
+
+<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample5/index.html', 670, 510) }}</p>
+
+<p><a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample5">View the complete code</a> | <a href="http://mdn.github.io/webgl-examples/tutorial/sample5/">Open this demo on a new page</a></p>
+
+<p>{{PreviousNext("Web/API/WebGL_API/Tutorial/Animating_objects_with_WebGL", "Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL")}}</p>
diff --git a/files/ru/web/api/webgl_api/webgl_best_practices/index.html b/files/ru/web/api/webgl_api/webgl_best_practices/index.html
new file mode 100644
index 0000000000..90b595c096
--- /dev/null
+++ b/files/ru/web/api/webgl_api/webgl_best_practices/index.html
@@ -0,0 +1,46 @@
+---
+title: Лучшие практики WebGL
+slug: Web/API/WebGL_API/WebGL_best_practices
+translation_of: Web/API/WebGL_API/WebGL_best_practices
+---
+<p>{{WebGLSidebar}}</p>
+
+<p>Эта статья содержит советы и рекомендации по улучшению качества ваших WebGL приложений. Следование данным советам поможет улучшить совместимость ваших веб-приложений с большим количеством устройств и браузеров, а также увеличить их производительность.</p>
+
+<h2 id="Чего_следует_избегать">Чего следует избегать</h2>
+
+<ul>
+ <li>Убедитесь, что ваше приложение не выдает какие-либо ошибки WebGL, возвращаемые функцией <code>getError(). В Firefox при каждой ошибке (до определенного предела) или при любой другой проблеме в работе WebGL выводится JavaScript предупреждение с подробным описанием. Вам же не хочется, что бы ваше приложение выдавало множество ошибок в консоль, не так ли?</code></li>
+ <li>Не следует использовать <code>#ifdef GL_ES в шейдерах WebGL. Несмотря на то что в некоторых ранних примерах используются эти директивы, это не обязательно в том случае, если проверяемое условие всегда истинно.</code></li>
+ <li>Использование высокой точности (<code>highp</code> precision) во фрагментных шейдерах может приводить к несовместимости вашего приложения с некоторыми устаревшими мобильными устройствами. Вы можете использовать среднюю точность (<code>mediump), но помните, что это может привести к некорректному результату отрисовки из-за потери данных на большинстве мобильных устройств, причем этот некорректный результат не будет заметен на обычном компьютере. В общем, только использование высокой точности (highp) в вершинном и фрагментном шейдерах является более надежными решением, если нет возможности тщательно проверить работу шейдеров на различных платформах. В Firefox версии 11 и выше реализована функция WebGL getShaderPrecisionFormat(), которая позволяет проверить, поддерживается ли высокая точность и, более того, запросить реальную точность всех поддерживаемых квалификаторов точности. </code></li>
+</ul>
+
+<h2 id="О_чем_следует_помнить.">О чем следует помнить.</h2>
+
+<ul>
+ <li>Некоторые возможности WebGL зависят от клиента. Перед тем как задействовать ту или иную возможность, используйте функцию WebGL <code>getParameter() чтобы определить, какие возможности поддерживаются на клиенте. Например, максимально допустимый размер двухмерной текстуры можно узнать с помощью вызова webgl.getParameter(webgl.MAX_TEXTURE_SIZE). В Firefox версии 10 и выше реализован параметр webgl.min_capability_mode, позволяющий имитировать минимальные значения возможностей WebGL для проверки переносимости приложения.</code></li>
+ <li>В частности, использование текстур в вершинном шейдере возможно только если значение <code>webgl.getParameter(webgl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) больше ноля. Как правило, эта возможность не поддерживается на текущих мобильных устройствах.</code></li>
+ <li>Доступность большинства расширений WebGL зависит от клиента. Если это возможно, проектируйте приложение так, чтобы оно оставалось работоспособным даже в случае, когда используемое расширение недоступно. В Firefox версии 10 и выше есть настройка<code> webgl.disable-extensions, позволяющая сымитировать отсутствие всех расширений для проверки переносимости приложения.</code></li>
+ <li>Рендеринг в floating-point текстуру может не выполняться даже если расширение <code>OES_texture_float поддерживается. Обычно это случается на современных мобильных устройствах. Проверить эту возможность можно с помощью функции WebGL checkFramebufferStatus().</code></li>
+ <li>Вы можете выполнять отрисовку на холсте, реальные размеры которого отличается от значений, определенных в таблице стилей. При проблемах с производительностью рассмотрите возможность рендеринга в более низком разрешении. (<em>Уменьшение области рендеринга ускорит обработку пиксельных шейдеров, например, эффектов постобработки</em>, <em>однако, на скорость работы вершинных шейдеров это не повлияет.</em> <span class="forum_post_content med1" style="word-wrap: break-word;"><span class="ln_height" id="post_text_1166974"><em>прим. перев.).</em></span></span></li>
+</ul>
+
+<h2 id="Общие_советы_по_повышению_производительности">Общие советы по повышению производительности</h2>
+
+<ul>
+ <li>Все, что требует синхронизации ЦП и ГП потенциально приводит в уменьшению производительности. Поэтому избегайте в цикле отрисовки следующих вызовов функций WebGL: <code>getError()</code>, <code>readPixels()</code> и <code>finish()</code>. Вызовы функций, получающих значения, такие как <code>getParameter()</code> и <code>getUniformLocation() тоже должны рассматриваться как медленные и их значения следует сохраняться в переменных JavaScript.</code></li>
+ <li>Несколько больших операций отрисовки выполняются быстрее, чем много мелких. Если вам нужно нарисовать 1000 спрайтов, попробуйте реализовать это одним вызовом функции<code> drawArrays()</code> или <code>drawElements(). Вы также можете использовать вырожденные (плоские) треугольники для рисования нескольких объектов за один вызов drawArrays().</code></li>
+ <li>Уменьшение переключений состояний также увеличивает производительность. В частности, если есть возможность упаковать несколько изображений в одну текстуру <em>(т.н. текстурный атлас, прим. перев.)</em> и отображать требуемое изображение с помощью поправок текстурных координат, то это приведет к уменьшению переключений между текстурами, что увеличит производительность.
+ <ul>
+ <li>В некоторых редких случаях разные одноцветные изображения можно упаковать в разные цветовые каналы текстуры.</li>
+ </ul>
+ </li>
+ <li>Маленькие текстуры обрабатываются быстрее, чем большие. Используйте mipmapping для ускорения отрисовки.</li>
+ <li>Простые шейдеры выполняются быстрее, чем сложные. В частности, условия (if) замедляют работу. Операции деления и математические функции, например, <code>log() должны также рассматриваться как дорогие.</code>
+ <ul>
+ <li>Однако сегодня даже мобильные устройства обладают мощными графическими процессорами которые способны быстро обрабатывать относительно сложные шейдерные программы. Более того, шейдеры компилируются в машинные коды, которые могут быть оптимизированы под конкретный процессор. Может оказаться, что дорогой вызов функции может быть скомпилирован в несколько (или даже в одну) процессорную инструкцию. Частично это справедливо для функций {{Glossary("GLSL")}}, выполняющих операции над векторами, таких как <code>normalize()</code>, <code>dot()</code> и <code>mix()</code>. Лучшим советом будет использовать встроенные функции, нежели пытаться реализовать, например, собственную версию скалярного произведения или линейной интерполяции, которые будут скомпилированы в набор сложных и неоптимальных инструкций процессора.</li>
+ </ul>
+ </li>
+ <li>Выносите как можно больше операций в вершинный шейдер. Из-за того, что в процессе отрисовки фрагментные шейдеры выполняются гораздо чаще, чем вершинные, любые вычисления, которые можно выполнить с вершинами и интерполировать между пикселями, будут работать быстрее (интерполяция будет "бесплатна", т.к. это этап конвеера WebGL). Например, простая анимация текстурированной поверхности может быть реализована с помощью преобразований текстурных координат (простейший вариант - прибавлять значение uniform-вектора к attribute-вектору текстурных координат). Если результат будет визуально приемлем, то такой вариант будет работать быстрее, чем реализация во фрагментном шейдере.</li>
+ <li>Всегда задействуйте атрибут вершин c нулевым индексом. Отрисовка с неактивным вершинным атрибутом с индексом 0 вынуждает браузер выполнять сложную эмуляцию настольного OpenGL (например, как на Mac OSX). Вызывайте функцию <code>bindAttribLocation()</code> чтобы вершинный атрибут использовал нулевой индекс и активируйте сам атрибут с помощью функции<code> enableVertexAttribArray().</code></li>
+</ul>