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.
In Part 1 you learned a mesh is geometry + material. {Ở Phần 1 bạn đã biết một mesh là geometry + material.} Now we fill the toolbox: which shapes Three.js gives you for free, and which surface model to wrap them in. {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.}
Mix them in the gallery — pick a geometry, pick a material, drag metalness and roughness, and toggle the lights off to feel the difference between a material that obeys light and one that ignores it. {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.}
Open the full demo {Mở demo đầy đủ}: /tools/threejs-geometry-material-demo/.
Geometry — vertices, faces, and the data behind a shape {Geometry — đỉnh, mặt, và dữ liệu sau một hình}
A geometry is really just arrays of numbers: vertex positions, surface normals (which way each face points, for lighting), and UVs (texture coordinates, covered in Part 5). {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 generates these for you for a dozen primitives. {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);
The segment arguments control smoothness. {Tham số segment điều khiển độ mượt.} A SphereGeometry(1, 8, 6) is a chunky gem; SphereGeometry(1, 64, 48) is glassy-smooth — but every extra segment is more vertices for the GPU. {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.} The demo’s HUD shows the vertex and triangle count live; watch it jump when you switch shapes. {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.}
Materials — five models, one decision {Material — năm mô hình, một quyết định}
Picking a material is mostly about how it reacts to light and how much it costs. Here they are, cheapest to richest. {Chọn material chủ yếu là về cách nó phản ứng với ánh sáng và chi phí bao nhiêu. Đây là chúng, từ rẻ nhất tới giàu nhất.}
MeshBasicMaterial — ignores light {MeshBasicMaterial — phớt lờ ánh sáng}
Flat, unlit, always shows its full colour. {Phẳng, không chiếu sáng, luôn hiện đủ màu.} In the demo, toggle the lights off — Basic doesn’t flinch. {Trong demo, tắt đèn đi — Basic không hề nao núng.} Perfect for UI overlays, wireframe debugging, skyboxes, or anything that should not be shaded. {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 — cheap matte {MeshLambertMaterial — matte rẻ}
Diffuse-only lighting computed per vertex. {Chỉ tính ánh sáng khuếch tán, theo từng đỉnh.} Fast, good for large matte surfaces (walls, terrain) where you don’t need highlights. {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 — shiny plastic {MeshPhongMaterial — nhựa bóng}
Adds specular highlights via a shininess value — the classic early-2000s glossy look. {Thêm điểm sáng specular qua giá trị shininess — vẻ bóng kinh điển đầu thập niên 2000.} Still cheaper than PBR, fine for stylised work. {Vẫn rẻ hơn PBR, ổn cho phong cách cách điệu.}
MeshStandardMaterial — the modern default {MeshStandardMaterial — mặc định hiện đại}
Physically-based rendering (PBR). {Render dựa trên vật lý (PBR).} Instead of fiddling with shininess, you describe the real material with two intuitive sliders: {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 = dielectric like plastic/wood, 1 = metal) {metalness (0 = phi kim như nhựa/gỗ, 1 = kim loại)}
- roughness (0 = mirror, 1 = fully matte) {roughness (0 = gương, 1 = matte hoàn toàn)}
new THREE.MeshStandardMaterial({ color: 0xc8ff00, metalness: 0.1, roughness: 0.35 });
Drag those two sliders in the demo: low roughness + high metalness gives a polished chrome; high roughness + zero metalness gives chalk. {Kéo hai slider đó trong demo: roughness thấp + metalness cao cho crôm bóng; roughness cao + metalness 0 cho phấn.} This is the material you’ll reach for 80% of the time. {Đây là material bạn sẽ dùng 80% thời gian.}
MeshPhysicalMaterial — Standard with extras {MeshPhysicalMaterial — Standard có thêm đồ chơi}
Extends Standard with clearcoat (a glossy layer over the base — car paint, lacquered wood), transmission (real glass), sheen (fabric), and iridescence. {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.} Richer, but more expensive — use it only when Standard can’t express the surface. {Giàu hơn nhưng đắt hơn — chỉ dùng khi Standard không tả nổi bề mặt.}
MeshNormalMaterial — the debugger {MeshNormalMaterial — công cụ debug}
Colours each face by its normal direction (RGB = XYZ). {Tô mỗi mặt theo hướng normal (RGB = XYZ).} Not for production — it’s the fastest way to see whether your geometry’s normals are correct (flipped normals = broken lighting later). {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).}
Material properties every senior sets {Thuộc tính material mà senior nào cũng chỉnh}
Beyond color, a few flags come up constantly: {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)
The classic trap: setting opacity = 0.5 and seeing no change. {Cái bẫy kinh điển: đặt opacity = 0.5 mà không thấy đổi gì.} You must also set transparent = true, otherwise Three.js renders the object fully opaque. {Bạn phải đặt thêm transparent = true, không thì Three.js vẫn vẽ vật đục hoàn toàn.} The other one: a PlaneGeometry vanishing when you orbit behind it — its faces only point one way; set side: THREE.DoubleSide. {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 — the memory rule {Dispose — quy tắc bộ nhớ}
Geometries and materials hold GPU resources that JavaScript’s garbage collector cannot free. {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.} When you replace a mesh (as the demo does on every geometry/material switch), dispose the old one: {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();
Skip this in a loop and you leak GPU memory until the context crashes — a very common “my app gets slower over time” bug. {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”.} We go deep on this in Part 10. {Ta sẽ đào sâu việc này ở Phần 10.}
The master’s warnings {Lời cảnh báo của sư phụ}
opacityignored? Settransparent = truefirst. {opacitybị lờ? Đặttransparent = truetrước.}- Plane disappears from behind? Use
side: THREE.DoubleSide. {Plane biến mất khi nhìn từ sau? Dùngside: THREE.DoubleSide.} - Laggy scene? Check your segment counts — a
TorusKnot(…, 256, 64)is a lot of triangles. {Scene giật? Kiểm tra số segment —TorusKnot(…, 256, 64)là rất nhiều tam giác.} - Switching shapes leaks memory?
dispose()the old geometry and material. {Đổi hình bị rò bộ nhớ?dispose()geometry và material cũ.}
Practice, or it didn’t happen {Luyện tập, không thì coi như chưa học}
- Find the chrome {Tìm ra crôm}: with
Standard, set metalness 1 and roughness 0.05. Now raise roughness to 0.6 — watch it turn to brushed metal. {vớiStandard, đặt metalness 1, roughness 0.05. Rồi nâng roughness lên 0.6 — xem nó thành kim loại chải.} - Prove Basic ignores light {Chứng minh Basic lờ ánh sáng}: switch to
Basic, toggle the lights off, confirm nothing changes. Then do the same withLambert. {đổi sangBasic, tắt đèn, xác nhận không đổi. Rồi làm vậy vớiLambert.} - Read the HUD {Đọc HUD}: compare the triangle count of an
Icosahedronvs a smoothSphere. {so số tam giác củaIcosahedronvớiSpheremượt.}
What’s next {Phần tiếp theo}
You can now build any single object and dress its surface. {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ó.} But scenes are made of many objects that move together — an arm attached to a body, a moon orbiting a planet. {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.} In Part 3 we wire up the scene graph: position/rotation/scale, parent-child hierarchies where children inherit transforms, and the two camera types — with a live sun-earth-moon rig you can drive. {Ở 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.}