0% found this document useful (0 votes)
24 views24 pages

LabWebGL&ThreeJS Ve Cac Doi Tuong Co Ban

The document discusses drawing basic 2D and 3D graphics objects in WebGL. It covers drawing a triangle, three parallel lines, a quadrilateral, and demonstrates translation, scaling, rotation, and drawing an interactive 3D cube. Code examples and results are provided for each topic.

Uploaded by

chung27032004
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views24 pages

LabWebGL&ThreeJS Ve Cac Doi Tuong Co Ban

The document discusses drawing basic 2D and 3D graphics objects in WebGL. It covers drawing a triangle, three parallel lines, a quadrilateral, and demonstrates translation, scaling, rotation, and drawing an interactive 3D cube. Code examples and results are provided for each topic.

Uploaded by

chung27032004
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 24

LẬP TRÌNH WEBGL

VẼ CÁC ĐỐI TƯỢNG ĐỒ HỌA CƠ BẢN

Họ và tên Sinh viên: Mã Sinh viên:


Nhóm học phần:

MỤC LỤC
1. Draw a Triangle.................................................................................................1
1.1. File WebGLDrawTriangle01.htm..............................................................................1
1.2. File WebGLDrawTriangle02.htm..............................................................................4
1.3. Bài tập........................................................................................................................6
2. Draw Three Parallel Lines................................................................................6
2.1. File WebGLDrawThreeParallelLines.htm.................................................................6
2.2. Kết quả thực hiện.......................................................................................................8
2.3. Bài tập........................................................................................................................8
3. Draw a Quadrilateral........................................................................................8
3.1. File WebGLDrawQuadrilateral.html.........................................................................8
3.2. Kết quả thực hiện.....................................................................................................10
4. Translate...........................................................................................................10
4.1. File WebGLTranslate.html......................................................................................10
4.2. Kết quả thực hiện.....................................................................................................12
5. Scaling...............................................................................................................12
5.1. File WebGLScale.html............................................................................................12
5.2. Kết quả thực hiện.....................................................................................................14
6. Rotation............................................................................................................14
6.1. File WebGLRotation.html.......................................................................................14
6.2. Kết quả thực hiện.....................................................................................................16
7. Rotating 3D cube.............................................................................................16
7.1. File WebGLRotation3DCube.html..........................................................................16
7.2. Kết quả thực hiện.....................................................................................................19
8. Interactive 3D cube..........................................................................................19
8.1. File WebGLRotation3DCubeMouse.html...............................................................19
8.2. Kết quả thực hiện.....................................................................................................23
9. Bài tập...............................................................................................................23
10. Tham khảo........................................................................................................24

>> Yêu cầu chụp hình ảnh là kết quả thực hành của SV. Không sử dụng lại hình ảnh của
bài lab.

1. Draw a Triangle
1.1. File WebGLDrawTriangle01.htm
<!doctype html>

KhoaCNTT-Trường ĐHBK, ĐHĐN


<html>
<body>
<canvas width = "570" height = "570" id = "my_Canvas"></canvas>

<script>
/*============== Creating a canvas ====================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');

/*======== Defining and storing the geometry ===========*/

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

indices = [0,1,2];

// Create an empty buffer object to store vertex buffer


var vertex_buffer = gl.createBuffer();

// Bind appropriate array buffer to it


gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

// Pass the vertex data to the buffer


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

// Unbind the buffer


gl.bindBuffer(gl.ARRAY_BUFFER, null);

// Create an empty buffer object to store Index buffer


var Index_Buffer = gl.createBuffer();

// Bind appropriate array buffer to it


gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);

// Pass the vertex data to the buffer


gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

// Unbind the buffer


gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

/*================ Shaders ====================*/

// Vertex shader source code


var vertCode =
'attribute vec3 coordinates;' +

'void main(void) {' +


' gl_Position = vec4(coordinates, 1.0);' +
'}';

// Create a vertex shader object


var vertShader = gl.createShader(gl.VERTEX_SHADER);

// Attach vertex shader source code


gl.shaderSource(vertShader, vertCode);

// Compile the vertex shader


gl.compileShader(vertShader);

//fragment shader source code

KhoaCNTT-Trường ĐHBK, ĐHĐN


var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';

// Create fragment shader object


var fragShader = gl.createShader(gl.FRAGMENT_SHADER);

// Attach fragment shader source code


gl.shaderSource(fragShader, fragCode);

// Compile the fragmentt shader


gl.compileShader(fragShader);

// Create a shader program object to store


// the combined shader program
var shaderProgram = gl.createProgram();

// Attach a vertex shader


gl.attachShader(shaderProgram, vertShader);

