jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

Three.js from Zero to Senior · Part 2 — Geometries, Materials & Meshes

The shape-and-surface toolkit: built-in geometries, the five core material types (Basic, Lambert, Phong, Standard, Physical) and when each earns its place — with a live gallery to mix geometry, material, metalness, and roughness.

4 MIN READ Updated JUL 12, 2026

Ở Phần 1 bạn đã biết một mesh là geometry + material. Giờ ta lấp đầy hộp đồ nghề: Three.js cho sẵn những hình nào, và nên bọc chúng bằng mô hình bề mặt nào.

Trộn thử trong gallery — chọn geometry, chọn material, kéo metalness và roughness, và tắt đèn để cảm nhận khác biệt giữa material tuân theo ánh sáng và material phớt lờ ánh sáng.

Mở demo toàn màn hình

Geometry — đỉnh, mặt, và dữ liệu sau một hình

Geometry thực ra chỉ là các mảng số: position của đỉnh, normal của bề mặt (mỗi mặt hướng về đâu, dùng cho ánh sáng), và UV (toạ độ texture, sẽ học ở Phần 5). Three.js sinh sẵn những dữ liệu này cho cả tá hình cơ bản.

new THREE.BoxGeometry(width, height, depth);
new THREE.SphereGeometry(radius, widthSegments, heightSegments);
new THREE.TorusGeometry(radius, tube, radialSeg, tubularSeg);
new THREE.TorusKnotGeometry(radius, tube, tubularSeg, radialSeg);
new THREE.ConeGeometry(radius, height, radialSeg);
new THREE.CylinderGeometry(radiusTop, radiusBottom, height, radialSeg);
new THREE.PlaneGeometry(width, height);

Tham số segment điều khiển độ mượt. SphereGeometry(1, 8, 6) là viên đá thô; SphereGeometry(1, 64, 48) mượt như thuỷ tinh — nhưng mỗi segment thêm là thêm đỉnh cho GPU. HUD của demo hiện số đỉnh và tam giác trực tiếp; xem nó nhảy khi bạn đổi hình.

Material — năm mô hình, một quyết định

Chọn material chủ yếu là về cách nó phản ứng với ánh sángchi phí bao nhiêu. Đây là chúng, từ rẻ nhất tới giàu nhất.

MeshBasicMaterial — phớt lờ ánh sáng

Phẳng, không chiếu sáng, luôn hiện đủ màu. Trong demo, tắt đèn đi — Basic không hề nao núng. Hoàn hảo cho lớp UI phủ, debug wireframe, skybox, hay bất cứ thứ gì không nên bị đổ bóng.

new THREE.MeshBasicMaterial({ color: 0xc8ff00 });

MeshLambertMaterial — matte rẻ

Chỉ tính ánh sáng khuếch tán, theo từng đỉnh. Nhanh, hợp với bề mặt matte lớn (tường, địa hình) khi không cần điểm sáng.

MeshPhongMaterial — nhựa bóng

Thêm điểm sáng specular qua giá trị shininess — vẻ bóng kinh điển đầu thập niên 2000. Vẫn rẻ hơn PBR, ổn cho phong cách cách điệu.

MeshStandardMaterial — mặc định hiện đại

Render dựa trên vật lý (PBR). Thay vì vọc shininess, bạn mô tả vật liệu thật bằng hai slider trực giác:

  • metalness (0 = phi kim như nhựa/gỗ, 1 = kim loại)
  • roughness (0 = gương, 1 = matte hoàn toàn)
new THREE.MeshStandardMaterial({ color: 0xc8ff00, metalness: 0.1, roughness: 0.35 });

Kéo hai slider đó trong demo: roughness thấp + metalness cao cho crôm bóng; roughness cao + metalness 0 cho phấn. Đây là material bạn sẽ dùng 80% thời gian.

MeshPhysicalMaterial — Standard có thêm đồ chơi

Mở rộng Standard với clearcoat (lớp bóng phủ trên nền — sơn xe, gỗ phủ verni), transmission (kính thật), sheen (vải), và iridescence. Giàu hơn nhưng đắt hơn — chỉ dùng khi Standard không tả nổi bề mặt.

MeshNormalMaterial — công cụ debug

Tô mỗi mặt theo hướng normal (RGB = XYZ). Không dùng cho production — đây là cách nhanh nhất để nhìn xem normal của geometry có đúng không (normal bị lật = ánh sáng sau này hỏng).

Thuộc tính material mà senior nào cũng chỉnh

Ngoài color, vài cờ hay gặp liên tục:

material.wireframe = true;      // see the triangle mesh
material.flatShading = true;    // faceted look (no smooth normals)
material.transparent = true;    // REQUIRED before opacity < 1 has any effect
material.opacity = 0.5;
material.side = THREE.DoubleSide; // render back faces too (planes, open shapes)

Cái bẫy kinh điển: đặt opacity = 0.5 mà không thấy đổi gì. Bạn phải đặt thêm transparent = true, không thì Three.js vẫn vẽ vật đục hoàn toàn. Cái khác: PlaneGeometry biến mất khi bạn xoay ra sau — mặt của nó chỉ hướng một phía; đặt side: THREE.DoubleSide.

Dispose — quy tắc bộ nhớ

Geometry và material giữ tài nguyên GPU mà bộ thu gom rác của JavaScript không giải phóng được. Khi bạn thay một mesh (như demo làm mỗi lần đổi geometry/material), hãy dispose cái cũ:

scene.remove(mesh);
mesh.geometry.dispose();
mesh.material.dispose();

Bỏ qua bước này trong vòng lặp là bạn rò bộ nhớ GPU cho tới khi context sập — một lỗi rất phổ biến kiểu “app của tôi chậm dần theo thời gian”. Ta sẽ đào sâu việc này ở Phần 10.

Lời cảnh báo của sư phụ

  • opacity bị lờ? Đặt transparent = true trước.
  • Plane biến mất khi nhìn từ sau? Dùng side: THREE.DoubleSide.
  • Scene giật? Kiểm tra số segment — TorusKnot(…, 256, 64) là rất nhiều tam giác.
  • Đổi hình bị rò bộ nhớ? dispose() geometry và material cũ.

Luyện tập, không thì coi như chưa học

  1. Tìm ra crôm: với Standard, đặt metalness 1, roughness 0.05. Rồi nâng roughness lên 0.6 — xem nó thành kim loại chải.
  2. Chứng minh Basic lờ ánh sáng: đổi sang Basic, tắt đèn, xác nhận không đổi. Rồi làm vậy với Lambert.
  3. Đọc HUD: so số tam giác của Icosahedron với Sphere mượt.

Phần tiếp theo

Giờ bạn dựng được bất kỳ vật thể đơn lẻ nào và khoác áo bề mặt cho nó. Nhưng scene gồm nhiều vật di chuyển cùng nhau — cánh tay gắn vào thân, mặt trăng quay quanh hành tinh. Ở Phần 3 ta nối scene graph: position/rotation/scale, phân cấp cha-con nơi con kế thừa biến đổi, và hai loại camera — với một mô hình mặt-trời-trái-đất-mặt-trăng cho bạn điều khiển trực tiếp.