(91) 350-9520 support@omarine.org M-F: 7 AM - 7 PM; Weekends: 9 AM - 5 PM

Môi trường lập trình Android, phần 1: Lập trình OpenGL ES, bài 1: Các ma trận biến đổi, mục 4: Ma trận biến đổi khung nhìn (viewport transformation matrix)

viewport

Sau khi áp dụng ma trận biến đổi phép chiếu, chúng ta được tọa độ clip. Kể từ đó, chương trình đi vào chặng hàm cố định của OpenGL (và OpenGL ES). Tọa độ clip được chia phối cảnh và trở thành tọa độ thiết bị chuẩn hóa trong khoảng [-1,1]. Tọa độ thiết bị chuẩn hóa chỉ là tọa độ logic, nó phải được biến đổi sang tọa độ cửa sổ (hay tọa độ màn ảnh đối với chương trình toàn màn hình) để hiển thị trong một khung nhìn cụ thể. Khung nhìn có thể là toàn bộ cửa sổ (mặc định) hoặc là một hình chữ nhật bộ phận của cửa sổ. Gốc tọa độ đặt tại góc dưới bên trái của cửa sổ, trục x hướng sang phải, trục y hướng lên trên. Trục z chỉ mang tính chất qui ước, mặc định hướng vào trong màn ảnh. Trong khi các tọa độ x, y ấn định vị trí của một điểm ảnh, tọa độ z được dùng để xử lý buffer độ sâu để qui định điểm ảnh được hiển thị nếu nó gần nhất tới người xem, và không nếu đã có một điểm ảnh gần hơn.

Góc dưới bên trái của khung nhìn được xác định trên cửa sổ tại tọa độ x = x0 và y = y0, cả hai tính theo đơn vị là điểm ảnh (pixel). Chiều rộng khung nhìn là w và chiều cao là h. Thang độ sâu mặc định đi từ nw tới fw, trong đó nw là ánh xạ của mặt phẳng clip gần và fw là ánh xạ của mặt phẳng clip xa, được đặt bởi hàm glDepthRangef như sau

glDepthRangef(nw, fw); //cả hai tham số cùng có kiểu là GLfloat

Giá trị mặc định là nw = 0.0f và fw =1.0f.

Giá trị mặc định của thang độ sâu thường là đủ dùng, và hàm đặt viewport chỉ liên quan đến không gian 2 chiều của màn ảnh

glViewport(x0, y0, w, h); //x0, y0 có kiểu GLint; w, h có kiểu là GLsizei

nw không nhất thiết phải nhỏ hơn fw, có thể là ngược lại, ví dụ nw = 1 và fw =0. Trong trường hợp này tọa độ z không còn mang ý nghĩa của độ sâu mà hình dung như “độ nhô ra” của ảnh, càng về phía mặt phẳng clip gần hay càng gần với người xem thì ảnh nhô ra càng lớn, và trục z hướng từ trong ra ngoài màn ảnh. Tuy nhiên, để sử dụng như vậy chúng ta cần điều chỉnh một số thao tác: điều hướng hàm so sánh độ sâu theo hướng ngược lại, tức là chọn giá trị “độ nhô ra” lớn hơn (thay vì mặc định chọn giá trị độ sâu nhỏ hơn); đối với hàm xóa buffer độ sâu sau mỗi lượt vẽ, chọn giá trị đặt lại là “độ nhô ra” nhỏ nhất, ví dụ là 0 (thay vì giá trị đặt lại mặc định là độ sâu lớn nhất, là 1). Điều đó được thực hiện bởi 2 hàm như sau

glDepthFunc(GL_GREATER);

glClearDepthf(0.0f);

Nếu bạn không thực hiện 2 hàm này thì chương trình sẽ vẽ bề mặt của đối tượng ở phía xa mà không vẽ bề mặt của đối tượng ở phía gần, và đối tượng trông bị rỗng.

Nếu chỉ hàm thứ nhất được thực hiện mà không có hàm thứ hai thì sau mỗi lần bị xóa, buffer độ sâu sẽ được điền giá trị tại mặt phẳng clip gần và mặt phẳng này sẽ chắn toàn bộ cảnh phía sau nên không có cảnh nào được vẽ ngoài nền.

Nếu chỉ hàm thứ hai được thực hiện mà không có hàm thứ nhất thì sau mỗi lần bị xóa, buffer độ sâu sẽ được điền giá trị tại mặt phẳng clip xa nhưng hàm so sánh độ sâu chọn giá trị nhỏ hơn nên nó chọn các cảnh phía sau mặt phẳng clip xa, và không có gì ở đó nên cũng không có cảnh nào được vẽ.