// Attach a fragment shader


gl.attachShader(shaderProgram, fragShader);

// Link both the programs


gl.linkProgram(shaderProgram);

// Use the combined shader program object


gl.useProgram(shaderProgram);

/*======= Associating shaders to buffer objects =======*/

// Bind vertex buffer object


gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

// Bind index buffer object


gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);

// Get the attribute location


var coord = gl.getAttribLocation(shaderProgram, "coordinates");

// Point an attribute to the currently bound VBO


gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);

// Enable the attribute


gl.enableVertexAttribArray(coord);

/*=========Drawing the triangle===========*/

// Clear the canvas


gl.clearColor(0.5, 0.5, 0.5, 0.9);

// Enable the depth test


gl.enable(gl.DEPTH_TEST);

// Clear the color buffer bit


gl.clear(gl.COLOR_BUFFER_BIT);

// Set the view port


gl.viewport(0,0,canvas.width,canvas.height);

// Draw the triangle


gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);

KhoaCNTT-Trường ĐHBK, ĐHĐN


</script>
</body>
</html>

 Kết quả thực hiện

1.2. File WebGLDrawTriangle02.htm


<!DOCTYPE html>
<html>

<head>
<title>Draw a triangle</title>
</head>

<body onload="init()">
<canvas id="myCanvas" width="640" height="480"></canvas>
</body>

<script id="shaderVs" type="x-shader/x-vertex">


attribute vec4 a_Position;
void main() {
gl_Position = a_Position;
}
</script>

<script id="shaderFs" type="x-shader/x-fragment">


void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
</script>

<script>
function init() {
// Get canvas object from the DOM
var canvas = document.getElementById("myCanvas");

// Init WebGL context


var gl = canvas.getContext("webgl");
if (!gl) {
console.log("Failed to get the rendering context for WebGL");
return;
}

// Init shaders
var vs = document.getElementById('shaderVs').innerHTML;
var fs = document.getElementById('shaderFs').innerHTML;
if (!initShaders(gl, vs, fs)) {
console.log('Failed to intialize shaders.');
return;
}

// Write the positions of vertices to a vertex shader


var n = initVertexBuffers(gl);
if (n < 0) {
console.log('Failed to set the positions of the vertices');
return;

KhoaCNTT-Trường ĐHBK, ĐHĐN


}

// Clear canvas
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

// Draw
gl.drawArrays(gl.TRIANGLES, 0, n);
}

function initVertexBuffers(gl) {
// Vertices
var dim = 3;
var vertices = new Float32Array([
0, 0.5, 0, // Vertice #1
-0.5, -0.5, 0, // Vertice #2
0.5, -0.5, 0 // Vertice #3
]);

// Create a buffer object


var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log('Failed to create the buffer object');
return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// Assign the vertices in buffer object to a_Position variable


var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return -1;
}
gl.vertexAttribPointer(a_Position, dim, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);

// Return number of vertices


return vertices.length / dim;
}

function initShaders(gl, vs_source, fs_source) {


// Compile shaders
var vertexShader = makeShader(gl, vs_source, gl.VERTEX_SHADER);
var fragmentShader = makeShader(gl, fs_source, gl.FRAGMENT_SHADER);

// Create program
var glProgram = gl.createProgram();

// Attach and link shaders to the program


gl.attachShader(glProgram, vertexShader);
gl.attachShader(glProgram, fragmentShader);
gl.linkProgram(glProgram);
if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
alert("Unable to initialize the shader program");
return false;
}

// Use program
gl.useProgram(glProgram);
gl.program = glProgram;

return true;

KhoaCNTT-Trường ĐHBK, ĐHĐN


}

function makeShader(gl, src, type) {


var shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert("Error compiling shader: " +
gl.getShaderInfoLog(shader));
return;
}
return shader;
}
</script>

</html>

1.3. Bài tập


 Tổ chức file Web trên thành 02 file riêng: file html và file .js

2. Draw Three Parallel Lines


2.1. File WebGLDrawThreeParallelLines.htm
<!doctype html>
<html>
<body>
<canvas width = "300" height = "300" id = "my_Canvas"></canvas>

<script>
/*======= Creating a canvas =========*/

var canvas = document.getElementById('my_Canvas');


var gl = canvas.getContext('experimental-webgl');

/*======= Defining and storing the geometry ======*/

var vertices = [
-0.7,-0.1,0,
-0.3,0.6,0,
-0.3,-0.3,0,
0.2,0.6,0,
0.3,-0.3,0,
0.7,0.6,0
]

// Create an empty buffer object


var vertex_buffer = gl.createBuffer();

// Bind appropriate array buffer to it


gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

