Kiến trúc và tối ưu 3D Editor thực chiến với Three.js
Mở đầu
Sau khi xây dựng được:
- selection
- drag
- rotate
- scale
- snapping
- transform controls
… bạn sẽ bắt đầu nhận ra một điều:
render object chỉ là bước khởi đầu.
Phần khó thật sự của một 3D editor nằm ở:
- architecture
- state management
- performance
- synchronization
- UX
- scalability
Đây là lý do:
- một demo Three.js có thể viết trong vài giờ
- nhưng một editor production có thể mất:
- vài tháng
- vài năm
Khi mới học Three.js, đa số developer thường nghĩ:
“3D khó vì đồ họa.”
Nhưng sau khi build editor thật:
bạn sẽ nhận ra phần khó nhất là software engineering.
Trong bài này, chúng ta sẽ đi sâu vào:
- editor architecture
- manager pattern
- undo/redo
- instancing
- serialization
- asset pipeline
- performance bottleneck
- optimization mindset
- production architecture
Đây là:
bước chuyển từ demo → sản phẩm thực tế.
1. Sai lầm lớn nhất khi build editor
Ban đầu ai cũng viết kiểu:
scene.ts
và:
- mọi logic nằm chung
- state global lung tung
- object update trực tiếp
- interaction viết inline
- không separation of concerns
Lúc đầu:
- cực nhanh
- rất dễ làm
Nhưng sau vài tháng:
- bug bắt đầu xuất hiện
- code khó maintain
- interaction chồng chéo
- editor trở nên “mong manh”
Đây là lúc:
technical debt bắt đầu bùng nổ.
2. Vì sao editor architecture khó?
Bởi vì editor:
không phải chỉ render object.
Mà còn phải quản lý:
- interaction
- history
- hierarchy
- selection
- synchronization
- transform propagation
- persistence
- rendering lifecycle
Ví dụ:
- drag object
- update hierarchy
- push history
- update snapping
- check collision
- sync UI panel
Một action nhỏ:
có thể ảnh hưởng rất nhiều hệ thống.
3. Cách suy nghĩ đúng về editor
Đừng nghĩ:
“editor là scene.”
Hãy nghĩ:
“editor là tập hợp các systems.”
Ví dụ:
- rendering system
- selection system
- transform system
- history system
- asset system
- snapping system
Đây là mindset:
cực kỳ quan trọng.
4. Một editor production thường chia như nào?
Ví dụ:
core/
systems/
managers/
stores/
tools/
renderers/
utils/
5. Core layer
Chứa:
- constants
- shared types
- math utils
- transform helpers
Đây là:
phần nền móng của editor.
6. Systems layer
Đây là:
nơi xử lý logic lớn.
Ví dụ:
SelectionSystem
TransformSystem
RenderSystem
HistorySystem
7. Managers layer
Manager thường quản lý:
- lifecycle
- object registry
- synchronization
Ví dụ:
SceneManager
AssetManager
CameraManager
InputManager
8. Vì sao separation quan trọng?
Nếu:
- selection update transform
- transform update renderer
- renderer update history
… mà tất cả gọi trực tiếp nhau:
project sẽ rất khó maintain.
Đây gọi là:
tightly coupled architecture.
9. State management trong editor
Editor thường có rất nhiều state:
selectedObjects
hoveredObject
activeTool
transformMode
snapEnabled
historyStack
cameraState
Nếu state nằm rải rác:
synchronization sẽ trở thành ác mộng.
10. Sai lầm phổ biến với React
Rất nhiều người:
- đưa toàn bộ editor state vào React state.
Ví dụ:
const [objects, setObjects] = useState([])
Ban đầu:
- có vẻ ổn.
Nhưng khi scene lớn:
- re-render liên tục
- FPS giảm mạnh
- interaction lag
11. Cách đúng hơn
React nên:
- quản lý UI state
Three.js engine nên:
- quản lý realtime state
Ví dụ:
- sidebar → React
- object transform realtime → engine/store riêng
12. Undo/Redo khó hơn bạn nghĩ
Nhiều beginner nghĩ:
history.push(state)
là đủ.
Nhưng editor production:
phức tạp hơn rất nhiều.
13. Vì sao snapshot toàn bộ state là sai?
Ví dụ:
- scene có 5000 object
Nếu mỗi action:
clone full scene
→ memory sẽ tăng cực nhanh.
14. Command Pattern
Đây là pattern cực kỳ phổ biến trong editor.
Ví dụ:
MoveCommand
RotateCommand
ScaleCommand
DeleteCommand
15. Command hoạt động thế nào?
Ví dụ:
class MoveCommand {
execute() {}
undo() {}
}
Mỗi command biết:
- apply như nào
- revert như nào
Đây là:
nền tảng của undo/redo chuyên nghiệp.
16. Vì sao command pattern mạnh?
Bởi vì:
- scalable
- maintainable
- dễ debug
- hỗ trợ grouped actions
Ví dụ:
- drag liên tục → gom thành 1 history action.
17. Serialization — lưu editor state
Một editor production:
luôn phải lưu scene.
Ví dụ:
{
"position": [0,0,0],
"rotation": [0,0,0],
"scale": [1,1,1]
}
Nhưng thực tế:
- hierarchy
- metadata
- asset id
- material
- editor config
- hidden state
… đều cần serialize.
18. Sai lầm phổ biến khi serialize
Nhiều beginner:
JSON.stringify(scene)
→ không hoạt động như mong đợi.
Bởi vì:
- circular reference
- internal data
- GPU resource
19. Cách đúng hơn
Nên serialize:
editor data model.
Không serialize trực tiếp:
Three.js object.
20. Asset pipeline quan trọng thế nào?
Một editor thật:
- không chỉ có cube.
Mà còn:
- GLTF
- texture
- material
- HDRI
- animation
- compressed asset
21. GLTF — chuẩn quan trọng nhất hiện nay
GLTF gần như là:
“JPEG của thế giới 3D.”
Ưu điểm:
- nhẹ
- nhanh
- portable
- hỗ trợ animation/material tốt
Đây là format:
gần như bắt buộc phải học.
22. Vì sao asset loading khó?
Bởi vì:
- model lớn
- texture nặng
- network latency
- GPU upload cost
Ví dụ:
- load 500MB texture → browser có thể crash.
23. Lazy loading cực kỳ quan trọng
Đừng load:
mọi thứ ngay từ đầu.
Hãy:
- load khi cần
- unload khi không dùng
- cache intelligently
Đây là:
mindset rất quan trọng.
24. Performance bottleneck thật sự nằm ở đâu?
Người mới thường nghĩ:
React render là vấn đề lớn nhất.
Nhưng với Three.js:
- bottleneck thường nằm ở GPU.
25. Những thứ giết FPS nhiều nhất
Draw calls
Mỗi mesh:
- thường = 1 draw call
10000 mesh: → FPS giảm rất mạnh.
Shadow
Dynamic shadow:
- cực tốn GPU.
Texture size
Texture:
- 4K
- 8K
→ VRAM tăng cực nhanh.
Postprocessing
Ví dụ:
- bloom
- SSAO
- depth effects
→ rất nặng nếu lạm dụng.
26. Instancing — kỹ thuật cực kỳ quan trọng
Nếu scene có:
- 10000 cây
- 5000 ghế
- 20000 object giống nhau
Mà mỗi object:
new Mesh()
→ performance sẽ sụp đổ.
27. InstancedMesh
new THREE.InstancedMesh()
Cho phép:
render hàng nghìn object chỉ bằng vài draw call.
28. Vì sao instancing mạnh?
Thông thường:
- 1000 mesh → 1000 draw calls
Nhưng instancing:
- 1000 object → có thể chỉ 1 draw call
Đây là:
optimization cực kỳ lớn.
29. Nhưng instancing cũng có tradeoff
Ví dụ:
- selection khó hơn
- transform riêng khó hơn
- material customization hạn chế hơn
Đây là:
bài toán tradeoff engineering.
30. Bounding box và collision
Editor production thường cần:
- overlap detection
- snapping
- selection box
- placement validation
Ví dụ:
new THREE.Box3()
31. AABB vs OBB
AABB
Axis-aligned bounding box.
Nhanh:
- nhưng không chính xác khi rotate.
OBB
Oriented bounding box.
Chính xác hơn:
- nhưng tính toán nặng hơn.
32. Đây là nơi toán học 3D bắt đầu phức tạp
Ví dụ:
- local matrix
- world matrix
- inverse matrix
- quaternion
- projection
Đây là lý do:
editor engineering khó hơn demo rất nhiều.
33. Camera system cũng rất quan trọng
Một editor khó dùng thường do:
camera UX kém.
Ví dụ:
- zoom khó chịu
- orbit lag
- pan không tự nhiên
34. Camera UX tốt tạo cảm giác “professional”
Ví dụ:
- smooth damping
- inertia
- focus object
- framing selection
Đây là:
thứ tạo cảm giác editor “xịn”.
35. Vì sao UX là thứ khó nhất?
Bởi vì:
- UX không có công thức cố định.
Ví dụ:
- drag bao nhiêu là đủ mượt?
- snapping bao nhiêu là hợp lý?
- camera speed bao nhiêu là dễ dùng?
Đây là:
thứ cần trải nghiệm thực tế.
36. Điều mình học được khi build editor thật
Ban đầu mình nghĩ:
rendering là phần khó nhất.
Nhưng sau khi build:
- transform system
- snapping
- history
- hierarchy
- selection synchronization
- collision
… mình nhận ra:
software architecture mới là thứ quyết định editor sống được bao lâu.
37. Điều beginner nên tập trung
Đừng cố:
- shader phức tạp
- fancy graphics
- AAA rendering
Hãy tập trung:
- interaction
- transform math
- architecture
- UX
Bởi vì:
đó mới là phần tạo ra sản phẩm thực tế.
38. Roadmap mình khuyên cho người mới
Giai đoạn 1
Hiểu:
- scene
- camera
- mesh
- transform
Giai đoạn 2
Build:
- selection
- drag
- rotate
- scale
Giai đoạn 3
Hiểu:
- hierarchy
- local/world transform
- raycasting
- snapping
Giai đoạn 4
Học:
- optimization
- instancing
- architecture
- serialization
Giai đoạn 5
Build project thật.
Ví dụ:
- room editor
- map editor
- furniture editor
- digital twin
39. Điều quan trọng nhất mình muốn truyền tải
Three.js không chỉ dạy:
- đồ họa 3D
Nó còn dạy:
- software architecture
- optimization mindset
- UX engineering
- spatial thinking
Và đó là lý do:
build editor 3D là một trong những cách học engineering tốt nhất.
Kết bài
Nếu bạn đọc đến đây:
- bạn đã không còn ở level “render cube” nữa.
Mà đang bắt đầu:
suy nghĩ như một graphics/software engineer thật sự.
Và đó mới là:
bước khởi đầu thú vị nhất của Three.js.
All rights reserved