МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ ЛУГАНСКОЙ НАРОДНОЙ РЕСПУБЛИКИ ГОСУДАРСТВЕННОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ ЛУГАНСКОЙ НАРОДНОЙ РЕСПУБЛИКИ «ЛУГАНСКИЙ НАЦИОНАЛЬНЫЙ УНИВЕРСИТЕТ ИМЕНИ ВЛАДИМИРА ДАЛЯ» Факультет компьютерных систем и информационных технологий Кафедра информатики и программной инженерии Индивидуальная работа Прорисовка, текстурирование и анимация 3D модели «Молоток» на WebGL. (название темы индивидуальной работы) Студент-исполнитель Озеров В.П. (Ф.И.О., подпись) 2 курс ИТ-692____________________ (курс, группа) Приняли: Ромашова О. Н. __________________ (Ф.И.О., подпись) Чигрина А. Н. ___________________ (Ф.И.О., подпись) Оценка: ___________________ Луганск 2020 2 МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ ЛУГАНСКОЙ НАРОДНОЙ РЕСПУБЛИКИ ГОСУДАРСТВЕННОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ ЛУГАНСКОЙ НАРОДНОЙ РЕСПУБЛИКИ «ЛУГАНСКИЙ НАЦИОНАЛЬНЫЙ УНИВЕРСИТЕТ ИМЕНИ ВЛАДИМИРА ДАЛЯ» Факультет компьютерных систем и информационных технологий Кафедра информатики и программной инженерии Направление подготовки: 09.03.04 – Программная инженерия (шифр и название) ЗАДАНИЕ НА ИНДИВИДУАЛЬНУЮ РАБОТУ студенту Озерову Вячеславу Павловичу 1. Тема работы: «Прорисовка, текстурирование и анимация 3D модели «Молоток» на WebGL.»; 2. Руководитель работы: Чигрина Анастасия Николаевна, Ромашова Ольга Николаевна, старший преподаватель; 3. Срок представления студентом работы: 28.12.2020; 4. Содержание индивидуальной работы: а) Реферат б) Введение в) Ход работы г) Вывод д) Литература 5. Дата выдачи задания: 02.12.2020. 3 РЕФЕРАТ Работа содержит: 8 страниц основного текста, 28 страниц приложений, 6 рисунков, 4 использованных источников. Работа состоит из трех разделов, введения, выводов и приложений. Объектом исследования данной работы является WebGl. Предметом исследования является молоток. Целью работы является создание 3D модели молотка на WebGl. Результатом работы является 3D модель молотка. Ключевые слова: WEBGL, молоток. 4 СОДЕРЖАНИЕ ВВЕДЕНИЕ............................................................................................................. 5 РАЗДЕЛ 1 ................................................................................................................ 6 ДЕТАЛИ ДЛЯ ОБЪЕКТА ................................................................................... 6 БИБЛИОТЕКА GL.MATRIX.JS ..................................................................... 6 glMatrix предназначен для выполнения векторных и матричных операций. Вручную настраивая каждую функцию для максимальной производительности и поощряя эффективные шаблоны использования с помощью соглашений API моделирование объекта ................................ 6 РАЗДЕЛ 2 ................................................................................................................ 7 ОСВЕЩЕНИЕ И АНИМАЦИЯ ......................................................................... 7 ОСВЕЩЕНИЕ .................................................................................................... 7 АНИМАЦИЯ ..................................................................................................... 10 СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ ..................................... 13 ПРИЛОЖЕНИЯ .................................................................................................. 14 5 ВВЕДЕНИЕ WebGL представляет собой технологию, базирующуюся на OpenGL ES 2.0 и предназначенную для рисования и отображения интерактивной 2D- и 3Dграфики в веб-браузерах. При этом для работы с данной технологией не требуются сторонние плагины или библиотеки. Вся работа веб-приложений с использованием WebGL основана на коде JavaScript, а некоторые элементы кода - шейдеры могут выполняться непосредственно на графических процессорах на видеокартах, благодаря чему разработчики могут получить доступ к дополнительным ресурсам компьютера, увеличить быстродействие. Таким образом, для создания приложений разработчики могу использовать стандартные для веб-среды технологии HTML/CSS/JavaScript и при этом также применять аппаратное ускорение графики. В проекте будет рассмотрена задача по моделированию различных объектов, а также добавление анимации и освещения. 6 РАЗДЕЛ 1 ДЕТАЛИ ДЛЯ ОБЪЕКТА БИБЛИОТЕКА GL.MATRIX.JS glMatrix предназначен для выполнения векторных и матричных операций. Вручную настраивая каждую функцию для максимальной производительности и поощряя эффективные шаблоны использования с помощью соглашений API моделирование объекта Объект «Молоток» можно создать, с использованием библиотеки glMatrix, но чистый объект создается с помощью геометрии двух перпендикулярно расположенных друг к другу параллелограмма. Полный html - код написания модели изложен в Приложении. Получаем готовый Объект «Молоток». (Рис 1.1) Рис 1.1 – 3D модель молотка 7 РАЗДЕЛ 2 ОСВЕЩЕНИЕ И АНИМАЦИЯ ОСВЕЩЕНИЕ Освещение сделано с помощью библиотеки glMatrix; Имеет такой вид в коде. // получаем вектор направления света vec3 lightDirection = normalize(uLightPosition - vertexPositionEye3); // получаем нормаль vec3 normal = normalize(uNMatrix * aVertexNormal); // получаем скалярное произведение векторов нормали и направления света float diffuseLightDot = max(dot(normal, lightDirection), 0.0); // получаем вектор отраженного луча и нормализуем его vec3 reflectionVector = normalize(reflect(-lightDirection, normal)); float specularLightDot = max(dot(reflectionVector, viewVectorEye), 0.0); float specularLightParam = pow(specularLightDot, shininess); // отраженный свет равен сумме фонового, диффузного и зеркального отражений света vLightWeighting = (uAmbientMaterialColor * uAmbientLightColor + uDiffuseMaterialColor * uDiffuseLightColor * uSpecularMaterialColor * uSpecularLightColor * diffuseLightDot + specularLightParam); gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 21.0); vTextureCoords = vec2(aVertexPosition.x+0.5,aVertexPosition.y+0.5); 8 Есть возможность менять положение источника света объекта вручную с выбора значения осей x, y, z,(Рис 2.1) Рис 2.1 Источник света можно расположить в любом месте модели по X Y Z. (Рис 2.2) Рис 2.2 – источник света, расположенный с верху объекта 9 Либо поменять освещение с помощью готовых предустановок. Для этого всего лишь требуется выбрать значение в меню intensive. (Рис 2.3, 60% освещение) Рис 2.3 10 АНИМАЦИЯ Для того, чтобы анимировать наш объект, требуется создать функции, которые будут управлять моделью. Управлять объектом мы будем с помощью стрелочек клавиатуры. А с помощью клавиш w s изменять масштаб объекта. Часть кода отвечающая за это: function handleKeyDown(e){ switch(e.keyCode) { case 39: // стрелка вправо yAngle+=0.1; break; case 37: // стрелка влево yAngle-=0.1; break; case 40: // стрелка вниз xAngle+=0.1; break; case 38: // стрелка вверх xAngle-=0.1; break; case 87: // клавиша w zTranslation+=step*scale; break; case 83: // клавиша s zTranslation-=step; break; 11 рис. 2.4(вид сверху) рис. 2.4 рис. 2.5(вид сбоку) рис. 2.5 12 рис. 2.6(приближённый объект) Рис. 2.6 13 СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ 1. Лекции. 2. https://webglfundamentals.org/webgl/lessons/ru/webgl-3d-geometrylathe.html 3. https://developer.mozilla.org/enUS/docs/Web/API/WebGL_API/Tutorial/Creating_3D_objects_using_W ebGL 4. Онлайн книга по WebGL (https://metanit.com/web/webgl/) 14 ПРИЛОЖЕНИЯ <!DOCTYPE html> <html> <head> <title>3D in WebGL!</title> <meta charset="utf-8" /> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <canvas id="canvas3D" width="1000" height="600">Ваш браузер не поддерживает элемент canvas</canvas> <div class="menu"> <label>setLightOX:<select id="setLightOX"> <option value="0">0</option> <option value="1">1</option> <option value="3">3</option> <option value="5">5</option> <option value="10">10</option> <option value="30">30</option> 15 </select></label> <label>setLightOY:<select id="setLightOY"> <option value="0">0</option> <option value="1">1</option> <option value="3">3</option> <option value="5">5</option> <option value="10">10</option> <option value="30">30</option> </select></label> <label>setLightOZ:<select id="setLightOZ"> <option value="0">0</option> <option value="1">1</option> <option value="3">3</option> <option value="5">5</option> <option value="10">10</option> 16 <option value="30">30</option> </select></label> <label>intensive:<select id="intensive"> <option value="0.1">5%</option> <option value="0.5">20%</option> <option value="1">40%</option> <option value="2">60%</option> <option value="3">80%</option> <option value="4">100%</option> </select></label> <label>scale:<select id="scale"> <option value="1">100%</option> <option value="1.5">150%</option> <option value="0.75">75%</option> <option value="0.5">50%</option> 17 <option value="0.25">25%</option> </select></label> </div> <script type="text/javascript" src="gl-matrix-min.js"></script> <script id="shader-vs" type="x-shader/x-vertex"> attribute vec3 aVertexPosition; attribute vec3 aVertexNormal; varying vec2 vTextureCoords; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; uniform mat3 uNMatrix; uniform vec3 uLightPosition; uniform vec3 uAmbientLightColor; uniform vec3 uDiffuseLightColor; uniform vec3 uSpecularLightColor; uniform vec3 uAmbientMaterialColor; uniform vec3 uDiffuseMaterialColor; uniform vec3 uSpecularMaterialColor; varying vec3 vLightWeighting; const float shininess = 16.0; 18 void main() { // установка позиции наблюдателя сцены vec4 vertexPositionEye4 = uMVMatrix * vec4(aVertexPosition, 1.0); vec3 vertexPositionEye3 = vertexPositionEye4.xyz / vertexPositionEye4.w; // получаем вектор направления света vec3 lightDirection = normalize(uLightPosition - vertexPositionEye3); // получаем нормаль vec3 normal = normalize(uNMatrix * aVertexNormal); // получаем скалярное произведение векторов нормали и направления света float diffuseLightDot = max(dot(normal, lightDirection), 0.0); // получаем вектор отраженного луча и нормализуем его vec3 reflectionVector = normalize(reflect(-lightDirection, normal)); // установка вектора камеры vec3 viewVectorEye = -normalize(vertexPositionEye3); float specularLightDot = max(dot(reflectionVector, viewVectorEye), 0.0); float specularLightParam = pow(specularLightDot, shininess); // отраженный свет равен сумме фонового, диффузного и зеркального отражений света vLightWeighting = (uAmbientMaterialColor * uAmbientLightColor + 19 uDiffuseMaterialColor * uDiffuseLightColor * uSpecularMaterialColor * uSpecularLightColor * diffuseLightDot + specularLightParam); gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 21.0); vTextureCoords = vec2(aVertexPosition.x+0.5,aVertexPosition.y+0.5); } </script> <script id="shader-fs" type="x-shader/x-fragment"> precision mediump float; precision highp float; uniform sampler2D uSampler; varying vec2 vTextureCoords; varying vec3 vLightWeighting; void main() { gl_FragColor = texture2D(uSampler, vTextureCoords) vec4(vLightWeighting.rgb, 1); //gl_FragColor = vec4(vLightWeighting.rgb, 1); // gl_FragColor = vec4(1.0, 0.5, 0.0, 1); } </script> <script type="text/javascript"> + 20 var texture; // переменная для хранения текстуры var gl; var shaderProgram; var wallVertexBuffer; var wallIndexBuffer; var roofVertexBuffer; var vertexBuffer; var roofIndexBuffer; var vertexNormalBuffer; var RoofvertexNormalBuffer var yAngle = 2.0;//угол вращения в радианах вокруг оси Y var zTranslation=-2.0; // смещение по оси Z var xTranslation=0.0; var yTranslation=0.0; var xAngle = 0.1; // угол вращения в радианах вокруг оси Х var zAngle = 0.1; // угол вращения в радианах вокруг оси Z var step= 0.1; var mvMatrix = mat4.create(); // матрица вида модели var pMatrix = mat4.create(); // матрица проекции var nMatrix = mat3.create(); // матрица нормалей // установка шейдеров function initShaders() { var fragmentShader = getShader(gl.FRAGMENT_SHADER, 'shaderfs'); var vertexShader = getShader(gl.VERTEX_SHADER, 'shader-vs'); shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, vertexShader); 21 gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { alert("Не удалсь установить шейдеры"); } gl.useProgram(shaderProgram); shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); // атрибут нормали shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal"); gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute); // настройка параметров uniform матриц для передачи в шейдер shaderProgram.MVMatrix = gl.getUniformLocation(shaderProgram, "uMVMatrix"); shaderProgram.ProjMatrix = gl.getUniformLocation(shaderProgram, "uPMatrix"); shaderProgram.NormalMatrix = gl.getUniformLocation(shaderProgram, "uNMatrix"); // настройка переменных uniform освещения для передачи в шейдер 22 // позиция источника света shaderProgram.uniformLightPosition = gl.getUniformLocation(shaderProgram, "uLightPosition"); // фоновое отражение света shaderProgram.uniformAmbientLightColor = gl.getUniformLocation(shaderProgram, "uAmbientLightColor"); // диффузное отражение света shaderProgram.uniformDiffuseLightColor = gl.getUniformLocation(shaderProgram, "uDiffuseLightColor"); // зеркальное отражение света shaderProgram.uniformSpecularLightColor = gl.getUniformLocation(shaderProgram, "uSpecularLightColor"); shaderProgram.uniformAmbientMaterialColor = gl.getUniformLocation(shaderProgram, "uAmbientMaterialColor"); shaderProgram.uniformDiffuseMaterialColor = gl.getUniformLocation(shaderProgram, "uDiffuseMaterialColor"); shaderProgram.uniformSpecularMaterialColor = gl.getUniformLocation(shaderProgram, "uSpecularMaterialColor"); } // настройка цветов освещения function setupLights() { var OX = document.getElementById("setLightOX").value; var OY = document.getElementById("setLightOY").value; var OZ = document.getElementById("setLightOZ").value; var intensive= document.getElementById("intensive").value; gl.uniform3fv(shaderProgram.uniformLightPosition, [OX, OY, OZ]); gl.uniform3fv(shaderProgram.uniformAmbientLightColor, [0.0, 0.2, 0.5]);//wdtn vjltkb 23 gl.uniform3fv(shaderProgram.uniformDiffuseLightColor, [intensive, intensive, intensive]); gl.uniform3fv(shaderProgram.uniformSpecularLightColor, [2.0, 1.0, 1.0]); } // настройка цветов освещения function setupLights() { var OX = document.getElementById("setLightOX").value; var OY = document.getElementById("setLightOY").value; var OZ = document.getElementById("setLightOZ").value; var intensive= document.getElementById("intensive").value; gl.uniform3fv(shaderProgram.uniformLightPosition, [OX, OY, OZ]); gl.uniform3fv(shaderProgram.uniformAmbientLightColor, [0.0, 0.2, 0.5]);//wdtn vjltkb gl.uniform3fv(shaderProgram.uniformDiffuseLightColor, [intensive, intensive, intensive]); gl.uniform3fv(shaderProgram.uniformSpecularLightColor, [2.0, 1.0, 1.0]); } function setupScale() { var OX = document.getElementById("setLightOX").value; var OY = document.getElementById("setLightOY").value; var OZ = document.getElementById("setLightOZ").value; var intensive= document.getElementById("intensive").value; gl.uniform3fv(shaderProgram.uniformLightPosition, [OX, OY, OZ]); gl.uniform3fv(shaderProgram.uniformAmbientLightColor, [0.0, 0.2, 0.5]);//wdtn vjltkb 24 gl.uniform3fv(shaderProgram.uniformDiffuseLightColor, [intensive, intensive, intensive]); gl.uniform3fv(shaderProgram.uniformSpecularLightColor, [2.0, 1.0, 1.0]); } // установка материалов function setupMaterials() { gl.uniform3fv(shaderProgram.uniformAmbientMaterialColor, [0.0, 0.0, 0.0]); gl.uniform3fv(shaderProgram.uniformDiffuseMaterialColor, [0.7, 0.7, 0.7]); gl.uniform3fv(shaderProgram.uniformSpecularMaterialColor, [1.0, 1.0, 1.0]); } function setMatrixUniforms(){ gl.uniformMatrix4fv(shaderProgram.ProjMatrix,false, pMatrix); gl.uniformMatrix4fv(shaderProgram.MVMatrix, false, mvMatrix); gl.uniformMatrix3fv(shaderProgram.NormalMatrix, false, nMatrix); } // Функция создания шейдера function getShader(type,id) { var source = document.getElementById(id).innerHTML; var shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 25 alert("Ошибка компиляции gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } function initWallBuffers() { var vertices =[ // первая колонна // лицевая часть -0.1, -0.5, 0.2, -0.1, 0.5, 0.2, 0.13, 0.5, 0.2, 0.13, -0.5, 0.2, // задняя часть -0.1, -0.5, 0.1, -0.1, 0.5, 0.1, 0.13, 0.5, 0.1, 0.13, -0.5, 0.1, // левая боковая часть -0.1, -0.5, 0.2, -0.1, 0.5, 0.2, -0.1, 0.5, 0.1, -0.1, -0.5, 0.1, // правая боковая часть шейдера: " + 26 0.13, -0.5, 0.2, 0.13, 0.5, 0.2, 0.13, 0.5, 0.1, 0.13, -0.5, 0.1, ]; var indices = [ // лицевая часть 0, 1, 2, 2, 3, 0, // задняя часть 4, 5, 6, 6, 7, 4, //левая боковая часть 8, 9, 10, 10, 11, 8, // правая боковая часть 12, 13, 14, 14, 15, 12, // вторая колонна // лицевая часть 16, 17, 18, 18, 19, 16, // задняя часть 20, 21 ,22, 22, 23, 20, //левая боковая часть 24, 25, 26, 26, 27, 24, // правая боковая часть 28, 29, 30, 27 30, 31, 28, //третья колонна // лицевая часть 32, 33, 34, 34, 35, 32, // // задняя часть 36, 37, 38, 38, 39, 36, // //левая боковая часть 40, 41, 42, 42, 43, 40, // // правая боковая часть 44, 45, 46, 46, 47, 44, // четвертая колонна // лицевая часть 48, 49, 50, 50, 51, 48, // задняя часть 52, 53, 54, 54, 55, 52, //левая боковая часть 56, 57, 58, 58, 59, 56, // правая боковая часть 60, 61, 62, 62, 63, 60 28 ]; wallVertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, wallVertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); wallVertexBuffer.itemSize = 3; wallIndexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, wallIndexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, Uint16Array(indices), gl.STATIC_DRAW); wallIndexBuffer.numberOfItems = indices.length; var normals = [ // Лицевая сторона 0.0, 0.0, 1.0, //v0 0.0, 0.0, 1.0, //v1 0.0, 0.0, 1.0, //v2 0.0, 0.0, 1.0, //v3 // Задняя сторона 0.0, 0.0, -1.0, //v4 0.0, 0.0, -1.0, //v5 0.0, 0.0, -1.0, //v6 0.0, 0.0, -1.0, //v7 // Левая боковая сторона -1.0, 0.0, 0.0, //v8 -1.0, 0.0, 0.0, //v9 new 29 -1.0, 0.0, 0.0, //v10 -1.0, 0.0, 0.0, //v11 // Правая боковая сторона 1.0, 0.0, 0.0, //v12 1.0, 0.0, 0.0, //v13 1.0, 0.0, 0.0, //v14 1.0, 0.0, 0.0, //v15 // Лицевая сторона 0.0, 0.0, 1.0, //v0 0.0, 0.0, 1.0, //v1 0.0, 0.0, 1.0, //v2 0.0, 0.0, 1.0, //v3 // Задняя сторона 0.0, 0.0, -1.0, //v4 0.0, 0.0, -1.0, //v5 0.0, 0.0, -1.0, //v6 0.0, 0.0, -1.0, //v7 // Левая боковая сторона -1.0, 0.0, 0.0, //v8 -1.0, 0.0, 0.0, //v9 -1.0, 0.0, 0.0, //v10 -1.0, 0.0, 0.0, //v11 // Правая боковая сторона 1.0, 0.0, 0.0, //v12 1.0, 0.0, 0.0, //v13 30 1.0, 0.0, 0.0, //v14 1.0, 0.0, 0.0, //v15 // Лицевая сторона 0.0, 0.0, 1.0, //v0 0.0, 0.0, 1.0, //v1 0.0, 0.0, 1.0, //v2 0.0, 0.0, 1.0, //v3 // Задняя сторона 0.0, 0.0, -1.0, //v4 0.0, 0.0, -1.0, //v5 0.0, 0.0, -1.0, //v6 0.0, 0.0, -1.0, //v7 // Левая боковая сторона -1.0, 0.0, 0.0, //v8 -1.0, 0.0, 0.0, //v9 -1.0, 0.0, 0.0, //v10 -1.0, 0.0, 0.0, //v11 // Правая боковая сторона 1.0, 0.0, 0.0, //v12 1.0, 0.0, 0.0, //v13 1.0, 0.0, 0.0, //v14 1.0, 0.0, 0.0, //v15 // Лицевая сторона 0.0, 0.0, 1.0, //v0 0.0, 0.0, 1.0, //v1 31 0.0, 0.0, 1.0, //v2 0.0, 0.0, 1.0, //v3 // Задняя сторона 0.0, 0.0, -1.0, //v4 0.0, 0.0, -1.0, //v5 0.0, 0.0, -1.0, //v6 0.0, 0.0, -1.0, //v7 // Левая боковая сторона -1.0, 0.0, 0.0, //v8 -1.0, 0.0, 0.0, //v9 -1.0, 0.0, 0.0, //v10 -1.0, 0.0, 0.0, //v11 // Правая боковая сторона 1.0, 0.0, 0.0, //v12 1.0, 0.0, 0.0, //v13 1.0, 0.0, 0.0, //v14 1.0, 0.0, 0.0, //v15 ]; // Создаем буфер нормалей куба vertexNormalBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexNormalBuffer); gl.bufferData(gl.ARRAY_BUFFER, gl.STATIC_DRAW); vertexNormalBuffer.itemSize = 3; } new Float32Array(normals), 32 function initRoofBuffers() { var vertices =[ // лицевая часть -0.3, 0.5, 0.3, -0.3, 0.7, 0.3, 0.3, 0.7, 0.3, 0.3, 0.5, 0.3, // задняя часть -0.3, 0.5, 0.0, -0.3, 0.7, 0.0, 0.3, 0.7, 0.0, 0.3, 0.5, 0.0, // левая боковая часть -0.3, 0.5, 0.3, -0.3, 0.7, 0.3, -0.3, 0.7, 0.0, -0.3, 0.5, 0.0, // правая боковая часть 0.3, 0.5, 0.3, 0.3, 0.7, 0.3, 0.3, 0.7, 0.0, 0.3, 0.5, 0.0, // низ -0.3, 0.5, 0.3, -0.3, 0.5, 0.0, 0.3, 0.5, 0.0, 0.3, 0.5, 0.3, // верх -0.3, 0.7, 0.3, 33 -0.3, 0.7, 0.0, 0.3, 0.7, 0.0, 0.3, 0.7, 0.3, ]; var indices = [ 0, 1, 2, 2, 3, 0, // задняя часть 4, 5, 6, 6, 7, 4, //левая боковая часть 8, 9, 10, 10, 11, 8, // правая боковая часть 12, 13, 14, 14, 15, 12, // низ 16, 17, 18, 18, 19, 16, // верх 20, 21, 22, 22, 23, 20 ]; roofVertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, roofVertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, gl.STATIC_DRAW); roofVertexBuffer.itemSize = 3; new Float32Array(vertices), 34 vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); vertexBuffer.itemSize = 3; roofIndexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, roofIndexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); roofIndexBuffer.numberOfItems = indices.length; var Roofnormals = []; for (var i=0; i<6; i++) { Roofnormals.push(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0); RoofvertexNormalBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, RoofvertexNormalBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(Roofnormals), gl.STATIC_DRAW); RoofvertexNormalBuffer.itemSize = 3; var indices = [0, 1, 2, 2, 3, 0]; indexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, Uint16Array(indices), gl.STATIC_DRAW); indexBuffer.numberOfItems = indices.length; } } new 35 function wallDraw() { gl.bindBuffer(gl.ARRAY_BUFFER, wallVertexBuffer); gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, wallVertexBuffer.itemSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, vertexNormalBuffer); gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, vertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0); gl.enable(gl.DEPTH_TEST); gl.drawElements(gl.TRIANGLES, wallIndexBuffer.numberOfItems, gl.UNSIGNED_SHORT,0); } function roofDraw() { gl.bindBuffer(gl.ARRAY_BUFFER, roofVertexBuffer); gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, roofVertexBuffer.itemSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, RoofvertexNormalBuffer); gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, RoofvertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0); gl.enable(gl.DEPTH_TEST); 36 gl.drawElements(gl.TRIANGLES, roofIndexBuffer.numberOfItems, gl.UNSIGNED_SHORT,0); } function draw() { gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0); gl.drawElements(gl.TRIANGLES, indexBuffer.numberOfItems, gl.UNSIGNED_SHORT,0); } function setupWebGL() { gl.clearColor(0.0, 1.0, 1.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT || gl.DEPTH_BUFFER_BIT); scale = document.getElementById("scale").value; gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); mat4.perspective(pMatrix, 1.04, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0); mat4.identity(mvMatrix); mat4.translate(mvMatrix,mvMatrix,[xTranslation, zTranslation]); mat4.rotateX(mvMatrix,mvMatrix, xAngle); mat4.rotateY(mvMatrix,mvMatrix, yAngle); mat4.rotateZ(mvMatrix,mvMatrix, zAngle); yTranslation, 37 mat3.normalFromMat4(nMatrix, mvMatrix); } window.onload=function(){ var canvas = document.getElementById("canvas3D"); try { gl = canvas.getContext("webgl") canvas.getContext("experimental-webgl"); } catch(e) {} if (!gl) { alert("Ваш браузер не поддерживает WebGL"); } if(gl){ document.addEventListener('keydown', handleKeyDown, false); gl.viewportWidth = canvas.width; gl.viewportHeight = canvas.height; initShaders(); initRoofBuffers(); initWallBuffers(); setupMaterials(); setupLights(); setTextures(); (function animloop(){ setupWebGL(); setMatrixUniforms(); || 38 setupLights(); wallDraw(); roofDraw(); requestAnimFrame(animloop, canvas); })(); } } function setTextures() { console.log("fff") texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); var image = new Image(); image.onload = function () { handleTextureLoaded(image, texture); setupWebGL(); draw(); } image.src = "123.png"; shaderProgram.samplerUniform gl.getUniformLocation(shaderProgram, "uSampler"); gl.uniform1i(shaderProgram.samplerUniform, 0); } function handleTextureLoaded(image, texture) { = 39 gl.bindTexture(gl.TEXTURE_2D, texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); } function handleTextureLoaded(image, texture) { gl.bindTexture(gl.TEXTURE_2D, texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.NEAREST); } function handleKeyDown(e){ switch(e.keyCode) { case 39: // стрелка вправо yAngle+=0.1; break; case 37: // стрелка влево yAngle-=0.1; gl.TEXTURE_MIN_FILTER, 40 break; case 40: // стрелка вниз xAngle+=0.1; break; case 38: // стрелка вверх xAngle-=0.1; break; case 188: // клавиша < zAngle+=0.1; break; case 190: // клавиша > zAngle-=0.1; break; case 87: // клавиша w zTranslation+=step*scale; break; case 83: // клавиша s zTranslation-=step; break; case 65: // клавиша a xTranslation+=step; break; case 68: // клавиша d xTranslation-=step; break; case 81: // клавиша q yTranslation+=step; break; case 69: // клавиша e yTranslation-=step; 41 break; } } window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame window.msRequestAnimationFrame || || function(callback, element) { return window.setTimeout(callback, 1000/60); }; })(); </script> </body> </html> 42