// Pass the vertex data to the buffer


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

// Unbind the buffer


gl.bindBuffer(gl.ARRAY_BUFFER, null);

/*=================== Shaders ====================*/

KhoaCNTT-Trường ĐHBK, ĐHĐN


// Vertex shader source code
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'}';

// Create a vertex shader object


var vertShader = gl.createShader(gl.VERTEX_SHADER);

// Attach vertex shader source code


gl.shaderSource(vertShader, vertCode);

// Compile the vertex shader


gl.compileShader(vertShader);

// Fragment shader source code


var fragCode =
'void main(void) {' +
'gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';

// Create fragment shader object


var fragShader = gl.createShader(gl.FRAGMENT_SHADER);

// Attach fragment shader source code


gl.shaderSource(fragShader, fragCode);

// Compile the fragmentt shader


gl.compileShader(fragShader);

// Create a shader program object to store


// the combined shader program
var shaderProgram = gl.createProgram();

// Attach a vertex shader


gl.attachShader(shaderProgram, vertShader);

// Attach a fragment shader


gl.attachShader(shaderProgram, fragShader);

// Link both the programs


gl.linkProgram(shaderProgram);

// Use the combined shader program object


gl.useProgram(shaderProgram);

/*======= Associating shaders to buffer objects ======*/

// Bind vertex buffer object


gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

// Get the attribute location


var coord = gl.getAttribLocation(shaderProgram, "coordinates");

// Point an attribute to the currently bound VBO


gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);

// Enable the attribute


gl.enableVertexAttribArray(coord);

/*============ Drawing the triangle =============*/

KhoaCNTT-Trường ĐHBK, ĐHĐN


// Clear the canvas
gl.clearColor(0.5, 0.5, 0.5, 0.9);

// Enable the depth test


gl.enable(gl.DEPTH_TEST);

// Clear the color and depth buffer


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

// Set the view port


gl.viewport(0,0,canvas.width,canvas.height);

// Draw the triangle


gl.drawArrays(gl.LINES, 0, 6);

// POINTS, LINE_STRIP, LINE_LOOP, LINES,


// TRIANGLE_STRIP,TRIANGLE_FAN, TRIANGLES
</script>
</body>
</html>

2.2. Kết quả thực hiện

2.3. Bài tập


 Tổ chức file Web trên thành 02 file riêng: file html và file .js
 Vẽ các hình tam giác, chữ nhật, ngôi sao, … có tô màu

3. Draw a Quadrilateral
3.1. File WebGLDrawQuadrilateral.html
<!doctype html>
<html>
<body>
<canvas width = "300" height = "300" id = "my_Canvas"></canvas>

<script>
/*============= Creating a canvas ==================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');

/*========== Defining and storing the geometry ==========*/

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

var colors = [0,0,1, 1,0,0, 0,1,0, 1,0,1,];

indices = [3,2,1,3,1,0];

// Create an empty buffer object and store vertex data


var vertex_buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

KhoaCNTT-Trường ĐHBK, ĐHĐN


gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);

// Create an empty buffer object and store Index data


var Index_Buffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

// Create an empty buffer object and store color data


var color_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

/*======================= Shaders =======================*/

// vertex shader source code


var vertCode = 'attribute vec3 coordinates;'+
'attribute vec3 color;'+
'varying vec3 vColor;'+
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'vColor = color;'+
'}';

// Create a vertex shader object


var vertShader = gl.createShader(gl.VERTEX_SHADER);

// Attach vertex shader source code


gl.shaderSource(vertShader, vertCode);

// Compile the vertex shader


gl.compileShader(vertShader);

// fragment shader source code


var fragCode = 'precision mediump float;'+
'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';

// Create fragment shader object


var fragShader = gl.createShader(gl.FRAGMENT_SHADER);

// Attach fragment shader source code


gl.shaderSource(fragShader, fragCode);

// Compile the fragmentt shader


gl.compileShader(fragShader);

// Create a shader program object to


// store the combined shader program
var shaderProgram = gl.createProgram();

// Attach a vertex shader


gl.attachShader(shaderProgram, vertShader);

// Attach a fragment shader


gl.attachShader(shaderProgram, fragShader);

// Link both the programs


gl.linkProgram(shaderProgram);

KhoaCNTT-Trường ĐHBK, ĐHĐN


// Use the combined shader program object
gl.useProgram(shaderProgram);

/* ======== Associating shaders to buffer objects =======*/

// Bind vertex buffer object


gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

// Bind index buffer object


gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);

// Get the attribute location


var coord = gl.getAttribLocation(shaderProgram, "coordinates");

// point an attribute to the currently bound VBO


gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);

// Enable the attribute


gl.enableVertexAttribArray(coord);

// bind the color buffer


gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);

// get the attribute location


var color = gl.getAttribLocation(shaderProgram, "color");

// point attribute to the volor buffer object


gl.vertexAttribPointer(color, 3, gl.FLOAT, false,0,0) ;

// enable the color attribute


gl.enableVertexAttribArray(color);

/*============Drawing the Quad====================*/

// Clear the canvas


gl.clearColor(0.5, 0.5, 0.5, 0.9);

// Enable the depth test


gl.enable(gl.DEPTH_TEST);

// Clear the color buffer bit


gl.clear(gl.COLOR_BUFFER_BIT);

// Set the view port


gl.viewport(0,0,canvas.width,canvas.height);

//Draw the triangle


gl.drawElements(gl.TRIANGLES, indices.length,
gl.UNSIGNED_SHORT,0);
</script>
</body>
</html>

3.2. Kết quả thực hiện

KhoaCNTT-Trường ĐHBK, ĐHĐN


4. Translate
4.1. File WebGLTranslate.html
<!doctype html>
<html>
<body>
<canvas width = "300" height = "300" id = "my_Canvas"></canvas>

<script>
/*=================Creating a canvas=========================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');

/*===========Defining and storing the geometry==============*/


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

//Create an empty buffer object and store vertex data


var vertex_buffer = gl.createBuffer();

//Create a new buffer


gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

//bind it to the current buffer


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

// Pass the buffer data


gl.bindBuffer(gl.ARRAY_BUFFER, null);

/*========================Shaders============================*/

//vertex shader source code


var vertCode =
'attribute vec4 coordinates;' +
'uniform vec4 translation;'+
'void main(void) {' +
' gl_Position = coordinates + translation;' +
'}';

//Create a vertex shader program object and compile it


var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);

//fragment shader source code


var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';

//Create a fragment shader program object and compile it


var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);

//Create and use combiened shader program

KhoaCNTT-Trường ĐHBK, ĐHĐN


var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);

gl.useProgram(shaderProgram);

/* ===========Associating shaders to buffer objects============*/

gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
var coordinatesVar = gl.getAttribLocation(shaderProgram,
"coordinates");
gl.vertexAttribPointer(coordinatesVar, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(coordinatesVar);

/* ==========translation======================================*/
var Tx = 0.5, Ty = 0.5, Tz = 0.0;
var translation = gl.getUniformLocation(shaderProgram,
'translation');
gl.uniform4f(translation, Tx, Ty, Tz, 0.0);

/*=================Drawing the riangle and transforming


it========================*/

gl.clearColor(0.5, 0.5, 0.5, 0.9);


gl.enable(gl.DEPTH_TEST);

gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0,0,canvas.width,canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
</body>
</html>

4.2. Kết quả thực hiện

5. Scaling
5.1. File WebGLScale.html
<!doctype html>
<html>
<body>
<canvas width = "300" height = "300" id = "my_Canvas"></canvas>

<script>
/*=================Creating a canvas=========================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');

/*===========Defining and storing the geometry==============*/


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

//Create an empty buffer object and store vertex data

var vertex_buffer = gl.createBuffer();

KhoaCNTT-Trường ĐHBK, ĐHĐN


gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices),
gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);

/*========================Shaders============================*/

//Vertex shader source code


var vertCode =
'attribute vec4 coordinates;' +
'uniform mat4 u_xformMatrix;' +
'void main(void) {' +
' gl_Position = u_xformMatrix * coordinates;' +
'}';

//Create a vertex shader program object and compile it


var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);

//fragment shader source code


var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';

//Create a fragment shader program object and compile it


var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);

//Create and use combiened shader program


var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);

gl.useProgram(shaderProgram);

/*===================scaling==========================*/

var Sx = 1.0, Sy = 1.5, Sz = 1.0;


var xformMatrix = new Float32Array([
Sx, 0.0, 0.0, 0.0,
0.0, Sy, 0.0, 0.0,
0.0, 0.0, Sz, 0.0,
0.0, 0.0, 0.0, 1.0
]);

var u_xformMatrix = gl.getUniformLocation(shaderProgram,


'u_xformMatrix');
gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);

/* ===========Associating shaders to buffer objects============*/


gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

