WebGL - Vẽ một Tam giác

Xin chào các pháp sư WebGL tương lai! Hôm nay, chúng ta sẽ bắt đầu một hành trình thú vị vào thế giới của đồ họa máy tính. Chúng ta sẽ học cách vẽ một tam giác sử dụng WebGL, điều này có thể听起来 đơn giản, nhưng hãy tin tôi, nó là nền tảng của tất cả những hình ảnh 3D tuyệt vời mà bạn thấy trong các trò chơi và phim ảnh. Hãy thắt dây an toàn và cùng nhau lặn vào!

WebGL - Drawing a Triangle

WebGL là gì?

Trước khi chúng ta bắt đầu vẽ tam giác, hãy dành một chút thời gian để hiểu WebGL là gì. WebGL (Web Graphics Library) là một API JavaScript cho phép chúng ta渲染 đồ họa 2D và 3D trong các trình duyệt web mà không cần sử dụng bất kỳ plugin nào. Nó giống như có một siêu năng lực cho phép bạn tạo ra những hình ảnh ấn tượng ngay trong trình duyệt web của bạn!

Các bước cần thiết để vẽ một tam giác

Việc vẽ một tam giác trong WebGL có thể trông có vẻ khó khăn ban đầu, nhưng đừng lo lắng! Chúng ta sẽ chia nhỏ nó thành các bước quản lý được. Dưới đây là những gì chúng ta cần làm:

  1. Thiết lập canvas HTML
  2. Lấy ngữ cảnh WebGL
  3. Tạo và biên dịch bộ vi xử lý đỉnh (vertex shader)
  4. Tạo và biên dịch bộ vi xử lý片段 (fragment shader)
  5. Tạo một chương trình shader
  6. Định nghĩa các đỉnh của tam giác
  7. Tạo một bộ nhớ đệm và tải dữ liệu đỉnh
  8. Liên kết các thuộc tính đỉnh
  9. Vẽ tam giác

Bây giờ, hãy đi qua từng bước chi tiết.

1. Thiết lập canvas HTML

Đầu tiên, chúng ta cần tạo một canvas trong tệp HTML để WebGL có thể render tam giác của chúng ta. Dưới đây là cách chúng ta làm:

<canvas id="glCanvas" width="640" height="480"></canvas>

Điều này tạo ra một canvas với ID là "glCanvas" và kích thước 640x480 pixel. Bạn có thể điều chỉnh các kích thước này theo nhu cầu.

2. Lấy ngữ cảnh WebGL

Bây giờ, hãy chuyển sang JavaScript. Chúng ta cần lấy ngữ cảnh WebGL từ canvas của mình:

const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('Không thể khởi tạo WebGL. Trình duyệt của bạn có thể không hỗ trợ.');
return;
}

Mã này tìm kiếm canvas của chúng ta, yêu cầu ngữ cảnh WebGL, và kiểm tra xem WebGL có được hỗ trợ trong trình duyệt hay không.

3. Tạo và biên dịch bộ vi xử lý đỉnh

Một bộ vi xử lý đỉnh là một chương trình xử lý dữ liệu đỉnh. Dưới đây là cách chúng ta tạo một bộ vi xử lý đỉnh:

const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;

function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('Đã xảy ra lỗi biên dịch shader: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);

Mã này xác định mã nguồn của bộ vi xử lý đỉnh và một hàm để tạo và biên dịch các shader.

4. Tạo và biên dịch bộ vi xử lý片段

Một bộ vi xử lý片段 xác định màu sắc của mỗi pixel. Dưới đây là cách chúng ta tạo một bộ vi xử lý片段:

const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

Bộ vi xử lý片段 này sẽ màu đỏ cho tam giác của chúng ta.

5. Tạo một chương trình shader

Bây giờ chúng ta cần liên kết các shader của mình vào một chương trình:

const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.error('Không thể khởi tạo chương trình shader: ' + gl.getProgramInfoLog(shaderProgram));
return;
}

6. Định nghĩa các đỉnh của tam giác

