OpenGL – C++ Bài 6: Display List trong OpenGL
Hi. Chào mừng các bạn đến với chủ đề Học Lập Trình OpenGL Tại blog: Phát Triển Phần Mềm 123a-z
Bài viết hôm nay, chúng ta sẽ cùng tìm hiểu về Display list trong OpenGL.
1. Lý Thuyết Cơ Bản.
Thông thường khi chúng ta render một đối tượng nào đó.
Ví dụ như vẽ một cube, một sphere hay một đối tượng nào đó mà là một tập hợp của nhiều vertext.
Thì chúng ta thường xây dựng trong hàm RenderScene. Trong khi RenderScene là một hàm chạy liên tục và do đó đó chúng sẽ liên tục vẽ lại đối tượng.
Điều này làm cho chương trình trở nên chậm chạp, ì ạch nhất là khi đối tượng càng phức tạp và kích thước to lớn.
Do đó Display List được xây dựng để giải quyết vấn đề này.
Display List chỉ thực hiện gọi hàm render đối tượng một lần khi trong hàm Init().
Sau đó chúng sẽ lưu kết quả render đó vào trong bộ nhớ của display list.
Và khi nào cần đến đối tượng. Chỉ việc thực hiện gọi kết quả đã thực hiện xong.
Do đó những tính năng nào của sản phẩm trong đồ họa OpenGL mà ít thay đổi sẽ được đưa vào Display List để giải quyết cho bài toán tối ưu.
Note:
Giải quyết được vấn đề tối ưu, nhưng display list cũng có nhược điểm của nó.
Đó là khi đã thực hiện xong display list rồi thì kết quả đó sẽ không thể bị tác động bởi các nhân tốt khác thực hiện sau đó.
Bên cạnh đó. Không phải câu lệnh nào của OpenGL cũng có thể được đưa vào trong display list
glFlush, glFinish, glRenderMode, glEnableClientState, glVertextPointer….
2. Các Step thực hiện Display list trong OpenGL
+ Khái báo 1 biến toàn cục g_box
GLuint g_box;
+ Viết một hàm render một đối tượng nào đó mà bạn muốn. Ví dụ ở đây tôi viết hàm tạo cube như sau:
GLuint MakeCube() { GLuint boxDisplay; boxDisplay=glGenLists(1); // Bắt đầ thực hiện Display List glNewList(boxDisplay,GL_COMPILE); glBegin(GL_QUADS); // Render Đối tượng trong vùng Display List // Front Face glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Back Face glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Face glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Bottom Face glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Right face glVertex3f( 1.0f, -1.0f, -1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Left Face glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glEnd(); glEndList(); // Kết thúc quá trình Dislay list return boxDisplay; }
+ Gọi hàm Render đối tượng có Display List trong hàm Init của Opengl
và gán kết quả trả về cho biến toàn cục định nghĩa trong step 1
void Init() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); g_box = MakeCube(); }
+ Cuối cùng trong hàm RenderScene ta chỉ việc dùng kết quả của Display List.
glCallList(g_box);
Đối tượng sẽ được render một cách rất tối ưu.
Full Code:
#include <gl\glut.h> GLfloat g_box; void DrawCoordinate() { glDisable(GL_LIGHTING); glBegin(GL_LINES); glColor3f(1.0, 0.0, 0.0); glVertex3f(0.0, 0.0, 0.0); glVertex3f(10.0, 0.0, 0.0); glEnd(); glBegin(GL_LINES); glColor3f(0.0, 1.0, 0.0); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 10.0, 0.0); glEnd(); glBegin(GL_LINES); glColor3f(0.0, 0.0, 1.0); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 0.0, 10.0); glEnd(); glEnable(GL_LIGHTING); } GLuint MakeCube() { GLuint boxDisplay; boxDisplay=glGenLists(1); glNewList(boxDisplay,GL_COMPILE); glBegin(GL_QUADS); // Front Face glNormal3f(0.0, 0.0, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Back Face glNormal3f(0.0, 0.0, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Face glNormal3f(0.0, 0.1, 0.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Bottom Face glNormal3f(0.0, -1.0, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Right face glNormal3f(1.0, 0.0, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Left Face glNormal3f(-1.0, 0.0, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glEnd(); glEndList(); return boxDisplay; } void RendenScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(5.0, 5.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glPushMatrix(); DrawCoordinate(); glCallList(g_box); glPopMatrix(); glFlush(); } void ReShape(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float ratio = (float)width/(float)height; gluPerspective(45.0, ratio, 1, 100.0); glMatrixMode(GL_MODELVIEW); } void Init() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); GLfloat light_pos [] = {0.0, 0.0, 1.0, 0.0}; glLightfv(GL_LIGHT0, GL_POSITION, light_pos); GLfloat ambient[] = {1.0, 1.0, 0.0, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); GLfloat diff_use[] = {0.5, 0.5, 0.0, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff_use); GLfloat specular[] = {1.0, 1.0, 1.0, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); GLfloat shininess = 50.0f; glMateriali(GL_FRONT, GL_SHININESS, shininess); g_box = MakeCube(); } void main() { glutInitDisplayMode(GLUT_SINGLE |GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("Opengl Study"); Init(); glutReshapeFunc(ReShape); glutDisplayFunc(RendenScene); glutMainLoop(); }
Pingback: Học lập trình OpenGL Bài 7: Vẽ Các Đối Tượng Hình Học 3d cơ bản