From bb04680cdee142847e0d48e1ef934149f76a07ff Mon Sep 17 00:00:00 2001 From: Syndamia Date: Thu, 27 Oct 2022 21:18:50 +0300 Subject: [WGL/H03] Implemented very roughly general shape generation --- .../Homework 03 - The wall/Homework.html | 135 +++++++ .../Homework 03 - The wall/webgl-fmi.js | 434 +++++++++++++++++++++ 2 files changed, 569 insertions(+) create mode 100644 Year 2/Computer Graphics with WebGL/Homework 03 - The wall/Homework.html create mode 100644 Year 2/Computer Graphics with WebGL/Homework 03 - The wall/webgl-fmi.js diff --git a/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/Homework.html b/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/Homework.html new file mode 100644 index 0000000..9fe1d56 --- /dev/null +++ b/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/Homework.html @@ -0,0 +1,135 @@ + + + + + Стената + + + + + + + + + + + +

Стената

+ + + + + Искаме canvas, но няма! + + diff --git a/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/webgl-fmi.js b/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/webgl-fmi.js new file mode 100644 index 0000000..0009854 --- /dev/null +++ b/Year 2/Computer Graphics with WebGL/Homework 03 - The wall/webgl-fmi.js @@ -0,0 +1,434 @@ +// Библиотека WebGL-FMI v0.07.01 +// +// Работа с контексти и шейдъри +// getContext(id) +// getShader(id,type) +// getProgram(idv,idf) +// +// Математически функции +// random(a,b) +// radians(degrees) +// +// Работа с вектори +// unitVector(x) +// vectorProduct(x,y) +// scalarProduct(x,y) +// vectorPoints(x,y) +// +// Трансформации с матрици +// unitMatrix(); +// translateMatrix(v) +// scaleMatrix(v) +// xRotateMatrix(a) +// yRotateMatrix(a) +// zRotateMatrix(a) +// rotateMatrix(a,v) +// +// Трансформации със съставни матрици +// identity() +// translate(v) +// scale(v) +// xRotate(a) +// yRotate(a) +// zRotate(a) +// useMatrix() +// +// Проектиране с матрици +// viewMatrix (eye, focus, up) +// orthoMatrix(width, height, near, far) +// perspMatrix(angle, aspect, near, far) +// + + +var gl; // глобален WebGL контекст +var glprog; // глобална GLSL програма +var glmat; // глобална матрица на модела +var glmatnew; // true, ако матрицата е променена, но не е подадена на шейдъра + + +// брой байтове в един WebGL FLOAT (трябва да са 4 байта) +var FLOATS = Float32Array.BYTES_PER_ELEMENT; + + +// връща WebGL контекст, свързан с HTML елемент с даден id +function getContext(id) +{ + var canvas = document.getElementById(id); + if (!canvas) + { + alert("Искаме canvas с id=\""+id+"\", а няма!"); + return null; + } + + var context = canvas.getContext("webgl"); + if (!context) + { + context = canvas.getContext("experimental-webgl"); + } + + if (!context) + { + alert("Искаме WebGL контекст, а няма!"); + } + + return context; +} + + +// връща компилиран шейдър +function getShader(id,type) +{ + var source = document.getElementById(id).text; + var shader = gl.createShader(type); + + gl.shaderSource(shader,source); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader,gl.COMPILE_STATUS)) + { + alert(gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +} + + +// връща готова програма +function getProgram(idv,idf) +{ + var vShader = getShader(idv,gl.VERTEX_SHADER); + var fShader = getShader(idf,gl.FRAGMENT_SHADER); + + if (!vShader || !fShader) {return null;} + + var shaderProgram = gl.createProgram(); + gl.attachShader(shaderProgram,vShader); + gl.attachShader(shaderProgram,fShader); + gl.linkProgram(shaderProgram); + + if (!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)) + { + alert(gl.getProgramInfoLog(shaderProgram)); + return null; + } + + gl.useProgram(shaderProgram); + return shaderProgram; +} + + +// случайно дробно число в интервал +function random(a,b) +{ + return a+(b-a)*Math.random(); +} + + +// преобразува градуси в радиани +function radians(degrees) +{ + return degrees*Math.PI/180; +} + + +// създава матрица за ортографска проекция +function orthoMatrix(width, height, near, far) +{ + var matrix = [ + 2.0/width, 0, 0, 0, + 0, 2.0/height, 0, 0, + 0, 0, 2.0/(near-far), 0, + 0, 0, (far+near)/(near-far), 1]; + return new Float32Array(matrix); +} + + +// създава матрица за перспективна проекция +// ъгълът на зрителното поле е в градуси +function perspMatrix(angle, aspect, near, far) +{ + var fov = 1/Math.tan(radians(angle)/2); + var matrix = [ + fov/aspect, 0, 0, 0, + 0, fov, 0, 0, + 0, 0, (far+near)/(near-far), -1, + 0, 0, 2.0*near*far/(near-far), 0]; + return new Float32Array(matrix); +} + + +// единичен вектор +function unitVector(x) +{ + var len = 1/Math.sqrt( x[0]*x[0]+x[1]*x[1]+x[2]*x[2] ); + return [ len*x[0], len*x[1], len*x[2] ]; +} + + +// векторно произведение на два вектора +function vectorProduct(x,y) +{ + return [ + x[1]*y[2]-x[2]*y[1], + x[2]*y[0]-x[0]*y[2], + x[0]*y[1]-x[1]*y[0] ]; +} + + +// скаларно произведение на два вектора +function scalarProduct(x,y) +{ + return x[0]*y[0] + x[1]*y[1] + x[2]*y[2]; +} + + +// вектор между две точки +function vectorPoints(x,y) +{ + return [ x[0]-y[0], x[1]-y[1], x[2]-y[2] ]; +} + + +// генерира матрица за гледна точка, параметрите са масиви с по 3 елемента +function viewMatrix (eye, focus, up) +{ + // единичен вектор Z' по посоката на гледане + var z = unitVector(vectorPoints(eye,focus)); + + // единичен вектор X', перпендикулярен на Z' и на посоката нагоре + var x = unitVector(vectorProduct(up,z)); + + // единичен вектор Y', перпендикулярен на X' и Z' + var y = unitVector(vectorProduct(z,x)); + + // резултатът е тези три вектора + транслация + var matrix = [ + x[0], y[0], z[0], 0, + x[1], y[1], z[1], 0, + x[2], y[2], z[2], 0, + -scalarProduct(x,eye), + -scalarProduct(y,eye), + -scalarProduct(z,eye), 1 ]; + return new Float32Array(matrix); +}; + + +// единична матрица +function unitMatrix() +{ + var matrix = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + return new Float32Array(matrix); +} + +// матрица за транслация по вектор V +function translateMatrix(v) +{ + var matrix = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + v[0], v[1], v[2], 1]; + return new Float32Array(matrix); +} + + +// матрица за мащабиране с вектор V +function scaleMatrix(v) +{ + var matrix = [ + v[0], 0, 0, 0, + 0, v[1], 0, 0, + 0, 0, v[2], 0, + 0, 0, 0, 1]; + return new Float32Array(matrix); +} + + +// матрица за въртене от X към Y около Z на ъгъл A +function zRotateMatrix(a) +{ + a = radians(a); + var c = Math.cos(a); + var s = Math.sin(a); + var matrix = [ + c, s, 0, 0, + -s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + return new Float32Array(matrix); +} + + +// матрица за въртене от Y към Z около X на ъгъл A +function xRotateMatrix(a) +{ + a = radians(a); + var c = Math.cos(a); + var s = Math.sin(a); + var matrix = [ + 1, 0, 0, 0, + 0, c, s, 0, + 0,-s, c, 0, + 0, 0, 0, 1]; + return new Float32Array(matrix); +} + + +// матрица за въртене от X към Z около Y на ъгъл A +function yRotateMatrix(a) +{ + a = radians(a); + var c = Math.cos(a); + var s = Math.sin(a); + var matrix = [ + c, 0, s, 0, + 0, 1, 0, 0, + -s, 0, c, 0, + 0, 0, 0, 1]; + return new Float32Array(matrix); +} + + +// матрица за въртене около вектор V на ъгъл A +function rotateMatrix(a, v) +{ + a = radians(a); + v = unitVector(v); + + var c = Math.cos(a); + var s = Math.sin(a); + + var xx = v[0]*v[0]*(1-c); + var xy = v[0]*v[1]*(1-c); + var xz = v[0]*v[2]*(1-c); + var yy = v[1]*v[1]*(1-c); + var yz = v[1]*v[2]*(1-c); + var zz = v[2]*v[2]*(1-c); + + var matrix = [ + xx+c, xy-v[2]*s, xz+v[1]*s, 0, + xy+v[2]*s, yy+c, yz-v[0]*s, 0, + xz-v[1]*s, yz+v[0]*s, zz+c, 0, + 0, 0, 0, 1]; + return new Float32Array(matrix); +} + + +// зарежда единичната матрица в матрицата на модела +function identity() +{ + glmatnew = true; + glmat = new Float32Array( [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1] ); +} + + +// добавя транслация към матрицата на модела +function translate(v) +{ + glmatnew = true; + glmat[12] += glmat[0]*v[0]+glmat[4]*v[1]+glmat[8]*v[2]; + glmat[13] += glmat[1]*v[0]+glmat[5]*v[1]+glmat[9]*v[2]; + glmat[14] += glmat[2]*v[0]+glmat[6]*v[1]+glmat[10]*v[2]; +} + + +// добавя мащабиране към матрицата на модела +function scale(v) +{ + glmatnew = true; + glmat[0] *= v[0]; + glmat[1] *= v[0]; + glmat[2] *= v[0]; + + glmat[4] *= v[1]; + glmat[5] *= v[1]; + glmat[6] *= v[1]; + + glmat[8] *= v[2]; + glmat[9] *= v[2]; + glmat[10] *= v[2]; +} + + +// ако матрицата на модела е променена, изпраща я към шейдъра +function useMatrix() +{ + if (glmatnew) + { + glmatnew = false; + gl.uniformMatrix4fv(uModelMatrix,false,glmat); + } +} + + +// добавя въртене около X към матрицата на модела +function xRotate(a) +{ + glmatnew = true; + + a = radians(a); + var s = Math.sin(a); + var c = Math.cos(a); + + a = glmat[4]*s+glmat[8]*c; + glmat[4]=glmat[4]*c-glmat[8]*s; + glmat[8]=a; + + a = glmat[5]*s+glmat[9]*c; + glmat[5]=glmat[5]*c-glmat[9]*s; + glmat[9]=a; + + a = glmat[6]*s+glmat[10]*c; + glmat[6]=glmat[6]*c-glmat[10]*s; + glmat[10]=a; +} + + +// добавя въртене около Y към матрицата на модела +function yRotate(a) +{ + glmatnew = true; + + a = radians(a); + var s = Math.sin(a); + var c = Math.cos(a); + + a = glmat[0]*s+glmat[8]*c; + glmat[0]=glmat[0]*c-glmat[8]*s; + glmat[8]=a; + + a = glmat[1]*s+glmat[9]*c; + glmat[1]=glmat[1]*c-glmat[9]*s; + glmat[9]=a; + + a = glmat[2]*s+glmat[10]*c; + glmat[2]=glmat[2]*c-glmat[10]*s; + glmat[10]=a; +} + + +// добавя въртене около Z към матрицата на модела +function zRotate(a) +{ + glmatnew = true; + + a = radians(a); + var s = Math.sin(a); + var c = Math.cos(a); + + a = glmat[0]*s+glmat[4]*c; + glmat[0]=glmat[0]*c-glmat[4]*s; + glmat[4]=a; + + a = glmat[1]*s+glmat[5]*c; + glmat[1]=glmat[1]*c-glmat[5]*s; + glmat[5]=a; + + a = glmat[2]*s+glmat[6]*c; + glmat[2]=glmat[2]*c-glmat[6]*s; + glmat[6]=a; +} -- cgit v1.3.1-23-gd82d