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();

}

 

 

 

One thought on “OpenGL – C++ Bài 6: Display List trong OpenGL

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.