
















Preview text:
  lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh 
Chương 3. Màu sắc và thuật toán tô màu   (tiếp theo)          lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh 
5. Tô màu theo dòng quét  
Giải thuật này thường ược dùng ể tô màu các a giác, ường tròn, ellipse, và 
một số ường cong ơn giản khác. 
Giải thuật tô theo dòng quét (scan-line fill): tìm giao iểm của dòng quét 
ngang với các cạnh của a giác. Từ các giao iểm, xác ịnh các oạn con nằm bên 
trong a giác, rồi tô màu các oạn con này.   
Đối với mỗi dòng quét, cần tìm các giao iểm của dòng quét với a giác. 
Các giao iểm cần ược sắp xếp theo thứ tự tăng dần theo hoành ộ: x1, x2,..., x2n 
(n>0). Tô các oạn x1..x2; x3..x4;...; x2n-1..x2n. 
Khi dòng quét i qua một ỉnh của a giác:  - 
Nếu 2 cạnh từ ỉnh này nằm cùng phía với dòng quét thì tính  là 2 giao iểm.  - 
Nếu 2 cạnh từ ỉnh này nằm khác phía với dòng quét thì tính  là 1 giao iểm. 
Nếu cạnh a giác trùng với dòng quét thì không cần tô cạnh này. 
Trên cùng một cạnh, giao iểm của dòng quét kế ược tính dựa theo giao 
iểm của dòng quét trước:  -  m = dy/dx = (yb-ya)/(xb-xa)  - 
Giao iểm ở ầu oạn: A(xa, ya)  - 
Giao iểm tiếp theo: (xa + 1/m, ya + 1)  - 
Giao iểm tiếp theo: (xa + 1/m + 1/m, ya + 1 + 1) = (xa +  2/m, ya + 2) - v.v….      lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh  B(xb,yb)  ya +1  xa +1/m  ya  A(xa,ya)        Giải thuật: 
1/ Đối với mỗi cạnh không nằm ngang của biên a giác, xác ịnh ỉnh trên và 
dưới, (xl, yl) và (xu, yu), sao cho yu > yl và tạo một mẫu tin cho mỗi cạnh  - 
yu, tọa ộ y tại ỉnh trên  - 
x = xl, giao iểm x hiện tại  - 
w = 1/m = (xu − xl)/(yu − yl), với m là hệ số góc của cạnh 
2/ Đặt bảng AET (active edge table /bảng cạnh ang hoạt ộng) bằng rỗng. 
3/ Áp dụng thuật toán sắp xếp nhóm (bucket) ể sắp xếp các cạnh với yl làm 
khóa chính, xl làm khóa phụ và w làm khóa phụ kế. Mỗi nhóm chứa một danh 
sách. Tập hợp các nhóm ược gọi là bảng ET (edge table /bảng cạnh):   
4/ Đặt y bằng chỉ số nhỏ nhất trong ET có nhóm không rỗng. 
5/ Lặp lại cho ến khi hết ET và AET: 
(a) Dời bất kỳ cạnh nào từ nhóm y trong ET sang AET. 
(b) Loại bỏ bất kỳ cạnh nào khỏi AET mà có yu bằng y.        lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh  (c) Sắp xếp AET theo x. 
(d) Vẽ (tô) các oạn giữa các cặp giao iểm lẻ và chẵn liền kề trong AET: 
làm tròn lên tọa ộ x của các giao iểm bên trái, làm tròn xuống tọa ộ x của các  giao iểm bên phải.  (e) Tăng y thêm một. 
(f) Cập nhật x = x + w cho mọi cạnh không thẳng ứng trong AET. Bảng  AET    
Ký hiệu 1/m [1,5] là W15 = 1/m , với m là hệ số góc của oạn thẳng từ ỉnh 
thứ 1 ến ỉnh thứ 5.    
6. Tô màu với OpenGL  
a. Chỉ ịnh hệ màu 
Hàm glutInitDisplayMode ược dùng ể chỉ ịnh chế ộ màu GLUT_RGBA  hoặc GLUT_INDEX. 
GLUT_RGBA là hệ màu mặc ịnh trong OpenGL. 
Hàm này ược viết trong hàm main.  
VD: glutInitDisplayMode(GLUT_RGB); 
GLUT_RGB là bí danh của GLUT_RGBA.         lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh  b. Tô màu ơn 
Sử dụng glPolygonMode(face, mode) và glColor* ể thiết lập mặt tô và 
màu nền (hoặc màu ường vẽ) của hình vẽ.   
c. Tô màu phối hợp 
Mỗi ỉnh của hình vẽ có màu khác nhau.   glBegin(GL_QUADS); 
 glColor3f(1.0f, 0.0f, 0.0f); // Red  glVertex2f(0.0f, 0.0f); 
