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.

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ángchi 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ụ}

  • opacity ignored? Set transparent = true first. {opacity bị lờ? Đặt transparent = true trước.}
  • Plane disappears from behind? Use side: THREE.DoubleSide. {Plane biến mất khi nhìn từ sau? Dùng side: 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}

  1. 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ớ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. 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 with Lambert. {đổi sang Basic, tắt đèn, xác nhận không đổi. Rồi làm vậy với Lambert.}
  3. Read the HUD {Đọc HUD}: compare the triangle count of an Icosahedron vs a smooth Sphere. {so số tam giác của Icosahedron với Sphere mượ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.}