Hãy định nghĩa các đỉnh của tam giác của chúng ta:

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

Những tọa độ này xác định một tam giác trong không gian剪辑, nơi mỗi tọa độ có giá trị từ -1 đến 1.

7. Tạo một bộ nhớ đệm và tải dữ liệu đỉnh

Bây giờ chúng ta cần tạo một bộ nhớ đệm và tải dữ liệu đỉnh vào nó:

const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

8. Liên kết các thuộc tính đỉnh

Chúng ta cần告诉 WebGL cách hiểu dữ liệu đỉnh của chúng ta:

const aVertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aVertexPosition);

9. Vẽ tam giác

Cuối cùng, chúng ta có thể vẽ tam giác của mình:

gl.useProgram(shaderProgram);
gl.drawArrays(gl.TRIANGLES, 0, 3);

Tóm lại

Dưới đây là mã đầy đủ để vẽ một tam giác:

// Lấy ngữ cảnh WebGL
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('Không thể khởi tạo WebGL. Trình duyệt của bạn có thể không hỗ trợ.');
return;
}

// Mã nguồn bộ vi xử lý đỉnh
const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;

// Mã nguồn bộ vi xử lý片段
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

// Hàm tạo shader
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('Đã xảy ra lỗi biên dịch shader: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

// Tạo shaders
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

// Tạo chương trình shader
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.error('Không thể khởi tạo chương trình shader: ' + gl.getProgramInfoLog(shaderProgram));
return;
}

// Định nghĩa đỉnh
const vertices = [
0.0,  0.5,  0.0,
-0.5, -0.5,  0.0,
0.5, -0.5,  0.0
];

// Tạo bộ nhớ đệm và tải dữ liệu đỉnh
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// Liên kết thuộc tính đỉnh
const aVertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aVertexPosition);

// Vẽ tam giác
gl.useProgram(shaderProgram);
gl.drawArrays(gl.TRIANGLES, 0, 3);

Và thế là bạn đã vẽ thành công tam giác đầu tiên của mình bằng WebGL. Có thể có vẻ như nhiều bước cho một tam giác đơn giản, nhưng hãy nhớ rằng, đây là nền tảng để tạo ra đồ họa 3D phức tạp. Mỗi bước chúng ta đã qua là rất quan trọng cho việc渲染 nâng cao.

Kết luận

Chúc mừng bạn đã vẽ thành công tam giác WebGL đầu tiên! Bạn đã迈出了进入计算机图形编程领域的第一步。记住,每一次旅程都是从第一步开始的 - hoặc trong trường hợp của chúng ta, là một tam giác. Hãy tiếp tục thực hành, khám phá, và trước khi bạn biết điều đó, bạn sẽ tạo ra những hình ảnh 3D tuyệt vời làm người khác kinh ngạc!

Dưới đây là bảng tóm tắt các phương thức WebGL chính chúng ta đã sử dụng:

Phương thức Mô tả
getContext('webgl') Lấy ngữ cảnh WebGL
createShader() Tạo một đối tượng shader
shaderSource() Đặt mã nguồn của shader
compileShader() Biên dịch shader
createProgram() Tạo một đối tượng chương trình
attachShader() Gắn shader vào chương trình
linkProgram() Liên kết chương trình
createBuffer() Tạo một đối tượng bộ nhớ đệm
bindBuffer() Gắn bộ nhớ đệm vào một mục tiêu
bufferData() Tạo và�始化 dữ liệu của bộ nhớ đệm
getAttribLocation() Trả về vị trí của một thuộc tính
vertexAttribPointer() Xác định cách hiểu dữ liệu đỉnh
enableVertexAttribArray() Bật một thuộc tính đỉnh
useProgram() Đặt chương trình làm phần của trạng thái渲染 hiện tại
drawArrays() Render các đối tượng từ dữ liệu mảng

Giữ bảng này handy khi bạn tiếp tục hành trình WebGL của mình. Chúc bạn may mắn và hy vọng các tam giác của bạn luôn được render hoàn hảo!

Credits: Image by storyset