This programming guide is only available in Vietnamese. Switch the language toggle to Vietnamese to read the full article.

Vẽ các đa giác được tô màu trơn hoặc chiếu sáng đơn thuần vẫn chưa đủ để mô tả chi tiết của vật thể phức tạp (như vân gỗ, bề mặt gạch, hay khuôn mặt nhân vật). Để đạt được độ chi tiết cao mà không cần gia tăng số lượng lưới tam giác khổng lồ làm sập hệ thống, người ta nạp hình ảnh 2D dán lên bề mặt 3D. Kỹ thuật này gọi là Texture Mapping (Bản đồ kết cấu).

1. Hệ tọa độ UV (UV Coordinate System)

Để dán một bức ảnh 2D lên đa giác 3D, chúng ta cần một hệ tọa độ quy chiếu ánh xạ. Tọa độ UV là hệ tọa độ phẳng chuẩn hóa nằm trong khoảng từ `0.0` đến `1.0`:

  • Trục U đại diện cho chiều ngang (trái qua phải).
  • Trục V đại diện cho chiều dọc (dưới lên trên).

Mỗi đỉnh của tam giác 3D ngoài tọa độ không gian `(x, y, z)` sẽ được gán thêm tọa độ `(u, v)` tương ứng. Khi tam giác được rasterization, bộ Rasterizer tự động nội suy tọa độ UV này cho từng pixel bề mặt đa giác. Fragment Shader nhận tọa độ UV nội suy này và dùng hàm `texture2D` để lấy mẫu màu sắc tương ứng từ ảnh texture.

2. Cơ chế nạp Texture trong WebGL

Các bước nạp hình ảnh lên bộ nhớ của GPU:

  1. Tạo đối tượng Texture: const texture = gl.createTexture();
  2. Kích hoạt và bind texture: gl.bindTexture(gl.TEXTURE_2D, texture);
  3. Đảo ngược trục Y: Hình ảnh thông thường tải bằng trình duyệt có gốc tọa độ (0,0) nằm tại góc trên-trái. Tuy nhiên, OpenGL/WebGL quy ước tọa độ texture gốc (0,0) nằm tại góc dưới-trái. Do đó, chúng ta phải cấu hình lật trục Y:
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  4. Nạp dữ liệu điểm ảnh lên GPU: `gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);`

3. Bộ lọc Texture (Texture Filtering)

Khi kích thước đa giác hiển thị trên màn hình không khớp hoàn hảo với kích thước gốc của ảnh texture, GPU phải thực hiện bộ lọc để phóng to/thu nhỏ ảnh:

  • gl.NEAREST (Bộ lọc điểm gần nhất): GPU chọn pixel gần nhất để hiển thị. Nhanh nhất nhưng tạo hiện tượng vỡ hạt ô vuông (pixelation) thô thiển khi phóng to đối tượng.
  • gl.LINEAR (Bộ lọc nội suy tuyến tính): GPU lấy trung bình trọng số của 4 pixel xung quanh. Cho kết quả mịn màng hơn nhưng có thể bị mờ nhòe.
  • Mipmapping: GPU sinh sẵn một chuỗi các ảnh thu nhỏ lũy thừa của 2 (ví dụ: 512x512, 256x256, 128x128... tới 1x1). Khi đối tượng ở xa và có kích thước nhỏ trên màn hình, GPU tự chọn ảnh mipmap có độ phân giải phù hợp để lấy mẫu, giảm thiểu nhiễu răng cưa (aliasing) và tăng tốc độ xử lý bộ nhớ cache. Cú pháp khởi tạo mipmap:
    gl.generateMipmap(gl.TEXTURE_2D);

4. Multi-texturing (Nạp nhiều Texture)

GPU chứa các bộ đệm nạp texture song song gọi là Texture Units. Trong Fragment Shader, chúng ta có thể định nghĩa nhiều sampler2D và pha trộn màu sắc giữa chúng bằng phép toán toán học (như hàm `mix`):

texture_blend.frag
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D u_texture1; // Texture Unit 0
uniform sampler2D u_texture2; // Texture Unit 1
uniform float u_mixRatio;

void main() {
    vec4 color1 = texture2D(u_texture1, v_texCoord);
    vec4 color2 = texture2D(u_texture2, v_texCoord);
    gl_FragColor = mix(color1, color2, u_mixRatio); // Trộn màu theo tỷ lệ
}
🎮 Demo tương tác: 3D Cube Texture Blending & Filtering

5. Câu hỏi trắc nghiệm ôn tập

Trắc nghiệm 1: Lật ngược trục Y khi nạp ảnh (UNPACK_FLIP_Y_WEBGL)

Tại sao khi tải ảnh thông thường từ thẻ HTML <img> để làm texture trong WebGL, ta thường thấy ảnh bị lộn ngược theo chiều dọc và phải dùng lệnh lật trục Y?

Trắc nghiệm 2: Ý nghĩa bộ lọc Mipmapping

Tại sao dùng bộ lọc Mipmapping lại giúp khử hiện tượng răng cưa nhiễu hạt tốt hơn khi đối tượng di chuyển ra rất xa?

Trắc nghiệm 3: Khác biệt giữa gl.NEAREST và gl.LINEAR

Khi phóng to một texture có độ phân giải thấp, đâu là khác biệt cốt lõi giữa bộ lọc gl.NEARESTgl.LINEAR?

Mã nguồn đầy đủ của bài thực hành nạp và blend texture:

Tải về mã nguồn Texture Mapping

Related Articles

Bài viết liên quan trong series

Lesson 7: Normal, Bump & Parallax Mapping Bài 7: Normal Mapping, Bump & Parallax Mapping Lesson 5: 3D Lighting Models - Phong & Blinn-Phong Bài 5: Mô Hình Chiếu Sáng Chuyên Sâu — Gouraud, Phong & Blinn-Phong Back to WebGL Course Overview Quay lại Lộ trình WebGL Series