var coordinatesVar = gl.getAttribLocation(shaderProgram,


"coordinates");
gl.vertexAttribPointer(coordinatesVar, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(coordinatesVar);

/*=================Drawing the Quad========================*/


gl.clearColor(0.5, 0.5, 0.5, 0.9);

KhoaCNTT-Trường ĐHBK, ĐHĐN


gl.enable(gl.DEPTH_TEST);

gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0,0,canvas.width,canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
</body>
</html>

5.2. Kết quả thực hiện

6. Rotation
6.1. File WebGLRotation.html
<!doctype html>
<html>
<body>
<canvas width = "400" height = "400" id = "my_Canvas"></canvas>

<script>
/*=================Creating a canvas=========================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');

/*===========Defining and storing the geometry==============*/

var vertices = [ -1,-1,-1, 1,-1,-1, 1, 1,-1 ];


var colors = [ 1,1,1, 1,1,1, 1,1,1 ];
var indices = [ 0,1,2 ];

//Create and store data into vertex buffer


var vertex_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices),
gl.STATIC_DRAW);

//Create and store data into color buffer


var color_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors),
gl.STATIC_DRAW);

//Create and store data into index buffer


var index_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices),
gl.STATIC_DRAW);

/*==========================Shaders=========================*/

var vertCode = 'attribute vec3 position;'+


'uniform mat4 Pmatrix;'+
'uniform mat4 Vmatrix;'+
'uniform mat4 Mmatrix;'+
'attribute vec3 color;'+//the color of the point
'varying vec3 vColor;'+

'void main(void) { '+//pre-built function

KhoaCNTT-Trường ĐHBK, ĐHĐN


'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);'+
'vColor = color;'+
'}';

var fragCode = 'precision mediump float;'+


'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';

var vertShader = gl.createShader(gl.VERTEX_SHADER);


gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);

var fragShader = gl.createShader(gl.FRAGMENT_SHADER);


gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);

var shaderProgram = gl.createProgram();


gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);

/*===associating attributes to vertex shader ============*/

var Pmatrix = gl.getUniformLocation(shaderProgram, "Pmatrix");


var Vmatrix = gl.getUniformLocation(shaderProgram, "Vmatrix");
var Mmatrix = gl.getUniformLocation(shaderProgram, "Mmatrix");
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

var position = gl.getAttribLocation(shaderProgram, "position");


gl.vertexAttribPointer(position, 3, gl.FLOAT, false,0,0) ;
//position
gl.enableVertexAttribArray(position);
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);

var color = gl.getAttribLocation(shaderProgram, "color");


gl.vertexAttribPointer(color, 3, gl.FLOAT, false,0,0) ; //color
gl.enableVertexAttribArray(color);
gl.useProgram(shaderProgram);

/*========================= MATRIX ========================= */

function get_projection(angle, a, zMin, zMax) {


var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5
return [
0.5/ang, 0 , 0, 0,
0, 0.5*a/ang, 0, 0,
0, 0, -(zMax+zMin)/(zMax-zMin), -1,
0, 0, (-2*zMax*zMin)/(zMax-zMin), 0
];
}

var proj_matrix = get_projection(40, canvas.width/canvas.height, 1, 100);


var mov_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
var view_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];

//translating z
view_matrix[14] = view_matrix[14]-6; //zoom

/*=======================rotation========================*/
function rotateZ(m, angle) {
var c = Math.cos(angle);

KhoaCNTT-Trường ĐHBK, ĐHĐN


var s = Math.sin(angle);
var mv0 = m[0], mv4 = m[4], mv8 = m[8];

m[0] = c*m[0]-s*m[1];
m[4] = c*m[4]-s*m[5];
m[8] = c*m[8]-s*m[9];
m[1] = c*m[1]+s*mv0;
m[5] = c*m[5]+s*mv4;
m[9] = c*m[9]+s*mv8;
}

/*=================Drawing===========================*/

