OpenGL – C++ Bài 8: Load Texture cơ bản.
Hi chào mừng các bạn đến với chủ đề: Học Lập Trình OpenGL tại blog phattrienphanmem123az
Bài viết tiếp theo này. Mình chia sẻ với các bạn về kỹ thuật load texture cho một đối tượng trong opengl.
Kỹ thuật về texture có thể nói là đa dạng và phức tạp.
Và trong bài viết này, mình sẽ chia sẻ ở mức cơ bản để bước đầu chúng ta nắm bắt được nguyên lý của nó.
I. Tìm hiểu về Texture, xem nó là cái gì.
Hiểu đơn giản là chúng phủ vật liệu lên một đối tượng đồ họa 3d mà chúng ta tạo ra.
Vật liệu ở đây chính là một tấm ảnh dạng bitmap và chúng được gọi là texture.
Ví dụ tôi tạo ra một hình lập phương. Và tôi muốn phủ vật liệu cho nó là dạng gạch.
Thì kết quả tạo ra sẽ như sau.
Như vậy tính thực tế được thể hiện rất rõ ở đây.
Và texture giúp bạn mô phỏng thế giới thực gần như chân thực nhất.
Ví dụ khi bạn render một bức tường. Bạn có thể dùng texture để phủ vật liệu cho bức tường để nó giống thực tế hơn so khi mô phỏng.
II. Các Step thực hình cơ bản để phủ một vật liệu lên một hình cube như ở trên.
1. Các bạn download thêm thư viện glaux bao gồm file header và file lib ở đây : => Download glaux lib
Sau đó các bạn copy và paste file header và file lib vào cùng thư mục như file glut.h mà trong bài đầu tiên tôi đã chia sẻ.
=> Xem lại bài một, cách cấu hình opengl.
Và sau đó nhớ add lib trong linker với tên lib là: glaux.lib.
2. Các bạn copy một file bitmap trên mạng bất kỳ về với kích thước width và height bằng nhau ví dụ như là: 256×256.
Sau đó copy vào cùng folder với file source trong project.
3. Khai báo 3 biến global như sau:
GLuint g_box; // sử dụng để tạo display list cho đối tượng. GLuint texture; // quản lý texture char texture_name[100]={"brics.bmp"}; // lưu trữ tên file texture
4. Viết một hàm Load bitmap sử dụng thư viện glaux.lib như sau:
AUX_RGBImageRec *LoadBMP(char *Filename) { FILE *File = NULL; if (!Filename) return NULL; fopen_s(&File, Filename, "r"); if (File) { fclose(File); return auxDIBImageLoadA((LPCSTR)Filename); } return NULL; }
Hàm này sẽ thực hiện việc đó và phân tích bitmap và trả ra dữ liệu của bitmap.
5. Viết một hàm Load Texture.
bool LoadGLTextures() { int ret = false; AUX_RGBImageRec *texture_image =NULL; if (texture_image = LoadBMP(texture_name)) { glGenTextures(1, &texture); // Bắt đầu quá trình gen texture. glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //map dữ liệu bit map vào texture. glTexImage2D(GL_TEXTURE_2D, 0, 3, texture_image->sizeX, texture_image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_image->data); } else { ret = false; if (texture_image) { if (texture_image->data) free(texture_image->data); free(texture_image); } } return ret; }
Chế độ filter min mag trong câu lệnh glTexparameteri ở trên có hai loại như sau:
GL_LINEAR và GL_NEAREST.
Sự khác nhau giữa hai kiểu này như sau.
Khi view càng gần, thì NEAREST thể hiện là sự kết hợp bởi các hình vuông nhỏ, nó giống như điểm ảnh sắp xếp với nhau trên một bức ảnh.
Còn LINEAR thì như một sự hòa trộn lại với nhau.
Hãy xem hình vẽ dưới đây.
Các bạn sẽ thấy rõ sự khác biệt giữa nearest và linear.
6. Trong hàm Init của project OpengGL.
Chúng ta enable chế độ load texture.
Sau đó chúng ta gọi hàm LoadTexture đã xây dựng ở trên.
void Init() { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); LoadGLTextures(); // Tạo một cube và load texture cho cube này (đang sử dụng cơ chế display list để render đối tượng) g_box = MakeCube(1.0); }
7. Trong hàm MakeCube ở. Sử dụng hàm glTexcoord2f để map texture vào từng face của cube.
Cơ chế load như sau.
Chúng ta sẽ thấy một texture vuông thì sẽ có tọa độ như ở trên. Góc ở mép dưới sẽ là gốc O. trục Y hương lên và trục X hướng ngang. Và toàn bộ size của texture được coi là mức đơn vị. Từ đó nó sẽ map tương ứng sang các face của đối tượng.
Và đây là hàm MakeCube.
GLuint MakeCube(const float& size) { GLuint boxDisplay; boxDisplay=glGenLists(1); glNewList(boxDisplay,GL_COMPILE); glBegin(GL_QUADS); // Front Face glTexCoord2f(0.0f, 0.0f); glVertex3f(-size, -size, size); glTexCoord2f(1.0f, 0.0f); glVertex3f( size, -size, size); glTexCoord2f(1.0f, 1.0f); glVertex3f( size, size, size); glTexCoord2f(0.0f, 1.0f); glVertex3f(-size, size, size); // Back Face glTexCoord2f(1.0f, 0.0f); glVertex3f(-size, -size, -size); glVertex3f(-size, size, -size); glVertex3f( size, size, -size); glTexCoord2f(0.0f, 0.0f); glVertex3f( size, -size, -size); // Top Face glTexCoord2f(0.0f, 1.0f); glVertex3f(-size, size, -size); glTexCoord2f(0.0f, 0.0f); glVertex3f(-size, size, size); glTexCoord2f(1.0f, 0.0f); glVertex3f( size, size, size); glTexCoord2f(1.0f, 1.0f); glVertex3f( size, size, -size); // Bottom Face glTexCoord2f(1.0f, 1.0f); glVertex3f(-size, -size, -size); glTexCoord2f(0.0f, 1.0f); glVertex3f( size, -size, -size); glTexCoord2f(0.0f, 0.0f); glVertex3f( size, -size, size); glTexCoord2f(1.0f, 0.0f); glVertex3f(-size, -size, size); // Right face glTexCoord2f(1.0f, 0.0f); glVertex3f( size, -size, -size); glTexCoord2f(1.0f, 1.0f); glVertex3f( size, size, -size); glTexCoord2f(0.0f, 1.0f); glVertex3f( size, size, size); glTexCoord2f(0.0f, 0.0f); glVertex3f( size, -size, size); // Left Face glTexCoord2f(0.0f, 0.0f); glVertex3f(-size, -size, -size); glTexCoord2f(1.0f, 0.0f); glVertex3f(-size, -size, size); glTexCoord2f(1.0f, 1.0f); glVertex3f(-size, size, size); glTexCoord2f(0.0f, 1.0f); glVertex3f(-size, size, -size); glEnd(); glEndList(); return boxDisplay; }
8. Trong hàm RenderScene.
void RenderScene() { glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(15.0, 5.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glBindTexture(GL_TEXTURE_2D, texture); glCallList(g_box); glFlush(); }
Và như vậy chúng ta đã có thể map texture vào một đối tượng đồ họa 3d cơ bản.
Many thanks for such an excellent blog. Where else could anyone havethat kind of info written in such a great way?I have a presentation that i’m currently workingon, and I happen to be searching for suchinformation.Many thanks for blogging and i enjoy your posts.
Nice post. I was checking constantly this blog andI’m impressed! Very helpful information specially the last part 🙂 I care for such info much. I was seeking this certain information for a very long time.Thank you and good luck.