WebGL - Các Chế Độ Vẽ

Xin chào, những pháp sư WebGL tương lai! ? Hôm nay, chúng ta sẽ lặn sâu vào thế giới đầy thú vị của các chế độ vẽ trong WebGL. Là giáo viên máy tính ở khu phố của bạn, tôi ở đây để hướng dẫn bạn trong hành trình này, ngay cả khi bạn chưa từng viết một dòng mã trước đây. Vậy, cầm lấy cọ vẽ ảo của bạn, và hãy cùng tạo ra những kiệt tác số!

WebGL - Modes of Drawing

Tham Số mode

Trước khi chúng ta bắt đầu vẽ, hãy nói về ngôi sao của chúng ta: tham số mode. Hãy tưởng tượng nó như một cây c魔法, chỉ định WebGL cách nối các điểm (hoặc trong trường hợp của chúng ta, các đỉnh) để tạo ra các hình dạng và mẫu khác nhau.

Trong WebGL, khi chúng ta gọi hàm gl.drawArrays() hoặc gl.drawElements(), chúng ta cần chỉ định một tham số mode. Tham số này giống như đưa ra hướng dẫn cho một bài nối chấm - nó告诉 WebGL cách nối các điểm chúng ta đã xác định.

Dưới đây là bảng các chế độ vẽ khác nhau trong WebGL:

Chế Độ Mô Tả
gl.POINTS Vẽ một điểm cho mỗi đỉnh
gl.LINES Vẽ một đường giữa mỗi cặp đỉnh
gl.LINE_STRIP Vẽ một đường liên tục nối các đỉnh
gl.LINE_LOOP Giống như LINE_STRIP, nhưng đóng lại hình dạng
gl.TRIANGLES Vẽ một tam giác cho mỗi ba đỉnh
gl.TRIANGLE_STRIP Vẽ một nhóm tam giác nối với nhau
gl.TRIANGLE_FAN Vẽ một hình giống như tua.wind của các tam giác nối với nhau

Đừng lo lắng nếu những điều này có vẻ rối rắm bây giờ. Chúng ta sẽ khám phá từng chế độ với các ví dụ khi chúng ta tiếp tục!

Ví Dụ - Vẽ Ba Đường song song

Hãy bắt đầu với một ví dụ đơn giản: vẽ ba đường song song. Điều này sẽ giúp chúng ta hiểu cách tham số mode hoạt động trong thực tế.

// Đầu tiên, hãy thiết lập ngữ cảnh WebGL của chúng ta
const canvas = document.getElementById('myCanvas');
const gl = canvas.getContext('webgl');

// Bây giờ, hãy xác định bộ vi xử lý đỉnh của chúng ta
const vertexShaderSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
`;

// Và bộ vi xử lý phần tử của chúng ta
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Màu đỏ
}
`;

// Tạo và biên dịch các bộ vi xử lý (đừng lo lắng, chúng ta sẽ giải thích chi tiết trong các bài học sau)
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

// Tạo một chương trình và liên kết các bộ vi xử lý
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// Xác định vị trí của các đường của chúng ta
const positions = new Float32Array([
-0.8, -0.8,  // Điểm bắt đầu của Đường 1
-0.8,  0.8,  // Điểm kết thúc của Đường 1
-0.3, -0.8,  // Điểm bắt đầu của Đường 2
-0.3,  0.8,  // Điểm kết thúc của Đường 2
0.2, -0.8,  // Điểm bắt đầu của Đường 3
0.2,  0.8   // Điểm kết thúc của Đường 3
]);

// Tạo một bộ nhớ đệm và đặt các vị trí vào đó
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

// Chỉ định cách WebGL đọc bộ nhớ đệm và gán nó cho thuộc tính `a_position`
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

// Xóa canvas
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

// Vẽ các đường
gl.drawArrays(gl.LINES, 0, 6);

Bây giờ, hãy phân tích điều này:

  1. Chúng ta thiết lập ngữ cảnh WebGL và xác định các bộ vi xử lý. Đừng lo lắng quá nhiều về这部分 bây giờ; chúng ta sẽ cover chi tiết các bộ vi xử lý trong các bài học sau.

  2. Chúng ta tạo một chương trình và liên kết các bộ vi xử lý vào nó. Điều này giống như chuẩn bị cọ vẽ kỹ thuật số của chúng ta.

  3. Chúng ta xác định vị trí của các đường. Mỗi đường được xác định bởi hai điểm (điểm bắt đầu và điểm kết thúc), và mỗi điểm được xác định bởi hai tọa độ (x và y). Vậy, chúng ta có tổng cộng 6 điểm cho 3 đường của chúng ta.

  4. Chúng ta tạo một bộ nhớ đệm và đặt các vị trí vào đó. Hãy tưởng tượng này như là tải mực vào cọ.

  5. Chúng ta chỉ định cách WebGL đọc bộ nhớ đệm và liên kết nó với thuộc tính a_position trong bộ vi xử lý đỉnh.

  6. Cuối cùng, chúng ta gọi gl.drawArrays(gl.LINES, 0, 6). Đây là nơi phép thuật xảy ra!

  • gl.LINES là chế độ của chúng ta. Nó告诉 WebGL vẽ đường giữa các cặp đỉnh.
  • 0 là chỉ số bắt đầu trong mảng vị trí của chúng ta.
  • 6 là số lượng đỉnh cần xem xét (nhớ lại, chúng ta có 6 điểm cho 3 đường của chúng ta).