var time_old = 0;
var animate = function(time) {
var dt = time-time_old;
rotateZ(mov_matrix, dt*0.002);
time_old = time;

gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clearDepth(1.0);
gl.viewport(0.0, 0.0, canvas.width, canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

gl.uniformMatrix4fv(Pmatrix, false, proj_matrix);


gl.uniformMatrix4fv(Vmatrix, false, view_matrix);
gl.uniformMatrix4fv(Mmatrix, false, mov_matrix);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
window.requestAnimationFrame(animate);
}
animate(0);
</script>
</body>
</html>

6.2. Kết quả thực hiện

7. Rotating 3D cube
7.1. File WebGLRotation3DCube.html
<!doctype html>
<html>
<body>
<canvas width = "570" height = "570" id = "my_Canvas"></canvas>

<script>
/*============= Creating a canvas =================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');

/*============ Defining and storing the geometry =========*/

var vertices = [
-1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1,
-1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1,

KhoaCNTT-Trường ĐHBK, ĐHĐN


-1,-1,-1, -1, 1,-1, -1, 1, 1, -1,-1, 1,
1,-1,-1, 1, 1,-1, 1, 1, 1, 1,-1, 1,
-1,-1,-1, -1,-1, 1, 1,-1, 1, 1,-1,-1,
-1, 1,-1, -1, 1, 1, 1, 1, 1, 1, 1,-1,
];

var colors = [
5,3,7, 5,3,7, 5,3,7, 5,3,7,
1,1,3, 1,1,3, 1,1,3, 1,1,3,
0,0,1, 0,0,1, 0,0,1, 0,0,1,
1,0,0, 1,0,0, 1,0,0, 1,0,0,
1,1,0, 1,1,0, 1,1,0, 1,1,0,
0,1,0, 0,1,0, 0,1,0, 0,1,0
];

var indices = [
0,1,2, 0,2,3, 4,5,6, 4,6,7,
8,9,10, 8,10,11, 12,13,14, 12,14,15,
16,17,18, 16,18,19, 20,21,22, 20,22,23
];

// Create and store data into vertex buffer


var vertex_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// Create and store data into color buffer


var color_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

// Create and store data into index buffer


var index_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

/*=================== Shaders =========================*/

var vertCode = 'attribute vec3 position;'+


'uniform mat4 Pmatrix;'+
'uniform mat4 Vmatrix;'+
'uniform mat4 Mmatrix;'+
'attribute vec3 color;'+//the color of the point
'varying vec3 vColor;'+

'void main(void) { '+//pre-built function


'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);'+
'vColor = color;'+
'}';

var fragCode = 'precision mediump float;'+


'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';

var vertShader = gl.createShader(gl.VERTEX_SHADER);


gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);

var fragShader = gl.createShader(gl.FRAGMENT_SHADER);


gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);

KhoaCNTT-Trường ĐHBK, ĐHĐN


var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);

/* ====== Associating attributes to vertex shader =====*/


var Pmatrix = gl.getUniformLocation(shaderProgram, "Pmatrix");
var Vmatrix = gl.getUniformLocation(shaderProgram, "Vmatrix");
var Mmatrix = gl.getUniformLocation(shaderProgram, "Mmatrix");

gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
var position = gl.getAttribLocation(shaderProgram, "position");
gl.vertexAttribPointer(position, 3, gl.FLOAT, false,0,0) ;

// Position
gl.enableVertexAttribArray(position);
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
var color = gl.getAttribLocation(shaderProgram, "color");
gl.vertexAttribPointer(color, 3, gl.FLOAT, false,0,0) ;

// Color
gl.enableVertexAttribArray(color);
gl.useProgram(shaderProgram);

/*==================== MATRIX =====================*/

function get_projection(angle, a, zMin, zMax) {


var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5
return [
0.5/ang, 0 , 0, 0,
0, 0.5*a/ang, 0, 0,
0, 0, -(zMax+zMin)/(zMax-zMin), -1,
0, 0, (-2*zMax*zMin)/(zMax-zMin), 0
];
}

var proj_matrix = get_projection(40, canvas.width/canvas.height, 1, 100);

var mov_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];


var view_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];

// translating z
view_matrix[14] = view_matrix[14]-6;//zoom

/*==================== Rotation ====================*/

function rotateZ(m, angle) {


var c = Math.cos(angle);
var s = Math.sin(angle);
var mv0 = m[0], mv4 = m[4], mv8 = m[8];

m[0] = c*m[0]-s*m[1];
m[4] = c*m[4]-s*m[5];
m[8] = c*m[8]-s*m[9];

m[1]=c*m[1]+s*mv0;
m[5]=c*m[5]+s*mv4;
m[9]=c*m[9]+s*mv8;
}

function rotateX(m, angle) {


var c = Math.cos(angle);

KhoaCNTT-Trường ĐHBK, ĐHĐN


var s = Math.sin(angle);
var mv1 = m[1], mv5 = m[5], mv9 = m[9];

m[1] = m[1]*c-m[2]*s;
m[5] = m[5]*c-m[6]*s;
m[9] = m[9]*c-m[10]*s;

m[2] = m[2]*c+mv1*s;
m[6] = m[6]*c+mv5*s;
m[10] = m[10]*c+mv9*s;
}

function rotateY(m, angle) {


var c = Math.cos(angle);
var s = Math.sin(angle);
var mv0 = m[0], mv4 = m[4], mv8 = m[8];

m[0] = c*m[0]+s*m[2];
m[4] = c*m[4]+s*m[6];
m[8] = c*m[8]+s*m[10];

m[2] = c*m[2]-s*mv0;
m[6] = c*m[6]-s*mv4;
m[10] = c*m[10]-s*mv8;
}

/*================= Drawing ===========================*/


var time_old = 0;