glColor3f(0.0f, 1.0f, 0.0f); // Green  glVertex2f(0.3f, 0.0f); 
glColor3f(0.0f, 0.0f, 1.0f); // Blue  glVertex2f(0.3f, 0.3f); 
glColor3f(1.0f, 1.0f, 0.0f); // Yellow 
glVertex2f(0.0f, 0.3f); glEnd();       
d. Tô màu và vẽ ường 
 Vẽ hình thứ 1 với màu nền, sau ó vẽ hình thứ 2 trùng với hình thứ 1 mà  chỉ vẽ ường.     glBegin(GL_TRIANGLES);   glColor3f(0.0, 0.0, 1.0);        lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh   glVertex2i(50, 50);  glColor3f(1.0, 0.0, 0.0);  glVertex2i(150, 50);  glColor3f(0.0, 1.0, 0.0);  glVertex2i(75, 150);  glEnd(); glColor3f(1.0,  0.0, 0.0); 
 glPolygonMode(GL_FRONT, GL_LINE);  glBegin(GL_TRIANGLES);   glVertex2i(50, 50);  glVertex2i(150, 50);  glVertex2i(75, 150);  glEnd(); glFlush();   
e. Tô màu bằng mẫu cho a giác lồi 
1/ Định nghĩa mẫu tô bằng ma trận 32x32 bit (= 1024 bit). 
VD: Mẫu tô là hình con ruồi. Mỗi ô là 1 bit dữ liệu. Nếu ô màu en thì bit 
có giá trị 1. Ngược lại bit có giá trị 0.      lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh   
Đi từ hàng dưới lên, i trừ phải sang trái, ta có các bit dữ liệu sau: 
Hàng 0: 00000000, 00000000, 00000000, 00000000, 
Hàng 1: 00000000, 00000000, 00000000, 00000000, 
Hàng 2: 00000011, 10000000, 00000001, 11000000,  …. 
Cứ mỗi 4 bit số nhị phân, ta chuyển sang 1 chữ số hệ 16 (thập lục phân): 
4 bit số nhị phân Số hệ 16 4 bit số nhị phân Số hệ 16  0000  0  1000  8  0001  1  1001  9  0010  2  1010  A  0011  3  1011  B  0100  4  1100  C  0101  5  1101  D  0110  6  1110  E  0111  7  1111  F  Vậy        lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh  Hàng 0: 00, 00, 00, 00,  Hàng 1: 00, 00, 00, 00,  Hàng 2: 03, 80, 01, C0  …. 
2 số hệ 16 gộp lại thành 1 byte. Để chỉ báo số hệ 16 cần thêm tiền số 0x. 
2/ Ta lưu các số hệ 16 của ma trận mẫu tô vào mảng 1 chiều như sau:  GLubyte fly[] = {   
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   
0x03, 0x80, 0x01, 0xC0, 0x06, 0xC0, 0x03, 0x60, 
 0x04, 0x60, 0x06, 0x20, 0x04, 0x30, 0x0C, 0x20,   
0x04, 0x18, 0x18, 0x20, 0x04, 0x0C, 0x30, 0x20,   
0x04, 0x06, 0x60, 0x20, 0x44, 0x03, 0xC0, 0x22, 
 0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,   
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,   
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,   
0x66, 0x01, 0x80, 0x66, 0x33, 0x01, 0x80, 0xCC,   
0x19, 0x81, 0x81, 0x98, 0x0C, 0xC1, 0x83, 0x30,   
0x07, 0xe1, 0x87, 0xe0, 0x03, 0x3f, 0xfc, 0xc0,   
0x03, 0x31, 0x8c, 0xc0, 0x03, 0x33, 0xcc, 0xc0,   
0x06, 0x64, 0x26, 0x60, 0x0c, 0xcc, 0x33, 0x30, 
 0x18, 0xcc, 0x33, 0x18, 0x10, 0xc4, 0x23, 0x08,   
0x10, 0x63, 0xC6, 0x08, 0x10, 0x30, 0x0c, 0x08,   
0x10, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x08 };   
3/ Các hàm thiết lập việc tô theo mẫu: 
void glEnable(GL_POLYGON_STIPPLE): cho phép tô theo mẫu void 
glDisable(GL_POLYGON_STIPPLE): không cho phép tô theo mẫu      lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh 
void glPolygonStipple(const GLubyte *mask): chỉ ịnh mẫu tô, mask là 
tham số nhận ma trận mẫu tô. 
Xem thêm glPixelStore* và GL_UNPACK*   
Ví dụ: Hình chữ nhựt thứ 1 có nền trắng theo mặc ịnh. Hình chữ nhựt thứ 
2 có mẫu tô là các ường chấm chấm, mẫu tô này ược thiết lập lại là màu blue bằng 
hàm glColor3f. Hình chữ nhựt thứ 3 có mẫu tô là hình con ruồi, mẫu tô này ược 
thiết lập là màu green bằng hàm glColor3f. Hình chữ nhựt thứ 4 có nền ơn màu 
green như màu hình thứ 3.    #include    void display(void)  {    GLubyte fly[] = {   
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   
0x03, 0x80, 0x01, 0xC0, 0x06, 0xC0, 0x03, 0x60, 
 0x04, 0x60, 0x06, 0x20, 0x04, 0x30, 0x0C, 0x20,   
