0

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

Viblo
Let's register a Viblo Account to get more interesting posts.