opengl 的贴图功能是很基本的,不过也难住了我这个新手,所以特意写了一个示例程序,以便以后查阅。
程序很简单,只是在在 x, y 平面画一个框,然后贴上一张图。并且可以保存opengl窗口到图片。
程序:
//本程序的目的是展示贴图和保存图片 #include <Windows.h> #include <gl/glut.h> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; // Rotation amounts static GLfloat xRot = 0.0f; static GLfloat yRot = 0.0f; const int height = 600; const int width = 800; static GLbyte TextData[1000*1000*4]; static GLuint TexName; static int picrows = 0; static int piccols = 0; void savepic() { GLint viewPort[4] = {0}; glGetIntegerv(GL_VIEWPORT, viewPort); int winrows = viewPort[3]; int wincols = viewPort[2]; GLbyte *colorArr = new GLbyte[winrows*wincols*3]; glReadPixels(viewPort[0], viewPort[1], viewPort[2], viewPort[3], GL_RGB, GL_UNSIGNED_BYTE, colorArr); for(int i=0; i<winrows * wincols * 3; i ++) { if(colorArr[i] == -1) { colorArr[i] = 255; } } Mat show = Mat(winrows, wincols, CV_8UC3, Scalar::all(0)); for (int i = 0; i< winrows; i++) { for (int j = 0; j< wincols; j++) { show.at<Vec3b>(winrows-i-1, j) = Vec3b(colorArr[(i*wincols+j)*3+2], colorArr[(i*wincols+j)*3+1], colorArr[(i*wincols+j)*3]); } } delete colorArr; imshow("show", show); waitKey(33); } // Called to draw scene void RenderScene(void) { // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Save the matrix state and do the rotations glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); //模型 glBegin(GL_QUADS); glNormal3f(0.0f, 0.0f, 1.0f); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 0); glNormal3f(0.0f, 0.0f, 1.0f); glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0); glNormal3f(0.0f, 0.0f, 1.0f); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 0); glNormal3f(0.0f, 0.0f, 1.0f); glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 0); glEnd(); // Restore the matrix state glPopMatrix(); // Display the results glutSwapBuffers(); //savepic(); } // This function does any needed initialization on the rendering // context. void SetupRC() { // Black background glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); ////////////set pixel storage modes glPixelStoref( GL_UNPACK_ALIGNMENT, 1 ); glGenTextures( 1, &TexName ); glBindTexture( GL_TEXTURE_2D, TexName ); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, piccols, picrows, 0, GL_RGBA, GL_UNSIGNED_BYTE, TextData ); //设置s方向纹理重复,为重复设置。 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); //t方向的纹理重复 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); //设置滤波方式为线性滤波 // when texture area is large, bilinear filter the first mipmap glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); // when texture area is small, bilinear filter the closest mipmap glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); //GL_DECAL表示只用纹理颜色,不关心物体表面颜色 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glEnable(GL_TEXTURE_2D); } ///////////////////////////////////////////////////// // Handle arrow keys void SpecialKeys(int key, int x, int y) { if(key == GLUT_KEY_UP) { xRot-= 5.0f; } if(key == GLUT_KEY_DOWN) { xRot += 5.0f; } if(key == GLUT_KEY_LEFT) yRot -= 5.0f; if(key == GLUT_KEY_RIGHT) yRot += 5.0f; if(key > 356.0f) xRot = 0.0f; if(key < -1.0f) xRot = 355.0f; if(key > 356.0f) yRot = 0.0f; if(key < -1.0f) yRot = 355.0f; // Refresh the Window glutPostRedisplay(); } ////////////////////////////////////////////////////////// // Reset projection void ChangeSize(int w, int h) { // Prevent a divide by zero if(h == 0) h = 1; // Set Viewport to window dimensions glViewport(0, 0, w, h); // Reset coordinate system glMatrixMode(GL_PROJECTION); glLoadIdentity(); //GLfloat fAspect = (GLfloat) w / (GLfloat) h; //gluPerspective(45.0f, fAspect, 1.0f, 225.0f); glOrtho(-1.3, 1.3, -1.3, 1.3, -10, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } //载入图片 void gettex(string name) { Mat t = imread(name); piccols = t.cols; picrows = t.rows; assert(picrows<=1000 &&piccols<=1000); for (int i = picrows-1; i>= 0; i--) { for (int j = 0; j< piccols; j++) { TextData[((picrows-1-i)*piccols+j)*4+0] = (GLubyte)t.at<Vec3b>(i, j)[2]; TextData[((picrows-1-i)*piccols+j)*4+1] = (GLubyte)t.at<Vec3b>(i, j)[1]; TextData[((picrows-1-i)*piccols+j)*4+2] = (GLubyte)t.at<Vec3b>(i, j)[0]; TextData[((picrows-1-i)*piccols+j)*4+3] = 255; } } } int main(int argc, char* argv[]) { //读取tex gettex("test.jpg"); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(800,600); glutCreateWindow("pic"); glutReshapeFunc(ChangeSize); glutSpecialFunc(SpecialKeys); glutDisplayFunc(RenderScene); SetupRC(); glutMainLoop(); return 0; }
需要注意的是,当打开savepic开关,并且缩小窗口的时候,会提示错误,目前不太清楚是什么原因。
原因在于保存的时候长宽必须是4的倍数才行。不然会出错。所以,改变窗口大小的话,可以在reshape函数里强制要求长宽被4整除即可。
另外放上一个obj读取的代码,写的很好。不过只能读取点,没有显示。http://download.csdn.net/detail/lcbwlx/6923111