0x04, 0x18, 0x18, 0x20, 0x04, 0x0C, 0x30, 0x20,   
0x04, 0x06, 0x60, 0x20, 0x44, 0x03, 0xC0, 0x22, 
 0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,   
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,   
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,   
0x66, 0x01, 0x80, 0x66, 0x33, 0x01, 0x80, 0xCC, 
 0x19, 0x81, 0x81, 0x98, 0x0C, 0xC1, 0x83, 0x30,   
0x07, 0xe1, 0x87, 0xe0, 0x03, 0x3f, 0xfc, 0xc0,        lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh   
0x03, 0x31, 0x8c, 0xc0, 0x03, 0x33, 0xcc, 0xc0,   
0x06, 0x64, 0x26, 0x60, 0x0c, 0xcc, 0x33, 0x30,   
0x18, 0xcc, 0x33, 0x18, 0x10, 0xc4, 0x23, 0x08,   
0x10, 0x63, 0xC6, 0x08, 0x10, 0x30, 0x0c, 0x08,   
0x10, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x08 };      lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh    GLubyte pattern[] = {   
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55,   
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55,   
0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,   
0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,   
0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00,   
0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00,   
0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   
0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55,   
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55,   
0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,   
0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,   
0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00,   
0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 
 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   
0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 
 //Màu nền theo mặc ịnh   
glRectf(25.0f, 25.0f, 125.0f, 300.0f); //hình chữ nhựt thứ 1   //Màu nền blue    glColor3f(0.0f, 0.0f, 1.0f);   //cho phép mẫu tô    glEnable(GL_POLYGON_STIPPLE);   //tô theo mẫu pattern    glPolygonStipple(pattern); 
 glRectf(125.0f, 25.0f, 225.0f, 300.0f); //hình chữ nhựt thứ 2   //Màu nền green    glColor3f(0.0f, 1.0f, 0.0f);   //tô theo mẫu fly    glPolygonStipple(fly);    Trang 11  Downloaded by  ANhh Trân  (Anhhtrann14062003@gmail.com)    lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh 
 glRectf(225.0f, 25.0f, 325.0f, 300.0f); //hình chữ nhựt thứ 3  //không cho phép mẫu tô   
glDisable(GL_POLYGON_STIPPLE); 
 //Màu nền theo mặc ịnh   
glRectf(325.0f, 25.0f, 425.0f, 300.0f); //hình chữ nhựt thứ 4    glFlush();  } int main(int argc, char**  argv)  {   glutInit(&argc,  argv);  glutInitWindowSize(500,  500);  glutCreateWindow("My  App!");  glutDisplayFunc(display);  gluOrtho2D(0.0,  500.0,  0.0,  500.0);  glutMainLoop(); return 0;  } 
Lưu ý: Nếu không tô mẫu nền mới và không cấm tô mẫu nền, thì hình chữ 
nhựt thứ 4 sẽ có mẫu nền như hình thứ 3.   
f. Tô màu bằng mẫu cho a giác không lồi 
OpenGL chỉ tô theo mẫu cho a giác lồi. 
Giải pháp: Ta chia nhỏ a giác không lồi thành các a giác lồi, thường là thành 
các tam giác. Ta vẽ các a giác lồi này và tô nền chúng. Tuy nhiên, nó sẽ vẽ luôn 
các cạnh không mong muốn bên trong a giác. 
VD: Đa giác không lồi ban ầu ược chia thành 3 tam giác ể vẽ. Nó dư thừa 
các cạnh so với a giác ban ầu.  Trang 12 
Downloaded by ANhh Trân (Anhhtrann14062003@gmail.com)    lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh       
Khắc phục: Khi vẽ một a giác, ta có thể cho phép cạnh nào ược vẽ hoặc 
không ược vẽ. glEdgeFlag(GL_TRUE): cho phép cạnh ược vẽ. 
glEdgeFlag(GL_FALSE): không cho phép cạnh ược vẽ.  VD:   
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);    glColor3f(0.0f, 0.0f, 1.0f);    glBegin(GL_POLYGON);   
glEdgeFlag(GL_TRUE); //cạnh i từ ỉnh sau ây sẽ ược vẽ   glVertex2i(200,250);   
glEdgeFlag(GL_TRUE); //cạnh i từ ỉnh sau ây sẽ ược vẽ   glVertex2i(180,350);   
glEdgeFlag(GL_FALSE); //cạnh i từ ỉnh sau ây không ược vẽ   glVertex2i(130,300);  glEnd();   
VD: Vẽ lại hình a giác trên bằng các tam giác và có tô nền theo mẫu. Sử 
dụng glEdgeFlag ể không vẽ các cạnh không mong muốn.  #include void  display(void)  {    GLubyte fly[] = {   
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    Trang 13  Downloaded by  ANhh Trân  (Anhhtrann14062003@gmail.com)    lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh   
0x03, 0x80, 0x01, 0xC0, 0x06, 0xC0, 0x03, 0x60, 
 0x04, 0x60, 0x06, 0x20, 0x04, 0x30, 0x0C, 0x20,   
