Bài 6 KỸ THUẬT LẬP TRÌNH XỬ LÝ ĐỒ HỌA VỚI THƯ VIỆN OPENGL
6.4. Bề mặt, màu sắc và ánh sáng
Kỹ thuật đồ họa và Thực tại ảo - Bài 6 Trang 13 Trong phần này, xem xét các vấn đề về tô màu bề mặt, chế độ ánh sáng trên các hình
vẽ.
Trước hết, hãy xem xét việc tô màu bề mặt hình vẽ kín. Thứ nhất, tô màu các hình
vẽ kín bằng lệnh đặt màu glColor3f đã làm ở ví dụ trước. Thứ hai là tô miền kín bằng các mẫu hoặc hình ảnh cho trước và được gọi là texture.
Việc tô màu bằng texture nhằm đạt mục đích hiện thực hóa các đối tượng tốt hơn, tiết kiệm tài nguyên khi dùng các mẫu nhỏ để tô bề mặt lớn (tức sẽ nhân bản các mẫu hoặc co giãn – mipmaps).
Để thực hiện tô theo mẫu texture, có ba bước cơ bản sau:
Bước 1) Tạo và quy định một đối tượng mẫu tô (texture).
Bước 2) Thiết lập các tham số cho mẫu tô, liên kết đối tượng mẫu tô đến đối tượng
đồ họa, và bật chế độ chạy mẫu tô.
Bước 3) Gán tọa độ của mẫu tô đến các đỉnh của hình vẽ để thực hiện tô bề mặt.
Thông thường Bước 1, Bước 2 được lập trình trong hàm init của đối tượng GLEventListener, Bước 3 được thực hiện trong hàm display của đối tượng GLEventListener.
Bây giờ xem xét kỹ các bước thực bằng các lệnh tương ứng.
Bước 1, để tạo đối tượng mẫu tô từ một ảnh dùng lệnh “newTexture” trên lớp TextureIO, truyền tham số là dòng đối tượng File chứa nội dung ảnh cần lấy làm mẫu và đặt chế độ có chạy phép co giãn.
Bước 2 liên kết từ đối tượng mẫu tô đến đối tượng đồ họa GL2 bằng lệnh “bind”, thiết lập các yếu tố cho việc sử dụng mẫu tô bằng lệnh “glTexParameteri” với 3 tham số sau:
Tham số pTarget xác định kiểu áp dụng, thường là GL2.GL_TEXTURE_2D.
Tham số pName là tên loại tham số cần thiết lập, thường dùng để quy định về việc nhân bản mẫu tô, co giãn mẫu tô.
Tham số param là giá trị cần thiết lập cho tham số, sẽ xem xét chi tiết ở phần sau. Cũng trong bước này, phải bật chế độ sử dụng mẫu tô bằng lệnh glEnable với tham
số pTarget là GL2.GL_TEXTURE_2D.
Bước 3, gán tọa của mẫu texture đến tọa độ hình vẽ bằng lệnh glTexCoord2f với 2 tham số s và t theo chiều ngang và chiều dọc trên mẫu, mặc định giá trị của s và t từ 0 đến
Kỹ thuật đồ họa và Thực tại ảo - Bài 6 Trang 14
1 để chứa toàn bộ mẫu, nếu vượt ra ngoài khoảng (0,1) thì sẽ nhân bản mẫu đó lên sang phía trái hoặc phải đối với s, phía trên hoặc dưới đối với t. Theo sau mỗi lệnh glTexCoord2f là lệnh đặt tọa độ điểm vẽ glVertex2f hoặc glVertex3f.
Kết nối đến GL2, thiết lập tham số và khởi chạy texturing
pTarget: kiểu áp dụng, thường là GL2.GL_TEXTURE_2D.
pName: tham số cần quy định, xem xét chi tiết trang sau.
param: giá trị đặt cho tham số, chi tiết ở trang sau.
Gán tọa độ từ texture đến hình vẽ
(s,t) là tọa độ trên texture;
(x,y) là tọa độ trên hình vẽ.
Thực hành việc tô mẫu texture thông qua một ví dụ sau :
Yêu cầu lập trình vẽ hình tam giác và tô theo mẫu từ một ảnh có sẵn, chẳng hạn như trên màn hình với tên tệp ảnh là “photo_of_me.jpg” tại thư mục gốc đĩa D.
Chương trình chủ yếu viết hai hàm là init và display, còn các hàm khác tương tự như các ví dụ trước.
Kỹ thuật đồ họa và Thực tại ảo - Bài 6 Trang 15 Trong hàm init, tạo một đối tượng mẫu tô từ tệp ảnh cho trước ở dòng 45, biến texture phải được khải báo ở phía trên thuộc cùng lớp. Sau đó là lệnh liên kết ở dòng 46
và bật chế độ tô mẫu ở dòng 47. Do lệnh đọc tệp ảnh có thể phát sinh ngoại lệ nên phải đặt vào khối try-catch để xử lý ngoại lệ nếu phát sinh.
Hàm display thực hiện vẽ và đồng thời gán tọa độ mẫu tô để tô màu hình vẽ. Dòng
29 bắt đầu chế độ vẽ hình tam giác bằng lệnh glBegin với tham số GL2.GL_TRIANGLES. Các dòng 30, 31, 32 là các cặp lệnh quy định tọa độ một điểm trên mẫu tô tương ứng với tọa độ 1 đỉnh tam giác khi vẽ.
Có thể thay đổi sự tương ứng một điểm trên mẫu với tọa độ đỉnh tam giác, khi đó kết quả sẽ quay mẫu tô để phù hợp với quy định. Hình ảnh nhỏ phía dưới là kết quả thu được khi thay đổi thiết lập tọa độ tương ứng giữa mẫu và đỉnh tam giác (xem các lệnh ở hình chữ nhật màu đỏ bên cạnh).
Một số tham số thiết lập cho việc tô hình vẽ theo mẫu texture, trong đó lệnh glTexCoord2f quy định tọa độ trên mẫu, lệnh có 2 tham số là s và t để xác định tọa độ theo chiều ngang và dọc. Tọa độ s và t nằm trong đoạn [0,1] đối với không gian ảnh mẫu. Nếu s < 0 thì ảnh mẫu sẽ được nhân lên sang phía bên trái, s > 1 thì nhân lên ảnh mẫu sang phía bên phải. Tương tự với t khi < 0 hoặc > 1 thì ảnh mẫu được nhân lên phía dưới hoặc phía trên. Mỗi ảnh mẫu tương ứng với kích thước đơn vị là 1. Chẳng hạn, khi đặt tọa
độ của s và t từ (-1,-1) đến (2,2) thì ảnh mẫu sẽ được nhân lên thành 9 ảnh, mỗi chiều ngang dọc là 3 ảnh.
Tuy nhiên, để nhân ảnh mẫu lên nhiều lần khi tọa độ nằm ngoài đoạn [0,1] thì phải thiết lập bằng lệnh “glTexParameteri” với tham số thứ nhất là GL2.GL_TEXTURE_2D, tham số thứ hai là GL2.TEXTURE_WRAP_S hoặc GL2.TEXTURE_WRAP_T tương ứng theo chiều ngang hoặc dọc, tham số thứ ba là GL2.GL_REPEAT để nhân ảnh mẫu lên nhiều lần, GL2.GL_MIRRORED_REPEAT để nhân ảnh mẫu theo kiểu đối xứng, GL2.GL_CLAMP để kéo vệt ảnh mẫu,…
Tham số thứ hai thường thiết lập cho việc tô hình vẽ theo ảnh mẫu là quy định về chế độ co giãn.
Khi hình vẽ có vùng cần tô với kích thước lớn, trong khi ảnh mẫu có kích thước bé, thì việc tô bề mặt sẽ phải phóng to ảnh mẫu đó để phủ kín vùng cần tô. Ngược lại, khi ảnh mẫu lớn và vùng tô bé thì phải thu nhỏ ảnh mẫu lại. Thậm chí, việc quy định tọa độ trên ảnh mẫu so với tọa điểm hình vẽ có thể làm xoay, bóp méo, hoặc co giãn một phần của ảnh mẫu để phủ kín bề mặt cần tô.
Kỹ thuật đồ họa và Thực tại ảo - Bài 6 Trang 16
Có hai phép co, giãn hình mẫu và được quy định bởi lệnh “glTexParameteri” với tham số đầu là GL2.GL_TEXTURE_2D, tham số thứ hai là GL2.GL_TEXTURE_MAG_FILTER để quy định kiểu phóng ảnh hoặc GL2.GL_TEXTURE_MIN_FILTER để quy định kiểu thu ảnh, tham số thứ ba là GL2.GL_NEAREST hoặc GL2.GL_LINEAR để quy định chế độ thu/phóng bằng điểm gần nhất hoặc lấy trung bình tuyến tính. Trong đó, phép lấy trung bình sẽ cho ảnh kết quả thu/phóng là mịn hơn nhưng xử lý chậm, còn phép lấy điểm gần nhất sẽ cho kết quả có thể bị vỡ ảnh nhưng xử lý nhanh hơn.
Để minh những vấn đề vừa nêu trên, làm ví dụ lập trình vẽ tam giác và tô bề mặt bằng ảnh mẫu với việc nhân lên nhiều lần.
Trong chương trình, hàm init, từ dòng 37 đến 48, để thực hiện tạo đối tượng mẫu tô texture từ tệp ảnh trên ổ đĩa, xem lệnh TextureIO.newTexture ở dòng 40. Tiếp đó, dòng
41 là lệnh liên kết từ đối tượng mẫu tô texture đến đối tượng đồ họa GL2. Các dòng từ 42 đến 45 là lệnh quy định chế độ nhân ảnh mẫu theo kiểu đối xứng lên nhiều lần theo cả chiều ngang và dọc, chế phóng to ảnh mẫu bằng phép tuyến tính, thu nhỏ bằng phép lấy điểm gần nhất. Cuối cùng, dòng 46 là bật chế độ tô bề mặt theo mẫu.
Hàm display chỉ đơn giản quy định tọa độ ảnh mẫu tương ứng với tọa điểm vẽ hình tam giác. Các lệnh glTexCoord2f thiết lập tọa độ trên ảnh mẫu từ 0 đến 3 nên sẽ được nhân lên 3 lần ảnh mẫu cả chiều ngang và dọc.
Kết quả vẽ và tô bề mặt được thể hiện ở trên màn hình.
Ở phần tiếp theo của bài này, xem xét về việc thiết lập chế độ màu sắc và ánh sáng của hình vẽ.
Trong JOGL, hai chế độ tô màu có thể áp dụng là đơn màu hoặc trộn màu, sử dụng lệnh “glShadeModel” với tham số GL2.GL_FLAT là chế độ đơn màu hoặc GL2.GL_SMOOTH là chế độ trộn màu.
Một điều quan trọng là để đồ họa đạt hiệu quả và có tính thực tế cao nhất, phải sử dụng chế độ ánh sáng đối với các hình vẽ khi tô màu. Phần này sẽ sử dụng các yếu tố, tính chất vật lý của ánh sáng, của vật thể để thể hiện trên đồ họa. Chú ý, về nguyên lý, ánh sáng trắng là tổng hợp nhiều tia sáng đơn sắc, khi nguồn sáng chiếu vào vật thể, màu sắc của vật thể mà ta nhìn thấy là do sự phản xạ của những tia sáng có màu tương ứng, còn các tia sáng màu khác bị hấp thu bởi vật thể đó (tức không bị phản xạ).
Kỹ thuật đồ họa và Thực tại ảo - Bài 6 Trang 17 Thư viện JOGL cung cấp 3 kiểu nguồn sáng gồm ánh sáng từ mặt trời với các tia sáng song song, ánh sáng từ 1 điểm như bóng đèn, ánh sáng từ đèn chiếu như là đèn pin. Mỗi vật thể sẽ có các mô hình màu được tính toán gồm màu phản chiếu (các tia sáng phản chiếu từ vật thể đến mắt), màu khuếch tán (các tia sáng bị khuếch tán trên vật thể), màu bóng sáng và màu xung quanh.
Tiếp theo, sử dụng các lệnh để thiết lập chế độ ánh sáng cho việc tính toán màu trên vật thể.
Trước hết, cần bật chế độ ánh sáng bằng lệnh “glEnable” với tham số GL2.GL_LIGHTING.
Thư viện JOGL cung cấp 8 nguồn sáng với định danh từ GL2.GL_LIGHT0 đến GL2.GL_LIGHT7. Để sử dụng nguồn nào, phải kích hoạt bằng lệnh glEnable với tham số định danh nguồn sáng tương ứng. Ví dụ, sử dụng lệnh glEnable với tham số GL2.GL_LIGHT0 là kích hoạt nguồn sáng thứ nhất.
Mỗi nguồn sáng có các thuộc tính và được quy định giá trị thuộc tính bởi lệnh glLightfv, lệnh này gồm 4 tham số:
Thứ nhất là định danh nguồn sáng, chẳng hạn GL2.GL_LIGHT0.
Thứ hai là tên thuộc tính cần thiết lập, chia thành 2 nhóm thuộc tính cơ bản: nhóm 1
để quy định màu như thuộc tính GL_AMBIENT là màu xung quanh, GL_DIFFUSE là màu khuếch tán, GL_SPECULAR là màu phản chiếu; nhóm 2 để quy định vị trí và kiểu nguồn sáng như thuộc tính GL_POSITION là vị trí, GL_SPOT_DIRECTION là hướng của kiểu nguồn sáng đèn chiếu,…
Thứ ba là bộ giá trị dùng để quy định cho thuộc tính tương ứng, thường là một mảng các giá trị tùy theo thuộc tính đó cần.
Thứ tư là vị trí bắt đầu dùng của mảng, thường là 0.
Trong đó, để ý là nếu quy định vị trí của nguồn sáng với bộ giá trị có số 0 hoặc 1 đứng ở thứ tự số 4 sẽ quy định là kiểu nguồn sáng mặt trời hoặc spotlight.
Thông thường quy định nguồn chiếu sáng là ánh sáng trắng với bộ 3 giá trị thành phần màu (red,green,blue) đều bằng 1.
Để thiết lập thuộc tính cho vật thể sử dụng lệnh glMaterialfv với 4 tham số.
Tham số đầu xác định bề mặt vật thể gồm GL_FRONT là mặt trước, GL_BACK là mặt sau, hoặc GL_FRONT_AND_BACK là cả hai.
Kỹ thuật đồ họa và Thực tại ảo - Bài 6 Trang 18 Tham số thứ 2 xác định thuộc tính cần thiết lập gồm GL_AMBIENT là màu xung quanh, GL_DIFFUSE là màu khuếch tán,…
Tham số thứ 3 là bộ các giá trị cần đặt cho thuộc tính tương ứng, thường phải dùng một mảng để chứa.
Tham số thứ 4 là vị trí bắt đầu sử dụng trong mảng các giá trị, thường là 0.
Bây giờ cần tổng hợp các bước lập trình xử lý liên quan đến thiết lập ánh sáng. Có 3 bước chung như sau:
Bước 1) Bật chế độ thực hiện ánh sáng và nguồn sáng: sử dụng lệnh glEnable
Bước 2) Thiết lập vị trí và tham số cho nguồn sáng cần dùng: sử dụng lệnh glLightfv()
Bước 3) Thực hiện vẽ đối tượng:
Bước 3.1) Thiết lập các thuộc tính vật liệu cho đối tượng
Bước 3.2) Thực hiện vẽ hình cho đối tượng.