Chạy mã này, và voilà! Bạn nên thấy ba đường红线 trên nền đen. Chúc mừng, bạn vừa tạo ra bức vẽ WebGL đầu tiên của mình! ?

Các Chế Độ Vẽ

Bây giờ chúng ta đã thấy gl.LINES trong hành động, hãy khám phá một số chế độ vẽ khác. Chúng ta sẽ sử dụng cùng một thiết lập như trước, nhưng thay đổi vị trí và chế độ vẽ.

gl.POINTS

Hãy bắt đầu với chế độ đơn giản nhất: gl.POINTS. Chế độ này vẽ một điểm cho mỗi đỉnh.

// ... (mã thiết lập trước đó)

const positions = new Float32Array([
-0.5, 0.5,
0.0, 0.0,
0.5, -0.5
]);

// ... (mã thiết lập bộ nhớ đệm)

gl.drawArrays(gl.POINTS, 0, 3);

Điều này sẽ vẽ ba điểm đỏ trên canvas. Đơn giản phải không?

gl.LINE_STRIP

Bây giờ, hãy thử gl.LINE_STRIP. Chế độ này vẽ một đường liên tục nối các đỉnh.

// ... (mã thiết lập trước đó)

const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);

// ... (mã thiết lập bộ nhớ đệm)

gl.drawArrays(gl.LINE_STRIP, 0, 3);

Bạn nên thấy một đường hình V nối các điểm.

gl.LINE_LOOP

gl.LINE_LOOP tương tự như LINE_STRIP, nhưng nó đóng lại hình dạng bằng cách nối điểm cuối cùng với điểm đầu tiên.

// ... (mã thiết lập trước đó)

const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);

// ... (mã thiết lập bộ nhớ đệm)

gl.drawArrays(gl.LINE_LOOP, 0, 3);

Điều này sẽ vẽ một đường viền tam giác.

gl.TRIANGLES

Bây giờ, hãy chuyển sang.fill shapes với gl.TRIANGLES. Chế độ này vẽ một tam giác cho mỗi ba đỉnh.

// ... (mã thiết lập trước đó)

const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
0.0, 0.5
]);

// ... (mã thiết lập bộ nhớ đệm)

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

Bạn nên thấy một tam giác đỏ.

gl.TRIANGLE_STRIP

gl.TRIANGLE_STRIP phức tạp hơn một chút. Nó vẽ một nhóm tam giác nối với nhau, nơi mỗi tam giác chia sẻ hai đỉnh với tam giác trước đó.

// ... (mã thiết lập trước đó)

const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
0.5, 0.5
]);

// ... (mã thiết lập bộ nhớ đệm)

gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

Điều này sẽ vẽ hai tam giác nối với nhau tạo thành hình chữ nhật.

gl.TRIANGLE_FAN

Cuối cùng, hãy xem xét gl.TRIANGLE_FAN. Chế độ này vẽ một hình tua.wind của các tam giác, nơi tất cả các tam giác chia sẻ đỉnh đầu tiên làm điểm chung.

// ... (mã thiết lập trước đó)

const positions = new Float32Array([
0.0, 0.0,    // Điểm trung tâm
0.5, 0.0,    // Điểm 1
0.35, 0.35,  // Điểm 2
0.0, 0.5,    // Điểm 3
-0.35, 0.35  // Điểm 4
]);

// ... (mã thiết lập bộ nhớ đệm)

gl.drawArrays(gl.TRIANGLE_FAN, 0, 5);

Điều này sẽ vẽ một hình looks a bit like a quarter of a circle.

Và thế là xong! Chúng ta đã khám phá tất cả các chế độ vẽ trong WebGL. Nhớ rằng chìa khóa để thành thạo những chế độ này là thực hành. Hãy thử kết hợp các chế độ khác nhau, thay đổi màu sắc và chơi với vị trí đỉnh. Trước khi bạn biết, bạn sẽ tạo ra các cảnh WebGL phức tạp một cách dễ dàng!

Trong bài học tiếp theo, chúng ta sẽ đi sâu hơn vào các bộ vi xử lý và học cách thêm một chútazz vào các bức vẽ của chúng ta với màu sắc và材质. Đến那时, chúc các bạn vui vẻ mã hóa, các nghệ sĩ WebGL tương lai! ??‍??‍?

Credits: Image by storyset