0x04, 0x18, 0x18, 0x20, 0x04, 0x0C, 0x30, 0x20,   
0x04, 0x06, 0x60, 0x20, 0x44, 0x03, 0xC0, 0x22, 
 0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,   
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22, 
 0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,   
0x66, 0x01, 0x80, 0x66, 0x33, 0x01, 0x80, 0xCC, 
 0x19, 0x81, 0x81, 0x98, 0x0C, 0xC1, 0x83, 0x30,   
0x07, 0xe1, 0x87, 0xe0, 0x03, 0x3f, 0xfc, 0xc0,   
0x03, 0x31, 0x8c, 0xc0, 0x03, 0x33, 0xcc, 0xc0,   
0x06, 0x64, 0x26, 0x60, 0x0c, 0xcc, 0x33, 0x30, 
 0x18, 0xcc, 0x33, 0x18, 0x10, 0xc4, 0x23, 0x08,   
0x10, 0x63, 0xC6, 0x08, 0x10, 0x30, 0x0c, 0x08,   
0x10, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x08 };    glEnable(GL_POLYGON_STIPPLE);   glPolygonStipple(fly); 
 //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);    glColor3f(0.0f, 0.0f, 1.0f);   //vẽ tam giác thứ 1    glBegin(GL_POLYGON);   glEdgeFlag(GL_TRUE);   glVertex2i(200,250);   glEdgeFlag(GL_TRUE);   glVertex2i(180,350);   glEdgeFlag(GL_FALSE);   glVertex2i(130,300);  glEnd();   //vẽ tam giác thứ 2  Trang 14 
Downloaded by ANhh Trân (Anhhtrann14062003@gmail.com)    lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh    glBegin(GL_POLYGON);    glEdgeFlag(GL_TRUE);   glVertex2i(130, 300);   glEdgeFlag(GL_TRUE);   glVertex2i(20, 350);   glEdgeFlag(GL_FALSE);   glVertex2i(20, 250);  glEnd();    //vẽ tam giác thứ 3  glBegin(GL_POLYGON);    glEdgeFlag(GL_TRUE);   glVertex2i(20, 250);   glEdgeFlag(GL_FALSE);   glVertex2i(200, 250);   glEdgeFlag(GL_FALSE);   glVertex2i(130, 300);   glEnd();  glFlush();  } int main(int argc, char**  argv)  {   glutInit(&argc,  argv);  glutInitWindowSize(500,  500);  glutCreateWindow("My  App!");  glutDisplayFunc(display);  gluOrtho2D(0.0,  500.0,  0.0,  500.0);  glutMainLoop(); return 0;  } 
Lưu ý: Khi tô nền theo mẫu, bỏ thiết lập chế ộ vẽ ường.    Trang 15  Downloaded by  ANhh Trân  (Anhhtrann14062003@gmail.com)    lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh         Trang 16 
Downloaded by ANhh Trân (Anhhtrann14062003@gmail.com)    lOMoAR cPSD| 48704538  ĐỒ HỌA MÁY TÍNH  GV: Hồ Ngọc Thanh  BÀI TẬP   Thực hành 
1. Thiết kế mẫu, viết chương trình toán tô theo mẫu bằng glPolygonStipple cho 
hình vương miện sau (phải có ường vẽ)      Trang 17  Downloaded by  ANhh Trân  (Anhhtrann14062003@gmail.com)