Độ phân giải buffer độ sâu và mối liên quan tới kiến trúc không gian camera

Hai hàm glViewportglDepthRangef áp dụng ma trận biến đổi viewport sau đây

viewport2

Gọi zndc là thành phần z của tọa độ thiết bị chuẩn hóa và zw là thành phần z của tọa độ cửa sổ, chúng ta có

viewport3

Gọi ze là thành phần z của tọa độ camera, trong biến đổi phép chiếu chúng ta đã tính được

viewport4

Thay zndc vào biểu thức tính zw

viewport5

Chúng ta biến đổi đẳng thức trên để biểu diễn ze như một hàm của zw

viewport6

Giả sử buffer độ sâu chứa dữ liệu dạng điểm cố định (fixed point) với k bits, hệ số định tỉ lệ (scale) 1/s trong đó s = 2k – 1, thì độ sâu zwi trong buffer độ sâu bằng zw nhân với s rồi làm tròn thành số nguyên

viewport7

Và giá trị tính toán thực tế của zw là zwi/s, thay giá trị này cho zw trong công thức tính ze

viewport8

Với giá trị mặc định nw = 0 và fw =1

viewport9

mặt khác công thức tính zw theo ze trở thành

viewport10

Suy ra

viewport11

Để thấy ảnh hưởng độ phân giải của buffer độ sâu, chúng ta xem kết quả một thực nghiệm dưới đây:

Vẽ một hình lập phương, cố ý vẽ mặt trước của nó sau cùng để thấy mặt trước của nó biến mất, và hình lập phương trông như rỗng và bị cậy mất mặt trước.

Trong thực nghiệm này, hình lập phương có độ dài cạnh là 2 trong mô hình, được scale lên 20 lần. Như vậy cạnh của nó có chiều dài là 40 trong không gian toàn cảnh cũng như trong không gian camera. Hình lập phương được tịnh tiến tới vị trí (0, 0, -150) trong không gian toàn cảnh. Camera đặt tại (0, 75, 0), nhìn vào (0, 0, -150), hướng lên (up) là (0, 1, 0). Như vậy, tọa độ z trung bình của mặt trước và mặt sau của hình lập phương là vào khoảng

ze_front = -145

ze_back = -190

Dữ liệu của hình chóp cụt view như sau

fovy = 450, a = 4.0/3.0

n = 0.00002

f = 10000

Độ sâu bit của buffer độ sâu k = 24, vậy s = 2k -1 = 224 -1 = 16777215

Chúng ta tính độ sâu đã ở trong buffer độ sâu của mặt sau của hình lập phương, và độ sâu cần so sánh để vẽ mặt trước của hình lập phương, cho rằng phương pháp làm tròn số nguyên là lấy số nguyên gần nhất với tham số

viewport12

Như vậy độ sâu của mặt sau và của mặt trước của hình lập phương đều bằng 16777213, với kiểu so sánh mặc định (GL_LESS) thì mặt trước của hình lập phương không được vẽ

cube

Độ phân giải buffer độ sâu

Chúng ta viết lại công thức tính ze theo zwi

viewport13

Tọa độ z trong không gian camera chỉ có thể phân biệt được nếu nó làm thay đổi zwi, trong khi đó zwi là một số nguyên nên thay đổi nhỏ nhất của nó là 1, vậy độ phân giải buffer độ sâu được phản ánh bởi đạo hàm của ze theo zwi

viewport14

Công thức đạo hàm cho thấy, càng tới mặt phẳng clip xa thì trị tuyệt đối của đạo hàm càng lớn hay độ phân giải càng nhỏ. Tại mặt phẳng clip xa zwi = s

viewport15

Tỉ lệ f/n có ảnh hưởng lớn tới độ phân giải này. Với một f nhất định, tăng n sẽ cải thiện độ phân giải. Điều kiện cần để một đối tượng tại mặt phẳng clip xa phân giải được là nó phải có kích thước lớn hơn trị tuyệt đối của đạo hàm. Trong ví dụ nêu trên, suốt một quãng dài của tọa độ z trong không gian camera từ -625 tới -10000 độ sâu có cùng một giá trị là 16777215 nên không phân giải được độ sâu tại mặt phẳng clip xa. Nếu chúng ta thay đổi n = 0.1 thì kích thước tối thiểu cần có của một đối tượng tại mặt phẳng clip xa là

viewport16

Advertisements

Gửi phản hồi

Website này sử dụng Akismet để hạn chế spam. Tìm hiểu bình luận của bạn được duyệt như thế nào.

%d bloggers like this: