// програм маань эндээс эхлэж дуудагдан ажиллана main(); function main() { var canvas = document.getElementById("myCanvas"); initGL(canvas); // opengl тохиргоо initShaders(); // shader програмаа холбох initBuffer(); // зурах гэж байгаа өгөгдлүүдээ буферлэх gl.clearColor(0.0, 0.0, 0.0, 1.0); // арын дэвсгэр хар өнгөөр будах gl.enable(gl.DEPTH_TEST); // DEPTH горим идэвхижүүлэх setInterval(render, 1000 / 60); // 1 секунт тутамд 60-н удаа render // функцийг дуудаж ажиллуулах // ингэснээр өгөгдлөө зурна } var gl; // opengl ийн контекст // canvas дээр opengl зурах боломжийг олгоно function initGL(canvas) { try { // opengl контекстээ canvas-аас авна gl = canvas.getContext("experimental-webgl"); // контекстын урт өргөнийг тохируулна gl.viewportWidth = canvas.width; gl.viewportHeight = canvas.height; } catch (e) {} if (!gl) { alert("Таны хөтөч WebGL гүй юм байна."); } } // id элемент дээр байрлах shader програмыг уншиж авч хөрвүүлнэ function getShader(gl, id) { // id дээр байгаа shader-ийн эх кодыг нь уншиж авна var shaderScript = document.getElementById(id); if (!shaderScript) { return null; } var str = ""; var k = shaderScript.firstChild; while (k) { if (k.nodeType == 3) { str += k.textContent; } k = k.nextSibling; } var shader; // shader програмыг төлөөлнө if (shaderScript.type == "x-shader/x-fragment") { // fragment shader үүсгэнэ shader = gl.createShader(gl.FRAGMENT_SHADER); } else if (shaderScript.type == "x-shader/x-vertex") { // vertex shader үүсгэнэ shader = gl.createShader(gl.VERTEX_SHADER); } else { return null; } gl.shaderSource(shader, str); // shader програмын эх коодыг зааж өгнө gl.compileShader(shader); // кодыг нь компайлдаж хөрвүүлнэ // компайлдахад алдаа өгсөн эсэхийг шалгана if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert(gl.getShaderInfoLog(shader)); return null; } // бэлэн болсон shader програмаа буцаана return shader; } // vertex болон fragment хоёрыг үүнд нэгтгэж // GPU дээр ажиллах програм болгоно var shaderProgram; // vertex болон fragment shader-үүдээ уншиж авч хөрвүүлээд // GPU-рүү upload хийж ажиллахад бэлэн болгоно. function initShaders() { // fragment shader коодыг shader-fs элемэнтээс уншиж авч хөрвүүлнэ var fragmentShader = getShader(gl, "shader-fs"); // vertex shader коодыг shader-vs элемэнтээс уншиж аваад хөрвүүлнэ var vertexShader = getShader(gl, "shader-vs"); // GPU дээр ажилладаг програм үүсгэнэ shaderProgram = gl.createProgram(); // програмруу vertex shader ээ нэмнэ gl.attachShader(shaderProgram, vertexShader); // програмруу fragment shader ийг бас нэмнэ gl.attachShader(shaderProgram, fragmentShader); // нийлүүлээд холбоно ингэснээр GPU дээр ажиллах боломжтой болно gl.linkProgram(shaderProgram); // холболт амжилттай болсон эсэхийг шалгана if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { alert("shader програм холбож чадсангүй."); } // програмаа хэрэглэхээр тохируулна gl.useProgram(shaderProgram); // гурвалжингийн оройнууд програмруу aVertexPosition хувьсагчид // оролт болон очино гэдгийг тохируулна shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); // гурвалжингийн орой тус бүрийн өнгийг aVertexColor хувьсагчид // оролт болон очино гэдгийг тохируулна shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor"); gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute); // uniform хувьсагчидийг тохируулна. shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix"); shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); } var mvMatrix = mat4.create(); // model-view матриц var mvMatrixStack = []; // матриц стак var pMatrix = mat4.create(); // projection матриц var triangleVertexPositionBuffer; // байрлал хадгалах буфер var triangleVertexColorBuffer; // өнгө хадгалах буфер var rotationAngle = 0; // эргүүлэлтийн өнцөг var lastTime = 0; // timer байдлаар хэрэглэнэ // stack бүтэцрүү матриц хадгалах. Ингэснээрээ ялгаатай // объектүүдийн transformation утгуудыг хадгалж рэндэрлэх боломжтой function mvPushMatrix() { var copy = mat4.create(); mat4.set(mvMatrix, copy); mvMatrixStack.push(copy); } // stack-д хийсэн утгыг сэргээн хадгалаад function mvPopMatrix() { if (mvMatrixStack.length == 0) { throw "Invalid popMatrix!"; } mvMatrix = mvMatrixStack.pop(); } // буферт өгөгдлөө тохируулж upload хийгээд зурахад бэлэн болгоно function initBuffer() { // GPU-ийн санах ой дээр буфер үүсгэнэ triangleVertexPositionBuffer = gl.createBuffer(); // үүсгэсэн буферээ ашиглахаар тохируулна gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer); // хост програмын санах ойд гурвалжингийн оройнуудыг тодорхойлсон // хэсэг өгөгдөл үүсгэнэ var vertices = [ 0.0, 1.0, 0.0, // дээд орой -1.0, -1.0, 0.0, // зүүн доод орой 1.0, -1.0, 0.0 // баруун доод орой ]; // санах ойд байгаа өгөгдлөө GPU-ийн ой дээр үүсгэсэн буферлүү upload хийнэ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); // нэг оройд хэдэн өгөгдөл байгааг тохируулна triangleVertexPositionBuffer.itemSize = 3; // хэдэн ширхэг орой байгааг тохируулна triangleVertexPositionBuffer.numItems = 3; // оройн өнгөний мэдээлэлд зориулж GPU дээр буфер үүсгэнэ triangleVertexColorBuffer = gl.createBuffer(); // өнгөнд зориулж үүсгэсэн буферээ ашиглахаар идэвхижүүлнэ gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer); var colors = [ 1.0, 0.0, 0.0, 1.0, // дээд оройн өнгө 0.0, 1.0, 0.0, 1.0, // зүүн доод оройн өнгө 0.0, 0.0, 1.0, 1.0 // баруун доод оройн өнгө ]; // өнгөний утгуудаа GPU-рүү дээрхи буферлүү upload хийнэ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); // нэг оройн өнгө нь 4-н ширхэг тоогоор төлөөлөгдөнө. RGBA triangleVertexColorBuffer.itemSize = 4; // 3-н ширхэг өнгө байна triangleVertexColorBuffer.numItems = 3; } // canvas дээр opengl ээр зурах функц function render() { // зурах хэмжээс gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); // өнгөний болон depth буферүүдийг цэвэрлэнэ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // projection матрицын тохиргоо mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix); // нэгж матриц утгаар дүүргэнэ mat4.identity(mvMatrix); // зурах байрлалыг матрицад оноож байна mat4.translate(mvMatrix, [0.0, 0.0, -7.0]); // одоогийн байгаа model-view матрицийг стакрүү хийж хадгалж авна // ингэснээрээ камерийн transformation мэдээллийг хадгалж чадна mvPushMatrix(); // дүрсээ эргүүлэх mat4.rotate(mvMatrix, rotationAngle*Math.PI/180, [0.5, 1, 0]); // зурах гэж байгаа буферласан өгөгдлийг зааж өгнө gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer); // одоо идэвхитэй байгаа shader програмд буфер нь хэдэн ширхэг // өгөгдөлтэй ямар төрөлтэй гэх мэт тохиргоог хийнэ gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0); // өнгөний мэдээлэл хадгалсан байгаа буферийг идэвхижүүлнэ gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer); // буферт тохиргоо хийнэ gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, triangleVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0); // shader програм дотор буюу GPU дээр ажиллаж байгаа vertex shader // кодын үйл ажиллагаанд ашиглагдаж байгаа uPMatrix, uMVMatrix гэсэн // хувьсагчдад хост програмаас матрицийн утгуудыг дамжуулж оноож өгнө gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix); gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix); // зурах команд. буферийн 0-р элементээс numItems-р элемент хүртэл // гурвалжин горимоор зурах үйл ажиллагааг үйлдэнэ. gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems); // хадгалсан model-view матрицаа сэргээн байрлуулна mvPopMatrix(); // delta time тооцох //var deltaTime; //var timeNow = new Date().getTime(); //if (lastTime != 0) { // deltaTime = timeNow - lastTime; //} //lastTime = timeNow; // эргүүлэлтийн өнцөгийг өөрчилөх //rotationAngle += (90 * deltaTime) / 1000.0; //rotationAngle += 1; }
<!-- матрицтай холбоотой математикийн үйлдлүүдэд хэрэглэнэ --> <script src="http://glmatrix.googlecode.com/hg/glMatrix.js"></script> <!-- дээр нь OpenGL-ээр дүрсээ зурах зориулалттай canvas --> <canvas id="myCanvas" width="500" height="500"></canvas> <!-- vertex shader програмын код --> <script id="shader-vs" type="x-shader/x-vertex"> attribute vec3 aVertexPosition; attribute vec4 aVertexColor; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying vec4 vColor; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vColor = aVertexColor; } </script> <!-- fragment shader програмын код --> <script id="shader-fs" type="x-shader/x-fragment"> precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; } </script>
#myCanvas { }