Tìm hiểu WebGL Phần 3: Đi sau vào cách code WebGL appication - các ví dụ
Bài đăng này đã không được cập nhật trong 3 năm
Lời Nói Đầu
Ở phần này chúng ta tiếp tục tìm hiểu cách lập trình WebGL: liên kết các attribute với các buffer object, sử dụng các hàm để vẽ các mô hình từ dữ liệu truyền vào. Sau đó là các ví dụ đơn giản về vẽ các điểm, mô hình 2D, 3D
Lập Trình WebGL (tiếp)
Liên kết các attribute và buffer object.
Mỗi attrubute trong vertex shader program trỏ tới một vertex buffer object. Sau khi tạo vertex buffer object, coder cần liên kết chúng với các attribute của vertex shader program. Mỗi attribute chỉ trỏ tới một vertex buffer object mà từ đó chúng lấy dữ liệu và sau đó các attributes được truyền cho shader program. Để liên kết các vertext buffer object với các attribute của vertex shader program ta cần làm theo các bước sau:
1. Lấy vị trí của attribute bằng phương thức getAttrubLocation():
Cú pháp:
ulong getAttribLocation(Object program, string name)
Tham số đầu tiên là vertex shader program object Tham số thứ hai là attrubte của shader program.
2 Trỏ attribute tới vertex buffer object.
Để gán buffer object cho một biến attribute, ta dùng phương thức vertexAttrubPointer(). Cú pháp
void vertexAttribPointer(location, int size, enum type, bool normalized, long stride, long offset)
Các tham số bao gồm:
- Location: Vị trí của biến attribute. Ta sẽ truyền vào giá trị trả về của getAttribLocation().
- Size: Số thành phần của mỗi đỉnh trong buffer object.
- Type: kiểu dữ liệu.
- Normalized: có chuẩn hóa dữ liệu hay không, nếu có dữ liệu được chuẩn hóa về [0, 1], còn không nó sẽ được chuẩn hóa về [-1, 1]
- Stride: nó chỉ ra số byte giữa các thành phần dữ liệu các đỉnh khác nhau.
- Offset: nó chỉ ra offset trong buffer object xác định byte nào được dùng để bắt đầu lưu trữ data.
3 Kích hoạt attribute.
Kích hoạt vertex shader program attribute để truy cập buffer object trong vertex shader sử dụng phương thức enableVertexAttribArray(). Cú pháp:
gl.enableVertexAttribArray(coordinatesVar);
Tham số truyền vào là tên của attribute.
Vẽ các mô hình.
Sau khi liên kết buffer với shader, bước cuối cùng là vẽ các hình. Ta sử dụng hai phương thức drawArrays() và drawElements().
1. drawArrays()
Được dùng để vẽ các mô hình sử dụng các đỉnh.
void drawArrays(enum mode, int first, long count)
Có 3 tham số của phương thức này:
- mode: được dùng để chỉ ra kiểu sẽ được vẽ mà WebGL đã định sẵn: gl.POINTS - vẽ điểm, gl.LINES - vẽ đường thẳng, gl.TRIANGLES - vẽ tam giác ...
- first: chỉ ra phần tử bắt đầu để vẽ trong mảng dữ liệu.
- count: chỉ ra số phần tử được render.
Ví dụ với dữ liệu đầu vào gồm tọa độ 3D của 3 đỉnh:
var vertices = [-0.5,-0.5, -0.25,0.5, 0.0,-0.5,];
Ta vẽ hình tam giác như sau:
gl.drawArrays(gl.TRIANGLES, 0, 3);
kết quả
2. drawElements()
Được dùng để vẽ các mô hình sử dụng đỉnh và các chỉ số.
void drawElements(enum mode, long count, enum type, long offset)
Các tham số:
- mode: được dùng để chỉ ra kiểu sẽ được vẽ mà WebGL đã định sẵn.
- count: chỉ ra số phân tử được render.
- type: chỉ ra kiểu dữ liệu của các chỉ số là UNSIGNED_BYTE hoặc UNSIGNED_SHORT.
- offset: chỉ ra điểm bắt đầu để render.
Ví dụ với dữ liệu đầu vào gồm tọa độ 3D của 3 đỉnh cùng với chỉ số 3 đỉnh:
var vertices = [ -0.5,-0.5,0.0, -0.25,0.5,0.0, 0.0,-0.5,0.0 ];
var indices = [0,1,2];
Ta vẽ hình tam giác như sau:
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
kết quả
3.Các yêu cầu khác khi làm việc với WebGL.
Dọn dep Canvas: sử dụng phương thức clearColor():
gl.clearColor(0.5, 0.5, .5, 1);
Kích hoạt depth test.
gl.enable(gl.DEPTH_TEST);
Dọn dẹp color buffer bit.
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
Thiết lập view port. View port là vùng hình chữ nhật chứa các hình là kết quả của việc rendering, và được thiết lập sử dụng phương thức viewport().
gl.viewport(0,0,canvas.width,canvas.height);
Như vậy để làm một ứng dụng WebGL ta cần các bước sau:
- Chuẩn bị WebGL context.
- Chuẩn bị dữ liệu cho mô hình cần vẽ dưới dạng mảng javascript và lưu chúng vào các buffer object.
- Tạo các vertex shader và fragment shader, biên dịch và liên kết chúng với nhau.
- Liên kết các attributes của shader program với các buffer object để từ đó khai thác dữ liệu và truyền chúng vào các shader program.
- Sử dụng các phương thức cần thiết để vẽ các hình.
Các ví dụ về tạo các ứng dụng WebGL.
Vẽ các điểm
Ta sẽ thực hiện thoe các bước đã nêu ở trên.
- Chuẩn bị canvas và WebGL context.
<canvas width = "570" height = "570" id = "my_Canvas"></canvas>
<script>
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
</script>
- Tạo dữ liệu hình học cho điểm và lưu trữ vào các buffer object. Các điểm như là các vertex ta có thể định nghĩa nó trong tọa độ 3D hoặc 2D. Dưới đây là định nghĩa các đỉnh trong tọa độ 3D và lưu vào vertex buffer.
var vertices = [
-0.5,0.5,0.0,
0.0,0.5,0.0,
-0.25,0.25,0.0,
];
//Tạo vertex buffer object
var vertex_buffer = gl.createBuffer();
//Bind mảng buffer thích hợp cho buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
// Truyền dữ liệu cho vertex buffer object
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// Unbind the buffer
gl.bindBuffer(gl.ARRAY_BUFFER, null);
- Tạo và biên dịch các shader program.
- Để xử lý dữ liệu về vị trí của các đỉnh (vertex) ta định nghĩa vertex shader program. Trong vertex shader program ta định một vector attribute để lưu trữ tạo độ 3D và gán nó cho biến gl_Position. Ngoài ra để các điểm có thể nhìn được rõ ta thiết lập kích thước cho điển thông qua biến gl_PointSize.
// Mã nguồn được lưu dưới dạng một chuỗi vào một biến javascript
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'gl_PointSize = 10.0;'+
'}';
// Tạo vertex shader object
var vertShader = gl.createShader(gl.VERTEX_SHADER);
// Gán mã nguồn cho đối tượng vertex shader mới được tạo
gl.shaderSource(vertShader, vertCode);
// Biên dịch vertex shader object
gl.compileShader(vertShader);
- Để xử lý màu sắc cho các điểm ta định nghĩa fragment shader program. Trong fragment shader program ta thiết lập màu bằng việc gán giá trị cho biến gl_FragColor.
// Mã nguồn fragment shader được lưu dưới dạng một chuỗi.
var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';
// Tạo fragment shader object
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
// Gán mã nguồn cho fragment shader object
gl.shaderSource(fragShader, fragCode);
// Biên dịch fragment shader object
gl.compileShader(fragShader);
- Sau khi tạo và biên dịch các shader program cần thiết ta sẽ liên kết chúng lại.
// Tạo shader program object để phối hợp 2 shader đã tạo ở trên
var shaderProgram = gl.createProgram();
// Gán vertex shader cho shader program
gl.attachShader(shaderProgram, vertShader);
// Gán fragment shader cho shader program
gl.attachShader(shaderProgram, fragShader);
// Liên kết hai program với nhau
gl.linkProgram(shaderProgram);
// Sử dụng phối hợp vertex và shader program
gl.useProgram(shaderProgram);
- Liên kết các shader program với các buffer object.
// Bind vertex buffer object với mảng buffer thích hợp
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
// Lấy vị trí của attribute của vertex shader
var coord = gl.getAttribLocation(shaderProgram, "coordinates");
// Trỏ attribute tới vertex buffer objet ở trên.
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
// Sử dụng attribute
gl.enableVertexAttribArray(coord);
- Vẽ các điểm Ở đây ta sẽ sử dụng drawArrays() để vẽ các điểm.
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);
// vẽ điểm
gl.drawArrays(gl.POINTS, 0, 3);
Ở trên ta vẽ 3 điểm với dữ liệu vị trí được xử lý bởi vertex shader program và màu sắc được xử lý bởi fragment shader program, kết quả sẽ là:
Kết Luận
Bài viết vừa giới thiệu hai bước cuối dùng để lập trình một ứng dụng WebGL, cùng với một ví dụ cơ bản là vẽ ba đểm sử dụng WebGL. Ở phần tiếp theo của bài báo cáo sẽ là các ví dụ phức tạp hơn như mô hình 3D, tương tác với các mô hình.
Tài Liệu Tham Khảo
All rights reserved