var animate = function(time) {

var dt = time-time_old;
rotateZ(mov_matrix, dt*0.005);//time
rotateY(mov_matrix, dt*0.002);
rotateX(mov_matrix, dt*0.003);
time_old = time;

gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clearDepth(1.0);

gl.viewport(0.0, 0.0, canvas.width, canvas.height);


gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniformMatrix4fv(Pmatrix, false, proj_matrix);
gl.uniformMatrix4fv(Vmatrix, false, view_matrix);
gl.uniformMatrix4fv(Mmatrix, false, mov_matrix);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);

gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

window.requestAnimationFrame(animate);
}
animate(0);
</script>
</body>
</html>

7.2. Kết quả thực hiện

KhoaCNTT-Trường ĐHBK, ĐHĐN


8. Interactive 3D cube
Draw a 3D cube that can be rotated using mouse controls
8.1. File WebGLRotation3DCubeMouse.html
<!doctype html>
<html>
<body>
<canvas width = "570" height = "570" id = "my_Canvas"></canvas>

<script>
/*============= Creating a canvas ======================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');

/*========== Defining and storing the geometry ==========*/

var vertices = [
-1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1,
-1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1,
-1,-1,-1, -1, 1,-1, -1, 1, 1, -1,-1, 1,
1,-1,-1, 1, 1,-1, 1, 1, 1, 1,-1, 1,
-1,-1,-1, -1,-1, 1, 1,-1, 1, 1,-1,-1,
-1, 1,-1, -1, 1, 1, 1, 1, 1, 1, 1,-1,
];

var colors = [
5,3,7, 5,3,7, 5,3,7, 5,3,7,
1,1,3, 1,1,3, 1,1,3, 1,1,3,
0,0,1, 0,0,1, 0,0,1, 0,0,1,
1,0,0, 1,0,0, 1,0,0, 1,0,0,
1,1,0, 1,1,0, 1,1,0, 1,1,0,
0,1,0, 0,1,0, 0,1,0, 0,1,0
];

var indices = [
0,1,2, 0,2,3, 4,5,6, 4,6,7,
8,9,10, 8,10,11, 12,13,14, 12,14,15,
16,17,18, 16,18,19, 20,21,22, 20,22,23
];

// Create and store data into vertex buffer


var vertex_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// Create and store data into color buffer


var color_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

// Create and store data into index buffer


var index_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

/*=================== SHADERS =================== */

var vertCode = 'attribute vec3 position;'+


'uniform mat4 Pmatrix;'+
'uniform mat4 Vmatrix;'+
'uniform mat4 Mmatrix;'+

KhoaCNTT-Trường ĐHBK, ĐHĐN


'attribute vec3 color;'+//the color of the point
'varying vec3 vColor;'+
'void main(void) { '+//pre-built function
'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);'+
'vColor = color;'+
'}';

var fragCode = 'precision mediump float;'+


'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';

var vertShader = gl.createShader(gl.VERTEX_SHADER);


gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);

var fragShader = gl.createShader(gl.FRAGMENT_SHADER);


gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);

var shaderprogram = gl.createProgram();


gl.attachShader(shaderprogram, vertShader);
gl.attachShader(shaderprogram, fragShader);
gl.linkProgram(shaderprogram);

/*======== Associating attributes to vertex shader =====*/


var _Pmatrix = gl.getUniformLocation(shaderprogram, "Pmatrix");
var _Vmatrix = gl.getUniformLocation(shaderprogram, "Vmatrix");
var _Mmatrix = gl.getUniformLocation(shaderprogram, "Mmatrix");

gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
var _position = gl.getAttribLocation(shaderprogram, "position");
gl.vertexAttribPointer(_position, 3, gl.FLOAT, false,0,0);
gl.enableVertexAttribArray(_position);

gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
var _color = gl.getAttribLocation(shaderprogram, "color");
gl.vertexAttribPointer(_color, 3, gl.FLOAT, false,0,0) ;
gl.enableVertexAttribArray(_color);
gl.useProgram(shaderprogram);

/*==================== MATRIX ====================== */

function get_projection(angle, a, zMin, zMax) {


var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5
return [
0.5/ang, 0 , 0, 0,
0, 0.5*a/ang, 0, 0,
0, 0, -(zMax+zMin)/(zMax-zMin), -1,
0, 0, (-2*zMax*zMin)/(zMax-zMin), 0
];
}

var proj_matrix = get_projection(40, canvas.width/canvas.height, 1, 100);


var mo_matrix = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ];
var view_matrix = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ];

view_matrix[14] = view_matrix[14]-6;

/*================= Mouse events ======================*/

var AMORTIZATION = 0.95;

