Lý Thuyết Dò Tia Whitted - SieuDoTia/doTia-whitted GitHub Wiki
Có nhiều cách cho vẽ ảnh trong lĩnh vực đồ họa. Một cách vẽ để lắm là "dò tia". Ý kiến này rất đơn giản, phát tia ra từ một điểm và xem nó trúng vật thể nào gần nhất, tô màu theo màu vật thể và hướng tia nguồn ánh sáng từ điểm đó.
Chương trình này dùng giải thuật Whitted từ 1980 vì áp dụng dơn giản (so với Truyền Áng Sáng Metropolis) và nó kết xuất kiểu ''đồ họa vi tính cổ đại'' rất đẹp, khác với phần mềm dò tia phổ biến hiện đại.
![Tọa đồ cho màn ảnh](https://github.com/SieuDoTia/doTia-whitted/blob/master/MinhHoaLyTuyet/Tọa%20Đồ%20Máy%20Quay %20Phim.svg)
Trước phải chọn định hướng tọa độ. Tôi chọn trục x chỉ phía phải, trục y chỉ thẳng lên, và trục z chỉ đến phía chúng tôi (giống tọa độ OpenGL, nếu bạn không biết OpenGL là cái gì, làm ơn lên mạng và tìm kiếm nó đi).
Tiếp chọn điểm nhìn cho máy quay phim và hướng nó sẽ xem. Cho chương trình này tôi đặt điểm nhìn tại (0; 0; 10) và nhìn hướng âm z, vectơ (0; 0; -1). Phần mềm công nghiệp nên có khả năng cho người dùng đổi điểm và hướng nhìn mà cho bài tập này chúng tôi sẽ không quan tâm vấn đề này.
Màn ảnh được chia thành một mảng ô điểm ảnh. Giải thuất tia dùng các ô này để biết hướng phát tia đầu tiên trong cảnh.
Để vẽ hình trong vị tính chúng tôi cần có một phương pháp nào cho giữ thông tin màu. Màn vô tuyến và ví tính thường dùng ba màu để chiếu ảnh: đỏ, lục, xanh. Mỗi màu được gọi là "kênh" màu hay "thành phần" màu (ba giá trị chung cũng được gọi vectơ màu, hay tọa độ màu trong không gian đỏ, lục, và xanh!).
Tệp dạng hình ảnh như PNG hay JPEG ưa xài 8 hay 16 bit cho mỗi kênh. Nếu xài 8 bit, có thể biểu diễn giá trí 0 đến 28 - 1 hay 255 (0 là không sáng và 255 là sáng nhất). Nghĩa là co 256 giá trị số nguyên khác nhau cho mỗi điểm ảnh trong mỗi kênh. Nếu kèm 3 kênh với nahu có 24 bit được biểu diễn giá trị 0 đến 224 - 1, tức là 16 777 216 màu khác nhau. Cho công việc hàng ngày trên mạng số lượng màu này cứ đủ.
Cho công nghệ như điện ảnh và phim, hế thống này không đủ đâu. Vấn đề xuất hiện liên nếu cần chỉnh độ sáng và độ tối màu nhiều. Đầu thế kỷ 21 có một tếp chuẩn khác gọi EXR dùng 16 bit hay 32 bit số thật đổng phẩy, dùng giá trị số thật từ 0,0 đến 1,0 (thực cũng có biển diễn giá trị hơn 1,0 và âm nữa!). Vì xài số thật đổng phẩy có thể chỉnh độ sáng và tối nhiều mà còn giữ chất lượng ảnh. Khuyết điểm là tệp ảnh to hơn: 16 bit gấp đôi 8 bit còn 32 bit gấp 4 lần!
Cho chương trình dò tia này chúng ta sẽ dùng kiểu số thật đổng phẩy vì chương trình sẽ tính màu bằng giá trị số thật, không cần đổi sang số nguyên. Còn nữa tệp EXR không yêu cầu nén ảnh như PNG hay JPEG, viết mã nguồn lưu tệp EXR sẽ dễ hơn.
Tán xạ (hay khuếch xạ?) là ánh sáng phản xạ ngẫu nhiên từ mặt vật thể. Xem vật thể không bóng, bạn nhìn thấy gì đây? Nó có màu và bóng tối nhưng không thể thấy hình của vật thể xung quanh. Ánh sáng từ nguồn ánh sáng và bị phản xạ mà không có hướng nhất định, gọi là tán xạ ánh sáng. Mặt của đồ không bóng thường không mền và tại cỡ kích vi mô không đục toàn phần, cho nên ánh sáng trúng mặt như vậy được phản xạ nhiều lần đến không biết nó đến từ hướng nào.
Một cách mô phòng hiện tượng này xài tích vô hướng pháp tướng mặt và hướng tia áng sáng đến bằng cộng thức:
m = -(h • n) nếu -tích > 0
m = 0 nếu -tích ≤ 0
m - sức tán xạ
h - hướng tia ánh sáng (đơn vị hóa)
n - pháp tuyến (đơn vị hóa)
còn phải có dấu trừ vì hướng tia từ nguồn ánh sáng nghịch hướng với pháp tuyến mặt. Nếu -(h • n) âm, nghĩa là điểm đó trên mặt không thể thấy nguồn ánh sáng và nên tô một màu cho bóng tối. Sau biết m, nhân m với màu vật thể tô màu cho điểm đó.
màuTanXa = m * màuVậtThe
Nếu nguồn ánh sáng không màu trắng bạn có thể nhân màu ánh sáng nữa
màuTanXa = màuTanXạ * màuÁnhSáng
Để tránh bóng tối qúa đèn, tôi cộng một chút màu của vật thể như đây:
màuTanXa = màuTánXạ + 0,05 * màuVậtThể
Cộng thêm màu vật thể sẽ làm đồ vật sáng hơn một chút nhưng tôi thấy cái đó không tạo vấn đề gì.
Phản Xạ
Khi ánh sáng trúng mặt nào bóng, nó sẽ phẳng xạ. Góc giữa vectơ phản xạ và pháp tuyến mặt bằng góc giữa pháp tuyến mặt và hướng ánh sáng trúng mặt (xem sơ đồ). Để tính vectơ phản xạ:
1) tính tích vô tuyến vectơ pháp tuyến (đơn vị hóa) với vectơ ánh sáng trúng (không đơn vị hóa)
2) nhân giá trị tích vô tuyến với pháp tuyến cho được thành phần của vectơ trúng vuông góc với mặt.
3) nhân 2 và trừ thành phần Viết bằng toán vectơ:
p = a - 2 (n • a) n
p - vectơ phản xạ
a - vectơ ánh sáng (hướng tia ánh sáng)
n - pháp tuyến (đơn vị hóa)
Khúc xạ hơi khó hơn phản xạ. Nhờ cộng thức khúc xạ cho tính hướng vectơ khúc xạ:
c1 sin θ1 = c2 sin θ2
c1 - chiết suất mối trường 1
c2- chiết suất mối trường 2
θ1 - góc giữa vectơ ánh sáng và pháp tuyến
θ2 - góc giữa vectơ khúc và pháp tuyến ngược chiều
Trước đơn vị hóa hướng ánh sáng a. Tính thành phần tiếp tuyến với mặt:
a - (a • n) n
Đồ dài của nó = sin θ1. Vì sau? Bởi đồ dài |a| = 1 (trước đã yêu cầu đơn vị hóa a), tích vô hướng
(a • n) = cos θ1. chúng tôi có thể tính đồ dài cạnh cuối. Nhớ
(sin θ1)2 + (cos θ1)2 = 1
hay
√[1 - (cos θ1)2] = sin θ1
Tôi đã vẽ hình tam giác dưới cho xem. Chỉ cần áp dụng cộng thức khúc xạ và tính đồ dài của thành phần songๆ mặt của vectơ khúc xạ k:
sin θ2 = sin θ1 * c1/c2
Vì |a - (a • n)n| = sin θ1 chỉ cần phóng to thành phần songๆ mặt vectơ ánh sáng như này:
[a - (a • n) n] * c1/c2)2
Khúc tiếp là tính thành phần vuông góc mặt hay nghịch hướng với pháp tuyến mặt -n. Đây không khó đâu vì chúng tôi biết độ dài thành phần songๆ mặt và đồ dài |k| = 1, cho nên đồ dài cho thành phần vuộng góc mặt là:
√[1 - (sin θ2)2] = √[1 - (sin θ1 * c1/c2)2]
hay
√[1 - ({a - (a • n) n} * c1/c2)2]
Cho thành phần vuông mặt:
-n √[1 - ({a - (a • n) n} * c1/c2)2]
Kết qủa cuối cho vectơ khúc xạ k:
[a - (a • n) n] * c1/c2 - n √[1 - ({a - (a • n) n} * c1/c2)2]
Cẩn Thận: Nếu chiết suất c1 > c2, đồ dài thành phần vuông mặt k có thể là số ảo vì:
[1 - ({a - (a • n) n} * c1/c2)2] < 0
Nếu c2 < c1 nên tính gía trị này trước và nếu < 0 tia ánh sáng sẽ không khúc xạ mà sẽ phản xạ, nên dùng cộng thức phản xạ thay thể!
Cao Quang
Tôi quên giải thích về lý thuyết cho cao qung. Cao quang là điểm sáng ưa thấy trên mặt vật thể bóng như hòn bi, gọt nước, v.v. Nó xuật hiện tại khi ánh sáng từ nguồn ánh sáng phản xạ thẳng đến mặt của chúng ta. Cho chương trình dò tia, vì chúng ta phát tia ra từ máy quay phim, vật thể có cao quang khi tia từ máy quay phim phản xạ đến nguồn ánh sáng (xem sơ đồ). Để tính hướng tia phản xạ gần đến nguồn ánh sáng tới mức nào, xài tích vô hướng tia phàn xạ p với hướng tia ánh sáng:
c = -(h • p) nếu -tích > 0
c = 0 nếu -tích ≤ 0
c - sức cao quang
h - hướng tia ánh sáng (đơn vị hóa)
p - hướng tia phản xạ từ mặt vật thể (đơn vị hóa)
Tại sao có dấu âm? Vì hướng tia nguồn ngược hướng với tia phản xạ. Nếu c âm cho điểm nào trên mặt, điểm đó không thể thấy nguồn ánh sáng và cao quang phải = 0. Thặt nếu làm kiểu này điểm quang sẽ rất rộng và không xem như sư thật. Một cách giải quyết vấn đề này làm dùng hàm số lũy thừa như vậy:
c = {-(h • p)}n nếu c > 0
c = 0 nếu ≤ 0
n - số lũy thừa hay mũ
và chọn giá trị 'hợp ý' cho n. Tôi thường xài n = 250. Giá trị cành cao sẽ làm cao quanh nhỏ hơn. Sau biết c rồi, nhân với màu ánh sáng cho tính màu cao quang:
màuCaoQuang = c * màuÁnhsáng
Bạn củng có thể làm n là hàm số của tỉ số phản xạ mặt của vật thể nữa. Tỉ số phản xạ gần 1,0 n được giá trị lớn và gần 0,0 được giạ trị nhỏ và giảm độ sáng của cao quang. Hiệu ứng này là 'xảo thuật' hơn vật lý!