Trong đồ hoạ máy tính, mỗi điểm của hình là một vector, và mỗi phép xoay, co giãn, lật hay trượt là một ma trận; áp phép biến đổi lên hình nghĩa là nhân ma trận với từng vector. Riêng phép tịnh tiến không phải phép biến đổi tuyến tính, nên người ta thêm một toạ độ phụ, gọi là toạ độ thuần nhất, để mọi phép, kể cả tịnh tiến, đều viết được thành phép nhân ma trận.
Đây là một trong những ứng dụng dễ thấy nhất của đại số tuyến tính, và cũng là cách học phép biến đổi tuyến tính trực quan nhất: bạn có thể kiểm mọi phép tính bằng cách vẽ ra giấy. Bài này đi qua từng loại ma trận cơ bản trong mặt phẳng, cách ghép chúng, lý do cần toạ độ thuần nhất, và một số chỗ lập trình viên mới hay vấp.
Nguyên tắc nền: nhìn cột của ma trận là thấy phép biến đổi
Một phép biến đổi tuyến tính của mặt phẳng được xác định hoàn toàn bởi nơi nó gửi hai vector cơ sở (1, 0) và (0, 1). Hai ảnh đó là hai cột của ma trận. Muốn viết ma trận cho một phép biến đổi, bạn không cần công thức: chỉ cần hỏi "trục hoành đi đâu, trục tung đi đâu" rồi ghi hai câu trả lời thành hai cột.
Áp dụng cho phép xoay góc theta ngược chiều kim đồng hồ: vector (1, 0) đi tới (cos theta, sin theta), vector (0, 1) đi tới (−sin theta, cos theta). Vậy ma trận xoay có hàng (cos theta, −sin theta) và hàng (sin theta, cos theta). Với theta bằng 90 độ, cos bằng 0, sin bằng 1, ma trận gồm hàng (0, −1) và (1, 0). Kiểm với điểm (3, 1): kết quả là (0·3 − 1·1, 1·3 + 0·1) = (−1, 3), đúng là điểm (3, 1) quay một góc vuông quanh gốc.
Cách nghĩ theo cột này đáng giá hơn mọi công thức thuộc lòng. Khi đọc mã nguồn đồ hoạ và gặp một ma trận lạ, hãy nhìn từng cột và tự hỏi hai trục bị đưa đi đâu; phần lớn trường hợp bạn sẽ nhận ra ngay đó là phép gì.
Các ma trận biến đổi cơ bản trong mặt phẳng
Bảng dưới liệt kê các phép thường gặp, viết theo hàng, kèm ảnh của điểm (2, 1) để bạn tự kiểm bằng hình vẽ.
| Phép biến đổi | Ma trận (theo hàng) | Ảnh của (2, 1) | Định thức |
|---|---|---|---|
| Xoay 90 độ ngược chiều kim đồng hồ | (0, −1); (1, 0) | (−1, 2) | 1 |
| Co giãn trục hoành gấp 2, trục tung còn một nửa | (2, 0); (0; 0,5) | (4; 0,5) | 1 |
| Phóng to đều gấp 3 | (3, 0); (0, 3) | (6, 3) | 9 |
| Đối xứng qua trục hoành | (1, 0); (0, −1) | (2, −1) | −1 |
| Đối xứng qua đường y = x | (0, 1); (1, 0) | (1, 2) | −1 |
| Trượt ngang hệ số 1 | (1, 1); (0, 1) | (3, 1) | 1 |
| Chiếu vuông góc xuống trục hoành | (1, 0); (0, 0) | (2, 0) | 0 |
Cột định thức nhắc lại một điều từ bài về định thức: xoay và trượt giữ nguyên diện tích, phóng to đều gấp 3 nhân diện tích lên 9, đối xứng lật chiều nên mang dấu âm, còn phép chiếu làm mất một chiều nên định thức bằng 0 và không thể hoàn tác.
Ghép phép biến đổi: thứ tự là tất cả
Ghép bằng phép nhân. Muốn xoay rồi phóng to, nhân ma trận phóng to với ma trận xoay, ma trận làm trước đứng bên phải, sát với vector. Một ma trận tích duy nhất thay cho hai bước, và có thể áp lên hàng nghìn điểm.
Đổi thứ tự là đổi kết quả. Với xoay và phóng to đều, thứ tự không quan trọng vì phóng to đều giao hoán với mọi phép. Nhưng với xoay và co giãn không đều thì kết quả khác nhau. Tự kiểm với phép kéo trục hoành gấp 2: xoay 90 độ trước đưa (1, 0) tới (0, 1), kéo giãn trục hoành không làm gì nó, kết quả (0, 1); kéo giãn trước thành (2, 0), xoay sau thành (0, 2). Cùng hai phép, hai điểm cuối khác nhau.
Xoay quanh một điểm khác gốc. Ma trận xoay chỉ xoay quanh gốc toạ độ. Muốn xoay quanh điểm P, làm ba bước: tịnh tiến để P về gốc, xoay, rồi tịnh tiến trở lại. Đây là lý do cần biểu diễn tịnh tiến bằng ma trận, để ba bước gộp thành một.
Ma trận xoay không bao giờ cần nghịch đảo tốn công. Nghịch đảo của ma trận xoay bằng chuyển vị của nó, vì các cột vuông góc và có độ dài 1. Phần mềm đồ hoạ lợi dụng điều này để hoàn tác phép xoay gần như không tốn phép tính.
Toạ độ thuần nhất: mẹo để tịnh tiến cũng là phép nhân
Tịnh tiến điểm (x, y) đi một đoạn (a, b) cho (x + a, y + b). Phép này không tuyến tính vì nó đưa gốc toạ độ đi chỗ khác, trong khi mọi phép biến đổi tuyến tính đều giữ gốc đứng yên. Không có ma trận 2×2 nào làm được việc này.
Cách giải quyết là viết điểm (x, y) thành bộ ba (x, y, 1) và dùng ma trận 3×3. Ma trận tịnh tiến có ba hàng (1, 0, a), (0, 1, b), (0, 0, 1); nhân với (x, y, 1) cho đúng (x + a, y + b, 1). Các phép xoay, co giãn vẫn dùng được: đặt ma trận 2×2 cũ vào góc trên trái, cột thứ ba là (0, 0, 1). Bây giờ mọi phép đều là phép nhân ma trận 3×3, ghép được với nhau tuỳ ý.
Ví dụ kiểm thứ tự: điểm (1, 0), xoay 90 độ quanh gốc thành (0, 1), rồi tịnh tiến (2, 0) thành (2, 1). Làm ngược lại, tịnh tiến trước thành (3, 0), rồi xoay thành (0, 3). Hai điểm cuối khác hẳn nhau. Trong không gian ba chiều, ý tưởng giống hệt: điểm (x, y, z) thành (x, y, z, 1) và mọi phép là ma trận 4×4. Phép chiếu phối cảnh, làm vật ở xa trông nhỏ hơn, cũng viết được bằng ma trận 4×4 nhờ toạ độ thứ tư, sau đó chia cho toạ độ này để ra điểm trên màn hình.
Chuỗi ma trận trong một khung hình ba chiều
Khi một cảnh ba chiều được vẽ ra màn hình, mỗi đỉnh của mỗi vật thể đi qua một chuỗi ma trận 4×4 theo một trình tự quen thuộc trong giáo trình đồ hoạ. Ma trận mô hình đặt vật thể vào vị trí, hướng và kích thước của nó trong cảnh. Ma trận nhìn đổi toàn cảnh sang hệ toạ độ gắn với camera, tức là di chuyển cả thế giới ngược với chuyển động của camera. Ma trận chiếu đưa không gian nhìn thấy được về một khối chuẩn, sau đó chia cho toạ độ thứ tư để có phối cảnh.
Ba ma trận này thường được nhân sẵn thành một ma trận duy nhất cho mỗi vật thể, rồi phần cứng đồ hoạ áp nó lên hàng trăm nghìn đỉnh song song. Card đồ hoạ được thiết kế để làm thật nhiều phép nhân ma trận nhỏ cùng lúc, và chính khả năng này về sau được tận dụng cho việc huấn luyện mạng nơ-ron.
Một chi tiết tinh tế cho thấy giá trị của việc hiểu đại số tuyến tính: vector pháp tuyến của bề mặt, dùng để tính ánh sáng, không được biến đổi bằng cùng ma trận với các đỉnh khi có co giãn không đều. Nó phải được nhân với chuyển vị của nghịch đảo ma trận đó, nếu không ánh sáng trên vật thể bị kéo dẹt sẽ sai. Người chỉ chép công thức sẽ không hiểu vì sao; người hiểu tích vô hướng và nghịch đảo sẽ tự suy ra được.
Những chỗ người mới hay vấp khi lập trình đồ hoạ
Khi chuyển từ giấy sang code, các lỗi thường không đến từ toán mà từ quy ước. Danh sách dưới tổng hợp các lỗi phổ biến.
- Nhầm quy ước vector hàng và vector cột. Một số thư viện nhân vector bên trái ma trận, khi đó ma trận là chuyển vị của ma trận trong giáo trình và thứ tự ghép bị đảo. Đọc tài liệu của thư viện đang dùng, đúng phiên bản hiện hành.
- Nhầm thứ tự lưu ma trận trong bộ nhớ. Có thư viện lưu theo hàng, có thư viện lưu theo cột; truyền mảng 16 số sai thứ tự là ra hình bị méo hoặc biến mất.
- Dùng độ thay vì radian. Hàm sin, cos trong hầu hết ngôn ngữ lập trình nhận radian; xoay "90" thành xoay khoảng 90 radian.
- Trục tung hướng xuống. Toạ độ màn hình thường đặt gốc ở góc trên trái và trục tung hướng xuống, nên xoay "ngược chiều kim đồng hồ" trên giấy lại hiện thành cùng chiều trên màn hình.
- Sai số tích luỹ. Nhân ma trận xoay lặp lại hàng nghìn lần mỗi khung hình làm các cột dần mất vuông góc, vật thể bị méo nhẹ. Cách chữa phổ biến là chuẩn hoá lại định kỳ, hoặc lưu góc rồi dựng lại ma trận.
Tự luyện với giấy, bảng tính và AI
Chủ đề này có lợi thế lớn: mọi kết quả đều kiểm được bằng mắt. Một lộ trình luyện ngắn:
- Vẽ một hình chữ L đơn giản bằng bốn, năm điểm trên giấy kẻ ô.
- Áp từng ma trận trong bảng ở trên lên các điểm, tính tay, vẽ hình mới và so với điều bạn đoán trước.
- Ghép hai phép theo hai thứ tự, tính ma trận tích cả hai cách, vẽ ra để thấy khác biệt.
- Dùng một bảng tính hoặc phần mềm vẽ đồ thị để kiểm hàng loạt điểm thay vì tính từng cái.
- Hỏi AI với câu lệnh: "Mô tả bằng lời phép biến đổi mặt phẳng ứng với ma trận gồm hàng (1, 2) và (0, 1), rồi hỏi lại ảnh của một điểm để kiểm." Tự tính trước khi đọc lời giải thích.
- Nếu nhờ AI viết đoạn mã xoay hình, đọc kỹ quy ước hàng hay cột và đơn vị góc trong mã đó, chạy thử với điểm (1, 0) và góc 90 độ, kết quả phải là (0, 1) hoặc gần đúng.
Bài tập thiết kế trong trường có chấm điểm thì tự làm phần toán và mã chính, AI chỉ dùng để hỏi khái niệm hoặc tìm lỗi sau khi đã tự thử.
Câu hỏi thường gặp
Vì sao đồ hoạ ba chiều dùng ma trận 4×4 chứ không phải 3×3?
Ma trận 3×3 chỉ biểu diễn được các phép biến đổi tuyến tính giữ gốc đứng yên như xoay, co giãn. Thêm toạ độ thứ tư bằng 1 cho phép đưa tịnh tiến và phép chiếu phối cảnh vào cùng khuôn nhân ma trận, nên mọi phép ghép được thành một ma trận 4×4 duy nhất.
Quaternion liên quan gì tới ma trận xoay?
Quaternion là một cách khác để biểu diễn phép xoay trong ba chiều, do William Rowan Hamilton đưa ra năm 1843. Nó dùng bốn số thay vì chín, nội suy giữa hai hướng xoay mượt hơn và tránh được hiện tượng khoá trục khi dùng ba góc liên tiếp. Khi cần áp lên điểm, quaternion thường được đổi lại thành ma trận.
Phép chiếu phối cảnh có phải phép biến đổi tuyến tính không?
Không hẳn. Trong toạ độ thuần nhất, nó được viết bằng một ma trận 4×4, nhưng sau đó phải chia các toạ độ cho toạ độ thứ tư để ra điểm thật, và phép chia này không tuyến tính. Đó là lý do vật ở xa trông nhỏ đi, điều mà phép biến đổi tuyến tính thuần tuý không làm được.
Có cần thuộc lòng ma trận xoay không?
Không cần nếu bạn nhớ cách dựng: cột thứ nhất là ảnh của (1, 0), tức (cos, sin), cột thứ hai là ảnh của (0, 1), tức (−sin, cos). Vẽ vòng tròn đơn vị ra là suy được trong vài giây, và cách này không bị nhầm dấu như học thuộc.
Học đồ hoạ máy tính cần những phần nào của đại số tuyến tính?
Vector và tích vô hướng, tích có hướng trong ba chiều, phép nhân ma trận, nghịch đảo và chuyển vị, ma trận trực giao, toạ độ thuần nhất và đổi hệ toạ độ. Trị riêng ít xuất hiện trong phần dựng hình cơ bản nhưng quan trọng trong mô phỏng vật lý và xử lý lưới đa giác.