KhoaCNTT-Trường ĐHBK, ĐHĐN


var drag = false;
var old_x, old_y;
var dX = 0, dY = 0;

var mouseDown = function(e) {


drag = true;
old_x = e.pageX, old_y = e.pageY;
e.preventDefault();
return false;
};

var mouseUp = function(e){


drag = false;
};

var mouseMove = function(e) {


if (!drag) return false;
dX = (e.pageX-old_x)*2*Math.PI/canvas.width,
dY = (e.pageY-old_y)*2*Math.PI/canvas.height;
THETA+= dX;
PHI+=dY;
old_x = e.pageX, old_y = e.pageY;
e.preventDefault();
};

canvas.addEventListener("mousedown", mouseDown, false);


canvas.addEventListener("mouseup", mouseUp, false);
canvas.addEventListener("mouseout", mouseUp, false);
canvas.addEventListener("mousemove", mouseMove, false);

/*=========================rotation================*/

function rotateX(m, angle) {


var c = Math.cos(angle);
var s = Math.sin(angle);
var mv1 = m[1], mv5 = m[5], mv9 = m[9];

m[1] = m[1]*c-m[2]*s;
m[5] = m[5]*c-m[6]*s;
m[9] = m[9]*c-m[10]*s;

m[2] = m[2]*c+mv1*s;
m[6] = m[6]*c+mv5*s;
m[10] = m[10]*c+mv9*s;
}

function rotateY(m, angle) {


var c = Math.cos(angle);
var s = Math.sin(angle);
var mv0 = m[0], mv4 = m[4], mv8 = m[8];

m[0] = c*m[0]+s*m[2];
m[4] = c*m[4]+s*m[6];
m[8] = c*m[8]+s*m[10];

m[2] = c*m[2]-s*mv0;
m[6] = c*m[6]-s*mv4;
m[10] = c*m[10]-s*mv8;
}

/*=================== Drawing =================== */

var THETA = 0,

KhoaCNTT-Trường ĐHBK, ĐHĐN


PHI = 0;
var time_old = 0;

var animate = function(time) {


var dt = time-time_old;

if (!drag) {
dX *= AMORTIZATION,
dY*=AMORTIZATION;
THETA+=dX, PHI+=dY;
}

//set model matrix to I4

mo_matrix[0] = 1, mo_matrix[1] = 0, mo_matrix[2] = 0,


mo_matrix[3] = 0,

mo_matrix[4] = 0, mo_matrix[5] = 1, mo_matrix[6] = 0,


mo_matrix[7] = 0,

mo_matrix[8] = 0, mo_matrix[9] = 0, mo_matrix[10] = 1,


mo_matrix[11] = 0,

mo_matrix[12] = 0, mo_matrix[13] = 0, mo_matrix[14] = 0,


mo_matrix[15] = 1;

rotateY(mo_matrix, THETA);
rotateX(mo_matrix, PHI);

time_old = time;
gl.enable(gl.DEPTH_TEST);

// gl.depthFunc(gl.LEQUAL);

gl.clearColor(0.5, 0.5, 0.5, 0.9);


gl.clearDepth(1.0);
gl.viewport(0.0, 0.0, canvas.width, canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

gl.uniformMatrix4fv(_Pmatrix, false, proj_matrix);


gl.uniformMatrix4fv(_Vmatrix, false, view_matrix);
gl.uniformMatrix4fv(_Mmatrix, false, mo_matrix);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

window.requestAnimationFrame(animate);
}
animate(0);
</script>
</body>
</html>

8.2. Kết quả thực hiện

9. Bài tập
Vẽ các hình sau trên WebGL:

KhoaCNTT-Trường ĐHBK, ĐHĐN


1) Hình tròn, hình elippse, hình ngôi sao
2) Hình khối tam diện, tứ diện
3) Đồ thị một số hàm toán học
 y=sin(x)
 y=cos(x)
 x = t + 2.0*sin(2.0*t); y = t + 2.0*cos(5.0*t);
 x = cos(t) - cos(80*t)*sin(t); y = 2.0*sin(t) - sin(80*t);
 x = cos(t); y = sin(t + sin(5.0*t));
 x = sin(t+sin(t)); y = cos(t + cos(t));
 x = t + sin(2.0*t); y = t + sin(3.0*t);
 x = sin(3.0*t); y = sin(4.0*t);

10. Tham khảo


[1]. https://www.tutorialspoint.com/webgl/webgl_interactive_cube.htm
[2]. https://math.hws.edu/graphicsbook/c5/s2.html

(Tài liệu lưu hành nội bộ)


-----------------------------------------------

KhoaCNTT-Trường ĐHBK, ĐHĐN

You might also like